Android 如何确定视频文件';使用MediaCodec、MediaExtractor或MediaMetadataRetriever的s帧速率?

Android 如何确定视频文件';使用MediaCodec、MediaExtractor或MediaMetadataRetriever的s帧速率?,android,video,media,android-mediacodec,mediaextractor,Android,Video,Media,Android Mediacodec,Mediaextractor,如何提取已录制视频文件的帧速率?我知道有MediaFormat.KEY\u FRAME\u RATE,我可以通过MediaExtractor访问MediaFormat对象。但是,关键帧速率仅适用于编码器。相反,我想找出一个已经录制的视频的帧速率 有什么想法吗?看起来没有办法通过任何官方API函数获得帧速率。它可能需要一些额外的时间戳之间的逻辑计数时间或解析头信息。一般来说,h.264标准允许可变的帧速率,因此帧时间可能会有所不同。例如,如果可以显示几秒钟左右的静态图片,您可以使用ffmpeg获取

如何提取已录制视频文件的帧速率?我知道有MediaFormat.KEY\u FRAME\u RATE,我可以通过MediaExtractor访问MediaFormat对象。但是,关键帧速率仅适用于编码器。相反,我想找出一个已经录制的视频的帧速率


有什么想法吗?

看起来没有办法通过任何官方API函数获得帧速率。它可能需要一些额外的时间戳之间的逻辑计数时间或解析头信息。一般来说,h.264标准允许可变的帧速率,因此帧时间可能会有所不同。例如,如果可以显示几秒钟左右的静态图片,您可以使用ffmpeg获取视频的帧速率()-根据fadden和Marlon在对接受答案的评论中对可变帧速率所做的评论

在Android中包含ffmpeg有很多方法——我发现在复杂性和功能性之间最好的折衷方法是将命令行ffmpeg程序包装在Java JNI包装器中

有几个问题需要注意,包括通过包装器调用ffmpeg两次的问题,因此值得使用或研究现有的Android包装器解决方案-例如:

从文件中可以看出:

FFmpeg-FFmpeg=FFmpeg.getInstance(上下文);
试一试{
//要执行“ffmpeg-version”命令,只需传递“-version”
execute(cmd,newexecuteBinaryResponseHandler(){
@凌驾
public void onStart(){}
@凌驾
public void onProgress(字符串消息){}
@凌驾
public void onFailure(字符串消息){}
@凌驾
成功时公共无效(字符串消息){}
@凌驾
public void onFinish(){}
});
}捕获(FFmpegCommandAlreadyRunningException e){
//处理FFmpeg是否已在运行
}
获取帧速率的ffmpeg cmd示例,将文件名替换为要检查的文件名:

cmd=“-i文件名”;
然后,您的代码可以解析fps的输出-请参见下面的输出示例:

ffmpeg版本2.6.1版权所有(c)2000-2015 ffmpeg开发者
使用llvm gcc 4.2.1构建(llvm构建2336.11.00)
配置:--prefix=/Volumes/Ramdisk/sw--enable-gpl--enable-pthreads--enable-version3--enable-libvpx--disable-decoder=libvpx--enable-libmp3lame--enable-libvorbis--enable-libx264--enable-avfilter--enable-libopencore_amrwb--enable-libopencore_amrnb--enable过滤器--enable-libgsm--启用libvidstab--enable-libx265--disable doc--arch=x86_64--enable runtime cpudetect
libavutil 54。20.100 / 54. 20.100
libavcodec56。26.100 / 56. 26.100
libav56格式。25.101 / 56. 25.101
libav56设备。4.100 / 56.  4.100
libavfilter 5。11.102 /  5. 11.102
libswscale 3。1.101 /  3.  1.101
libswresample1。1.100 /  1.  1.100
Libroc 53。3.100 / 53.  3.100
从“/Users/BBB/Desktop/vid_bigbuckbunny.mp4”输入#0、mov、mp4、m4a、3gp、3g2、mj2:
元数据:
主要品牌:mp42
次要版本:1
兼容品牌:mp42avc1
创建时间:2010-02-09 01:55:39
持续时间:00:01:00.10,开始时间:0.000000,比特率:733KB/s
流#0:0(英文):音频:aac(LC)(mp4a/0x6134706D),22050 Hz,立体声,fltp,65 kb/s(默认)
元数据:
创建时间:2010-02-09 01:55:39
处理器名称:苹果声音媒体处理器
流#0:1(英文):视频:h264(约束基线)(avc1/0x31637661)、yuv420p(电视、smpte170m/smpte170m/bt709)、640x360、612 kb/s、23.96 fps、24 tbr、600 tbn、1200 tbc(默认)
元数据:
创建时间:2010-02-09 01:55:39
处理器名称:苹果视频媒体处理器
流#0:2(英文):数据:无(rtp/0x20707472),45 kb/s
元数据:
创建时间:2010-02-09 01:55:39
处理程序\u名称:提示媒体处理程序
流#0:3(英文):数据:无(rtp/0x20707472),5 kb/s
元数据:
创建时间:2010-02-09 01:55:39
处理程序\u名称:提示媒体处理程序
请记住,ffmpeg语法和输出格式可能会随着时间的推移而改变,因此对于解析,您尤其需要考虑到这一点,尽管在输出中查找“fps”通常会起作用

还应注意,许多视频“容器”(例如mp4,通常称为视频文件)可能包含多个视频流,并且不同的流可能具有不同的帧速率。这将包含在ffmpeg的输出中,以便在解析输出时检查其他内容


最后,再次提醒您,视频的帧速率可能不是恒定的,因此请记住这一点。

使用
MediaExtractor
时,如果您的视频曲目具有稳定的FPS,那么您肯定知道您的
MediaExtractor
正在按您正在搜索的帧持续时间前进

在执行任何操作之前,在设置了
MediaExtractor
之后,您可以执行以下操作:

mediaExtractor.Advance();
var fps = 1000000f / (float) mediaExtractor.SampleTime;
mediaExtractor.SeekTo(0, MediaExtractorSeekTo.None);

就像我说的,你不能认为所有的帧都有相同的持续时间。帧显示时间完全是任意的,但我觉得没有稳定的FPS并不常见。

一个简单的VFR示例是kitkat中“screenrecord”命令生成的视频。如果视频不是以恒定的帧速率录制的,就没有办法知道帧数(除了计算帧数),也没有帧速率。你可以计算一个峰值帧速率,这可能是OP所追求的。android设备上的硬件编码器是否需要在vfr模式下工作,是否有测试计划进行测试来检查?我不知道。我不再在那里工作了,所以很难找到答案。:-)我明白了:)offtopic您将来会支持和扩展grafika和bigflake吗?这些资源