在 JavaScript 中从视频中提取缩略图
可以使用 Mediabunny 从视频文件中提取单个帧(缩略图)。
🌐 Extracting a single frame (thumbnail) from a video file can be done using Mediabunny.
这是一个 extractThumbnail() 函数,你可以将其复制并粘贴到你的项目中:
🌐 Here's an extractThumbnail() function you can copy and paste into your project:
extract-thumbnail.tsimport {ALL_FORMATS ,Input ,InputDisposedError ,UrlSource ,VideoSample ,VideoSampleSink } from 'mediabunny'; export typeExtractThumbnailProps = {src : string;timestampInSeconds : number;signal ?:AbortSignal ; }; export async functionextractThumbnail ({src ,timestampInSeconds ,signal }:ExtractThumbnailProps ):Promise <VideoSample > { usinginput = newInput ({formats :ALL_FORMATS ,source : newUrlSource (src ), }); constvideoTrack = awaitinput .getPrimaryVideoTrack (); if (!videoTrack ) { throw newError ('No video track found in the input'); } if (signal ?.aborted ) { throw newError ('Aborted'); } constsink = newVideoSampleSink (videoTrack ); constsample = awaitsink .getSample (timestampInSeconds ); if (!sample ) { throw newError (`No frame found at timestamp ${timestampInSeconds }s`); } returnsample ; }
示例
🌐 Example
下面是如何将缩略图绘制到画布上的方法:
🌐 Here is how you can draw a thumbnail to a canvas:
const sample = await extractThumbnail ({
src : 'https://remotion.media/video.mp4',
timestampInSeconds : 5,
});
const canvas = document .createElement ('canvas');
canvas .width = sample .displayWidth ;
canvas .height = sample .displayHeight ;
const ctx = canvas .getContext ('2d');
sample .draw (ctx !, 0, 0);
sample .close ();内存管理
🌐 Memory management
该函数返回一个 VideoSample 对象。当它被垃圾回收清理时,它将被自动关闭,但会打印一个警告。
🌐 The function returns a VideoSample object. When it gets cleaned up by garbage collection, it will be automatically closed, but a warning will be printed.
你可以调用 .close() 来显式关闭样本并防止打印警告。
🌐 You can call .close() to explicitly close the sample and prevent the warning from being printed.
Explicitly closing a sampleconst sample = await extractThumbnail({ src: 'https://example.com/video.mp4', timestampInSeconds: 5, }); sample.draw(ctx!, 0, 0); sample.close();
或者,你可以使用 using 语句在样本超出作用域时进行清理。
🌐 Or, you can use the using statement to clean up the sample when it goes out of scope.
using sample = await extractThumbnail({
src: 'https://example.com/video.mp4',
timestampInSeconds: 5,
});
sample.draw(ctx!, 0, 0);中止帧提取
🌐 Abort frame extraction
传递一个 AbortSignal 来取消缩略图提取:
🌐 Pass an AbortSignal to cancel thumbnail extraction:
const controller = new AbortController ();
setTimeout (() => controller .abort (), 5000);
try {
using sample = await extractThumbnail ({
src : 'https://example.com/video.mp4',
timestampInSeconds : 10,
signal : controller .signal ,
});
console .log ('Got frame!');
} catch (error ) {
console .error ('Thumbnail extraction was aborted or failed:', error );
}设置超时
🌐 Setting a timeout
以下是如何设置提取缩略图的最大持续时间:
🌐 Here is how you can set a maximum duration for extracting a thumbnail:
Fail if not able to extract within 5 secondsconstcontroller = newAbortController (); consttimeoutPromise = newPromise <never>((_ ,reject ) => { consttimeoutId =setTimeout (() => {controller .abort ();reject (newError ('Thumbnail extraction timed out after 5 seconds')); }, 5000);controller .signal .addEventListener ('abort', () =>clearTimeout (timeoutId ), {once : true}); }); try { usingsample = awaitPromise .race ([extractThumbnail ({src : 'https://example.com/video.mp4',timestampInSeconds : 10,signal :controller .signal , }),timeoutPromise , ]);console .log ('Got frame!'); } catch (error ) {console .error ('Thumbnail extraction was aborted or failed:',error ); }
另请参阅
🌐 See also
- 提取视频帧 - 从视频中提取多帧
- Mediabunny 文档
- Mediabunny 的数据包和样品
VideoSampleSinkAPI- 支持的格式