本文へ移動
cccskills
無料GitHub で公開

ffprobe-cli

Read a media file's real structure with ffprobe through media_run - the JSON invocation and how to read it, what every family of field means, how to count frames, sample without decoding everything, detect HDR and interlacing, and diagnose a missing duration, a stream with no frames or a container that lies. Covers when media_probe's own report is already enough.

インストール方法を見る

含まれるファイル(2)

  • SKILL.md11.3 KB
  • reference/fields.md16.2 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Reading media with ffprobe

ffprobe answers questions about a file's header and its packets without decoding it. That makes it cheap and safe on a damaged or huge file, and it makes its answers statements about what the container claims: it will report a stream with zero frames, a duration of N/A, and a frame rate the file does not actually deliver, because those are the facts it has.

Run it through media_run with binary: "ffprobe". args is an array, and ffprobe gets none of the flags ffmpeg gets - no -n, no -nostdin, no -hide_banner. The wrapper still applies the timeout (120 s default, 600 s maximum), the output cap, and the cwd (the conversation workspace unless you name one).

The invocation worth memorising

{ "binary": "ffprobe",
  "args": ["-v","error","-print_format","json","-show_format","-show_streams","-show_chapters","-show_error","clip.mp4"] }

-v error keeps the answer JSON rather than JSON behind a warning; -print_format json (-of json is the same option) gives one parseable object instead of one key=value line per field; and each -show_* adds a section - format the container, streams every stream, chapters the chapters, error a structured error when there is one.

This is exactly what media_probe runs, which is the first thing to know: if a report is enough, do not run ffprobe at all. Reach for a raw call for a field the report does not print, or a section it does not read (packets, frames, programs, -count_frames).

Pulling one value out

{ "binary": "ffprobe", "args": ["-v","error","-select_streams","v:0",
  "-show_entries","stream=width,height,r_frame_rate","-of","default=nw=1","clip.mp4"] }
width=640
height=480
r_frame_rate=30/1
  • -select_streams v:0 reads only the first video stream; a = audio, s = subtitle, 0 = stream index 0.
  • -show_entries takes section=field,field pairs: stream=codec_name,profile, format=duration,bit_rate, stream_tags=language to reach a nested object.
  • -of default=nw=1 sets the default writer with noprint_wrappers (no section header); nokey=1 drops the key= half and leaves the value. They are independent, and nokey alone still prints [STREAM]/[/STREAM] wrappers - use nw=1:nk=1 for bare values, -of csv=p=0 for one per line, or -of compact=p=0:nk=1 for one space-free key=value line per stream.
  • Beware a section that prints events: asking for side_data=rotation with no -select_streams and no other restriction can bring back packets_and_frames too.

What the fields mean

Container. format_name is ffprobe's family list: mov,mp4,m4a,3gp,3g2,mj2 is the ISO-BMFF family, matroska,webm is MKV or WebM - which ffprobe cannot tell apart, so the extension is the tie-break, and that is why media_probe uses it. format_long_name is the human name. duration and bit_rate are the container's own claims, and start_time is its timeline origin - the number that explains a negative first-packet timestamp. probe_score (0-100) is ffprobe's confidence, and a high score on the wrong format is how a misnamed file gets accepted.

Video streams. codec_name (h264, hevc, vp9, mpeg4, png) is what to compare against a browser's decoders, with profile/level beside it. width and height are the coded pixels a decoder produces, which a rotation flag does not change. sample_aspect_ratio is the pixel shape (1:1 square, 32:27 anamorphic on 720x480) and display_aspect_ratio the shape a player shows (4:3 on 640x480, 16:9 on that anamorphic pair) - the pixels do not change, the DAR does, so a resize has to decide whether it means "look like the DAR". pix_fmt is yuv420p (universal), yuv420p10le (10-bit), yuv444p (many browsers draw black) or rgb24 (a PNG). r_frame_rate and avg_frame_rate are exact rationals - 30000/1001 is 29.97, 30/1 is exactly 30 - and r_frame_rate can be wrong on a raw elementary stream (a 30 fps H.264 dump read back as 60/1 on this host). field_order is progressive or tt/bb when interlaced. nb_frames is often absent, and N/A means "the header does not say", not "zero".

Audio streams. sample_rate (48000; a string in some builds and a number in others - read it as text), channels and channel_layout (2 / stereo, 1 / mono, 6 / 5.1 - the layout is what an encoder needs, channels alone is not enough), sample_fmt (fltp for AAC, s16 for PCM), bits_per_raw_sample (often absent; for PCM the depth is in codec_name, such as pcm_s16le).

Dispositions, tags, rotation. disposition is an object of 0/1 flags: default (what a player picks when nothing chooses), forced (show this subtitle even with subtitles off), comment, hearing_impaired, attached_pic (an embedded cover image, which is technically a video stream) and more. tags.language (eng, spa, und), tags.title, tags.handler_name. A hand-made MKV often has no language at all, which is not an error - it is a file that does not say. Rotation lives in side_data_list[].rotation, in degrees counter-clockwise (an iPhone's -90 is a clockwise 90° display rotation), and it is metadata, not pixels, so -c copy preserves it. Read it with -select_streams v:0 -show_entries "stream=width,height:side_data=rotation", which answers width=640, height=480, rotation=90.

Reading deeper when it matters

-count_frames decodes every frame, so on a two-hour file it is minutes of work - and the call has a timeout. On the 3-second fixture it returned nb_read_frames=90. -show_packets and -show_frames without a -read_intervals window print the whole file's packets, which is the one way to turn a small probing call enormous - always bound it:

["-v","error","-select_streams","v:0","-count_frames","-show_entries","stream=nb_read_frames","-of","default=nw=1","clip.mp4"]

%+#3 is "from the start, three items", %+3 a three-second window, 1:00%+10 a window starting at 1:00. flags=K__ on a packet means a keyframe. -read_intervals bounds packets; -skip_frame nokey is the option that makes a -show_frames walk decode keyframes only, and it does not filter a packet listing. HDR is color_transfer=smpte2084 (PQ, HDR10) or arib-std-b67 (HLG), with color_primaries=bt2020 and color_space=bt2020nc beside it; interlacing is anything but field_order=progressive; variable frame rate is avg_frame_rate differing from r_frame_rate. None of those colour fields appear in media_probe's report, which gives hevc (Main 10) · yuv420p10le (10-bit) and a transcode verdict instead.

reference/fields.md beside this file has the whole catalogue: every -show_* section with what it reads and what it costs, the container/codec/audio/subtitle/ attachment/side-data families in full, the working invocations with their measured output, and the long-form diagnosis. It also carries the three measurements a container does not give you - a bitrate from the packets, a frame count, and the proof that a file is really variable-rate - the transport-stream program/PID layer (-show_programs, which an MP4 simply does not have), and -show_data, which hexdumps the bytes behind a section so a stream's real configuration record can be read instead of assumed.

Diagnosing from the output alone

The five diagnoses worth knowing by heart:

  • duration=N/A with streams present means the container carries no duration
    • a raw .h264, a growing capture, a pipe - and media_probe says unknown on the same facts. Measure with -count_frames or -show_packets.
  • A stream with no frames at all is an empty track: a remux that dropped its packets, or a header written before the data. There is nothing to decode.
  • format_name=h264 with a nonsense r_frame_rate is a raw elementary stream: no container, no timestamps, no duration. Remux into MP4 before believing any timing.
  • An image reported as a one-frame video is a PNG/GIF/WebP - a video stream with no duration, which is exactly why media_probe gives it the image verdict instead of calling a PNG undecodable.
  • Only an audio stream, no video is an audio file: -select_streams v:0 returns nothing rather than an error, and the same is true in reverse.

reference/fields.md carries the rest of the table - a container that says one thing and holds another, a low probe_score, unreadable streams, and what an exit code of 1 with no output means.

media_probe first, ffprobe second

media_probe runs exactly the invocation at the top of this file and then translates the JSON: container, duration, bitrate, one line per stream with the dimensions, the exact rational frame rate and its decimal reading (30 fps (exact 30/1)), sample rate, channel layout, bit depth, rotation, language, title, disposition flags, and the chapters with their timestamps. It adds the one thing ffprobe cannot: a verdict on whether a Chrome/Firefox-class browser can play the file as it is - playable, image, remux or transcode - with the exact ffmpeg command that would fix a remux/transcode.

Use it first, always: it is cheap, it reads the header only, and it cannot fail on a damaged tail. Then:

  • If a field you need is missing from the report, call media_probe with raw: true - it appends ffprobe's own JSON under the report, one call instead of two.
  • Use a media_run ffprobe call for packets, frames, -count_frames, -read_intervals, -show_programs, and the colour/interlace fields, because those are not sections the report reads.
  • The report's browser verdict is an opinion about browser decoders. It says transcode for HEVC and nothing whatever about whether this host's ffmpeg can encode or decode HEVC - it very likely can. Do not read a browser verdict as a statement about ffmpeg, and do not read ffprobe's ability to read a codec as evidence a browser can play it. Nor does it know whether a technically playable file is watchable on the user's connection: a 40 Mb/s MP4 is decodable and still unwatchable.
  • A file media_probe cannot identify is a file ffprobe found no container in. Do not retry it with a longer timeout: re-check the path, and consider that a truncated download or a text file with a .mp4 name looks exactly like this.
  • When the question changes from reading to changing, this is the wrong skill. ffprobe never writes a byte: the moment the answer is a different container, a smaller file or a frame on disk, the work belongs to the ffmpeg-cli skill - whose own reference/failures.md (in that skill's folder, not this one) is also where to look when an action taken on a probe's answer fails.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Design a banner, social preview or poster from nothing: pick the destination preset, then the composition, then write the words, then apply ONE look - and prove it with canvas_audit before you render. Use when the person asks for a banner, an OG card, a social image, a README header, a poster or a launch card and no design exists yet.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

Design a canvas document the Canvas tab and the host both understand: the JSON language, the layout engine's sizing rules, the render report's codes, composition craft with numbers, copy budgets, and copy-paste recipes. A bundled reference carries every field and every validator code.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

Edit a house design instead of rewriting one: the twelve proven designs in canvas_read's gallery are all perfect, so start from one, keep its composition and its look, and change only what the person asked for - proving each round with canvas_audit and a look at the render. Use when the person asks to change, tweak, adjust, restyle or fix a banner that already exists, or asks for a new banner of a kind the gallery already carries.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

Drive ffmpeg through the media_run tool as an argv array - remux instead of re-encode, map streams explicitly, trim at keyframes, scale and crop, extract audio and frames, and build GIFs, contact sheets and concatenations. Covers the flags this pack injects, reading a failure from its exit code and last log lines, and the version-dependent spellings to hedge.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

Author Mermaid diagrams that parse the first time: choose the right diagram type for the question, write syntax the parser accepts, and keep the picture readable in a narrow panel. A bundled reference covers complex, large diagrams.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

Read and understand PDF documents with the pdf_* tools - inspect a document before reading it, extract text in reading order or as reconstructed layout, search a document without reading all of it, recognize scanned pages that have no text layer, and render pages as pictures. Covers scanned documents, chat attachments, page-range and character caps, and the read-only and untrusted-content rules.

日本語の概要は準備中です。原文の説明を表示しています。

vecnode/vncode82026年10月9日 更新

vecnode のスキルをすべて見る

このスキルの問題を報告する