HTMLMediaElement.currentTime does not appear to advance between requestMediaFrame callbacks

Solution 1:

Browsers don't give you precise timestamps to avoid fingerprinting, so the currentTime likely won't be frame-accurate. Also, requestAnimationFrame goes at the framerate of the page, not the video content - if you want to read by video frames there's the new WebCodecs API.

Check the video's paused or ended status instead of current position to know if it's done. You could also add event listeners for pause/ended.

Here's an example of doing what you want using async and promises:

async play() {
    // returns a promise that rejects if you have audio mute problems
    await this.video.play();
    // loop until video is no longer playing. Consider including a timeout or AbortController just in case, but not totally necessary...
    while (!(this.video.paused || this.video.ended)) {
        // wrap requestAnimationFrame in promise
        await new Promise(done => {
            requestAnimationFrame(() => {
                this.ctx.drawImage(...);
                done();
            });
        });
    }
}