| name | ffmpeg-playback |
| description | Preview and debug media with ffplay: quick A/V preview, filter-graph testing (-vf/-af), loudness meter (ebur128), AV-sync debug, seek/loop, show waveform/spectrum/vectorscope, pixel format overlay. Use when the user asks to preview a video, play back a file quickly, test a filter with live output, debug audio/video sync, inspect loudness visually, loop a clip, or scrub through frame-by-frame for QA.
|
| argument-hint | [input] |
Ffmpeg Playback
Context: $ARGUMENTS
Quick start
- Preview a file: Step 1 —
ffplay in.mp4
- Test a
-vf filter live without transcoding: Step 2
- Debug pixel format / SAR / frame info: Step 3
- Visualize audio (waveform / spectrum / loudness meter): Step 4
- Fix AV-sync drift: Step 3 (
-sync ext) + -vf setpts=PTS-STARTPTS
- Headless preview (no GUI): add
-nodisp -autoexit (audio only)
When to use
- User wants to eyeball a clip after a cut, filter, or encode (QA pass).
- User is iterating on a
-vf or -af chain and wants live feedback before running a full transcode.
- User needs visual AV diagnostics: waveform, spectrum, vectorscope, ebur128 loudness meter, or verbose logs to see pixel format / color range / SAR.
- User is debugging A/V drift, out-of-order PTS, or choppy playback.
Do NOT use for: long-term rendering (use ffmpeg-transcode), authoring filter chains to a file (use ffmpeg-video-filter / ffmpeg-audio-filter), inspecting metadata only (use ffmpeg-probe). ffplay is an interactive debug player — not a production media player.
Step 1 — Simple preview
ffplay in.mp4
ffplay -ss 60 -t 10 in.mp4
ffplay -autoexit in.mp4
ffplay -loop 0 in.mp4
ffplay -x 1280 -y 720 in.mp4
ffplay -an in.mp4
ffplay -vn in.mp4
ffplay -nodisp -autoexit in.mp4
-ss is ffplay's start-offset seek — it only accepts a single timestamp and goes before the input file on the command line. There is no "output-side" seek in ffplay.
Step 2 — Filter-graph test (live, no transcode)
Use ffplay to preview a filter you'll later apply with ffmpeg. No file is written.
ffplay -vf "scale=1280:-2,eq=brightness=0.1,unsharp=5:5:1.0" in.mp4
ffplay -af "loudnorm=I=-16:LRA=11:TP=-1.5" in.mp4
ffplay -vf "hqdn3d" -af "highpass=f=80" in.mp4
Press w during playback to cycle through / disable the video filter chain — useful for A/B comparison.
For complex graphs with multiple inputs, use -f lavfi with a source filter (movie=, amovie=) in a filtergraph:
ffplay -f lavfi "movie=in.mp4,split[a][b];[b]vflip[c];[a][c]hstack[out]"
When -f lavfi is used, the graph MUST terminate with labeled outputs. For combined audio+video use two sinks named [out0] (video) and [out1] (audio).
Step 3 — Debug mode: stats, pixel format, AV-sync
ffplay -stats in.mp4
ffplay -loglevel verbose in.mp4
AV-sync debugging. ffplay picks audio as the master clock by default. Swap masters to narrow down drift:
ffplay -sync audio in.mp4
ffplay -sync video in.mp4
ffplay -sync ext in.mp4
If you see monotonic drift, the fix is usually in a filter: prepend setpts=PTS-STARTPTS (video) and asetpts=PTS-STARTPTS (audio) to reset timestamps, or aresample=async=1 to soft-fix audio gaps.
Useful debug flags:
-framedrop — drop video frames if CPU can't keep up (on by default when sync source is not video).
-infbuf — unlimited demux buffer (for live/RTSP/slow sources).
-vf "showinfo" — log per-frame metadata (pts, pkt_pos, mean).
Step 4 — Visualize audio
ffplay can render audio as video via lavfi source filters (amovie=). The graph must end in [out0] (video) + [out1] (audio).
ffplay -f lavfi "amovie=in.mp3,asplit[a][w];[w]showwaves=s=1280x120:mode=cline[v];[a][v]concat=n=1:v=1:a=1[out0][out1]"
ffplay -f lavfi "amovie=in.mp3,showspectrum=s=1024x512:mode=combined:slide=scroll"
ffplay -f lavfi "amovie=in.mp3,ebur128=video=1:meter=18[out0][out1]"
ffplay -vf "split[a][b];[b]vectorscope=mode=color3[c];[a][c]overlay=W-w" in.mp4
ffplay -vf "split[a][b];[b]histogram[c];[a][c]hstack" in.mp4
Piped playback
ffplay reads stdin when the input is -:
ffmpeg -i in.mkv -c copy -f matroska - | ffplay -i -
ffmpeg -f lavfi -i testsrc=size=640x360:rate=30 -f mpegts - | ffplay -i -
Gotchas
- ffplay is a DEBUG player. There is no playlist, no UI for codec selection, no per-device audio routing. Do not ship it to end users.
- SDL2 is required. In headless SSH you get
Could not initialize SDL - No available video device. Fix: X-forward (ssh -Y), VNC, or add -nodisp for audio only. SDL_VIDEODRIVER=dummy lets ffplay start without a window but you also won't see any video — use -nodisp instead.
- macOS opens its own window (Cocoa). No menu bar — keyboard shortcuts only work when the ffplay window has focus. Click it first.
- Audio device isn't selectable via ffplay flags. Use SDL env vars:
SDL_AUDIODRIVER=coreaudio (mac) / alsa / pulse / dsp. To pick a specific device set AUDIODEV (OSS/ALSA) or configure PulseAudio default sink.
-f lavfi graphs MUST end in labeled outputs. For video+audio that's [out0] and [out1] — BOTH are required when using ebur128=video=1 or showwaves + concat with audio. Drop one label and you'll see Output pad "out1" ... not connected.
amovie / movie are lavfi source filters, not input flags. Use them INSIDE the -f lavfi graph string, not as -i.
-ss is a start offset, not an output-side seek. You cannot put -ss after an input or combine it with -to; use -t for duration.
- Exit status is not useful for automation. ffplay is interactive. Use
-autoexit to quit at EOF; use -nodisp to avoid needing a display. For CI/QA scripts, prefer ffmpeg with -f null - for filter validation.
-stats is on by default in newer builds — disable with -nostats if it clutters your log.
- High-DPI displays:
-x / -y are logical pixels on macOS/Wayland — the actual backing store is 2× on Retina.
Examples
Example 1 — Iterate on a color filter before a final encode
ffplay -vf "eq=contrast=1.1:brightness=0.05:saturation=1.1,unsharp=5:5:0.8" in.mp4
ffmpeg -i in.mp4 -vf "eq=contrast=1.1:brightness=0.05:saturation=1.1,unsharp=5:5:0.8" -c:a copy out.mp4
Example 2 — Is the audio too loud?
ffplay -f lavfi "amovie=mix.wav,ebur128=video=1:meter=18[out0][out1]"
Example 3 — AV is drifting after a concat
ffplay -sync ext concat_out.mp4
Example 4 — Preview an ffmpeg pipe without writing a file
ffmpeg -i in.mov -vf scale=640:-2 -c:v libx264 -preset ultrafast -f matroska - | ffplay -i -
Keyboard shortcuts (full table in references/commands.md)
Space / p — pause/play
s — step one frame forward
Left / Right — seek ±10s
Down / Up — seek ±1min
PgDown / PgUp — seek to previous/next chapter (or ±10min)
f — toggle fullscreen
w — cycle video filters (ffplay-only, for A/B)
a / v / t / c — cycle audio / video / subtitle / program stream
m — mute
9 / 0 — volume down / up
q / Esc — quit
- Left-click on video — seek to that horizontal position (% of duration)
- Right-click / drag — seek by percent
Available scripts
scripts/play.py — stdlib-only argparse wrapper around ffplay with subcommands: preview, filter-test, waveform, spectrum, vectorscope, loudness-meter, sync. Flags: --dry-run, --verbose. Prints the command before running, and downgrades to -nodisp when no DISPLAY is detected.
Workflow
python3 ${CLAUDE_SKILL_DIR}/scripts/play.py preview --input in.mp4 --start 60 --duration 10
python3 ${CLAUDE_SKILL_DIR}/scripts/play.py filter-test --input in.mp4 --vf "scale=1280:-2,eq=brightness=0.1"
python3 ${CLAUDE_SKILL_DIR}/scripts/play.py loudness-meter --input in.mp3
python3 ${CLAUDE_SKILL_DIR}/scripts/play.py sync --input in.mp4 --mode ext
Reference docs
- Read
references/commands.md for the full keyboard shortcut table, every ffplay flag, the lavfi visualization catalog, SDL audio env vars, pipe recipes, and headless troubleshooting.
Troubleshooting
Error: Could not initialize SDL - No available video device
Cause: no DISPLAY / Wayland / Quartz session (headless SSH, container, CI).
Solution: add -nodisp for audio-only; or X-forward with ssh -Y; or run under VNC/xvfb. SDL_VIDEODRIVER=dummy starts SDL but shows nothing — equivalent to -nodisp with extra steps.
Error: Output pad "out1" with type audio of the filtergraph is not connected to any destination
Cause: -f lavfi graph has only a video sink but the source (e.g. amovie) also produces audio, or you used ebur128=video=1 which emits both pads.
Solution: terminate with [out0][out1] and keep both audio + video, e.g. ...ebur128=video=1[out0][out1].
Error: Option 'ss' cannot be applied to output url
Cause: -ss placed after a -i or alongside -to. In ffplay, -ss is a global/input-side start offset only, given once.
Solution: ffplay -ss 60 -t 10 in.mp4 — -ss first, -i is implicit.
Video plays but audio is silent
Causes (in order): SDL audio driver mismatch, default output device muted, decoder can't produce planar format SDL wants.
Solution: set SDL_AUDIODRIVER=coreaudio (mac) / pulse / alsa; check system volume; re-run with -loglevel verbose and look for SDL_OpenAudioDevice errors.
AV out of sync on a file that plays fine in VLC
Cause: ffplay's default master clock is audio; if audio has gaps or VFR video has long frames, drift is visible.
Solution: -sync ext to use wall clock; or preprocess with setpts=PTS-STARTPTS + aresample=async=1.
Keyboard shortcuts do nothing
Cause: SDL window doesn't have focus, or terminal is capturing keys.
Solution: click the video window. On macOS, make sure a Terminal.app shortcut isn't swallowing the key.