1.Java調用命令行,如果沒有額外環境變量,不指定工作路徑,Runtime有兩個方法
public Process exec(String command) public Process exec(String cmdarray[])
ffmpeg推流本地視頻命令如下
ffmpeg -re -i test.mp4 <param> <url>
ffmpeg -re -i test.mp4 <param> "<url> socks=***" // 代理
如果用exec(String command) 有代理的情況下,就算將雙引號包含進去,也會不成功,會將<url>部分當做輸入的視頻文件位置。建議使用exec(String cmdarray[])方法。
在使用exec(String cmdarray[])時,內部處理是當如果中間有空格時,在首尾加上雙引號,具體使用具體分析。
2.調用命令行后,程序可能正常推流推一會兒,然后程序block住,后台進程ffmpeg還沒死。
Runtime.exec()執行時JVM會產生一個子進程,該進程與JVM建立三個通道鏈接:標准輸入,標准輸出,標准錯誤。
Java本地的系統對標准輸入和輸出所提供的緩沖池有限,所以錯誤的對標准輸出快速的寫入和從標准輸入快速的讀入都有可能造成子進程死鎖。
子進程的輸出流,也就是JVM的輸入流。子進程不斷向控制台輸出,如果Java沒有把輸入流及時清空,會導致緩存區滿,導致死鎖。
解決辦法就是及時清空輸入流,開兩個線程把process.getInputStream()和process.getErrorStream()讀出來就可以。對於ffmpeg只需要process.getErrorStream()讀出來就可以了。
Process process = Runtime.getRuntime().exec(command);
BufferedReader br= new BufferedReader(new InputStreamReader(process.getErrorStream())); while ((line = br.readLine()) != null) { System.out.println(line); }
process.waitFor();
或者ProcessBuilder重定向標准錯誤
ProcessBuilder processBuilder = new ProcessBuilder(commands); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); ProcessContext.getInstance().addProcess(process); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); }
process.waitFor();
3.在虛擬機上測試時,模擬服務器瞬間斷網的情況(拔網線),在虛擬機上跑的程序卡住了。
這種情況在正常服務器上沒有問題,只在自己的虛擬機上有問題,原因不明,建議這種case在物理機上測試。
4.ffmpeg推本地視頻文件時占用cpu過高,每個進程大約78-80%。
cpu主要是被圖像轉碼占用了。如果是本地視頻並且不需要對圖像轉碼的情況,使用參數 -vcodec copy不進行轉碼只是復制。會大大減低cpu使用率(僅占用2%左右)。
如果就是有轉碼的需求,可以嘗試參數 -threads 2。
幫助:
1.ffmepg推流的返回值(process.exitValue()),0為成功,其他失敗。
2.使用process.waitFor()等待子進程。
3.-ss **:**:** 跳過指定時長,對參數位置有要求。