如何使用MediaCodec,MediaExtractor或MediaMetadataRetriever确定视频文件的帧速率?

时间:2014-07-16 06:13:46

标签: android video media mediacodec mediaextractor

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

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

看起来没有办法通过任何官方API函数获得帧率。它可能需要一些额外的逻辑 - 时间戳之间的计数时间或解析头信息。通常,h.264标准允许可变帧率,因此帧时间可以从一对一不同。例如,如果可以显示一些静态图片几秒钟左右

答案 1 :(得分:2)

您可以使用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获取帧速率的示例,将filename替换为您要检查的文件的名称:

cmd = "-i filename";

然后您的代码可以解析f​​ps的输出 - 请参阅下面的示例输出:

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的输出中,以便在解析输出时检查其他内容。

最后,再次提醒一下,视频的帧速率可能不会是恒定的,所以请记住这一点。

答案 2 :(得分:2)

使用MediaExtractor时,如果您的视频轨道具有稳定的FPS,那么您确定MediaExtractor正在按照您要搜索的帧持续时间前进。

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

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

就像我说的那样,你不能承认所有的帧都有相同的持续时间。帧的呈现时间完全是随意的,但我觉得没有稳定的FPS并不常见。