如何使用 FFmpex 获得视频的原生帧率?

问题描述

背景

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

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

哪个返回:

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 获取视频的原生 fps?

解决方法

通过遵循@VC.One 的建议并检查源代码,我找到了 FFprobe.streams("filename")

这个函数将返回一个流列表和它们的 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","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","time_base" => "1/44100"
   }
 ]}

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

,

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

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

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

所以也许将那条线调整为:

cmd_args = ["-v","-show_entries stream=r_frame_rate",file_path]

以上内容可能会写成:

cmd_args = ["-v","-show_entries","stream=r_frame_rate",file_path]