以ffmpeg爲核心,包裝一款局域網內接收轉碼並推送互聯網的客戶端軟件。本文僅使用ffmpeg基礎功能,拉流、轉碼、推流及簡單播放設置。node
拉取遠端視頻流,視頻流格式爲 rtspnpm
轉換爲經常使用播放格式 rtmpelectron
推送至播放端口 rtmp://您的推送端地址,用戶使用播放軟件鏈接該地址後能夠直接進行內容播放ide
ffmpeg 命令行工具官網連接,選擇它的優點在於:工具
免費編碼
無需安裝,很大的減小用戶操做複雜度命令行
命令行啓動調用code
nodejs 版本號爲 v6.11.3。(實際項目中使用electron,但若沒有打包成客戶端的需求,nodejs便可正常運行)視頻
tsc 版本號爲 v2.6.1。項目使用TypeScript爲主要編寫語言,您使用JavaScript也沒有問題。進程
若使用tsc,請使用2.0以上版本,自帶的@type工具會極大提高編碼效率
fluent-ffmpeg 版本號爲 v2.1.2。該nodejs包封裝了ffmpeg的命令行調用部分,增強了代碼的可讀性,若熟悉ffmpeg 命令行使用手冊,亦可不使用該包。
npm install --save fluent-ffmpeg //使用js編碼的用戶,能夠忽略下條命令 npm install --save @types/fluent-ffmpeg
VLC播放軟件。用於監測推流、轉碼、播放是否正常。官網連接
const ffmpegPath = "./dist/ffmpegProgram/bin/ffmpeg.exe"; const ffprobePath = "./dist/ffmpegProgram/bin/ffprobe.exe"; const flvtoolPath = "./dist/ffmpegProgram/bin/ffplay.exe"; export function startPushVideo():void{ getCommands().then((commands:ffmpegPaths[])=>{ for(let key in commands){ let command = commands[key]; //設置輸入流地址 let ffCommand = ffmpeg(command.inputPath) //設置輸出流地址 .output(command.outputPath) //因須要打包客戶端軟件,故而將ffmpeg打包進軟件中 //需設置各應用程序的對應路徑 //若僅在本機使用,能夠跳過該步驟 //設置環境變量,添加 PATH 便可 .setFfmpegPath(ffmpegPath) .setFfprobePath(ffprobePath) .setFlvtoolPath(flvtoolPath) //爲保證靈活性,非必須參數採用配置文件讀取模式 .size(command.size); for(let key in command.args){ ffCommand.outputOption(command.args[key]); } ffCommand.on("start",(commandLine)=>{ //commandLine 爲實際上調用的命令行命令,拼接邏輯爲 //您的ffmpeg所在路徑 -i inputOptions 您的拉流協議和路徑 outputOptions 推送流協議和地址 //ffmpeg -i "rtsp://yourPullUrl" -f flv -r 25 -s 640x480 -an "rtmp://yourPushUrl" console.log('[' + showTime() + '] Vedio is Pushing !'); console.log('[' + showTime() + '] Spawned Ffmpeg with command !'); console.log('[' + showTime() + '] Command: ' + commandLine); }) .on('error', function(err, stdout, stderr) { console.log('error: ' + err.message); console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); }) .on('end', function() { console.log('[' + showTime() + '] Vedio Pushing is Finished !'); }) .run(); } },(error)=>{ console.log('error: ' + error); }) }
經過監聽"start"獲取的命令,亦能夠經過 exec(yourCommandLine) 進行調用操做,但此時沒法控制 ffmpeg 的運行結果。該程序結束運行以後,ffmpeg進程依然在運行,直至流報錯或手動中止進程。暫時不清楚爲什麼 fluent-ffmpeg 能夠作到在本體進程結束後,通知關閉第三方進程。猜想是經過命令行輸入切斷進程,若僅經過 ChildProcess.kill() 是沒法關閉第三方進程。
在I5 8G 機器上運行,單流推送已佔用35%左右cpu,多流推送需使用其餘方案解決。