FFmpeg Formats: Inspect, Join and Preserve Media Safely
You will finish with a small, repeatable workflow for FFmpeg formats: identify whether a format can be read or written, join compatible files with the concat demuxer, inspect probing behaviour, and export and restore metadata. The examples target FFmpeg 8.0.1, the version installed on this machine. Allow about 20 minutes, plus the time needed to copy your own media files.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the ffmpeg and ffprobe commands, input files you are allowed to read, and enough free space for any output. These commands run as an ordinary user. Do not use sudo unless your input is deliberately protected by filesystem permissions; elevated privileges do not fix an incompatible format.
1. Check the installed build and its formats
Start by recording the version and checking the tool that will do the work:
$ ffmpeg -version | sed -n '1p'
ffmpeg version 8.0.1 ...
$ command -v ffmpeg ffprobe
/home/linuxbrew/.linuxbrew/bin/ffmpeg
/home/linuxbrew/.linuxbrew/bin/ffprobe
The exact path and build flags may differ. FFmpeg calls the reader for a container or stream a demuxer, and the writer a muxer. The combined list marks them separately: D means demuxing is enabled, E means muxing is enabled, and d means the entry is a device.
$ ffmpeg -formats | grep -E '(^| )(D| E| DE).*(matroska|mp4|concat|ffmetadata)'
D concat Virtual concatenation script demuxer
DE matroska,webm Matroska / WebM
DE mp4 MP4 (MPEG-4 Part 14)
DE ffmetadata FFmpeg metadata in text
Your descriptions and spacing can vary. Use ffmpeg -demuxers or ffmpeg -muxers when you need one side of the list. A filename extension normally lets FFmpeg select an output muxer, but the extension is not proof that the installed build supports it.
Checkpoint
Before building a command, confirm that the desired input has a D entry and the desired output has an E entry. If either is absent, stop and choose another build or format.
2. Inspect a file before changing it
Use ffprobe to see the streams and container without producing output:
$ ffprobe -hide_banner -i INPUT.mkv
Input #0, matroska,webm, from 'INPUT.mkv':
Duration: 00:00:42.00, start: 0.000000, bitrate: ...
Stream #0:0: Video: ...
Stream #0:1: Audio: ...
Replace INPUT.mkv with a real path. The codec, time base, stream count and duration matter when you are going to join files. Do not infer compatibility from matching filenames or extensions.
FFmpeg analyses input data to discover streams. The generic input option -probesize defaults to 5,000,000 bytes and must be at least 32. Increasing it can find information that is spread further into a stream, but it also increases analysis latency. -analyzeduration defaults to 5,000,000 microseconds, or five seconds, and has the same accuracy-versus-latency trade-off.
$ ffprobe -hide_banner -probesize 10000000 -analyzeduration 10000000 -i INPUT.ts
Input #0, mpegts, from 'INPUT.ts': ...
These options are for a troublesome input, not a universal performance tweak. Start with the defaults and change one value at a time. A larger probe does not repair damaged timestamps or make a codec available.
3. Join compatible files with the concat demuxer
The concat demuxer presents several files as one virtual input. The files must have the same streams, codecs and time bases. Create a list whose first line is exactly ffconcat version 1.0:
$ mkdir -p ~/ffmpeg-work
$ cd ~/ffmpeg-work
$ cat > inputs.ffconcat
ffconcat version 1.0
file part-01.mkv
file part-02.mkv
^D
$ ffmpeg -f concat -safe 1 -i inputs.ffconcat -map 0 -c copy joined.mkv
The cat command ends when you press Ctrl-D on an empty line. Use a text editor instead if that is clearer. With -c copy, FFmpeg remuxes packets without re-encoding, so it is fast and does not improve the source quality. If the files are not genuinely compatible, expect an error, timestamp problems or a visibly broken result.
-safe 1 is the concat demuxer's default. It accepts relative paths made from portable characters and rejects protocol specifications and unsafe components. Keep it enabled for lists you did not write yourself. An absolute path or a name containing unusual characters may require -safe 0, but that broadens what the list can open. Treat the list as executable input, review every line, and never pass an untrusted list to a privileged process.
Verify the result before replacing anything:
$ ffprobe -v error -show_entries format=duration:stream=index,codec_name,codec_type -of default=noprint_wrappers=1 joined.mkv
index=0
codec_name=...
codec_type=video
duration=...
$ test -s joined.mkv && echo 'joined output exists'
joined output exists
The duration can expose a bad source estimate. The concat documentation allows a duration line after each file line to override a missing or inaccurate duration, and supplying durations for every file makes seeking through the virtual input possible. Measure or obtain those values first; do not guess them.
Warning
Writing joined.mkv can overwrite an existing file. Choose a new output name or check it first with test ! -e joined.mkv. To undo this example, delete only the output you created after checking its path: rm -- joined.mkv. The source files and list are not modified.
4. Export and restore metadata
FFmpeg's ffmetadata muxer writes a UTF-8, INI-like text file. Export it before editing:
$ ffmpeg -i INPUT.mkv -map_metadata 0 -f ffmetadata metadata.ffmeta
$ sed -n '1,20p' metadata.ffmeta
;FFMETADATA1
title=...
artist=...
The format uses key=value lines, with optional [STREAM] and [CHAPTER] sections. Characters such as =, semicolon, hash, backslash and newline must be escaped with a backslash. Whitespace is data, so title = name does not mean the same key as title=name.
Edit a copy, keep the header, and then create a new media file. This preserves the original as a rollback:
$ cp -- metadata.ffmeta metadata-edited.ffmeta
$ ffmpeg -i INPUT.mkv -i metadata-edited.ffmeta -map 0 -map_metadata 1 -c copy OUTPUT.mkv
$ ffprobe -v error -show_entries format_tags=title,artist -of default=nw=1 OUTPUT.mkv
Container support determines which tags can be stored, so verify the output rather than assuming every field survived. If the new file is wrong, remove OUTPUT.mkv and keep INPUT.mkv unchanged.
Done means
- You checked the installed FFmpeg version and the
D/Estatus of the formats you need. - You inspected streams before attempting a join.
- You used a reviewed concat list with compatible files and left
-safe 1enabled where possible. - You verified output duration, streams and metadata before replacing a source.
- You know that probing changes discovery time, not media compatibility.