问题描述
背景
我有一个 .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]