1.5.1 • Published 7 months ago

@podlove/html5-audio-driver v1.5.1

Weekly downloads
146
License
MIT
Repository
github
Last release
7 months ago

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 html5-audio-driver or yarn add html5-audio-driver

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/html5-audio-driver'

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/html5-audio-driver/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/html5-audio-driver'

const audioActions = actions(myAudioElement)

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

Available Actions:

FunctionActionparameters
playSafeplays the audio, initiates load if not already loadedvoid
pausepauses the audiovoid
loadloads the audiovoid
mutemutes the audiovoid
unmuteunmutes the audiovoid
setRatesets the play ratenumber: 0.5 ... 4
setPlaytimesets the current play timenumber: 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/html5-audio-driver/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/html5-audio-driver'

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:

FunctionEventOriginalCallback PayloadOnce
onLoadingWhen browser starts audio loadingprogressAll propstrue
onLoadedWhen browser loaded the entire filecanplaythroughAll propstrue
onReadyWhen browser has enough data to playcanplayAll propsfalse
onPlayWhen browser starts playing audioplayAll propsfalse
onPauseWhen browser pauses audiopauseAll propsfalse
onEndWhen browser reaches end of audioendedAll propsfalse
onBufferChangeWhen browser buffered a new audio segmentprogressbuffered segmentsfalse
onBufferingWhen browser waits for audio segments to playwaitingAll propsfalse
onPlaytimeUpdateWhen currentTime of audio changestimeupdateplaytimefalse
onVolumeChangeWhen volume of audio changesvolumechangevolumefalse
onErrorWhen an error occurred while playing the audioerrorNETWORK_NO_SOURCE, NETWORK_EMPTY, NETWORK_LOADING, MEDIA_ERRORfalse
onDurationChangeWhen browser has new information on audio durationdurationchangedurationfalse
onRateChangeWhen browser detects a change in audio playback rateratechangeratefalse
onFilterUpdateWhen a filter has been changedfilterUpdatedAll propsfalse

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/html5-audio-driver/props'

isPlaying(myAudioElement) // Will return false

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

import { props } from '@podlove/html5-audio-driver/props'

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

Available Properties:

FunctionDescriptionReturn ValueInitial Value
durationDuration of audio in secondsnumberundefined
bufferedBuffered audio segments start and end in seconds[number, number, ...][]
volumeAudio volumenumber: 0...1undefined
stateNetwork StateHAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATAundefined
playtimeCurrent audio playtime position in scondsnumberundefined
endedIndicates if audio has endedbooleanundefined
rateAudio playback ratenumber: 0.5 ... 4undefined
mutedIndicates if audio is mutedbooleanundefined
srcUsed audio sourcestringundefined
pausedIndicates if audio is pausedbooleanundefined
channelsAvailable audio channelsnumberundefined
playingIndicates if audio is playingbooleanfalse

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. html5-audio-driver 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

1.5.1

7 months ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.5.0

4 years ago

1.4.9

4 years ago

1.4.8

5 years ago

1.4.7

5 years ago

1.4.6

5 years ago

1.4.5

5 years ago

1.4.4

5 years ago

1.4.3

5 years ago

1.4.2

5 years ago

1.4.1

5 years ago

1.4.0

5 years ago

1.3.13

5 years ago

1.3.12

5 years ago

1.3.11

5 years ago

1.3.10

5 years ago

1.3.9

5 years ago

1.3.8

5 years ago

1.3.7

6 years ago

1.3.6

6 years ago

1.3.5

6 years ago

1.3.4

6 years ago

1.3.3

6 years ago

1.3.2

6 years ago

1.3.1

6 years ago

1.3.0

6 years ago

1.2.5

6 years ago

1.2.4

7 years ago

1.2.3

7 years ago

1.2.2

7 years ago

1.2.1

7 years ago

1.2.0

7 years ago

1.1.2

7 years ago

1.1.1

7 years ago

1.1.0

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago

0.7.1

7 years ago

0.7.0

7 years ago

0.6.5

7 years ago

0.6.4

7 years ago

0.6.3

7 years ago