npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@podlove/media-backend

v6.1.0-alpha.0

Published

Pure html5 media backend

Downloads

36

Readme

Pure HTML5 Audio Driver

npm version Standard Style Commitizen friendly FOSSA Status

Opinionated low level functional bindings to control html5 audio

Constraints (or what you won't find here)

  • Full functional audio player with controls and all the fuzz, instead you should use mediaelement
  • Support for multiple sounds and ambient control, instead you should use howler.js
  • No WebAudio, instead you should use pizzicato

Features (or what you will find here)

  • Full control over the audio element
  • Functional bindings to all necessary events
  • Composability for all audio actions
  • Helper functions to get relevant audio element properties
  • Written in vanilla es6 with only one dependency to ramda

Installation

npm install media-backend or yarn add media-backend

Usage

Creating an AudioElement

If you have already an audio element defined, good for you, skip this and use the dom reference. Otherwise you can use this helper, the helper will create an audio element without controls, preloading and loops:

import { audio } from '@podlove/media-backend'

const myAudioElement = audio([{
  url: 'audio-files/example.m4a',
  mimeType: 'audio/mp4'
}, {
  url: 'audio-files/example.mp3',
  mimeType: 'audio/mp3'
}, {
  url: 'audio-files/example.ogg',
  mimeType: 'audio/ogg'
}])

mimeType is needed so the browser can decide what source is appropriated to use.

Interacting with the audio element

All audio element actions are curried and accept as their first parameter the audio element. Also each action returns the audio element:

import { compose } from 'ramda'
import { play, setPlaytime } from '@podlove/media-backend/actions'

const setPlaytimeAndPlay = compose(play, setAudioPlaytime)(myAudioElement)
// Sets the playtime to 50 seconds and plays the audio
setPlaytimeAndPlay(50)

For convenience also a action composer is available:

import { actions } from '@podlove/media-backend'

const audioActions = actions(myAudioElement)

audioActions.load()
audioActions.play()
audioActions.pause()
audioActions.setPlaytime(50)
audioActions.setRate(1.5)
audioActions.mute()
audioActions.unmute()

Available Actions:

| Function | Action | parameters | |---------------|-----------------------------------------------------------|--------------------------| | play | Safeplays the audio, initiates load if not already loaded | void | | pause | pauses the audio | void | | load | loads the audio | void | | mute | mutes the audio | void | | unmute | unmutes the audio | void | | setRate | sets the play rate | number: [0.5 ... 4] | | setPlaytime | sets the current play time | number: [0 ... duration] |

Reacting to audio events

All audio events are curried and accept as their first parameter the audio element. The second parameter is always the callback function. Each event returns a different set of audio properties, depending on the event scope:

import { onPlay } from '@podlove/media-backend/events'

const playEvent = onPlay(myAudioElement)

playEvent(console.log) // similar to onPlay(myAudioElement, console.log)
/**
* Will log audio properties on audio play:
* {
*  duration,
*  buffered,
*  volume,
*  state,
*  playtime,
*  ended,
*  rate,
*  muted,
*  src,
*  paused,
*  playing
* }
*/

For convenience also a events composer is available:

import { events } from '@podlove/media-backend'

const audioEvents = events(myAudioElement)

audioEvents.onLoading(console.log)
audioEvents.onLoaded(console.log)
audioEvents.onReady(console.log)
audioEvents.onPlay(console.log)
audioEvents.onPause(console.log)
audioEvents.onBufferChange(console.log)
audioEvents.onBuffering(console.log)
audioEvents.onPlaytimeUpdate(console.log)
audioEvents.onVolumeChange(console.log)
audioEvents.onError(console.log)
audioEvents.onDurationChange(console.log)
audioEvents.onRateChange(console.log)
audioEvents.onEnd(console.log)

Available Events:

| Function | Event | Original | Callback Payload | Once | |---------------------|-------------------------------------------------------|-------------------|-------------------------------------------------------------------------|---------| | onLoading | When browser starts audio loading | progress | All props | true | | onLoaded | When browser loaded the entire file | canplaythrough | All props | true | | onReady | When browser has enough data to play | canplay | All props | false | | onPlay | When browser starts playing audio | play | All props | false | | onPause | When browser pauses audio | pause | All props | false | | onEnd | When browser reaches end of audio | ended | All props | false | | onBufferChange | When browser buffered a new audio segment | progress | buffered segments | false | | onBuffering | When browser waits for audio segments to play | waiting | All props | false | | onPlaytimeUpdate | When currentTime of audio changes | timeupdate | playtime | false | | onVolumeChange | When volume of audio changes | volumechange | volume | false | | onError | When an error occurred while playing the audio | error | NETWORK_NO_SOURCE, NETWORK_EMPTY, NETWORK_LOADING, MEDIA_ERROR | false | | onDurationChange | When browser has new information on audio duration | durationchange | duration | false | | onRateChange | When browser detects a change in audio playback rate | ratechange | rate | false | | onFilterUpdate | When a filter has been changed | filterUpdated | All props | false |

Audio Element Properties

Multiple different functions are provided to give you easy access to audio element properties. Initially most of them are undefined:


import { volume } from '@podlove/media-backend/props'

isPlaying(myAudioElement) // Will return false

For convenience also a composed version is available giving you all available properties:

import { props } from '@podlove/media-backend/props'

props(myAudioElement)
/**
* {
*  duration,
*  buffered,
*  volume,
*  state,
*  playtime,
*  ended,
*  rate,
*  muted,
*  src,
*  paused,
*  playing
* }
*/

Available Properties:

| Function | Description | Return Value | Initial Value | |-------------|---------------------------------------------------|-----------------------------------------------------------------------------------------------|-----------------| | duration | Duration of audio in seconds | number | undefined | | buffered | Buffered audio segments start and end in seconds | [[number, number], ...] | [] | | volume | Audio volume | number: [0...1] | undefined | | state | Network State | HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA | undefined | | playtime | Current audio playtime position in sconds | number | undefined | | ended | Indicates if audio has ended | boolean | undefined | | rate | Audio playback rate | number: [0.5 ... 4] | undefined | | muted | Indicates if audio is muted | boolean | undefined | | src | Used audio source | string | undefined | | paused | Indicates if audio is paused | boolean | undefined | | channels | Available audio channels | number | undefined | | playing | Indicates if audio is playing | boolean | false |

Handled HTML5 Quirks and Limitations (the nasty part :/)

HTML5 audio was a needed addition to get rid of the flash hell. Although it is already multiple years implemented in all the different browsers each implementation has it's flaws. If you want to dive deeper into the topic I recommend you the following article.

Play Action

Using the play action will give you a safe function that surpresses most of the errors. One source is that older browsers doesn't implement audio.play() as a promise. Also there is a race condition between play and pause that needs to be .catched.

Playtime (CurrentTime)

In Safari and mobile Safari it isn't possible to set the currentTime before loading the audio. You can set it but it won't mutate the audio currentTime value. media-backend therefore uses a custom playtime attribute that is synced wit the currentTime.

Mobile Environments

To play audio on mobile devices you have to trigger use a direct user interaction to trigger the audio. Also volume is not available on mobile devices.

Legacy Browser Support (IE11)

In case you need IE11 support you have to provide some polyfills in your application. Have a look at the test polyfills to see a working example.

Publishing

Run npm publish:prepare move to the dist/ folder and run npm publish --public

License

FOSSA Status