Skip to content

Commit cdfa6da

Browse files
committed
Video processing improvements
1 parent 54e151f commit cdfa6da

File tree

1 file changed

+30
-30
lines changed

1 file changed

+30
-30
lines changed

src/utils/video.js

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { RawImage } from "./image.js";
2+
import { apis } from "../env.js";
23

34
export class RawVideoFrame {
45

@@ -42,55 +43,52 @@ export class RawVideo {
4243
/**
4344
* Loads a video.
4445
*
45-
* @param {string|Blob|HTMLVideoElement} url The video to process.
46+
* @param {string|Blob|HTMLVideoElement} src The video to process.
4647
* @param {Object} [options] Optional parameters.
4748
* @param {number} [options.num_frames=null] The number of frames to sample uniformly.
48-
* If provided, the video is seeked to the desired positions rather than processing every frame.
4949
* @param {number} [options.fps=null] The number of frames to sample per second.
50-
* If provided (and num_frames is null), the video is seeked at fixed time intervals.
5150
*
52-
* @returns {Promise<RawVideo>} The video
51+
* @returns {Promise<RawVideo>} The loaded video.
5352
*/
54-
export async function load_video(url, { num_frames = null, fps = null } = {}) {
53+
export async function load_video(src, { num_frames = null, fps = null } = {}) {
54+
if (!apis.IS_BROWSER_ENV) {
55+
throw new Error("`load_video` is currently only supported in browser environments.");
56+
}
57+
58+
// TODO: Support efficiently loading all frames using the WebCodecs API.
59+
// Specfically, https://developer.mozilla.org/en-US/docs/Web/API/VideoDecoder
60+
if (num_frames == null && fps == null) {
61+
throw new Error("Either num_frames or fps must be provided.");
62+
}
63+
5564
const frames = [];
5665

57-
const video = document.createElement('video');
58-
if (typeof url === 'string') {
59-
video.src = url;
60-
} else if (url instanceof Blob) {
61-
video.src = URL.createObjectURL(url);
62-
} else if (url instanceof HTMLVideoElement) {
63-
video.src = url.src;
66+
const video = document.createElement("video");
67+
video.crossOrigin = "anonymous";
68+
video.muted = true; // mute to allow autoplay and seeking
69+
70+
if (typeof src === 'string') {
71+
video.src = src;
72+
} else if (src instanceof Blob) {
73+
video.src = URL.createObjectURL(src);
74+
} else if (src instanceof HTMLVideoElement) {
75+
video.src = src.src;
6476
} else {
6577
throw new Error("Invalid URL or video element provided.");
6678
}
67-
video.crossOrigin = "anonymous";
68-
video.muted = true; // mute to allow autoplay
69-
7079
// Wait for metadata to load to obtain duration
71-
await new Promise((resolve) => {
72-
video.onloadedmetadata = resolve;
73-
});
80+
await new Promise((resolve) => video.onloadedmetadata = resolve);
7481

7582
if (video.seekable.start(0) === video.seekable.end(0)) {
7683
// Fallback: Download entire video if not seekable
7784
const response = await fetch(video.src);
7885
const blob = await response.blob();
7986
video.src = URL.createObjectURL(blob);
80-
81-
await new Promise((resolve) => {
82-
video.onloadedmetadata = resolve;
83-
});
87+
await new Promise((resolve) => video.onloadedmetadata = resolve);
8488
}
8589

8690
const duration = video.duration;
8791

88-
// Build an array of sample times based on num_frames or fps
89-
let sampleTimes = [];
90-
if (num_frames == null && fps == null) {
91-
throw new Error("Either num_frames or fps must be provided.");
92-
}
93-
9492
let count, step;
9593
if (num_frames != null) {
9694
count = num_frames;
@@ -100,11 +98,13 @@ export async function load_video(url, { num_frames = null, fps = null } = {}) {
10098
count = Math.floor(duration / step);
10199
}
102100

103-
for (let i = 0; i < count; i++) {
101+
// Build an array of sample times based on num_frames or fps
102+
let sampleTimes = [];
103+
for (let i = 0; i < count; ++i) {
104104
sampleTimes.push(num_frames === 1 ? duration / 2 : i * step);
105105
}
106106

107-
const canvas = document.createElement('canvas');
107+
const canvas = document.createElement("canvas");
108108
canvas.width = video.videoWidth;
109109
canvas.height = video.videoHeight;
110110
const ctx = canvas.getContext("2d", { willReadFrequently: true });

0 commit comments

Comments
 (0)