【html】利用生成器函数和video元素,取出指定时间的视频画面

简言

有的时候想截取视频某一秒的视频画面。
手动截取操作麻烦,还得时刻关注视频播放时间。
于是,我搞出来了一个根据视频自动截取特定时间描述的页面。

效果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

实现步骤

  1. 获取视频对象
  2. 根据视频时长生成时间选择表单
  3. 根据表单选择的时间和视频地址,利用canvas和vido元素生成某一帧的视频画面图片
  4. 图片实现下载

源码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>处理视频</title><style>.container {margin: 50px;}</style>
</head><body><div class="container"><div class="upload__box"><input id="upVideo" name="upVideo" type="file" accept="video/*" placeholder="上传视频" /></div><div class="video__box"><video width="800" height="450" id="video" src="" controls></video></div><div class="select__box"></div><div class="analyze__text"><ul></ul></div></div><script>const upVideoDom = document.getElementById("upVideo")const videoDom = document.getElementById('video')const selectBoxDom = document.querySelector('.select__box')const TextListDom = document.querySelector('.analyze__text')upVideoDom.addEventListener("change", (e) => {const file = e.target.files[0];let videoURL = URL.createObjectURL(file)videoDom.src = videoURLvideoDom.onloadedmetadata = (e) => {//  视频时长let videoDuration = e.target.durationcreateTimeSelectDom(videoDuration)}})//  根据时长创建dom选择器function createTimeSelectDom(duration) {//  生成可选秒数列表let fragDom = document.createDocumentFragment()let form = document.createElement("form")form.id = 'selectForm'form.name = 'selectForm'if (duration < 60) {let selectDom = document.createElement("select")selectDom.multiple = trueselectDom.form = "selectForm"selectDom.name = "seconds"let optionDom = document.createElement("option")optionDom.innerText = '--选择秒数--'optionDom.value = ''selectDom.appendChild(optionDom)for (let i = 0; i < duration; i++) {let item = i.toString().padStart(2, '0')let optionDom = document.createElement("option")optionDom.innerText = itemoptionDom.value = itemselectDom.appendChild(optionDom)}form.appendChild(selectDom)} else if (duration < 3600) {let minute = duration / 60let seconds = duration % 60let miuteSelectDom = document.createElement("select")miuteSelectDom.form = "selectForm"miuteSelectDom.name = "mintue"let optionDom = document.createElement("option")optionDom.innerText = '--选择分--'optionDom.value = ''miuteSelectDom.appendChild(optionDom)for (let i = 0; i < minute; i++) {let item = i.toString().padStart(2, '0')let optionDom = document.createElement("option")optionDom.innerText = itemoptionDom.value = itemmiuteSelectDom.appendChild(optionDom)}let secondsSelectDom = document.createElement("select")secondsSelectDom.multiple = truesecondsSelectDom.form = "selectForm"secondsSelectDom.name = "seconds"let optionDom2 = document.createElement("option")optionDom2.innerText = '--选择秒数--'optionDom2.value = ''secondsSelectDom.appendChild(optionDom2)for (let i = 0; i < 59; i++) {let item = i.toString().padStart(2, '0')let optionDom = document.createElement("option")optionDom.innerText = itemoptionDom.value = itemsecondsSelectDom.appendChild(optionDom)}form.appendChild(miuteSelectDom)form.appendChild(secondsSelectDom)} else {}let submitInput = document.createElement("input")submitInput.type = 'submit'submitInput.value = '确定'form.onsubmit = formSubmitform.appendChild(submitInput)let resetInput = document.createElement("input")resetInput.type = 'reset'resetInput.value = '重置'form.appendChild(resetInput)fragDom.appendChild(form)selectBoxDom.appendChild(fragDom)}function formSubmit(e) {e.preventDefault()let mintueV = '00'if (selectForm.mintue) {mintueV = selectForm.mintue.value}let timeList = []for (let v of selectForm.seconds.options) {if (v.selected) {timeList.push(`${mintueV}:${v.value}`)}}//  生成帧图片TextListDom.children[0].innerHTML = ''createFramepicture({url: videoDom.src, timeList})}//  生成帧图片列表function createFramepicture({ url, timeList, }) {if (!url || !timeList) returnlet time;const video = document.createElement('video')video.width = 160video.height = 90video.crossorigin = "anonymous"video.src = urllet canvas = document.createElement("canvas"),width = video.width,height = video.height;canvas.width = widthcanvas.height = heightfunction* createTime() {for (let k = 0; k < timeList.length; k++) {time = timeList[k]let timeArr = time.split(':')let currentTime = Number(timeArr[0]) * 60 + Number(timeArr[1])video.currentTime = currentTime //  会导致 oncanplaythrough重新触发yield true}}let a = createTime()video.oncanplaythrough = () => {if (time) {//  当time存在时再渲染,避开video第一次加载成功analyzeVideo(video, time, canvas)}a.next()}}function analyzeVideo(video, time, canvas) {const ctx = canvas.getContext('2d')// ctx.clearRect(0, 0, video.width, video.height)ctx.drawImage(video, 0, 0, video.width, video.height);let dataURL = canvas.toDataURL("image/png")let li = document.createElement('li')let img = document.createElement('img')img.src = dataURLlet p = document.createElement('p')p.innerText = `${time}`let btn = document.createElement('button')btn.innerText = '下载'btn.onclick = () => {downloadImg(dataURL, time)}li.appendChild(p)li.appendChild(img)li.appendChild(btn)const fragDom = document.createDocumentFragment()fragDom.appendChild(li)TextListDom.children[0].appendChild(fragDom)}function downloadImg(src, time) {let a = document.createElement('a')a.href = srca.download = `frame picture`a.click()}</script>
</body></html>

结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/108843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据仓库】hadoop生态圈与数据仓库

文章目录 1.大数据定义2. Hadoop与数据仓库3. 关系数据库的可扩展性瓶颈4. CAP理论5. Hadoop数据仓库工具5.1. RDS和TDS5.2. 抽取过程5.3. 转换与装载过程5.4. 过程管理和自动化调度5.5&#xff0e;数据目录&#xff08;或者称为元数据管理&#xff09;5.6&#xff0e;查询引擎…

数仓建设(三)

4) 累积快照事实表 多个业务过程联合分析而构建的事实表&#xff0c;如采购单的流转环节。用于分析事件时间和时间之间的间隔周期。少量的且当前事务型不支持的&#xff0c;如关闭、发货等相关的统计。 4. DWS公共汇总层设计规范 数据仓库的性能是数据仓库建设是否成功的重要标…

【vue2高德地图api】03-完善展示页,并且调用poi搜索接口

系列文章目录 文章目录 系列文章目录前言一、编写页面内容样式1.1 html内容1.2 css内容解决报错 二、完善api接口变量方法1.data变量2. methods3. computed4. api接口方法 三、配置api接口方法创建map.jsgetParkList方法 移动端控制台插件四、编写components组件在main.js中引入…

[机缘参悟-110] :一个IT人对面具的理解:职业面具戴久了,就会忘记原本真实的自己,一个人是忠于职位,还是忠于内心?

目录 一、职业面具戴久了&#xff0c;就会忘记原本真实的自己 二、霸王别姬 三、没有对错&#xff0c;各走各路 3.1 程蝶衣&#xff1a;戏里戏外&#xff0c;忠于角色 3.2 段小楼&#xff1a;戏里戏外&#xff0c;角色分明 3.3 没有对错&#xff0c;各走各路 四、职场中…

RabbitMQ的LazyQueue

在默认情况下&#xff0c;RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。但在某些特殊情况下&#xff0c;这会导致消息积压&#xff0c;比如&#xff1a; 消费者宕机或出现网络故障消息发送量激增&#xff0c;超过了消费者处理速度消费者处理业务发生阻塞 一旦…

PyQt 小程序

设备管理程序 v0.0.1.0, 终于出了一个基础版本,… … 两个字典的键值判断 辛亏用的是Python 这个编码时间大大缩短了 对已有的命令行进行GUI 化 from typing import Optional import PySide6.QtCore import PySide6.QtWidgets from cmd_ui import Ui_MainWindow from PySide6.…

Qt 视口和窗口的区别

视口和窗口 绘图设备的物理坐标是基本的坐标系&#xff0c;通过QPainter的平移、旋转等变换可以得到更容易操作的逻辑坐标 为了实现更方便的坐标&#xff0c;QPainter还提供了视口(Viewport)和窗口(Window)坐标系&#xff0c;通过QPainter内部的坐标变换矩阵自动转换为绘图设…

Vue2使用定时器和闭包实现防抖和节流函数。将函数放入util.js中,供具体功能在methods中调用

Vue2使用定时器和闭包实现防抖和节流函数。将函数放入util.js中&#xff0c;供具体功能在methods中调用。<br/ 参考文档&#xff1a; 如何在Vue中优雅的使用防抖节流人类高质量JS防抖与节流机制Vue项目中使用防抖和节流vue2使用lodash中的防抖&#xff08;debounce&#xff…

小程序首页搭建

小程序首页搭建 1. Flex布局是什么&#xff1f;2. 容器的属性2.1 flex-direction属性2.2 flex-wrap属性2.3 flex-flow属性2.4 justify-content属性2.5 align-items属性2.6 align-content属性 二.首页布局搭建二.1moke模拟数据实现轮播图4.信息搭建 Flex弹性布局 1. Flex布局是…

我的创作纪念日———C/C++之动态内存管理

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.前言 2.为什么要有动态内存分配…

NSS [NISACTF 2022]easyssrf

NSS [NISACTF 2022]easyssrf 先看题目&#xff0c;给了一个输入框 看这提示就知道不是curl了&#xff0c;先file协议读一下flag&#xff0c;file:///flag 不能直接读flag&#xff0c;读个提示文件file:///fl4g 访问一下 <?phphighlight_file(__FILE__); error_reporting(0…

python每日一练(9)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

oracle库中数据利用datax工具同步至mysql库

查看oracle版本 $sqlplus aaa/aaaa192.168.1.1/lcfaSQL*Plus: Release 19.0.0.0.0 - Production on Tue Oct 17 15:56:46 2023 Version 19.15.0.0.0Copyright (c) 1982, 2022, Oracle. All rights reserved.Last Successful login time: Tue Oct 17 2023 15:56:03 08:00Conne…

linux下 u2net tensorrt模型部署

TensorRT系列之 Windows10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速…

iperf3交叉编译

简介 iperf3是一个用于执行网络吞吐量测量的命令行工具。它支持时序、缓冲区、协议&#xff08;TCP&#xff0c;UDP&#xff0c;SCTP与IPv4和IPv6&#xff09;有关的各种参数。对于每次测试&#xff0c;它都会详细的带宽报告&#xff0c;延迟抖动和数据包丢失。 如果是ubuntu系…

华为---PPP协议简介及示例配置

PPP协议简介 PPP是Point-to-Point Protocol的简称&#xff0c;中文翻译为点到点协议。与以太网协议一样,PPP也是一个数据链路层协议。以太网协议定义了以太帧的格式&#xff0c;PPP协议也定义了自己的帧格式&#xff0c;这种格式的帧称为PPP帧。 利用PPP协议建立的二层网络称为…

MIT6.5830 Lab0-Go tutorial实验记录(三)

MIT6.5830 Lab0-Go tutorial实验记录&#xff08;三&#xff09; – WhiteNights Site 标签&#xff1a;Golang 在前面两次实验记录的铺垫&#xff0c;是时候完成第一项任务了。 实验步骤 补全handlers.go中缺失的代码 先来看第一个部分&#xff0c;从RidershipDB获取图像数据…

设计模式:工厂方法模式(C#、JAVA、JavaScript、C++、Python、Go、PHP):

本节主要介绍设计模式中的工厂方法模式。 简介&#xff1a; 工厂方法模式&#xff0c;它是对简单工厂模式的进一步抽象化&#xff0c;其好处是可以使系统在不修改原来代码的情况下引进新的产品&#xff0c;即满足开闭原则。 它定义了一个用于创建对象的工厂接口&#xff0c;让…

12-k8s-HPA自动扩缩容

文章目录 一、k8s弹性伸缩类型二、HPA原理三、metrics-server插件四、创建nginx提供负载测试五、部署HPA master操作即可 一、k8s弹性伸缩类型 Cluster-Autoscale: 集群容量(node数量)自动伸缩&#xff0c;跟自动化部署相关的&#xff0c;依赖iaas的弹性伸缩&#xff0c;主要用…

户外运动盛行,运动品牌如何利用软文推广脱颖而出?

全民健康意识的提升和城市居民对亲近自然的渴望带来户外运动的盛行&#xff0c;这也使运动品牌的市场保持强劲发展势头&#xff0c;那么在激烈的市场竞争中&#xff0c;运动品牌应该如何脱颖而出呢&#xff1f;下面就让媒介盒子告诉你&#xff01; 一、 分享户外运动干货 用户…