如何提取錄製的視頻文件的幀速率?我知道有MediaFormat.KEY_FRAME_RATE,我可以通過MediaExtractor訪問MediaFormat對象。但KEY_FRAME_RATE僅適用於編碼器。相反,我想找出已錄製視頻的幀速率。如何使用MediaCodec,MediaExtractor或MediaMetadataRetriever確定視頻文件的幀率?
任何想法?
如何提取錄製的視頻文件的幀速率?我知道有MediaFormat.KEY_FRAME_RATE,我可以通過MediaExtractor訪問MediaFormat對象。但KEY_FRAME_RATE僅適用於編碼器。相反,我想找出已錄製視頻的幀速率。如何使用MediaCodec,MediaExtractor或MediaMetadataRetriever確定視頻文件的幀率?
任何想法?
看起來像沒有辦法通過任何官方API函數來獲取幀率。它可能需要一些額外的邏輯 - 時間戳之間的計數時間或解析標題信息。一般而言,h.264標準允許可變幀率,因此幀時間可能會不同於一比一。例如,如果可以顯示幾秒鐘左右的靜態圖片
您可以使用ffmpeg獲取視頻的幀速率(https://www.ffmpeg.org) - 服從fadden和Marlon對註釋中的可變幀速率做出的評論接受的答案。
有許多方法可以在Android中包含ffmpeg - 我發現複雜性和功能性之間最好的折中方法是將命令行ffmpeg程序包裝在Java JNI包裝中。
有幾個問題看出來的,包括通過包裝兩次調用的ffmpeg的問題,所以它是值得或者使用或學習現有的Android包裝解決方案 - 例如:
從文檔有:
FFmpeg ffmpeg = FFmpeg.getInstance(context);
try {
// to execute "ffmpeg -version" command you just need to pass "-version"
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {}
@Override
public void onProgress(String message) {}
@Override
public void onFailure(String message) {}
@Override
public void onSuccess(String message) {}
@Override
public void onFinish() {}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// Handle if FFmpeg is already running
}
的ffmpeg CMD的一個例子,以獲得幀速率,與文件的名稱替換文件名要檢查:
cmd = "-i filename";
你的代碼可以解析輸出的FPS - 參見下面的示例輸出:
ffmpeg version 2.6.1 Copyright (c) 2000-2015 the FFmpeg developers
built with llvm-gcc 4.2.1 (LLVM build 2336.11.00)
configuration: --prefix=/Volumes/Ramdisk/sw --enable-gpl --enable-pthreads --enable-version3 --enable-libspeex --enable-libvpx --disable-decoder=libvpx --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-avfilter --enable-libopencore_amrwb --enable-libopencore_amrnb --enable-filters --enable-libgsm --enable-libvidstab --enable-libx265 --disable-doc --arch=x86_64 --enable-runtime-cpudetect
libavutil 54. 20.100/54. 20.100
libavcodec 56. 26.100/56. 26.100
libavformat 56. 25.101/56. 25.101
libavdevice 56. 4.100/56. 4.100
libavfilter 5. 11.102/5. 11.102
libswscale 3. 1.101/3. 1.101
libswresample 1. 1.100/1. 1.100
libpostproc 53. 3.100/53. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/BBB/Desktop/vid_bigbuckbunny.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: mp42avc1
creation_time : 2010-02-09 01:55:39
Duration: 00:01:00.10, start: 0.000000, bitrate: 733 kb/s
Stream #0:0(eng): Audio: aac (LC) (mp4a/0x6134706D), 22050 Hz, stereo, fltp, 65 kb/s (default)
Metadata:
creation_time : 2010-02-09 01:55:39
handler_name : Apple Sound Media Handler
Stream #0:1(eng): Video: h264 (Constrained Baseline) (avc1/0x31637661), yuv420p(tv, smpte170m/smpte170m/bt709), 640x360, 612 kb/s, 23.96 fps, 24 tbr, 600 tbn, 1200 tbc (default)
Metadata:
creation_time : 2010-02-09 01:55:39
handler_name : Apple Video Media Handler
Stream #0:2(eng): Data: none (rtp/0x20707472), 45 kb/s
Metadata:
creation_time : 2010-02-09 01:55:39
handler_name : hint media handler
Stream #0:3(eng): Data: none (rtp/0x20707472), 5 kb/s
Metadata:
creation_time : 2010-02-09 01:55:39
handler_name : hint media handler
記住,FFmpeg的語法和輸出格式可能會隨時間而改變,所以對於解析特別是你需要考慮到這一點,儘管在輸出中尋找'fps'可能通常會起作用。另外請注意,許多視頻「容器」(例如,mp4,通常被稱爲視頻文件)可能包含多個視頻流,並且不同的流可能具有不同的幀速率。這將包含在ffmpeg的輸出中,以便在解析輸出時檢查其他內容。
最後,再次提醒您,視頻的幀頻可能不是恆定的,因此請牢記這一點。
當使用MediaExtractor
時,如果您的視頻軌道具有穩定的FPS,那麼您肯定知道您的MediaExtractor
正在前進您正在搜索的幀持續時間。
做什麼,只是已經成立後,之前你MediaExtractor
,你可以做到以下幾點:
mediaExtractor.Advance();
var fps = 1000000f/(float) mediaExtractor.SampleTime;
mediaExtractor.SeekTo(0, MediaExtractorSeekTo.None);
就像我說的,你不能把補助金,所有的幀具有相同的持續時間。幀展示時間完全是任意的,但我覺得沒有穩定的FPS並不常見。
VFR的一個簡單的例子是通過在奇巧的「screenrecord」命令生成的視頻。如果視頻沒有以一個固定的幀速率記錄下來,那麼就無法知道幀的數量(除了對它們進行計數),並且沒有像幀速率那樣的東西。你可以計算一個峯值幀速率,這可能是OP後面的。 – fadden
是否需要安卓設備上的hw編碼器才能在vfr模式下工作,並且是否有測試\計劃來進行測試以檢查它? – Marlon
我不知道。我現在不在那裏工作,所以很難找到答案。 :-) – fadden