如何提取录制的视频文件的帧速率?我知道有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