加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

前端canvas动画怎样转成mp4视频的要领

发布时间:2020-03-29 21:43:59 所属栏目:编程 来源:站长网
导读:副问题#e# 用户通过上传吻合尺寸的图片,选着渲染动画的结果和音乐,可以预览相同幻灯片的结果,最后点击确认天生视频,可以放到头条可能抖音播放。 天生视频也许的方案 纯前端的视频编码转换(譬喻WebM Encoder Whammy) 图片地点只能是相对地点 音乐不能收
副问题[/!--empirenews.page--]

用户通过上传吻合尺寸的图片,选着渲染动画的结果和音乐,可以预览相同幻灯片的结果,最后点击确认天生视频,可以放到头条可能抖音播放。

天生视频也许的方案

纯前端的视频编码转换(譬喻WebM Encoder Whammy)

图片地点只能是相对地点

音乐不能收录

天生的视频必要下载再上传

将每帧图片传给后端实现,由后端挪用FFmpeg举办视频转码

截图多的时辰,base64字符串情势的图片太大,在前端欠好传给后端

在前端截图还依靠用户电脑机能;

最后定的方案流程

canvas动画和截图在处事器端运行,后端按照标识获取截图

操作FFmpeg将图片归并成视频,并将视频存储在server端,并返回响应下载url

前端通过哀求获得视频文件

前端canvas怎样截图

每帧图片天生

图片天生可以通过canvas原生接口toDataURL实现,最终返回base64情势的图像数据

function generatePng() { var canvas = document.createElement('canvas'); let icavas = '#canvas' //渲染动画的canvas id if (wrapWidth == 2) { icavas = '#verticalCanvas' } var canvasNode = document.querySelector(icavas) canvas.width = canvasNode.width; canvas.height = canvasNode.height; var ctx = canvas.getContext('2d'); ctx.drawImage(canvasNode, 0, 0); var imgData = canvas.toDataURL("image/png"); return imgData; }

canvas动画截图的要领

用setInterval按时执行图片天生的要领,虽然也可以用requestAnimationFrame

setInterval(function() { imgsTemp.push(generatePng()) }, 1000/60)

后端怎样获取每帧图片

方案一:无头赏识器运行前端canvas动画js,然后js截图

最初假想:

截图用console.log打印出来,canvas截图是base64名目标,一个15秒的动画,截图有100多张,直接导致处事器运行瓦解(被否了);

试运行方案:

截图存储在js变量中,动画播放完成,在页面中加一个标识,然后后端去取这个变量,代码如下:

const pages = { imageZoomOut: import ('./image_zoom_inout.js'), //缩放 imageArt: import ('./image_art.js'), //擦除 imageGrid: import ('./image_grid.js'), //网格 imageRotate: import ('./image_rotate.js'), //开合 imageFlash: import ('./image_flash.js'), //图文快闪 imageVerticalArt: import ('./image_vertical_art.js'), //竖版擦除 imageVerticalGrid: import ('./image_vertical_grid.js'), //竖版网格 imageVerticalRotate: import ('./image_vertical_rotate.js'), //竖版开合 imageVerticalFlash: import ('./image_vertical_flash.js'), //竖国界文快闪 imageVerticalZoomOut: import ('./image_vertical_zoom_inout.js'), //竖版缩放 imageVertical: import ('./image_vertical.js'), //竖版通用 }; var isShow = false var imgsBase64 = [] var imgsTemp = [] var cutInter = null var imgsTimeLong = 0 function getQuerys(tag) { let queryStr = window.location.search.slice(1); let queryArr = queryStr.split('&'); let query = []; let spec = {} for (let i = 0, len = queryArr.length; i < len; i++) { let queryItem = queryArr[i].split('='); let qitem = decodeURIComponent(queryItem[1]) if (queryItem[0] == tag) { query.push(qitem); } else { spec[queryItem[0]] = qitem } } return { list: query, spec: spec }; } var getQuery = getQuerys('images') var effectTag = getQuery.spec.tid var wrapWidth = getQuery.spec.templateType let num = 0 let imgArr = [] function creatImg() { var images = getQuery.list let newImg = [] let vh = wrapWidth == 1 ? 360 : 640 let vw = wrapWidth == 1 ? 640 : 360 if (effectTag.indexOf('Flash') > -1) { images.map(function(item, index) { if (11 === index || 13 === index || 16 === index) { var temp = new Image(vw, vh) temp.setAttribute('crossOrigin', 'anonymous'); temp.src = item; newImg.push(temp) } else { newImg.push(item) } }) imgArr = newImg renderAnimate(effectTag) } else { images.map(function(item) { var temp = new Image(vw, vh) temp.setAttribute('crossOrigin', 'anonymous'); temp.src = item; temp.onload = function() { num++ if (num == images.length) { renderAnimate(effectTag) } } newImg.push(temp) }) imgArr = newImg } } async function renderAnimate(page) { //await creatImg() let me = this const pageA = await pages[page]; let oldDate = new Date().getTime() let icavas = '#canvas' if (wrapWidth == 2) { icavas = '#verticalCanvas' } let innerCanvas = document.querySelector(icavas) isShow = false pageA[page].render(null, { canvas: innerCanvas, images: imgArr }, function() { //动画播完 isShow = true; imgsTemp.push(generatePng()) imgsBase64.push(imgsTemp) let now = new Date().getTime() window.imgsTimeLong = now - oldDate clearInterval(cutInter) document.getElementById('cutImg').innerHTML = 'done'//页面标识 }) cutInter = setInterval(function() { imgsTemp.push(generatePng()) if (imgsTemp.length >= 50) { imgsBase64.push(imgsTemp) imgsTemp = [] } }, 130) } function getImgs() { return imgsBase64 } function generatePng() { var canvas = document.createElement('canvas'); let icavas = '#canvas' if (wrapWidth == 2) { icavas = '#verticalCanvas' } var canvasNode = document.querySelector(icavas) canvas.width = canvasNode.width; canvas.height = canvasNode.height; var ctx = canvas.getContext('2d'); ctx.drawImage(canvasNode, 0, 0); var imgData = canvas.toDataURL("image/png"); return imgData; } window.imgsBase64 = imgsBase64 //截图存储变量 creatImg()

试运行方案的破绽:

截图隔断130ms截一张图片,截图数目太少,导致天生的动画不流通;

截图隔断调成1秒60帧的话,动画播放迟钝,导致天生视频时刻变长;(settimeout和setinterval的机制)

图片尺寸在640x360可能360x640,天生的动画在手机端预览不清楚;

需求换成图片尺寸为1280x720可能720x1280之后,本来15秒的动画在处事器端执行酿成了70多秒

canvas截图存在跨域题目,可以如下配置

var temp = new Image(vw, vh) temp.setAttribute('crossOrigin', 'anonymous');

最终方案:在NODE端行为作画

用node-canvas,把每帧截图用 fs.writeFile 写到指定的文件夹里

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读