How to get the information and metadata of a media file (audio or video) in JSON format with FFPROBE

When working with FFMPEG from the command line, we have always dreamed of some kind of feature that would allow us to proceed with the execution of an instruction that only works if the given input fulfills some special characteristics like the number of streams, the codec, or other things.

In case that you are working with FFMPEG through the command line and manipulating it with a programming language like Python, JavaScript, PHP, or any other language, you may obtain an extra conditional layer of information about the input files using FFPROBE before working on the files with FFMPEG. FFPROBE gathers information from multimedia streams and prints it in human- and machine-readable fashion and comes as well with FFMPEG. For example, it can be used to check the format of the container used by a multimedia stream and the format and type of each media stream contained in it.

This information could be handled by any programming language that is capable of parsing the JSON format. In this article, I will show you a very basic command to extract information about the media files before processing them using FFPROBE (FFMPEG).

Extracting information

The command to extract the information of a media file using ffprobe in JSON format is the following one and each option is described as follows:

  • -loglevel -8: Shows absolute nothing of the output of ffprobe. If any error occurs and no information can be extracted, the process won't fail but will return an empty JSON.
  • -print_format <format>: Sets the output printing format to output in JSON, INI, XML, or CSV format.
  • -show_format: This option shows information about the container format of the input multimedia stream. All the container format information is printed within a section with the name "FORMAT".
  • -show_streams: This option shows information about each media stream contained in the input multimedia stream. Each media stream information is printed within a dedicated section (an array item) with the name "STREAM".
ffprobe -loglevel 0 -print_format json -show_format -show_streams <input-file.{avi,mp3,mp4,mkv}>

This will print a JSON output similar to the following one in your terminal (of course depending on the file input format and content, it will change, in this case, we are executing the command with an MP3 audio file):

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mp3",
            "codec_long_name": "MP3 (MPEG audio layer 3)",
            "codec_type": "audio",
            "codec_time_base": "1/44100",
            "codec_tag_string": "[0][0][0][0]",
            "codec_tag": "0x0000",
            "sample_fmt": "fltp",
            "sample_rate": "44100",
            "channels": 2,
            "channel_layout": "stereo",
            "bits_per_sample": 0,
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/14112000",
            "start_pts": 353600,
            "start_time": "0.025057",
            "duration_ts": 7566336000,
            "duration": "536.163265",
            "bit_rate": "192000",
            "disposition": {
                "default": 0,
                "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": {
                "encoder": "Lavc57.64"
            }
        }
    ],
    "format": {
        "filename": "November Rain.mp3",
        "nb_streams": 1,
        "nb_programs": 0,
        "format_name": "mp3",
        "format_long_name": "MP2/3 (MPEG audio layer 2/3)",
        "start_time": "0.025057",
        "duration": "536.163265",
        "size": "12868682",
        "bit_rate": "192011",
        "probe_score": 51,
        "tags": {
            "major_brand": "dash",
            "minor_version": "0",
            "compatible_brands": "iso6mp41",
            "encoder": "Lavf57.56.101"
        }
    }
}

In case that you don't want to extract this information from the output of the command, you may store that information as well inside a file redirecting the output:

ffprobe -v quiet -print_format json -show_format -show_streams myinputfile.mp3 > output_file.json

Of course, depending on your needs you may need as well to log errors or display more information on the files. You can check the official documentation of ffprobe in order to add new options to your command to catch errors or information that may appear with other extra options. For example:

ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams -show_programs -show_chapters -show_private_data -print_format json <input-file.{mp3,mp4,mkv,avi}>

That would output for example from an MP4 video:

{
    "programs": [

    ],
    "streams": [
        {
            "index": 0,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "High",
            "codec_type": "video",
            "codec_time_base": "1001/120000",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 3840,
            "height": 2160,
            "coded_width": 3840,
            "coded_height": 2160,
            "closed_captions": 0,
            "has_b_frames": 0,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "16:9",
            "pix_fmt": "yuv420p",
            "level": 52,
            "chroma_location": "left",
            "refs": 1,
            "is_avc": "true",
            "nal_length_size": "4",
            "r_frame_rate": "60000/1001",
            "avg_frame_rate": "60000/1001",
            "time_base": "1/60000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 12018006,
            "duration": "200.300100",
            "bit_rate": "9024217",
            "bits_per_raw_sample": "8",
            "nb_frames": "12006",
            "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": "2021-01-01T18:10:32.000000Z",
                "language": "eng",
                "handler_name": "Mainconcept MP4 Video Media Handler",
                "encoder": "AVC Coding"
            }
        },
        {
            "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": 0,
            "start_time": "0.000000",
            "duration_ts": 9614336,
            "duration": "200.298667",
            "bit_rate": "189465",
            "max_bit_rate": "340123",
            "nb_frames": "9389",
            "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": "2021-01-01T18:10:32.000000Z",
                "language": "eng",
                "handler_name": "Mainconcept MP4 Sound Media Handler"
            }
        }
    ],
    "chapters": [

    ],
    "format": {
        "filename": "how-to-fix-windows-10-issue-that-displays-internal-sata-connected-ssd-hdd-as-removable.mp4",
        "nb_streams": 2,
        "nb_programs": 0,
        "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
        "format_long_name": "QuickTime / MOV",
        "start_time": "0.000000",
        "duration": "200.300100",
        "size": "230790875",
        "bit_rate": "9217803",
        "probe_score": 100,
        "tags": {
            "major_brand": "mp42",
            "minor_version": "0",
            "compatible_brands": "isommp42",
            "creation_time": "2021-01-01T18:10:30.000000Z"
        }
    }
}

Happy coding ❤️!

This could interest you

Become a more social person