前端截取视频指定帧为封面的3种方法

一、使用本地canvas截取

我们在网页上传视频后,如果能给视频设置一个封面图,用户体验会比较好,但是如果使用video标签的默认实现,部分浏览器会显示视频的第一帧,有些浏览器则怎么都不会展示;

通过创建canvas标签,利用其context.drawImage() 方法在画布上绘制该视频,然后运用canvas.toDataURL方法转换canvas上的图片为base64格式,并将base64格式的url作为video标签的poster属性。toDataURL具有跨域问题,需要特殊处理,和图片的跨域处理一致。

注意:

  • canvas无法对跨域的图片进行操作,需要提前处理好跨域问题。
  • safari浏览器暂时还有些问题,只能截取第一帧。
/**
 * 获取视频的封面图信息
 * @param url 视频地址
 * @param second 秒数
 */
async function getVideoBase64(url, second = 0) {
    return new Promise((resolve) => {
        const video = document.createElement("video");
        video.setAttribute("crossOrigin", "anonymous"); // 处理跨域
        video.setAttribute("src", url);
        // 静音操作,防止播放失败
        video.setAttribute("muted", "muted");
        video.onloadeddata = () => {
            video.currentTime = second;
            video.onseeked = async () => {
                const canvas = document.createElement("canvas");
                console.dir(video);
                const { videoWidth: width, videoHeight: height } = video; // canvas的尺寸和图片一样
                canvas.width = width;
                canvas.height = height;
                canvas.getContext("2d")?.drawImage(video, 0, 0, width, height);
                resolve(canvas.toDataURL("image/png"));
            };
        };
    });
}

二、使用阿里云OSS截取视频

使用描述

使用了阿里OSS,我们可以基于OSS内置的功能实现指定帧截图,然后使用一个img标签来显示封面,效果就比较好了;

注意事项

1、使用视频截帧时,按视频截帧截取的图片数量计费。有关计费详情的更多信息,请参见数据处理费用
2、当前仅支持对视频编码格式为H264的视频文件进行视频截帧。
3、OSS当前没有默认保存视频截帧的操作,视频截帧的图片需手动下载到本地。

主要参数

追加参数:x-oss-process=video/snapshot,t_1,f_jpg,w_0,h_0,m_fast
内部参数名称和值使用下换线分割,例如t_1就代表是时间为第一毫秒

截图实例

https://s2.codooncdn.com/course-platform/1c5a1bc3-0439-4d66-bde8-d80b68a2af12/2020-12-21T14.16.12/1592951xWLD5xfNd0t2fE4g6sBmp4?x-oss-process=video/snapshot,t_1,f_jpg,w_0,h_0,m_fast

参考:
https://help.aliyun.com/document_detail/64555.html?spm=a2c4g.11186623.6.769.283a776bEOUKzW

三、使用video标签展示视频某一帧为图片

如果只是在页面展示,可以使用video标签来直接展示某一帧;
作为视频封面,#t=0.001 指定播放时间,如果是0可能会是黑屏;

<video
    src={`${src}#t=0.001`}
    poster={cover || ""}
    controls={false}
    playsInline={true}
    muted={true}
    preload={"metadata"}
    className={PREFIX}
/>

参考:

留下回复