简言
有的时候想截取视频某一秒的视频画面。
手动截取操作麻烦,还得时刻关注视频播放时间。
于是,我搞出来了一个根据视频自动截取特定时间描述的页面。
效果
实现步骤
- 获取视频对象
- 根据视频时长生成时间选择表单
- 根据表单选择的时间和视频地址,利用canvas和vido元素生成某一帧的视频画面图片
- 图片实现下载
源码
<!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>