extractFramesFromVideo方法提取画面帧
// 设定一个异步函数,输入参数为:
// videoUrl(需要提取画面帧的视频的URL)
// fps(每秒帧率,默认为25帧)
async function extractFramesFromVideo(videoUrl, fps = 25) {// 我们使用 Promise 将该函数设置为异步操作return new Promise(async (resolve) => {// 使用 fetch 函数从视频URL获取数据,并将其转换为 Blob 对象let videoBlob = await fetch(videoUrl).then((r) => r.blob());// 创建一个对应 Blob 对象的 URLlet videoObjectUrl = URL.createObjectURL(videoBlob);// 创建一个 HTML video 的新实例let video = document.createElement("video");// 定义一个新变量,在后面的 "seeked" 事件中赋值let seekResolve;// 当 "seeked" 事件触发,我们确认视频已经被加载到了特定的时间点video.addEventListener("seeked", async function () {if (seekResolve) seekResolve(); // 执行我们的 Promise 结束指令});// 将我们的视频 URL 设置为创建的 video 对象video.src = videoObjectUrl;// 我们等待视频加载,一旦加载成功,则能获取到视频的长度信息while ((video.duration === Infinity || isNaN(video.duration)) &&
video.readyState < 2) {await new Promise((r) => setTimeout(r, 1000)); // 等待 1000msvideo.currentTime = 10000000 * Math.random(); // 用一个随机的时间进行跳跃}// 获取视频长度let duration = video.duration;// 创建 canvas 对象和 2d 上下文进行画面帧的绘制let canvas = document.createElement("canvas");let context = canvas.getContext("2d");let [w, h] = [video.videoWidth, video.videoHeight]; // 获取视频的宽度和高度canvas.width = w;canvas.height = h;// 初始化一个数组用于存放提取出来的帧的数据let frames = [];let interval = 1 / fps; // 根据帧率(fps)计算间隔时间let currentTime = 0; // 初始化当前的播放时间// 从视频开始提取画面帧,直到视频的末尾while (currentTime < duration) {video.currentTime = currentTime; // 设置视频的当前播放时间await new Promise((r) => (seekResolve = r)); // 等待 "seeked" 事件完毕context.drawImage(video, 0, 0, w, h); // 将当前画面帧绘制到 canvas 上let base64ImageData = canvas.toDataURL(); // 获取绘制的图片数据frames.push(base64ImageData); // 将提取的画面帧加入到 frames 数组中currentTime += interval; // 将当前时间增加一个间隔时间}// 返回所有提取的画面帧resolve(frames);});
}
调用方式将视频URL作为参数传递给该函数:
let frames = await extractFramesFromVideo(‘http://example.com/example.mp4’, 25);
在这里,‘http://example.com/example.mp4’ 是视频的 URL,25 是你希望每秒提取的帧数。函数将返回一个数组,其中包含了一系列从视频中提取的画面帧(以 base64 编码的图片形式)。
WebCodecs API 提取视频帧
…WebCodecs API 提取视频帧的过程相对较复杂,包括以下步骤:
-
解析容器文件到单独的编码视频和/或音频块:这个步骤需要将文件(例如 .mp4 文件)解析到单独的编码视频和/或音频块。
-
解码编码的视频/音频块:WebCodecs 仅仅方便了这个过程中的解码步骤。你需要自己实现解析/处理容器文件的过程。
在这个过程中, MP4Box它能帮你获取编码的视频和音频块,然后你可以将这些块输入到 VideoDecoder 或 AudioDecoder。
使用 MP4Box,你的代码可能会围绕 onSamples 回调实现,大概如下所示:
mp4BoxFile.onSamples = (trackId, user, chunks) => {for (let i = 0; i < chunks.length; i++) {let chunk = chunks[i];let encodedChunk = new EncodedVideoChunk({// you'll need to deep-inspect chunk to figure these outtype: "key", // or "delta"timestamp: ...,duration: ...,data: chunk.data});// pass encodedChunk to a VideoDecoder instance's decode method}
};
以上是利用 WebCodecs API 提取视频帧的大体步骤,对于具体的应用细节可能需要根据你的具体需求进行调整。
mp4BoxFile是使用了MP4Box.js库的一个示例。MP4Box.js 是一个 JavaScript 库,用于处理 MP4 文件,特别是在浏览器端。
这个库提供了一个MP4Box类,你可以用new MP4Box.createFile()来创建一个mp4BoxFile。然后,你可以添加自定义的回调,例如 onReady 和 onSamples,然后向对象提供ArrayBuffer类型的数据。这个库支持逐步解析文件,所以你可以一边下载文件一边进行解析。
例如:
var mp4boxfile = MP4Box.createFile();mp4boxfile.onReady = info => {// do something when file is ready
};mp4boxfile.onSamples = (trackId, user, samples) => {// do something with samples
};// append data
mp4boxfile.appendBuffer(someArrayBufferData);
这个库可以帮助你从 MP4 文件中提取出音频和视频块,然后你可以将这些编码的块传递给 VideoDecoder 或者 AudioDecoder。
以上就是文章全部内容了,如果喜欢这篇文章的话,还希望三连支持一下,感谢!