I'm trying to use picobel.js audio player in a svelte project. The library creates stylable html elements for the html5 audio player.
It works initially but when I change the source of the audio element the picobel player isn't updated (playback time and duration). After changing the source a few more times it just says "error loading audio". I tried actions but it didn't work (not sure if I used it right..). I tried destroying / recreating the component on source change but that doesn't work at all (even tried in svelte5 with mount / unmoun), the previous instance isnt cleaned up and I have multiple instances of the picobel player)
Next I tried manually mounting it to a specific div by id, works the first time, removing the div cleans up but then the div is gone and I can't reload the picobel player:
<script>
import { mount, unmount } from 'svelte';
import { playlistObject, playlistItems } from '$lib/playlist.js';
import { authHeader, userId, jellyUrl, apiKey } from '$lib/jellyfin.js';
import { audioObject, audioPlayer } from '$lib/audio.js';
let loaded = false;
let cvsdfge;
$: $audioObject, LoadAudio();
async function LoadAudio() {
if (!$audioObject) return;
if (loaded) {
unmount(cvsdfge);
let as = document.querySelector('#myDiv');
as.remove();
}
loaded = true;
let tt = document.appendChild(document.createElement('div'));
tt.id = 'myDiv';
cvsdfge = mount(Player, { target: document.querySelector('#myDiv') });
}
</script>
<div id="myDiv"></div>
And I don't think that's the right way to go about it, seems really wrong to me.
What's the right way to solve the issue?
This is a very inflexible library, would not really recommend using it. It messes with the DOM in ways that are harder to deal with and has just about no API to influence the behavior.
Given this, a lot of manual interaction with the audio
element will be necessary. Would use an action for this, which can deal with cleanup and also update the element if e.g. the track changes.
import picobel from "picobel";
const tracks = [...]; // { src, title, artist } objects
let index = 0;
$: current = tracks[index];
function player(node, track) {
const audio = document.createElement('audio');
audio.setAttribute('controls', '');
node.append(audio);
picobel();
function changeTrack(track) {
const paused = audio.paused;
audio.src = track.src;
audio.setAttribute('title', track.title);
audio.setAttribute('data-artist', track.artist);
// TODO: reset play head while paused
if (!paused) audio.play();
}
changeTrack(track);
return {
update: changeTrack,
destroy() { audio.pause(); }
};
}
<div use:player={current}></div>