3

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

有任何想法吗?

4

3 回答 3

3

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

于 2014-07-16T13:33:35.357 回答
3

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

在做任何事情之前,在你设置好之后MediaExtractor,你可以做以下事情:

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

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

于 2015-08-04T02:53:29.527 回答
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 示例,将文件名替换为您要检查的文件的名称:

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

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

于 2015-05-13T08:31:13.357 回答