FFmpeg can do a massive amount of things, getting video details can be done with FFmpeg however there is a special offspring from FFmpeg called ffprobe that is dedicated to getting you this information.
Its use is super simple and what it can return is super beneficial.
You can view all the possible outputs here, I am going to show you how to output all the available data into a JSON file:
ffprobe -v quiet -print_format json -show_format -show_streams '/path/media/thevideo.mp4' > thevideo.json
or
ffprobe -v quiet -print_format json -show_format -show_streams 'https://website.com/media/avideo.mp4' > avideo.json
quite
means it runs without console output, -print_format json
is the JSON formatted output, -show_format
attaches the format section to the data (see example below) and -show_streams
shows the stream information which is the main part.
The output will look like this:
{ "streams": [ { "index": 0, "codec_name": "h264", "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", "profile": "Main", "codec_type": "video", "codec_time_base": "6337331/379867500", "codec_tag_string": "avc1", "codec_tag": "0x31637661", "width": 1280, "height": 720, "coded_width": 1280, "coded_height": 720, "has_b_frames": 2, "sample_aspect_ratio": "1:1", "display_aspect_ratio": "16:9", "pix_fmt": "yuv420p", "level": 31, "color_range": "tv", "color_space": "bt709", "color_transfer": "bt709", "color_primaries": "bt709", "chroma_location": "left", "refs": 1, "is_avc": "true", "nal_length_size": "4", "r_frame_rate": "30000/1001", "avg_frame_rate": "189933750/6337331", "time_base": "1/90000", "start_pts": 0, "start_time": "0.000000", "duration_ts": 152095950, "duration": "1689.955000", "bit_rate": "5885980", "bits_per_raw_sample": "8", "nb_frames": "50649", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0 }, "tags": { "creation_time": "2019-12-28T14:44:58.000000Z", "language": "und", "handler_name": "VideoHandler" } }, { "index": 1, "codec_name": "aac", "codec_long_name": "AAC (Advanced Audio Coding)", "profile": "LC", "codec_type": "audio", "codec_time_base": "1/48000", "codec_tag_string": "mp4a", "codec_tag": "0x6134706d", "sample_fmt": "fltp", "sample_rate": "48000", "channels": 2, "channel_layout": "stereo", "bits_per_sample": 0, "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/48000", "start_pts": -64, "start_time": "-0.001333", "duration_ts": 81121248, "duration": "1690.026000", "bit_rate": "164621", "max_bit_rate": "164621", "nb_frames": "79222", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0 }, "tags": { "creation_time": "2020-01-08T16:42:58.000000Z", "language": "eng", "handler_name": "SoundHandler" } } ], "format": { "filename": "/path/to/video.mp4", "nb_streams": 2, "nb_programs": 0, "format_name": "mov,mp4,m4a,3gp,3g2,mj2", "format_long_name": "QuickTime / MOV", "start_time": "-0.001333", "duration": "1690.070000", "size": "1279988019", "bit_rate": "6058863", "probe_score": 100, "tags": { "major_brand": "mp42", "minor_version": "512", "compatible_brands": "isomiso2avc1mp41", "creation_time": "2019-12-28T14:44:58.000000Z", "title": "Video title", "artist": "Admin", "album_artist": "Admin", "encoder": "HandBrake 1.2.0 2018122200", "description": "This video is about xyz" } } }
You will see the first index in streams is details about the video data and the second is about audio. The size value is in bytes whilst the bitrate is in bits.
You can get the true frame rate by following the equation listed at r_frame_rate which is 30000/1001 = 29.97 fps.
If the video file did not have audio then the index 2 would not exist, keep in mind the if there was subtitle tracks then there would also be data for that.