惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
Vercel News
Vercel News
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
N
News and Events Feed by Topic
Application and Cybersecurity Blog
Application and Cybersecurity Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 【当耐特】
WordPress大学
WordPress大学
Google Online Security Blog
Google Online Security Blog
博客园 - Franky
Attack and Defense Labs
Attack and Defense Labs
Help Net Security
Help Net Security
V
Visual Studio Blog
Jina AI
Jina AI
H
Heimdal Security Blog
小众软件
小众软件
O
OpenAI News
腾讯CDC
The Last Watchdog
The Last Watchdog
雷峰网
雷峰网
Cloudbric
Cloudbric
量子位
博客园_首页
The GitHub Blog
The GitHub Blog
L
LangChain Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
The Blog of Author Tim Ferriss
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Last Week in AI
Last Week in AI
V2EX - 技术
V2EX - 技术
Security Archives - TechRepublic
Security Archives - TechRepublic
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 司徒正美
M
MIT News - Artificial intelligence
大猫的无限游戏
大猫的无限游戏
T
Tor Project blog
C
CERT Recently Published Vulnerability Notes
W
WeLiveSecurity
B
Blog
C
Check Point Blog
TaoSecurity Blog
TaoSecurity Blog
T
Threatpost
Hugging Face - Blog
Hugging Face - Blog
Recent Announcements
Recent Announcements
Project Zero
Project Zero
Hacker News: Ask HN
Hacker News: Ask HN
U
Unit 42
Simon Willison's Weblog
Simon Willison's Weblog

博客园 - 冯叶青

OpenAI vs Anthropic API 对比:响应体、请求体、消息格式与工具调用 GitHub Actions 自动部署流程 Git分支自动合并脚本:基于时间戳的冲突解决方案 Next.js lingui.js 多语言自动提取翻译键 - ats-node React实现短信验证码输入组件 Next.js 中优雅地使用 Lottie 动画 Next.js 路由参数更新最佳实践:从 replaceState 到 nextReplaceState Jenkins构建时SWR模块导入报错解决方案 解决 Jenkins 环境下 Lingui 构建报错 "btoa is not defined" git 提交 实现大图自动压缩功能 React lingui.js 多语言自动提取翻译键 - ast node html2canvas 解决截图空白问题 react 实现前端发版监测 JS根据文件名获取文件类型 JS获取本机IP地址 适用于react、vue菜单格式化工具函数 git 内容提交 实现大图拦截功能 next.js 利用中间件(middleware.ts)实现PC与移动路由无缝切换 Android生成签名文件及对apk进行签名 JS-SDK 配置,实现微信分享功能
JS实现视频截图
冯叶青 · 2024-07-04 · via 博客园 - 冯叶青

截图原理:

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

贴代码

base64 转成文件

下面需要用到

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上

后面会用到

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
    })
  })
}

播放视频,图片截取

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代码示例

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

示例截图