NODEJS基於FFMPEG視頻推流測試

以ffmpeg爲核心,包裝一款局域網內接收轉碼並推送互聯網的客戶端軟件。本文僅使用ffmpeg基礎功能,拉流、轉碼、推流及簡單播放設置。node

工做流程

  1. 拉取遠端視頻流,視頻流格式爲 rtspnpm

  2. 轉換爲經常使用播放格式 rtmpelectron

  3. 推送至播放端口 rtmp://您的推送端地址,用戶使用播放軟件鏈接該地址後能夠直接進行內容播放ide

所需工具及軟件

  1. ffmpeg 命令行工具官網連接,選擇它的優點在於:工具

    • 免費編碼

    • 無需安裝,很大的減小用戶操做複雜度命令行

    • 命令行啓動調用code

  2. nodejs 版本號爲 v6.11.3。(實際項目中使用electron,但若沒有打包成客戶端的需求,nodejs便可正常運行)視頻

  3. tsc 版本號爲 v2.6.1。項目使用TypeScript爲主要編寫語言,您使用JavaScript也沒有問題。進程

    • 若使用tsc,請使用2.0以上版本,自帶的@type工具會極大提高編碼效率

  4. fluent-ffmpeg 版本號爲 v2.1.2。該nodejs包封裝了ffmpeg的命令行調用部分,增強了代碼的可讀性,若熟悉ffmpeg 命令行使用手冊,亦可不使用該包。

    npm install --save fluent-ffmpeg
        //使用js編碼的用戶,能夠忽略下條命令
        npm install --save @types/fluent-ffmpeg
  5. 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);
        })
    }

小結

  1. 經過監聽"start"獲取的命令,亦能夠經過 exec(yourCommandLine) 進行調用操做,但此時沒法控制 ffmpeg 的運行結果。該程序結束運行以後,ffmpeg進程依然在運行,直至流報錯或手動中止進程。暫時不清楚爲什麼 fluent-ffmpeg 能夠作到在本體進程結束後,通知關閉第三方進程。猜想是經過命令行輸入切斷進程,若僅經過 ChildProcess.kill() 是沒法關閉第三方進程。

  2. 在I5 8G 機器上運行,單流推送已佔用35%左右cpu,多流推送需使用其餘方案解決。

相關文章
相關標籤/搜索