Fl4m3Ph03n1x

Fl4m3Ph03n1x

How to get native frame rate of video with FFmpex?

Background

I have an .mp4 video and I need to get the video’s frame rate. Using ffmepg (in Linux) I know I can get this information via the following command:

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

Which returns:

r_frame_rate=24000/1001

FFmpex

Doing this in bash is fine, but what I really want is to use it in my Elixir application. To this end I found out about ffmpex.

First I tried using 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"
   }
 }}

Which gives me some information, but not the frame rate.

My next tentative was to use the command options:

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

But the problem here is that I can’t find in the documentation the video option I need to get the native frame rate. I only found vframe which is used to set the video frame rate.

Question

  • How can I get the native fps of a video using ffmpex?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

By looking at the source code, I was able to find FFprobe.streams("filename").

This function will return a list of streams with their avg_frame_rate, which is what the native command from the shell was doing:

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"
   }
 ]}

This answers my question. FFprobe.format/1 was never the solution, it was FFprobe.streams/1!

Also Liked

maz

maz

What is totally amazing about this command is that it works on a file on S3:

ffprobe -v quiet -print_format json -show_streams https://bucket.s3.region.amazonaws.com/file.mp4

wanton7

wanton7

It seems that I didn’t fully understand your question but you can just output as json from ffprobe with -print_format json then decode that in Elixir

Fl4m3Ph03n1x

Fl4m3Ph03n1x

The idea of my question was to use the Elixir library to achieve this, not the command line. In theory I could use System.cmd to directly send bash commands to the machine and then get the output as JSON format, but that was not the intent of the question.

Thanks for trying to help though!

Where Next?

Popular in Questions Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New

We're in Beta

About us Mission Statement