Skip to content

Instantly share code, notes, and snippets.

@nrk
Created April 2, 2012 19:19
Show Gist options
  • Save nrk/2286511 to your computer and use it in GitHub Desktop.
Save nrk/2286511 to your computer and use it in GitHub Desktop.
Using ffprobe to get info from a file in a nice JSON format
ffprobe -v quiet -print_format json -show_format -show_streams "lolwut.mp4" > "lolwut.mp4.json"
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"codec_type": "video",
"codec_time_base": "1001/48000",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 1280,
"height": 720,
"has_b_frames": 0,
"pix_fmt": "yuv420p",
"level": 31,
"is_avc": "1",
"nal_length_size": "4",
"r_frame_rate": "35029/1461",
"avg_frame_rate": "35029/1461",
"time_base": "1/35029",
"start_time": "0.000000",
"duration": "1239.195267",
"bit_rate": "1782423",
"nb_frames": "29711",
"tags": {
"creation_time": "1970-01-01 00:00:00",
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "Advanced Audio Coding",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "s16",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_time": "0.000000",
"duration": "1239.059396",
"bit_rate": "127966",
"nb_frames": "58081",
"tags": {
"creation_time": "2012-04-01 15:42:28",
"language": "jpn",
"handler_name": "GPAC ISO Audio Handler"
}
}
],
"format": {
"filename": "lolwut.mp4",
"nb_streams": 2,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime/MPEG-4/Motion JPEG 2000 format",
"start_time": "0.000000",
"duration": "1239.195000",
"size": "296323860",
"bit_rate": "1913008",
"tags": {
"major_brand": "isom",
"minor_version": "1",
"compatible_brands": "isom",
"creation_time": "2012-04-01 15:42:24"
}
}
}
@reinaldo
Copy link

reinaldo commented Jun 6, 2013

Perfect :)

@emanuelgaspar
Copy link

This is just brilliant. Obrigado!

@GregIngelmo
Copy link

Awesome!

@dustinrjo
Copy link

sweet

@amalgamatedclyde
Copy link

soooo grateful!

@croespino
Copy link

Thanks!

@estabij
Copy link

estabij commented Nov 15, 2015

thanks

@hebertreis
Copy link

Great!

@kdresser
Copy link

Thank you!

@nasermirzaei89
Copy link

how can i get ID3v2 frames?

http://id3.org/id3v2.3.0

@TeamKitsune
Copy link

Thanks for this. Works for xml as well.

@mikkorantalainen
Copy link

I'd suggest

ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams -show_programs -show_chapters -show_private_data -print_format json

because that allows getting possible error messages as JSON, too. In addition, that allows getting more information about the file.

@Casxt
Copy link

Casxt commented Mar 5, 2019

I'd suggest

ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams -show_programs -show_chapters -show_private_data -print_format json

because that allows getting possible error messages as JSON, too. In addition, that allows getting more information about the file.

thanks!

@vamsigarla
Copy link

thanks bro...!

@jsmette
Copy link

jsmette commented Mar 3, 2020

Thanks !

@ToshY
Copy link

ToshY commented May 7, 2020

Thanks

@suyog711
Copy link

do we get the size in bytes using ffprobe?

@Xonshiz
Copy link

Xonshiz commented Sep 12, 2021

If you run the very first command mentioned in this gist, you'll see "size" key/property in the JSON result. It's already in bytes.

@chapmanjacobd
Copy link

ffprobe -loglevel quiet -sexagesimal -print_format json=compact=1 -show_entries error:stream:format

Copy link

ghost commented Jan 15, 2022

  • -select_streams "s" for just subtitles. -select_streams "s:0" for just the first subtitle (index is zero based).
  • -find_stream_info fill-in missing information by actually read the streams instead of just parsing the header(s). it helps with corrupted files. optionally add -probesize "10000000" and -analyzeduration "2000000" as well, for better results.
  • -pretty a more human-readable output (works with other print formats as well, some builds have this on by default for JSON). it helps to debug stuff in console.
  • 2>/dev/null (linux) or 2>nul (Windows. note: the nul missing last l is intentional) to speed up the command, if you don't need output to console at all. you can keep whatever loglevel you currently have.

@daiplusplus
Copy link

daiplusplus commented Mar 24, 2022

If anyone wants it, here's my quick-and-dirty Newtonsoft.Json-compatible C# class for ffprobe's -print_format json -show_format -show_streams output:

Usage: If you've got ffprobe's output in a String ffprobeJsonOutput then just do FFProbeJsonOutput? parsedOutput = JsonConvert.DeserializeObject<FFProbeJsonOutput>( ffprobeJsonOutput );.

Almost every member is marked nullable because I wasn't sure which JSON properties FFprobe will always return for all formats/codecs.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;

using Newtonsoft.Json;

namespace MyProject
{
	public class FFProbeJsonOutput
	{
		/// <summary>Information about the streams within the container.</summary>
		[JsonProperty("streams")]
		[SuppressMessage( "Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly" )]
		public List<FFProbeStream>? Streams { get; set; }

		/// <summary>Information about the container.</summary>
		[JsonProperty("format")]
		public FFProbeFormat? Format { get; set; }
	}

	public class FFProbeStream
	{
		[JsonProperty("index")]
		public Int32 Index { get; set; }

		[JsonProperty("codec_name")]
		public String? CodecName { get; set; }

		/// <summary>Values like &quot;H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10&quot;.</summary>
		[JsonProperty("codec_long_name")]
		public String? CodecLongName { get; set; }

		[JsonProperty("codec_type")]
		public String? CodecType { get; set; }

		/// <summary>Contains the FourCC of a video codec or the TwoCC of an audio codec - or another textual representation as FourCC/TwoCC is container-specific!</summary>
		[JsonProperty("codec_tag_string")]
		public String? CodecTag { get; set; }

		/// <summary>Codec/format-specific profile information, e.g. for AVC (H.264) this may be &quot;High&quot; but for AAC this may be &quot;LC&quot;.</summary>
		[JsonProperty("profile")]
		public String? Profile { get; set; }

		[JsonProperty("level")]
		public Int32? Level { get; set; }

		/// <summary>Only specified for Video streams.</summary>
		[JsonProperty("width")]
		public Int32? Width { get; set; }

		/// <summary>Only specified for Video streams.</summary>
		[JsonProperty("height")]
		public Int32? Height { get; set; }

		// Don't worry about `coded_width`/`coded_height`, that's for when a video codec requires the encoded video's dimensions to be a multiple of a block-size, but the video is still cropped to an arbitrary size (the `width`/`height`) when rendered.

		[JsonProperty("duration")]
		public Double? Duration { get; set; }

		/// <summary>Duration expressed in integer time-base units (https://video.stackexchange.com/questions/27546/difference-between-duration-ts-and-duration-in-ffprobe-output</summary>
		[JsonProperty("duration_ts")]
		public Int64? DurationTS { get; set; }

		/// <summary>Values like &quot;1/600&quot;. See https://stackoverflow.com/questions/43333542/what-is-video-timescale-timebase-or-timestamp-in-ffmpeg </summary>
		[JsonProperty("time_base")]
		public String? TimeBase { get; set; }

		/// <summary>Stream-specific tags/metadata. See <see cref="KnownFFProbeVideoStreamTags"/>.</summary>
		[SuppressMessage( "Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly" )]
		[JsonProperty("tags")]
		public Dictionary<String,String>? Tags { get; set; }
	}

	public class FFProbeFormat
	{
		[JsonProperty("filename")]
		public String? FileName { get; set; }

		[JsonProperty("nb_streams")]
		public Int32? NBStreams { get; set; }

		[JsonProperty("nb_programs")]
		public Int32? NBPrograms { get; set; }

		[JsonProperty("format_name")]
		public String? FormatName { get; set; }

		[JsonProperty("format_long_name")]
		public String? FormatLongName { get; set; }

		/// <summary>Approximate duration in seconds (it's approximate because videos can start *after* the 00:00:00 timecode, e.g. see this SO question with a video that starts at 0.04: https://superuser.com/questions/650291/how-to-get-video-duration-in-seconds ).</summary>
		[JsonProperty("duration")]
		public Double? Duration { get; set; }

		[JsonProperty("bit_rate")]
		public Int32? BitRate { get; set; }

		[JsonProperty("probe_score")]
		public Int32? ProbeScore { get; set; }

		/// <summary>Container and format tags/metadata, not stream-specific tags. See <see cref="KnownFFProbeFormatTags"/>.</summary>
		[SuppressMessage( "Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly" )]
		[JsonProperty("tags")]
		public Dictionary<String,String>? Tags { get; set; }
	}

	/// <summary>Known tag-names for <see cref="FFProbeStream"/>'s <see cref="FFProbeStream.Tags"/>.</summary>
	public static class KnownFFProbeVideoStreamTags
	{
		/// <summary>Tag value is a decimal integer value in degrees, e.g. &quot;90&quot;.</summary>
		public const String Rotate = "rotate";

		/// <summary>Tag value is ISO 8601 e.g. &quot;2020-04-21T15:22:51.000000Z&quot;.</summary>
		public const String CreationTime = "creation_time";

		/// <summary>Values like &quot;H.264&quot;.</summary>
		public const String Encoder = "encoder";
	}

	/// <summary>Known tag-names for <see cref="FFProbeFormat"/>'s <see cref="FFProbeFormat.Tags"/>.</summary>
	public static class KnownFFProbeFormatTags
	{
		/// <summary>MPEG-4 container &quot;brand&quot; identifier.</summary>
		public const String MajorBrand = "major_brand";

		/// <summary>Tag value is ISO 8601 e.g. &quot;2020-04-21T15:22:51.000000Z&quot;.</summary>
		public const String CreationTime = "creation_time";

		/// <summary>E.g. &quot;Apple&quot;.</summary>
		public const String AppleMake     = "com.apple.quicktime.make";

		/// <summary>E.g. &quot;iPhone 8 Plus&quot;.</summary>
		public const String AppleModel    = "com.apple.quicktime.model";

		/// <summary>I think this is the iOS/iPhone OS software version if it's from an iPhone, e.g. &quot;13.4.1&quot;.</summary>
		public const String AppleSoftware = "com.apple.quicktime.software";
	}

	public static class FFProbeOutputExtensions
	{
		public static FFProbeStream? GetFirstVideoStreamOrNull( this FFProbeJsonOutput json )
		{
			if( json.Streams != null )
			{
				return json.Streams.FirstOrDefault( s => "video".Equals( s.CodecType, StringComparison.OrdinalIgnoreCase ) );
			}
			else
			{
				return null;
			}
		}

		public static FFProbeStream? GetFirstAudioStreamOrNull( this FFProbeJsonOutput json )
		{
			if( json.Streams != null )
			{
				return json.Streams.FirstOrDefault( s => "audio".Equals( s.CodecType, StringComparison.OrdinalIgnoreCase ) );
			}
			else
			{
				return null;
			}
		}

		public static Int32? GetRotation( this FFProbeStream ffProbeStream )
		{
			if( ffProbeStream.Tags != null )
			{
				if( ffProbeStream.Tags.TryGetValue( KnownFFProbeVideoStreamTags.Rotate, value: out String? rotateTagValue ) )
				{
					if( Int32.TryParse( rotateTagValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Int32 rotateTagValueInt ) )
					{
						return rotateTagValueInt;
					}
				}
			}

			return null;
		}

		/// <summary>If the <see cref="FFProbeJsonOutput.Format"/> has a duration, that's returned - otherwise the first stream duration is returned. Returns null if none of the streams (nor the <see cref="FFProbeJsonOutput.Format"/>) has a duration value set.</summary>
		public static TimeSpan? GetDuration( this FFProbeJsonOutput ffProbeOutput )
		{
			if( ffProbeOutput.Format != null )
			{
				Double? d = ffProbeOutput.Format.Duration;
				if( d.HasValue )
				{
					return TimeSpan.FromSeconds( d.Value );
				}
			}

			if( ffProbeOutput.Streams != null )
			{
				foreach( FFProbeStream? stream in ffProbeOutput.Streams )
				{
					Double? d = stream?.Duration;
					if( d.HasValue )
					{
						return TimeSpan.FromSeconds( d.Value );
					}
				}
			}

			return null;
		}
	}
}

@duffxp
Copy link

duffxp commented May 6, 2022

Hello.

Great list! However, does anyone know how to find the duration of stream (HLS or MPEG-DASH) segments?

@daiplusplus
Copy link

daiplusplus commented Jun 8, 2022

@quintanaplaca I believe that information is in the .m3u8 file's #EXTINF tags, and not the segment blob (while a segment blob will have a duration, I think (though am uncertain) that clients will prefer timing data from the m3u8 file as that's more canonical.... or something. YMMV. IANAL. Etc.

To quote Apple: https://developer.apple.com/documentation/http_live_streaming/example_playlists_for_http_live_streaming/video_on_demand_playlist_construction (emphasis mine)

#EXTINF: A record marker that describes the media file identified by the URL that follows it. Each media file URL must be preceded by an EXTINF tag. This tag contains a duration attribute that's an integer or floating-point number in decimal positional notation that specifies the duration of the media segment in seconds. This value must be less than or equal to the target duration.

@duffxp
Copy link

duffxp commented Jun 10, 2022

@Jehoel, thank you for your reply. Really, you are right. I would like a way to analyze HLS and MPEG-DASH stream with FFmpeg (the segmentSize, segmentDuration) and check its integrity.

@irzhywau
Copy link

irzhywau commented Sep 7, 2023

is there a way to grab these informations using one of library provided by ffmpeg using C?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment