前文地址:https://www.cnblogs.com/svenwu/p/9663038.html
前文已經對大多數正常情況可以支持了,但是我最近處理一些公司的視頻流,發現一些坑爹的情況
每次給的視頻流幀率不一致,甚至幀率為每秒3幀。。。。
以下代碼只適合已經錄制完成的視頻格式,不適合實時視頻流
還是直接上源碼
原代碼:
1 /** 2 * 按幀錄制視頻 3 * 4 * @param inputFile-該地址可以是網絡直播/錄播地址,也可以是遠程/本地文件路徑 5 * @param outputFile 6 * -該地址只能是文件地址,如果使用該方法推送流媒體服務器會報錯,原因是沒有設置編碼格式 7 * @throws FrameGrabber.Exception 8 * @throws FrameRecorder.Exception 9 * @throws org.bytedeco.javacv.FrameRecorder.Exception 10 */ 11 public static void frameRecord(String inputFile, String outputFile, int audioChannel) 12 throws Exception, org.bytedeco.javacv.FrameRecorder.Exception { 13 14 boolean isStart=true;//該變量建議設置為全局控制變量,用於控制錄制結束 15 // 獲取視頻源 16 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); 17 // 流媒體輸出地址,分辨率(長,高),是否錄制音頻(0:不錄制/1:錄制) 18 FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); 19 // 開始取視頻源 20 recordByFrame(grabber, recorder, isStart); 21 }
1 private static void recordByFrame(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder, Boolean status) 2 throws Exception, org.bytedeco.javacv.FrameRecorder.Exception { 3 try {//建議在線程中使用該方法 4 grabber.start(); 5 recorder.start(); 6 Frame frame = null; 7 while (status&& (frame = grabber.grabFrame()) != null) { 8 recorder.record(frame); 9 } 10 recorder.stop(); 11 grabber.stop(); 12 } finally { 13 if (grabber != null) { 14 grabber.stop(); 15 } 16 } 17 }
修改后代碼:
1 private static void recordByFrame(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder, Boolean status) 2 throws Exception, org.bytedeco.javacv.FrameRecorder.Exception { 3 try {//建議在線程中使用該方法 4 grabber.start(); 5 double frameLength = grabber.getLengthInFrames(); 6 long frameTime = grabber.getLengthInTime(); 7 recorder.setFrameRate(frameLength * 1000 * 1000/frameTime); 8 recorder.start(); 9 Frame frame = null; 10 while (status&& (frame = grabber.grabFrame()) != null) { 11 recorder.record(frame); 12 } 13 recorder.stop(); 14 grabber.stop(); 15 } finally { 16 if (grabber != null) { 17 grabber.stop(); 18 } 19 } 20 }
這里主要看第5-7行
//表示視頻的總圖片數量
double frameLength = grabber.getLengthInFrames();
//表示視頻總時長,這里單位是微妙,所以計算幀率時 要乘以 1000 * 1000
long frameTime = grabber.getLengthInTime();
幀率為 frameLength * 1000 * 1000 / frameTime 單位:幀/秒
另外,
1.獲取這兩個參數,必須要在grabber.start()以后
2.只適合已經錄制完成的視頻格式,不適合實時視頻流
這樣就能自適應的適配視頻幀率了