node制作一個(gè)視頻幀長(zhǎng)圖生成器操作分享
前言
平時(shí)我們?cè)诎l(fā)布視頻的時(shí)候通常都需要從視頻中截取一幀圖片作為視頻的封面,而現(xiàn)在常見的封面動(dòng)態(tài)預(yù)覽效果則可以通過視頻幀長(zhǎng)圖來輔助實(shí)現(xiàn),今天就讓我們一起使用node來制作一個(gè)視頻幀長(zhǎng)圖生成工具。
效果展示
如上圖,這是從一個(gè)3分鐘左右的視頻中截取出來的30幀截圖合成的長(zhǎng)圖。
工具實(shí)現(xiàn)
獲取視頻時(shí)長(zhǎng)
- 1、引入依賴 我們可以使用
get-video-duration
這個(gè)庫中的getVideoDurationInSeconds
這個(gè)方法來獲取視頻的時(shí)長(zhǎng)。
const { getVideoDurationInSeconds } = require('get-video-duration');
- 2、獲取時(shí)長(zhǎng)
getVideoDurationInSeconds
是一個(gè)異步獲取圖片時(shí)長(zhǎng)的方法,入?yún)樾枰@取時(shí)長(zhǎng)的視頻路徑,返回的結(jié)果為視頻的時(shí)長(zhǎng)秒數(shù)。
getVideoDurationInSeconds(videoPath);
控制臺(tái)交互獲取相關(guān)參數(shù)
如上圖,我們可以在控制臺(tái)選擇相關(guān)的參數(shù),這里需要的參數(shù)主要有2個(gè),分別是視頻路徑和截取圖片數(shù)量。
這里使用了我自己基于inquirer封裝的一個(gè)控制臺(tái)文件選擇器插件,具體實(shí)現(xiàn)過程和使用方法可以查看我的這一篇文章:node封裝一個(gè)控制臺(tái)進(jìn)度條插件詳情
計(jì)算截取圖片的時(shí)間點(diǎn)集合
根據(jù)獲取到的時(shí)長(zhǎng)和輸入的截圖數(shù)量,我們可以計(jì)算出截取圖片的時(shí)間點(diǎn)集合。
const changTimeFormat = (seconds)=>{ seconds = parseInt(seconds); let h = Math.floor(seconds / 3600); h = h > 9 ? h : '0' + h; seconds %= 3600; let m = Math.floor(seconds / 60); m = m > 9 ? m : '0' + m; seconds %= 60; seconds = seconds > 9 ? seconds : '0' + seconds; return h + ':' + m + ':' + seconds; }; const countSplitPoint = (duration,cutNums = 30) => { cutNums = Math.min(cutNums,parseInt(duration)); const step = Math.floor(duration / cutNums); let start = 0; const res = []; while(cutNums--){ res.push(changTimeFormat(start)); start += step; } return res; };
獲取每一個(gè)時(shí)間點(diǎn)的視頻幀截圖
1、引入依賴
const cp = require('child_process'); const ffmpeg = require('ffmpeg');
引入child_process
后,我們可以在node中執(zhí)行shell腳本語句。ffmpeg
為比較常用的視頻處理工具庫。
2、功能實(shí)現(xiàn)
遞歸截取視頻各個(gè)時(shí)間點(diǎn)的截圖幀。
const execJpg = async(videoPath , saveFilePath, timeArr, index, cb )=>{ let ind = (index + 1) + ''; while(ind.length < (timeArr.length + '').length){ ind = '0' + ind; } const str = `ffmpeg -ss ${timeArr[index]} -i ${videoPath} -y -f image2 -t 0.001 ${saveFilePath + '\\' + ind}.jpg`; await cp.exec(str,async(err)=>{ if(err) console.log(err); const progressBar = new ProgressBar({ duration: timeArr.length - 1, tip:{ 0:'圖片截取中……', 100:'圖片截取完成!' } }); progressBar.run(index); if(index < timeArr.length - 1){ await execJpg(videoPath , saveFilePath, timeArr, index + 1, cb ) }else{ console.log('開始合并圖片') cb(); } }) }; const getVideoFrame = (config,cb)=>{ getVideoDurationInSeconds(config.videoPath).then(async(res)=>{ const timeArr = countSplitPoint(res,config.cutNums); await execJpg(config.videoPath , config.saveFilePath, timeArr, 0, cb ); }); };
圖片拼接長(zhǎng)圖
這里使用了我前面封裝的一個(gè)圖片拼接庫來進(jìn)行處理,該庫的實(shí)現(xiàn)過程及使用方法可以查看我的這一篇文章:node實(shí)現(xiàn)封裝一個(gè)圖片拼接插件
let jInquirer = new JInquirer(config); jInquirer.prompt().then(async(res)=>{ res.saveFilePath = '.\\img'; const ImgConcatClass = new ImgConcat(); getVideoFrame(res,()=>{ const p = { folderPath:'.\\img', //資源目錄 targetFolder:'.\\longImg', //合并后圖片存放目錄 direction:'y' //拼接方向,y為橫向,n為縱向 } ImgConcatClass.concatAll(p).then(ans=>{ console.log(ans); return ans; }); }); });
到此這篇關(guān)于node制作一個(gè)視頻幀長(zhǎng)圖生成器操作分享的文章就介紹到這了,更多相關(guān)node制作生成器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
package.json的版本號(hào)更新優(yōu)化方法
這篇文章主要為大家介紹了package.json的版本號(hào)更新優(yōu)化方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04Express中使用Swagger的實(shí)現(xiàn)示例
swagger-express是一個(gè)規(guī)范和完整的框架實(shí)現(xiàn),本文主要介紹了Express中使用Swagger的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12socket.io學(xué)習(xí)教程之基本應(yīng)用(二)
socket.io提供了基于事件的實(shí)時(shí)雙向通訊,下面這篇文章主要給大家介紹了socket.io基本應(yīng)用的相關(guān)資料,對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-04-04用node開發(fā)并發(fā)布一個(gè)cli工具的方法步驟
這篇文章主要介紹了用node開發(fā)并發(fā)布一個(gè)cli工具的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01深入理解Node.js 事件循環(huán)和回調(diào)函數(shù)
這篇文章主要介紹了深入理解Node.js 事件循環(huán)和回調(diào)函數(shù),詳細(xì)的介紹Node.js 事件循環(huán)和Node.js回調(diào)函數(shù),需要學(xué)習(xí)的可以參考一下。2016-11-11