国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Node + FFmpeg 實(shí)現(xiàn)Canvas動(dòng)畫導(dǎo)出視頻

開發(fā) 前端
Canvas為前端提供了動(dòng)畫展示的平臺(tái),隨著現(xiàn)在視頻娛樂的流行,你是否想過把Canvas動(dòng)畫導(dǎo)出視頻?目前純前端的視頻編碼轉(zhuǎn)換(例如WebM Encoder Whammy)還存在許多限制,較為成熟的方案是將每幀圖片傳給后端實(shí)現(xiàn),由后端調(diào)用FFmpeg進(jìn)行視頻轉(zhuǎn)碼。整體流程并不復(fù)雜,這篇文章將帶大家實(shí)現(xiàn)這個(gè)過程。

Node + FFmpeg 實(shí)現(xiàn)Canvas動(dòng)畫導(dǎo)出視頻

導(dǎo)言

Canvas為前端提供了動(dòng)畫展示的平臺(tái),隨著現(xiàn)在視頻娛樂的流行,你是否想過把Canvas動(dòng)畫導(dǎo)出視頻?目前純前端的視頻編碼轉(zhuǎn)換(例如WebM Encoder Whammy)還存在許多限制,較為成熟的方案是將每幀圖片傳給后端實(shí)現(xiàn),由后端調(diào)用FFmpeg進(jìn)行視頻轉(zhuǎn)碼。整體流程并不復(fù)雜,這篇文章將帶大家實(shí)現(xiàn)這個(gè)過程。

整體方案

  • 由前端記錄Canvas動(dòng)畫的每幀圖像,以base64字符串形式傳給后端
  • 利用node fluent-ffmpeg模塊,調(diào)用FFmpeg將圖片合并成視頻,并將視頻存儲(chǔ)在server端,并返回相應(yīng)下載url
  • 前端通過請(qǐng)求得到視頻文件

前端部分

每幀圖片生成

圖片生成可以通過canvas原生接口toDataURL實(shí)現(xiàn),最終返回base64形式的圖像數(shù)據(jù)。 

  1. generatePng () { 
  2.   ... 
  3.   var imgData = canvas.toDataURL("image/png"); 
  4.   return imgData; 
  5.  

動(dòng)畫錄制與圖片流傳輸

動(dòng)畫的記錄與傳送是個(gè)異步過程,這里返回一個(gè)Promise,等待后端處理完畢,收到回應(yīng)后,即完成此異步過程。

以下代碼將canvas每幀動(dòng)畫信息存入一個(gè)圖片數(shù)組imgs中,將數(shù)組轉(zhuǎn)成字符串的形式傳給后端。注意這里contentType設(shè)置為“text/plain”。

  1. generateVideo () { 
  2.   var that = this; 
  3.   return new Promise ( 
  4.     function (resolve, reject) { 
  5.       var imgs = []; 
  6.       ... 
  7.       window.requestAnimationFrame(that.recordTick.bind(that, imgs, resolve, reject)); 
  8.     } 
  9.   ) 
  10.   
  1. recordTick (imgs, resolve, reject) { 
  2.   ...//每幀動(dòng)畫的記錄信息,如時(shí)間戳等 
  3.  
  4.   if (...) {//動(dòng)畫終止條件 
  5.     this.stopPlay(); 
  6.     imgs.push(this.generatePng()); 
  7.     $.ajax({ 
  8.       url: '/video/record'
  9.       data: imgs.join(' '), 
  10.       method: 'POST'
  11.       contentType: 'text/plain'
  12.       success: function (data, textStatus, jqXHR) { 
  13.         resolve(data); 
  14.       }, 
  15.       error: function (jqXHR, textStatus, errorThrown) { 
  16.         reject(errorThrown); 
  17.       } 
  18.     }); 
  19.   } else { 
  20.     ...//每幀動(dòng)畫展示的代碼 
  21.  
  22.     imgs.push(this.generatePng()); 
  23.     window.requestAnimationFrame(this.recordTick.bind(this, imgs, resolve, reject)); 
  24.   } 
  25.  

視頻下載

上一節(jié)代碼中,動(dòng)畫停止時(shí),會(huì)通過post請(qǐng)求給后端傳送所有圖片數(shù)據(jù),后端處理完畢后,返回?cái)?shù)據(jù)中包含一個(gè)url,此url即為視頻文件的下載地址。

為了支持瀏覽器端用戶點(diǎn)擊下載,我們需要用到a標(biāo)簽的download屬性,此屬性可以支持點(diǎn)擊a標(biāo)簽后下載指定文件。

  1. editor.generateVideo().then(function (data) { 
  2.   videoRecordingModal.setDownloadLink(data.url, data.filename); 
  3.   videoRecordingModal.changeStatus('recorded'); 
  4. });   
  1. setDownloadLink: function (url, filename) { 
  2.   this.config.$dom.find('.video-download').attr('href', url); 
  3.   this.config.$dom.find('.video-download').attr('download', filename); 
  4.  

后端部分

圖片序列生成

接收到前端傳送的圖片數(shù)據(jù)后,我們首先需要將圖片解析、存儲(chǔ)在服務(wù)器中,我們建立以當(dāng)前時(shí)間戳命名的文件夾,將圖片序列以一定格式存儲(chǔ)于其中。由于每張圖片寫入都是異步過程,為確保所有圖片都已處理完畢后,才執(zhí)行視頻轉(zhuǎn)碼過程,我們需要用到Promise.all。

  1. Promise.all(imgs.map(function (value, index) { 
  2.   var img = decodeBase64Image(value) 
  3.   var data = img.data 
  4.   var type = img.type 
  5.   return new Promise(function (resolve, reject) { 
  6.     fs.writeFile(path.resolve(__dirname, (folder + '/img' + index + '.' + type)), data, 'base64'function(err) { 
  7.       if (err) { 
  8.         reject(err) 
  9.       } else { 
  10.         resolve() 
  11.       } 
  12.     }) 
  13.   }) 
  14. })).then(function () { 
  15.   …//視頻轉(zhuǎn)碼 
  16. })  

其中decodeBase64Image函數(shù)參考這里

視頻生成

視頻生成利用FFmpeg轉(zhuǎn)碼工具。首先確保server端安裝了FFmpeg

  1. brew install ffmpeg 

在項(xiàng)目中安裝fluent-ffmpeg,這是node調(diào)用ffmpeg的接口模塊

  1. npm install fluent-ffmpeg --save 

結(jié)合上一節(jié)圖片序列存儲(chǔ)的代碼,整個(gè)接口代碼如下:

  1. app.post('/video/record'function(req, res) { 
  2.   var imgs = req.text.split(' '
  3.   var timeStamp = Date.now() 
  4.   var folder = 'images/' + timeStamp 
  5.   if (!fs.existsSync(resolve(folder))){ 
  6.     fs.mkdirSync(resolve(folder)); 
  7.   } 
  8.  
  9.   Promise.all(imgs.map(function (value, index) { 
  10.     var img = decodeBase64Image(value) 
  11.     var data = img.data 
  12.     var type = img.type 
  13.     return new Promise(function (resolve, reject) { 
  14.       fs.writeFile(path.resolve(__dirname, (folder + '/img' + index + '.' + type)), data, 'base64'function(err) { 
  15.         if (err) { 
  16.           reject(err) 
  17.         } else { 
  18.           resolve() 
  19.         } 
  20.       }) 
  21.     }) 
  22.   })).then(function () { 
  23.     var proc = new ffmpeg({ source: resolve(folder + '/img%d.png'), nolog: true }) 
  24.       .withFps(25) 
  25.       .on('end'function() { 
  26.         res.status(200) 
  27.         res.send({ 
  28.           url: '/video/mpeg/' + timeStamp
  29.           filename: 'jianshi' + timeStamp + '.mpeg' 
  30.         }) 
  31.       }) 
  32.       .on('error'function(err) { 
  33.         console.log('ERR: ' + err.message) 
  34.       }) 
  35.       .saveToFile(resolve('video/jianshi' + timeStamp + '.mpeg')) 
  36.   }) 
  37. })  

視頻下載

最終將視頻文件傳輸給前端的接口代碼如下:

  1. app.get('/video/mpeg/:timeStamp'function(req, res) { 
  2.   res.contentType('mpeg'); 
  3.   var rstream = fs.createReadStream(resolve('video/jianshi' + req.params.timeStamp + '.mpeg')); 
  4.   rstream.pipe(res, {endtrue}); 
  5. })  

效果預(yù)覽 

  

注:此功能是個(gè)人項(xiàng)目”簡(jiǎn)詩”的一部分,完整代碼可以查看https://github.com/moyuer1992...

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2022-03-09 09:00:41

SwiftUI視圖生成器Swift

2012-07-13 13:52:54

Canvas

2022-08-29 10:39:32

FFmpeg多媒體框架開源

2022-08-11 09:30:52

transitionCSS

2012-07-11 15:54:59

canvas

2021-12-02 15:14:02

ffmpeg視頻Python

2024-02-27 13:03:38

前端視頻合成FFmpeg

2009-12-29 10:06:09

WPF Canvas

2022-06-29 14:06:54

canvas鴻蒙

2012-07-13 13:41:35

Canvas

2015-10-08 08:48:44

HTML5canvas動(dòng)畫

2022-11-28 17:22:02

CanvasCSS

2016-01-20 10:11:56

華麗CanvasHTML5

2021-02-21 07:49:40

Web動(dòng)畫SVG線條動(dòng)畫

2022-07-05 16:21:44

繪制表盤鴻蒙

2024-12-12 08:50:30

開源多媒體框架

2011-07-08 10:15:15

IPhone 動(dòng)畫

2022-03-10 11:04:04

Vue3Canvas前端

2016-10-20 15:54:12

CanvasHtml5Javascript

2021-06-01 09:27:52

視頻動(dòng)畫Remotion
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

欧美一区电影| 妞干网在线免费视频| 无码内射中文字幕岛国片| 日韩黄色大片网站| 欧美大片一区二区| 国内欧美日韩| 国产精品女同互慰在线看| 2020国产精品久久精品不卡| 97人人在线视频| 亚洲色图制服诱惑| 午夜精品一区二区三区在线观看| 香蕉视频亚洲一级| 日本一区二区免费在线观看视频 | 欧美a级理论片| 最新中文字幕亚洲| 91制片厂毛片| 夜夜夜久久久| 成人免费视频a| 日韩一级淫片| 日韩中文字幕网| 爱福利在线视频| 一区二区三区四区在线播放| 最新视频 - x88av| 国内精品久久久久久久影视蜜臀| 国产一区二区三区在线| 超碰中文在线| 精品福利一区二区三区| 久草在线官网| 亚洲欧洲精品成人久久奇米网| 午夜啪啪免费视频| 亚洲一区二区成人| 97欧洲一区二区精品免费| 国产欧美一区二区色老头 | 久久中文字幕二区| 宅男在线精品国产免费观看| 欧美韩国日本一区| 1024视频在线| 中文字幕亚洲欧美日韩高清| y111111国产精品久久久| 国产精品国产三级国产aⅴ浪潮| 欧美日韩国产在线一区| 精品一区二区成人免费视频| 琪琪久久久久日韩精品| 亚洲国产精品字幕| 奇米777日韩| 久久久999精品免费| 91亚洲无吗| 热久久免费视频精品| 亚洲国产精品成人| 偷拍视频一区二区| 国产成人免费在线观看不卡| 免费观看黄色的网站| 国产精品一品二品| 日韩视频在线视频| 国产精品欧美经典| 嫩草在线视频| 久久天天躁狠狠躁老女人| 一区二区三区日本久久久| av免费精品一区二区三区| 精品一区二区三区视频在线观看| 69精品丰满人妻无码视频a片| 国产欧美精品在线观看| av大全在线免费看| 日韩精品免费观看| 欧美日韩一区二区综合 | 黄色片网址在线观看| 亚洲欧美偷拍另类a∨色屁股| 国产在线免费观看| 日韩亚洲综合在线| 欧美亚洲视频| 免费观看v片在线观看| 欧美成人r级一区二区三区| 亚洲电影一区| 亚洲精品白虎| 五月婷婷久久丁香| 精品国产第一国产综合精品| 91中文字幕在线| 国产精品不卡一区二区三区| abab456成人免费网址| 91精品啪在线观看麻豆免费| 国产91富婆露脸刺激对白| 黄色在线免费看| 日韩男女性生活视频| 91免费国产在线观看| 三级在线看中文字幕完整版| 九九九九精品| 欧美精选午夜久久久乱码6080| 国产成人精品福利| 日本韩国欧美在线观看| 日韩亚洲欧美在线| 日韩欧美高清| 久久综合色播| 久久久久一本一区二区青青蜜月| 日本色综合中文字幕| 黄色在线视频网站| 久久精品国产美女| 色综合色综合久久综合频道88| 91极品美女在线| 97精品久久久午夜一区二区三区 | 精品无码三级在线观看视频| 在线免费看a| 亚洲va欧美va国产综合剧情| av亚洲精华国产精华| 久久99中文字幕| 精品久久国产字幕高潮| 国产精品1区2区| 妞干网免费在线视频| 欧美大尺度激情区在线播放| 99精品1区2区| 欧美专区日韩视频| 国产亚洲欧美日韩精品一区二区三区 | 午夜久久久久久久久| 天天干天天操天天做| 亚洲综合色区另类av| 成年人羞羞的网站| 玉米视频成人免费看| 男人操女人免费软件| 成人三级在线视频| 国产一二三四五| 91精品店在线| 国产日韩欧美在线播放| 色综合久久天天| 免费人成在线不卡| 激情亚洲小说| 国产真实老熟女无套内射| 色综合天天狠天天透天天伊人| 亚洲一区二区三区在线| 老司机精品久久| 狼人精品一区二区三区在线| 色综合久久影院| 国产老熟妇精品观看| 日本不卡免费一区| 日本久久电影网| 菠萝菠萝蜜在线观看| 国产在线拍偷自揄拍精品| 欧美日韩精品系列| 亚洲国产精品视频| 99精品视频在线观看免费| 国产精品专区在线| 日韩经典在线视频| 老汉色影院首页| 蜜桃传媒一区二区三区| 男女激情片在线观看| 在线视频专区| 99这里只有精品视频| 日本午夜一区二区| 一本大道av伊人久久综合| 国产一区二区三区久久精品| 5566日本婷婷色中文字幕97| 亚洲国产精品成人天堂| 色资源在线观看| 婷婷综合六月| 欧美黄在线观看| 久久精品免费在线观看| 日韩电影中文字幕一区| 动漫3d精品一区二区三区| www婷婷av久久久影片| 在线观看av网站| 久久久久久一区二区三区四区别墅| 欧美性久久久| 国产老女人精品毛片久久| 国产精品一区三区| 成人精品小蝌蚪| 中文字幕中文在线不卡住| 欧美综合久久久| 久久在线免费视频| 国产乱肥老妇国产一区二| 亚洲精品欧美一区二区三区| 国产欧美丝袜| 亚洲av综合色区| 免费观影入口看日本视频| 91大神在线网站| 国产私拍福利精品视频二区| 亚洲午夜一区| 国产清纯在线一区二区www| 91久久精品日日躁夜夜躁欧美| 欧美日韩dvd在线观看| 国产精品久久久久久五月尺| 青青草视频在线视频| 亚洲激情电影在线| 欧美一区二区影院| 九九热视频这里只有精品| 国产欧美日韩伦理| 波多野结衣精品| 中文字幕亚洲视频| 国产一区二区三区高清视频| av免费观看一区二区| 筱崎爱全乳无删减在线观看| 欧美大片1688网站| 国偷自产av一区二区三区| 亚洲久色影视| 中文字幕一区免费在线观看| 亚洲1区2区3区4区| 欧美日韩国产系列| 色偷偷88欧美精品久久久| 成人性视频免费网站| 一区二区影视| 成人动漫视频在线| 1024精品久久久久久久久| 综合激情视频|