-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Audio position resets when using (mobile) notification controls, Media Session API vs .play()/.pause(). #1262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Update: mobile-like media controls will land soon in Chrome (you can enable |
I found a workaround:
Please note that the examples of the older pen (linked above) might not work today-ish, the MP3 server is down. I'd be happy to provide a PR, but I lack experience with Howler and its intricacies. |
FYI, to whom it may concern in the future, the workaround above allowed me to integrate Howler somewhat successfully with the Media Session API (setActionHandler with |
...and I've managed to make it work with pre-MediaSession (older browsers, iOS Control Center) controls AND live streams. The solution above apparently worked only with fixed-length files.
|
Hello @bikubi 👋 Could you please share a full workaround example with us, while we all pray for #1530 to fix the problem eventually. It's not clear how you fixed it with the snippet above and setActionHandler |
After trials and errors this recipe worked #1175 (comment) |
@satyrius if you're still interested i could throw a MWE together next week (on vacation r/n) |
@bikubi It would be great to look at your solution. Ofc no rush with it. Some observation. I managed to make it work with Here's a snippet from my react component. import React, { useState, useEffect } from 'react'
import { getStorage, ref, getDownloadURL } from 'firebase/storage'
import { Howl } from 'howler'
function Player({ file }) {
const [position, setPosition] = useState(0)
const [isLoaded, setLoaded] = useState(false)
const [isPlaying, setPlaying] = useState(false)
const [audio, setAudio] = useState()
useEffect(() => {
if (file)
getDownloadURL(ref(getStorage(), file))
.then((url) => {
const howl = new Howl({
src: [url],
html5: true,
onplay: () => {
setPlaying(true)
showCurrentPosition()
},
onpause: () => {
setPlaying(false)
},
})
const showCurrentPosition = () => {
const sec = Math.floor(howl.seek())
setPosition(sec)
if (howl.playing()) {
setTimeout(showCurrentPosition, 200)
}
}
setAudio(howl)
setLoaded(true)
})
.catch((error) => {
setAudio(null)
setLoaded(false)
})
}, [file])
// Sync Media Session with Howl
// https://github.com/goldfire/howler.js/issues/1175
useEffect(() => {
if (audio && navigator && navigator.mediaSession) {
navigator.mediaSession.setActionHandler('play', () => audio.play())
navigator.mediaSession.setActionHandler('pause', () => audio.pause())
}
}, [audio])
// rendering...
} |
Or, more generally, does Howler handle mobile OS audio controls?
On mobile devices, when you play HTML5 Audio, the OS let's you control it. (Android: notification drawer, per-app + headset remote control, somewhat globally; iOS: "Control Center", globally).
My web app has regular (browser) control buttons, too. Both control schemes (let's call them "OS" and "browser") should work seamlessly & interchangeably, IMO. But, they only work as long as i stick to one scheme exclusively (pause/unpause by browser, pause/unpause by OS) - as soon as I mix (play by browser, pause by OS, unpause by browser), the audio position is reset to zero.
As far as I can tell, this happens somewhere in
play()
, but I could not pin it down exactly.I have made a Pen to reproduce the issue, with instructions. Tested on Android 9 / Chrome 78.
Note that this does not occur on the Music Player example, where you have to essentially pause twice (play by browser, pause by OS, pause again by browser, then play by browser).
Background:
play
andpause
events on the Audio node, but just by looking at the event AFAIK there is no way to tell that they came "from the OS"Any insight welcome!
The text was updated successfully, but these errors were encountered: