如何使用 FFmpeg 获得视频的本机帧速率?

How to get native frame rate of vide with FFmpex?

背景

我有一个 .mp4 视频,我需要获取视频的帧速率。使用 ffmepg(在 Linux 中)我知道我可以通过以下命令获取此信息:

ffprobe -v 0 -of compact=p=0 -select_streams 0 -show_entries stream=r_frame_rate 'MyVideoFIle.mp4'

哪个returns:

r_frame_rate=24000/1001

FFmpex

在 bash 中这样做很好,但我真正想要的是在我的 Elixir 应用程序中使用它。为此我查了一下ffmpex.

首先我尝试使用 FFprobe:

> FFprobe.format("Devil May Cry 5 Bury the Light LITTLE V COVER.mp4")

{:ok,
 %{
   "bit_rate" => "611784",
   "duration" => "482.999000",
   "filename" => "Devil May Cry 5 Bury the Light LITTLE V COVER.mp4",
   "format_long_name" => "QuickTime / MOV",
   "format_name" => "mov,mp4,m4a,3gp,3g2,mj2",
   "nb_programs" => 0,
   "nb_streams" => 2,
   "probe_score" => 100, 
   "size" => "36936415",
   "start_time" => "0.000000",
   "tags" => %{
     "compatible_brands" => "isomiso2avc1mp41",
     "encoder" => "Lavf58.19.102",
     "major_brand" => "isom",
     "minor_version" => "512"
   }
 }}

这给了我一些信息,但不是帧速率。

我的下一个尝试是使用命令选项:

command = 
  FFmpex.new_command() 
  |> add_input_file("Devil May Cry 5 Bury the Light LITTLE V COVER.mp4") 
  |> add_video_option(???) 

但这里的问题是我无法在文档中找到 获取 本机帧速率所需的视频选项。我只找到 vframe 用于 设置 视频帧率。

问题

我不使用 FFmpex,但通过快速查看 Github 上的源代码:

看到 第 71 行 ffmpex/lib/ffprobe.ex 是设置传递给 FFprobe 的选项:

cmd_args = ["-v", "quiet", "-print_format", "json", "-show_format", file_path]

所以也许将该行调整为:

cmd_args = ["-v", "quiet", "-print_format", "json", "-show_format", "-show_entries stream=r_frame_rate", file_path]

有可能上面写成:

cmd_args = ["-v", "quiet", "-print_format", "json", "-show_format", "-show_entries", "stream=r_frame_rate", file_path]

按照@VC.One的建议并查看源代码,我找到了FFprobe.streams("filename").

此函数将 return 流列表及其 avg_frame_rate,这是来自 shell 的本机命令所做的:

FFprobe.streams("Devil May Cry 5 Bury the Light LITTLE V COVER.mp4")
{:ok,
 [
   %{
     "refs" => 1,
     "avg_frame_rate" => "24000/1001",
     "level" => 31,
     "nb_frames" => "11579",
     "is_avc" => "true",
     "coded_height" => 720,
     "index" => 0,
     "display_aspect_ratio" => "16:9",
     "r_frame_rate" => "24000/1001",
     "nal_length_size" => "4",
     "has_b_frames" => 1,
     "height" => 720,
     "time_base" => "1/24000",
     "codec_time_base" => "1001/48000",
     "color_transfer" => "bt709",
     "color_space" => "bt709",
     "codec_tag_string" => "avc1",
     "pix_fmt" => "yuv420p",
     "bits_per_raw_sample" => "8",
     "bit_rate" => "478071",
     "codec_tag" => "0x31637661",
     "profile" => "Main",
     "sample_aspect_ratio" => "1:1",
     "chroma_location" => "left",
     "color_primaries" => "bt709",
     "coded_width" => 1280,
     "width" => 1280,
     "codec_type" => "video",
     "codec_long_name" => "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
     "start_time" => "0.000000",
     "duration" => "482.940792",
     "duration_ts" => 11590579,
     "codec_name" => "h264",
     "start_pts" => 0,
     "tags" => %{
       "handler_name" => "ISO Media file produced by Google Inc.",
       "language" => "und"
     },
     "color_range" => "tv",
     "disposition" => %{
       "attached_pic" => 0,
       "clean_effects" => 0,
       "comment" => 0,
       "default" => 1,
       "dub" => 0,
       "forced" => 0,
       "hearing_impaired" => 0,
       "karaoke" => 0,
       "lyrics" => 0,
       "original" => 0,                                                                                                                                                                      
       ...                                                                                                                                                                                   
     }
   },
   %{
     "avg_frame_rate" => "0/0",
     "bit_rate" => "127999",
     "bits_per_sample" => 0,
     "channel_layout" => "stereo",
     "channels" => 2,
     "codec_long_name" => "AAC (Advanced Audio Coding)",
     "codec_name" => "aac",
     "codec_tag" => "0x6134706d",
     "codec_tag_string" => "mp4a",
     "codec_time_base" => "1/44100",
     "codec_type" => "audio",
     "disposition" => %{
       "attached_pic" => 0,
       "clean_effects" => 0,
       "comment" => 0,
       "default" => 1,
       "dub" => 0,
       "forced" => 0,
       "hearing_impaired" => 0,
       "karaoke" => 0,
       "lyrics" => 0,
       "original" => 0,
       "timed_thumbnails" => 0,
       "visual_impaired" => 0
     },
     "duration" => "482.998277",
     "duration_ts" => 21300224,
     "index" => 1,
     "max_bit_rate" => "127999",
     "nb_frames" => "20801",
     "profile" => "LC",
     "r_frame_rate" => "0/0",
     "sample_fmt" => "fltp",
     "sample_rate" => "44100",
     "start_pts" => 0,
     "start_time" => "0.000000",
     "tags" => %{
       "handler_name" => "ISO Media file produced by Google Inc.",
       "language" => "und"
     },
     "time_base" => "1/44100"
   }
 ]}

这回答了我的问题。 FFprobe.format/1 从来都不是解决方案,它是 FFprobe.streams/1!