JS实现视频截图

截图原理:#

文件上传,将视频绘制到canvas中进行截图

贴代码

base64 转成文件#

下面需要用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export const dataURLtoFile = ({
  dataURL = "",
  filename = ""
}: {
  dataURL: string
  filename: string
}) => {
  const arr = dataURL.split(",")
  const mime = arr[0].match(/:(.*?);/)[1]
  const bstr = atob(arr[1])
  let n = bstr.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, { type: mime })
}

 

将视频绘制到canvas上#

后面会用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function drawVideoToCanvas({
  videoElement,
  filename
}: {
  filename: string
  videoElement: HTMLVideoElement
}): Promise<{ file: Blob; url: string }> {
  return new Promise(resolve => {
    const canvas = document.createElement("canvas")
    const ctx = canvas.getContext("2d")
    canvas.width = videoElement.videoWidth
    canvas.height = videoElement.videoHeight
    if (!ctx) {
      return new Error("ctx is not defined!")
    }
    ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height)
    const dataURL = canvas.toDataURL("image/png")
    const file = dataURLtoFile({
      dataURL,
      filename
    })
    const url = URL.createObjectURL(file) // 实现本地预览
    resolve({
      file,
      url
    })
  })
}

 

播放视频,图片截取#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export function captureFrame({
  file,
  time = 0,
  filename = "screenshot.png"
}: {
  file: Blob
  time?: number
  filename?: string
}): Promise<{ file: Blob; url: string }> {
  return new Promise(resolve => {
    // 因为dom节点没有渲染到浏览器,视频播放到指定的时间就会停止播放
    const videoElement = document.createElement("video")
    videoElement.currentTime = time // 设置截取的帧时间
    // 自动播放存在兼容性问题,设置静音解决自动播放在不同浏览器的兼容性问题
    videoElement.muted = true
    videoElement.autoplay = true
    videoElement.src = URL.createObjectURL(file)
    videoElement.oncanplay = async function () {
      const flame = await drawVideoToCanvas({ filename, videoElement })
      resolve(flame)
    }
  })
}

 

下面是react代码示例#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Example28 = () => {
  return (
    <div>
      <input
        type="file"
        onChange={event => {
          const [file] = event.target.files || []
          captureFrame({ file, time: 1 }).then(data => {
            console.log(data)
            const IMG = new Image()
            IMG.src = data.url
            IMG.width = 200
            document.body.append(IMG)
          })
        }}
      />
    </div>
  )
}
 
export default Example28

 

示例截图#

 

作者:冯叶青

出处:https://www.cnblogs.com/yz-blog/p/18284468

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   冯叶青  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示