如何提取录制的视频文件的帧速率?我知道有 MediaFormat.KEY_FRAME_RATE 并且我可以通过 MediaExtractor 访问 MediaFormat 对象。但是 KEY_FRAME_RATE 仅适用于编码器。相反,我想找出已录制视频的帧速率。
有任何想法吗?
如何提取录制的视频文件的帧速率?我知道有 MediaFormat.KEY_FRAME_RATE 并且我可以通过 MediaExtractor 访问 MediaFormat 对象。但是 KEY_FRAME_RATE 仅适用于编码器。相反,我想找出已录制视频的帧速率。
有任何想法吗?
看起来没有办法通过任何官方 API 函数获得帧率。它可能需要一些额外的逻辑 - 计算时间戳之间的时间或解析标头信息。一般来说,h.264 标准允许可变帧率,因此帧时间可能会因一而异。例如,如果可以显示一些静态图片几秒钟左右
使用 时MediaExtractor
,如果您的视频轨道具有稳定的 FPS,那么您肯定知道您MediaExtractor
正在按照您正在搜索的帧持续时间前进。
在做任何事情之前,在你设置好之后MediaExtractor
,你可以做以下事情:
mediaExtractor.Advance();
var fps = 1000000f / (float) mediaExtractor.SampleTime;
mediaExtractor.SeekTo(0, MediaExtractorSeekTo.None);
就像我说的,你不能理所当然地认为所有帧都具有相同的持续时间。帧显示时间完全是任意的,但我觉得没有稳定的 FPS 并不常见。
您可以使用 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 的输出中,以便在解析输出时检查其他内容。
最后,再次提醒一下,视频的帧速率可能不是恒定的,因此请记住这一点。