1

Again, working on my audio player...

I've rediscovered a mediasession updater in my code that adds a little notification from the browser with controls for my music, and it used to work ok, a little finicky, but now...

Nothing. I tinkered around a bit and got my play/pause buttons working, along with the next/prev songs and seek buttons, and the music title and artist. But I have now found that if you press the play button, the next/prev button, or sometimes the pause button, that the options and the song details disappear, leaving me with only the play/pause button, which works perfectly...

Now, to the code. I have a function that loads the songs in my player (loadSong(songIndex)), and near the end, I have a few lines of code that reset the navigator's metadata:

navigator.mediaSession.metadata.title = song.songname;
navigator.mediaSession.metadata.author = song.artistname;
navigator.mediaSession.metadata.artwork = ("./Music/" + song.thumbnail);

The artist and name work perfectly, but the thumbnail doesn't... More on that in a separate question.

I set up the actual controls like this:

/*media controls*/
let index = 0;
let skipTime = 10;

const actionHandlers = [
  ['play',          () => { main.playPauseControl.click(); navigator.mediaSession.playbackState = "playing"; updatePositionState();}],
  ['pause',         () => { main.playPauseControl.click(); navigator.mediaSession.playbackState = "paused"; updatePositionState();}],
  ['previoustrack', () => { main.prevControl.click(); updatePositionState();}],
  ['nexttrack',     () => { main.nextControl.click(); updatePositionState();}],
  ['seekbackward',  (details) => { main.audio.currentTime = Math.max(main.audio.currentTime - skipTime, 0); updatePositionState();}],
  ['seekforward',   (details) => { main.audio.currentTime = Math.min(main.audio.currentTime + skipTime, main.audio.duration); updatePositionState();}],
];

for (const [action, handler] of actionHandlers) {
  try {
    navigator.mediaSession.setActionHandler(action, handler);
  } catch (error) {
    console.log(`The media session action "${action}" is not supported yet.`);
  }
}

I have some other things linked to the mediaSession in order to register interactions outside the navigator

main.audio.addEventListener('play', function() {
  navigator.mediaSession.playbackState = 'playing';
  main.playPauseControl.classList.remove("paused");
});

main.audio.addEventListener('pause', function() {
  navigator.mediaSession.playbackState = 'paused';
  main.playPauseControl.classList.add("paused");
});

Now this all works, initially, but as soon as I interact with the navigator, BOOM, everything disappears. Can someone PLEASE tell me what's happening... this has been bugging me for a while...

P.S. sorry for the long question.

  • 1
    According to the documentation on [MediaMetadata.artwork](https://developer.mozilla.org/en-US/docs/Web/API/MediaMetadata/artwork) you should provide an array of [`MediaImage`](https://developer.mozilla.org/en-US/docs/Web/API/MediaImage) objects instead of setting a string. – Emiel Zuurbier Apr 11 '22 at 06:36
  • @EmielZuurbier does this mean I will have to add the sizes for every image? In the question I will be posting sometime tomorrow, I have details explaining why that would be such a huge task... Also can i use type: "image/*" as the MIME? – trynaCodeHereGoAway Apr 11 '22 at 06:49
  • 1
    You do have to specify the size of an image, but I don't think that you have to include every image size possible. Start with a larger image (512x512) and see what the API does. It might depend on the browser regarding what it does with `image/*`. [According to the docs](https://developer.mozilla.org/en-US/docs/Web/API/MediaImage) the browser might try to figure out the MIME-type of the image by itself even if the type is specified. But since there is no compatibility table, you'd have to test this out. – Emiel Zuurbier Apr 11 '22 at 06:59
  • I tried `navigator.mediaSession.metadata.artwork = [{ src: ("./Thumbnails/" + song.thumbnail), size: "512x512", type: "image/*"}];`, didn't work, gonna keep tinkering, let me know if you have any ideas and thank you so much for helping me! – trynaCodeHereGoAway Apr 11 '22 at 07:05
  • You're welcome. Maybe switch from a relative to an absolute path with the `src`. – Emiel Zuurbier Apr 11 '22 at 07:40

1 Answers1

0

This answer is going to sound weird but have you tried not touching the media session from inside the callbacks? I know the Google Chrome example calls updatePositionState, but it actually has the same play/pause issue as your code.

So concretely, try this:

const actionHandlers = [
  ['play',          () => { main.playPauseControl.click(); }],
  ['pause',         () => { main.playPauseControl.click(); }],
  ['previoustrack', () => { main.prevControl.click(); }],
  ['nexttrack',     () => { main.nextControl.click(); }],
  ['seekbackward',  (details) => { main.audio.currentTime = Math.max(main.audio.currentTime - skipTime, 0); }],
  ['seekforward',   (details) => { main.audio.currentTime = Math.min(main.audio.currentTime + skipTime, main.audio.duration); }],
];

I've done this for readtomyshoe and it no longer has this issue.

doomrobo
  • 88
  • 6