当前位置: 首页 > news >正文

视频抽帧并保存blob

视频抽帧

/***  @description 获取文件中的每一帧*  @param { File } file*  @param { Number } time 每一帧的时间间隔(单位:秒)*  @param { Boolean } isUseInterval 是否使用间隔 为false只会获取这一帧*  @returns { Map }*  @example await captureFrame({ file, 20  }) ==> Map { blob => {url:blobUrl,time:20},blob => {url:blobUrl,time:40} }*/
export async function captureFrame({ file, time = 0, isUseInterval = true }) {const map = new Map()try {if (!file) {throw new Error('file is required')}if (!file.file) {throw new Error('file.file is required')}if (!file.file.type.includes('video')) {throw new Error('file.file.type must be video')}const video = document.createElement('video')video.muted = truevideo.autoplay = truevideo.src = URL.createObjectURL(file.file)await new Promise((resolve) => video.oncanplay = resolve)const canvas = document.createElement('canvas')canvas.width = video.videoWidthcanvas.height = video.videoHeightfunction _clearCanvas() {canvas.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height);}function _drawImage() {canvas.getContext('2d')?.drawImage(video, 0, 0, canvas.width, canvas.height)}function _destroyVideoAndCanvas() {video.remove()canvas.remove()}function getBlob() {return new Promise((resolve) => {canvas.toBlob((blob) => resolve(blob));})}if (!isUseInterval) {video.currentTime = timeawait new Promise((resolve) => {video.onseeked = resolve;});_drawImage();const blob = await getBlob();map.set(blob, {url: URL.createObjectURL(blob),})_clearCanvas();} else {// 产生多帧的blobfor (let i = 0; i < video.duration; i += time) {video.currentTime = iawait new Promise((resolve) => {video.onseeked = resolve;});_drawImage();const blob = await getBlob();map.set(blob, {url: URL.createObjectURL(blob),time: i});_clearCanvas();}}_destroyVideoAndCanvas();} catch (error) {console.error('Error capturing frame:', error)}return map
}

相关文章:

  • 用户现场不支持路由映射,如何快速将安防监控EasyCVR视频汇聚平台映射到公网?
  • 分布式锁: Redisson红锁(RedLock)原理与实现细节
  • TC8:SOMEIP_ETS_029-030
  • R语言如何解决导出pdf中文不显示的问题
  • 【C++】 —— 笔试刷题day_30
  • 现在环保方面有什么新的技术动态
  • Python - 爬虫;Scrapy框架之items,Pipeline管道持久化存储(二)
  • 云计算与大数据进阶 | 26、解锁云架构核心:深度解析可扩展数据库的5大策略与挑战(上)
  • 主流数据库运维故障排查卡片式速查表与视觉图谱
  • 25-05-16计算机网络学习笔记Day1
  • SQLMesh 增量模型从入门到精通:5步实现高效数据处理
  • 基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL
  • OceanBase 的系统变量、配置项和用户变量有何差异
  • 捌拾伍- 量子傅里叶变换 (3)
  • 数据结构进阶:AVL树与红黑树
  • C++23:ranges::iota、ranges::shift_left和ranges::shift_right详解
  • JavaScript性能优化实战(10):前端框架性能优化深度解析
  • 嵌入式EasyRTC音视频实时通话SDK在工业制造领域的智能巡检/AR协作等应用
  • 医学影像系统性能优化与调试技术:深度剖析与实践指南
  • sqli-labs靶场29-31关(http参数污染)
  • 阳光保险拟设立私募证券投资基金,总规模200亿元
  • 江苏省委组织部副部长高颜已任南京市委常委、组织部部长
  • 外企聊营商|武田制药:知识产权保护助创新药研发
  • 董军在第六届联合国维和部长级会议上作大会发言
  • 现场丨在胡适施蛰存等手札与文献间,再看百年光华
  • 思想史家陈谷嘉逝世,曾为岳麓书院当代复兴奠定重要基础