导言
专注于为中小企业提供网站设计、成都网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业长寿免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了近千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
Canvas为前端提供了动画展示的平台,随着现在视频娱乐的流行,你是否想过把Canvas动画导出视频?目前纯前端的视频编码转换(例如WebM Encoder Whammy)还存在许多限制,较为成熟的方案是将每帧图片传给后端实现,由后端调用FFmpeg进行视频转码。整体流程并不复杂,这篇文章将带大家实现这个过程。
整体方案
前端部分
每帧图片生成
图片生成可以通过canvas原生接口toDataURL实现,最终返回base64形式的图像数据。
- generatePng () {
- ...
- var imgData = canvas.toDataURL("image/png");
- return imgData;
- }
动画录制与图片流传输
动画的记录与传送是个异步过程,这里返回一个Promise,等待后端处理完毕,收到回应后,即完成此异步过程。
以下代码将canvas每帧动画信息存入一个图片数组imgs中,将数组转成字符串的形式传给后端。注意这里contentType设置为“text/plain”。
- generateVideo () {
- var that = this;
- return new Promise (
- function (resolve, reject) {
- var imgs = [];
- ...
- window.requestAnimationFrame(that.recordTick.bind(that, imgs, resolve, reject));
- }
- )
- }
- recordTick (imgs, resolve, reject) {
- ...//每帧动画的记录信息,如时间戳等
- if (...) {//动画终止条件
- this.stopPlay();
- imgs.push(this.generatePng());
- $.ajax({
- url: '/video/record',
- data: imgs.join(' '),
- method: 'POST',
- contentType: 'text/plain',
- success: function (data, textStatus, jqXHR) {
- resolve(data);
- },
- error: function (jqXHR, textStatus, errorThrown) {
- reject(errorThrown);
- }
- });
- } else {
- ...//每帧动画展示的代码
- imgs.push(this.generatePng());
- window.requestAnimationFrame(this.recordTick.bind(this, imgs, resolve, reject));
- }
- }
视频下载
上一节代码中,动画停止时,会通过post请求给后端传送所有图片数据,后端处理完毕后,返回数据中包含一个url,此url即为视频文件的下载地址。
为了支持浏览器端用户点击下载,我们需要用到a标签的download属性,此属性可以支持点击a标签后下载指定文件。
- editor.generateVideo().then(function (data) {
- videoRecordingModal.setDownloadLink(data.url, data.filename);
- videoRecordingModal.changeStatus('recorded');
- });
- setDownloadLink: function (url, filename) {
- this.config.$dom.find('.video-download').attr('href', url);
- this.config.$dom.find('.video-download').attr('download', filename);
- }
后端部分
图片序列生成
接收到前端传送的图片数据后,我们首先需要将图片解析、存储在服务器中,我们建立以当前时间戳命名的文件夹,将图片序列以一定格式存储于其中。由于每张图片写入都是异步过程,为确保所有图片都已处理完毕后,才执行视频转码过程,我们需要用到Promise.all。
- Promise.all(imgs.map(function (value, index) {
- var img = decodeBase64Image(value)
- var data = img.data
- var type = img.type
- return new Promise(function (resolve, reject) {
- fs.writeFile(path.resolve(__dirname, (folder + '/img' + index + '.' + type)), data, 'base64', function(err) {
- if (err) {
- reject(err)
- } else {
- resolve()
- }
- })
- })
- })).then(function () {
- …//视频转码
- })
其中decodeBase64Image函数参考这里。
视频生成
视频生成利用FFmpeg转码工具。首先确保server端安装了FFmpeg
- brew install ffmpeg
在项目中安装fluent-ffmpeg,这是node调用ffmpeg的接口模块
- npm install fluent-ffmpeg --save
结合上一节图片序列存储的代码,整个接口代码如下:
- app.post('/video/record', function(req, res) {
- var imgs = req.text.split(' ')
- var timeStamp = Date.now()
- var folder = 'images/' + timeStamp
- if (!fs.existsSync(resolve(folder))){
- fs.mkdirSync(resolve(folder));
- }
- Promise.all(imgs.map(function (value, index) {
- var img = decodeBase64Image(value)
- var data = img.data
- var type = img.type
- return new Promise(function (resolve, reject) {
- fs.writeFile(path.resolve(__dirname, (folder + '/img' + index + '.' + type)), data, 'base64', function(err) {
- if (err) {
- reject(err)
- } else {
- resolve()
- }
- })
- })
- })).then(function () {
- var proc = new ffmpeg({ source: resolve(folder + '/img%d.png'), nolog: true })
- .withFps(25)
- .on('end', function() {
- res.status(200)
- res.send({
- url: '/video/mpeg/' + timeStamp,
- filename: 'jianshi' + timeStamp + '.mpeg'
- })
- })
- .on('error', function(err) {
- console.log('ERR: ' + err.message)
- })
- .saveToFile(resolve('video/jianshi' + timeStamp + '.mpeg'))
- })
- })
视频下载
最终将视频文件传输给前端的接口代码如下:
- app.get('/video/mpeg/:timeStamp', function(req, res) {
- res.contentType('mpeg');
- var rstream = fs.createReadStream(resolve('video/jianshi' + req.params.timeStamp + '.mpeg'));
- rstream.pipe(res, {end: true});
- })
效果预览
注:此功能是个人项目”简诗”的一部分,完整代码可以查看https://github.com/moyuer1992...
文章名称:Node+FFmpeg实现Canvas动画导出视频
转载源于:http://www.shufengxianlan.com/qtweb/news16/543166.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联