【前端】上传视频,截取第一帧图片

使用input上传视频,获得视频的第一帧
参考:JavaScript获取视频的尺寸信息和第一帧图片 - 掘金 (juejin.cn)

html:

<input
   bind:this={uploadRef}
   on:change={handleUpload}
   accept="video/*"
   type="file"
 />

视频类型校验:

const VIDEO_REG =
  /^(?:video\/avi|video\/mpeg|video\/mp4|video\/ogg|video\/webm|video\/x-ms-wmv|video\/x-msvideo)$/i;

handleUpload

  • 校验类型
  • 获得视频第一帧图片:调用getVideoImg方法
const handleUpload=(e)=>{
 const files = e.target.files[0];
 if(VIDEO_REG.test(files.type)){
	const videoImg = await getVideoImg(files);
  }
}

相关方法:getVideoImg

使用canvas实现:从一个视频文件中提取一帧图像,并将这个图像转换为一个可以在浏览器中使用的URL。

const getVideoImg = async (files: File): Promise<string> => {
  try {
    // 使用loadVideo函数加载视频文件,等待加载完成
    const video: HTMLVideoElement = await loadVideo(files);

    const canvasElem = document.createElement('canvas');

    // 设置canvas的宽度和高度与视频的宽度和高度相同
    canvasElem.width = video.videoWidth;
    canvasElem.height = video.videoHeight;

    // 获取canvas的2d渲染上下文,并在canvas上绘制视频的当前帧
    canvasElem
      .getContext('2d')
      ?.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);

    const pngFile = await new Promise<string>((resolve, reject) => {
      // 将canvas的内容导出成一个blob文件
      canvasElem.toBlob((blob) => {
        if (blob) {
          // 成功创建了blob文件,将其转换为File对象,然后创建一个指向这个File对象的URL
          resolve(URL.createObjectURL(toThumbFile(blob)));
        } else {
          // 创建blob文件失败,拒绝Promise
          reject('');
        }
      }, 'image/png');
    });

    // 返回Promise的结果,即指向File对象的URL
    return pngFile;
  } catch (error) {
    // 如果在上述过程中发生错误,打印错误信息
    console.error(error);
  }
};

其中调用了loadVideo

const loadVideo = (file: File): Promise<HTMLVideoElement> => {
  return new Promise(function (resolve, reject) {
  
    const videoElem = document.createElement('video');
    const dataUrl = URL.createObjectURL(file);

    videoElem.onloadeddata = function () {
      // 当video元素的当前帧的数据可用时,将video元素作为Promise的结果
      resolve(videoElem);
    };

    // 当video元素发生错误时的处理函数
    videoElem.onerror = function () {
      reject('video error');
    };

    // 设置video元素的preload属性为'auto',这样video元素会预加载数据
    // 如果不设置这个属性,可能会导致截图为黑色图片的情况
    videoElem.setAttribute('preload', 'auto');

    // 设置video元素的src属性为指向File对象的URL
    videoElem.src = dataUrl;
  });
};


// 输入的Blob对象,文件名是'video_img.png'
const toThumbFile = (blob) => new File([blob], 'video_img.png');

调用:

videoImg = await getVideoImg(files);

得到的videoImg 可以在<img src={videoImg }/> 中显示。

不用videoImg 后,要使用URL.revokeObjectURL释放:URL.createObjectURL生成的链接以blob:开头。一般来说在 销毁 的生命周期调用。

if (/^blob:/.test(videoImg)) {
   URL.revokeObjectURL(videoImg);
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值