Skip to content

Commit 1ce1cec

Browse files
authored
Update README.md
1 parent 6db1aaa commit 1ce1cec

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

README.md

+51-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,61 @@
33
So there is no way you can jump to next / prev frame in HTML5 video. You can adjust it to next second or next millisecond but you never know if it's going to be next or previous frame or not.
44
There is relatively new feature: https://web.dev/requestvideoframecallback-rvfc/ that we can possibly use to do some stupid per frame navigation.
55

6-
76
https://github.com/angrycoding/requestVideoFrameCallback-prev-next/assets/895042/49d1dabc-699e-4613-bc29-a11cf5082082
87

9-
I'm not going to explain that much, because if you need this then you probably can understand source code. But the idea is:
10-
**requestVideoFrameCallback** callback is called with two arguments: first one is some kind of timestamp, and second one is some kind
8+
Idea is: **requestVideoFrameCallback** callback is called with two arguments: first one is some kind of timestamp, and second one is some kind
119
of meta information about current video's position https://wicg.github.io/video-rvfc/#dictdef-videoframemetadata
1210

1311
So whenever you want next or previous frame we just call this **requestVideoFrameCallback** and get this **meta.mediaTime** which will be somehow
1412
related with the timestamp of the current frame. Then we try to increase video's position in the loop and call **requestVideoFrameCallback** on each
1513
iteration until value obtained from next **requestVideoFrameCallback** call will not be equals to the first one.
14+
15+
So our getMediaTime method looks like this:
16+
17+
```
18+
const getMediaTime = () => new Promise(resolve => {
19+
const video = document.getElementsByTagName('video')[0];
20+
if (!video) return;
21+
video.requestVideoFrameCallback((now, metadata) => {
22+
resolve(metadata.mediaTime);
23+
})
24+
});
25+
```
26+
27+
If you try to call it like this:
28+
29+
```await getMediaTime()``` then you'll notice that you'll notice that it's not resolved. And that is absolutely correct because requestVideoFrameCallback will only call it's callback when browser renders next frame of the video.
30+
31+
So what we need to do then? Force browser to render next frame of the video! How? Adjust it's currentTime back and forward:
32+
33+
```
34+
video.currentTime += 1;
35+
video.currentTime -= 1;
36+
const result = await getMediaTime();
37+
console.info(result);
38+
```
39+
40+
Now it's working? So jumping to the next frame is going to look like this:
41+
42+
```
43+
const jumpNextFrame = async () => {
44+
const video = document.getElementsByTagName('video')[0];
45+
if (!video) return;
46+
47+
// force rerender
48+
video.currentTime += 1;
49+
video.currentTime -= 1;
50+
51+
// get current frame time
52+
const firstMediaTime = await getMediaTime();
53+
54+
for (;;) {
55+
// now adjust video's current time until actual frame time changes
56+
video.currentTime += 0.01;
57+
if ((await getMediaTime()) !== firstMediaTime) break;
58+
}
59+
60+
}
61+
```
62+
63+
Have fun with it!

0 commit comments

Comments
 (0)