Changing the volume leads to frame drop

63 views Asked by At

I am using and learning Svelte. So I am creating a video player with help of hls.js library (because I did not found any readymade video players which worked properly and had the functionality I wanted). When I try to change the volume of the video, frame drop occurs.

function handleVolume(event) {
    volume = event.target.value;
    if (volume === 0) { isMuted = true; }
   else { isMuted = false; }
}

function debounce(func, delay) {
    let timeoutId;
    return function (...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    };
}

function updateVideoVolume() {
    video.volume = volume / maxVolume;
}

const updateVideoVolumeDebounced = debounce(updateVideoVolume, 200);

onMount(() => {
    if (Hls.isSupported()) {
        hls = new Hls();
        let src = 'http://localhost:3000/videos/video3';
        hls.loadSource(src);
        hls.attachMedia(video);
        hls.enableWorker = true;
        duration = video.duration;

        hls.on(Hls.Events.MEDIA_ATTACHED, function () {});
        hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
            console.log(data.levels);
            for (let i = 0; i < data.levels.length; i++) {
                resolutions = [...resolutions, [data.levels[i].height, data.levels[i].bitrate]];
            }
            console.log(resolutions);
        });
    }
});
</script>

<input
    type="range"
    on:input={handleVolume}
    on:change={updateVideoVolumeDebounced}
    id="volume"
    name="volume"
    min="0"
    max={maxVolume}
/>

It happens with both on:change and on:input when using the range input element. I also tried to debounce the handleVolume but then the frame drop occurs after the delay. I have also tested it on different browsers. In Firefox, the frame drop is less. Meanwhile in Brave, it is similar. I guess this is because of Chromium.

1

There are 1 answers

1
brunnerh On BEST ANSWER

The code in the question is mostly irrelevant.

You have a binding on video that gets and sets currentTime, the bound variable (playbackTime) is reactive with a dependency on video.

$: playbackTime = video ? video.currentTime : 0;
<video ...
    bind:currentTime={playbackTime} />

The volume change has an assignment to a property of video, thereby invalidating video. This in turn will update playbackTime which sets the video's currentTime, causing a jitter.

Would recommend limiting the use of reactive statement, don't see much point in playbackTime being one either, just initialize to 0 and maybe update once in onMount or on some other events.

let playbackTime = 0;