By ChatGPT & Benji Asperheim | 2025-06-19Blog Thumbnail

Customize FFprobe Metadata Output as JSON

If you've worked with media files on the command line, you're probably familiar with FFmpeg. But not everyone knows about its quieter, metadata-loving sibling: ffprobe.

In this article, you'll learn how to:

  • Use ffprobe to extract structured metadata from video and image files
  • Suppress the noisy banner output
  • Format the output as JSON
  • Use jq to extract just the fields you care about
  • Wrap all of this in a Bash function for clean, reusable scripting

What Is 'ffprobe' (and How Is It Different from 'ffmpeg')?

While ffmpeg is designed for media processing — transcoding, muxing, filtering, and converting — ffprobe is designed purely for analyzing media files. It gives you detailed information about formats, streams, codecs, resolution, colorspace, framerate, and embedded metadata.

| Tool | Purpose |

| --------- | --------------------------------------- |

| ffmpeg | Edit, convert, stream, and encode media |

| ffprobe | Inspect media metadata only |

Think of ffprobe as the ffmpeg version of exiftool for video, audio, and image containers.

Key ffprobe Flags You Should Know

Here are a few of the most essential ffprobe flags:

| Flag | Purpose |

| -------------------- | ---------------------------------------------------------------- |

| -v quiet | Suppresses log output (like progress info) |

| -hide_banner | Hides the FFmpeg build/version info |

| -print_format json | Outputs the metadata in JSON format |

| -show_format | Displays container-level metadata (like format name, tags, etc.) |

| -show_streams | Displays stream-level metadata (video/audio/image details) |

You can combine these like so:

ffprobe -v quiet -hide_banner -print_format json -show_format -show_streams myfile.avif

Why JSON? Why jq?

JSON is machine- and human-readable, and using tools like jq you can programmatically filter or extract exactly the data you need — no regex hacks, no fragile greps.

Here's how you can extract just the video codec and resolution of the first stream:

ffprobe -v quiet -hide_banner -print_format json \
  -show_streams myfile.avif | jq '.streams[0] | {codec_name, width, height}'

It should output something like this JSON:

{
  "codec_name": "av1",
  "width": 1170,
  "height": 659
}

Example: Extract Useful AVIF Metadata

Let's say you're working with .avif images and just want:

  • The container format
  • The "compatible_brands" tag
  • Key per-stream info like codec_name, pix_fmt, and resolution

Here's a raw one-liner (no Bash function yet):

ffprobe -v quiet -print_format json -show_format -show_streams -hide_banner duluth-childhood.avif |
  jq '{
    filename: .format.filename,
    format: .format.format_long_name,
    compatible_brands: .format.tags.compatible_brands,
    streams: [.streams[] | {
      index,
      codec_name,
      pix_fmt,
      width,
      height,
      color_space,
      color_range,
      color_transfer
    }]
  }'

This outputs a clean, color-coded JSON summary:

{
  "filename": "duluth-childhood.avif",
  "format": "QuickTime / MOV",
  "compatible_brands": "avifmif1miaf",
  "streams": [
    {
      "index": 0,
      "codec_name": "av1",
      "pix_fmt": "yuv420p",
      "width": 1170,
      "height": 659,
      "color_space": "smpte170m",
      "color_range": "pc",
      "color_transfer": "iec61966-2-1"
    },
    {
      "index": 1,
      "codec_name": "av1",
      "pix_fmt": "gray",
      "width": 1170,
      "height": 659,
      "color_space": null,
      "color_range": "pc",
      "color_transfer": null
    }
  ]
}

Add a Bash Function for Reuse

You can drop this into your ~/.profile, ~/.zshrc, ~/.bashrc, or ~/.zprofile to create a permanent helper function:

ffprobe_json() {
  local file_path="$1"

  if [[ -z "$file_path" ]]; then
    echo "Usage: ffprobe_json <media-file>" >&2
    return 1
  fi

  ffprobe -v quiet -print_format json -show_format -show_streams -hide_banner "$file_path" |
    jq '{
      filename: .format.filename,
      format: .format.format_long_name,
      compatible_brands: .format.tags.compatible_brands,
      streams: [.streams[] | {
        index,
        codec_name,
        pix_fmt,
        width,
        height,
        color_space,
        color_range,
        color_transfer
      }]
    }'
}

Then you can use it like:

ffprobe_json duluth-childhood.avif

Conclusion

With ffprobe, structured media introspection is just a command away. By suppressing verbose banners and leveraging JSON output, you can cleanly extract metadata for automation, reporting, or debugging. Pair it with jq and a few reusable functions in your shell, and you've got a powerful CLI toolkit for working with AVIF, MP4, and virtually any other multimedia format.

Discover expert insights and tutorials on adaptive software development, Python, DevOps, creating website builders, and more at Learn Programming. Elevate your coding skills today!