To join gaming VOD files in a chosen order on Ubuntu, put their filenames in that order in an FFmpeg concat list, then run the concat demuxer. With compatible input streams, -c copy joins them without re-encoding; it does not make incompatible recordings compatible or start a YouTube livestream.
The practical distinction is between preparing one continuous output file and broadcasting that file. First confirm the files can be joined as-is, preserve the sequence explicitly, and check the result before deciding how you will send it to YouTube Live.
Check FFmpeg on Ubuntu
Open a terminal on the Ubuntu machine that holds the VOD files and check whether FFmpeg is available:
ffmpeg -version
If the shell reports that the command is not found, FFmpeg is not available through the current command path. You can install FFmpeg from the Ubuntu repositories using the system’s package manager, or use a build you trust. The precise package version and enabled codecs can vary with the Ubuntu release and repository state, so do not assume a particular build from this guide. After installation, rerun the version check and make sure the command completes.
This is a local file-processing workflow. It does not require a live YouTube stream key to make the joined file. Keep that key out of shell history, screenshots, and shared scripts when you later configure a broadcast. FFmpeg’s command-line documentation explains how its input and output options are applied; the placement of options matters in the commands below.
If you are planning a longer playlist rather than a single joined programme, consider whether the simplest arrangement is one output file or a repeatable schedule. For a separate scheduling pattern, see how to schedule multiple YouTube stream playlists with cron on Ubuntu. The concat recipe here is narrower: it turns a finite set of local files into one file in a specified sequence.
Prepare compatible VOD files
The concat demuxer is not a general-purpose repair tool. It expects the inputs to have the same streams, codecs, and time bases, among other compatibility details. Gaming recordings that look alike in a player can still differ because one session used a different encoder preset, resolution, frame rate, audio layout, or capture configuration.
Before building the list, put the files somewhere predictable and decide what the final order should be. You might name three sessions gameplay-01.mp4, gameplay-02.mp4, and gameplay-03.mp4, but filename numbering alone does not guarantee they are compatible. A list can specify sequence; it cannot reconcile incompatible video or audio streams.
Use FFmpeg’s probe output to inspect the inputs. For example:
ffprobe -hide_banner gameplay-01.mp4
ffprobe -hide_banner gameplay-02.mp4
Compare the stream details reported for each file, not just the container extension. Look for matching stream count and types, video and audio codecs, dimensions, frame-rate/time-base information, and any extra audio or subtitle tracks. The exact fields vary by input. If one recording has an extra audio track or a different stream configuration, do not assume -c copy will produce a clean joined result.
You can keep the work in a dedicated directory to simplify relative paths:
mkdir -p ~/vod-join
cd ~/vod-join
Copy or move the intended inputs there, or create the concat list with appropriate paths. Retain the originals until the output has been checked. If you need to standardise recordings rather than concatenate them unchanged, that is a different workflow and will generally require decoding and re-encoding. A filter-based workflow gives you control over output settings, but it also means choosing settings that fit the actual footage and audio rather than applying a universal command.
For a related issue in a live playlist context, the guide to making playlist videos consistent when resolutions differ explains why mixed media properties can cause trouble downstream. The same principle applies here: check the source properties before relying on a no-re-encode join.
Write the concat list in the intended order
Create a plain text file named vod-list.txt. Write one file entry per VOD, in exactly the order you want the joined output to play:
file 'gameplay-01.mp4'
file 'gameplay-02.mp4'
file 'gameplay-03.mp4'
The first line is the first segment, the second line follows it, and so on. The ordering is explicit, so you do not depend on a shell wildcard or on how filenames happen to sort. This is useful when recordings are named by date, map, or session rather than a clean sequence. Review the list before running FFmpeg; a reversed pair here becomes a reversed pair in the output.
If you are already in the directory containing the files, relative names are convenient. If the list is elsewhere, use paths that resolve from the working directory or use absolute paths. FFmpeg’s safe-path behaviour restricts which paths are accepted by default. For ordinary local filenames using portable characters, relative entries are the least surprising choice. For trusted files in locations or names that do not meet the safe-path rules, you may see a safety error; understand the path and the list before considering -safe 0. Do not turn off path checks for a list from an untrusted source.
Spaces in a filename need to be represented correctly in the concat file. A normal entry such as file 'Session one.mp4' is readable, but unusual apostrophes or other special characters require care with the list syntax. Rather than guess at escaping, rename the files to simple names or consult the concat demuxer documentation for its file syntax. This also makes the process easier to reproduce later.
Do not use a broad wildcard as a substitute for an intentional list unless you have confirmed its expanded order. A list is a small bit of editorial control: it records the sequence you meant, and it lets you audit what will be joined before processing.
Run the concat-demuxer command
With the list and inputs ready, run this from the directory containing them:
ffmpeg -f concat -i vod-list.txt -c copy joined.mp4
-f concat selects the concat demuxer, -i vod-list.txt supplies the ordered list, and -c copy asks FFmpeg to copy the encoded streams into the output rather than decode and re-encode them. The output filename follows the input options. If joined.mp4 already exists, FFmpeg will ask before overwriting in an interactive terminal; choose a new output name or deliberately allow an overwrite only when you are certain the existing file is no longer needed.
This is the short recipe, not a guarantee that every set of MP4 files can be joined. It is appropriate when the inputs meet the demuxer’s requirements and their streams can be copied into the chosen output container. It avoids a quality loss associated with re-encoding and is usually the more efficient route for compatible files. It also means you cannot use this command to resize, crop, change frame rate, add a filter, or repair a codec mismatch. Those operations act on decoded frames and require a different path.
If FFmpeg stops with a stream mismatch, do not keep changing flags at random. Inspect the files again and identify what differs. Then either make a compatible set of inputs before concatenation or use a filter-based re-encode designed for the relevant tracks and target format. FFmpeg’s FAQ on concatenating media files distinguishes the demuxer route from filter-based concatenation when re-encoding is needed.
The concat protocol is another option sometimes mentioned in discussions, but it is not interchangeable with this list-based method. It physically joins file data and only suits certain formats that support such concatenation. Ordinary MP4 or MKV gaming VODs should not be assumed to work by byte-joining them. For a playlist of typical recordings, use the demuxer list and check compatibility instead.
Verify the joined output
A successful command exit is useful, but it is not the only check. Inspect the output’s stream information and duration, then play it from the beginning and skip to the joins between segments. Confirm that the sequence is right, that picture and audio are present, and that transitions do not contain a freeze, abrupt audio change, or unexpected gap.
For a quick technical inspection:
ffprobe -hide_banner joined.mp4
Compare the reported streams with the source files. Then play the output in a media player. A joined file can be structurally readable while still revealing a timestamp or duration problem at a boundary. The concat demuxer uses each file’s duration to position the next; incorrect duration metadata, including from a truncated or damaged input, can create timestamp artefacts. If a boundary behaves oddly, check that source file and its reported duration before rebuilding the list. The demuxer supports a duration directive for overriding a file duration when you have a reliable value, but do not add guessed durations as a first fix.
Keep the original files and list alongside the verified output until you are satisfied with playback. That gives you a clear way to correct an ordering mistake or replace one damaged segment without having to reconstruct the source sequence from memory.
For a 24/7 channel, a single joined file may be only one component of a larger playlist or broadcast setup. If you are planning multiple outputs or feeds, first understand whether the intended workflow is one continuous YouTube stream or several scheduled streams; this guide on scheduling YouTube livestreams with multiple RTMP streams addresses the latter kind of planning. It does not change the file-joining requirement: verify each programme file before using it live.
Understand when stream copy fits
Stream copy is the right choice when you want to preserve the source streams as they are, the concat inputs are compatible, and the target container can represent the copied streams. It is not a quality setting; it is a way of avoiding a decoding and encoding pass. That saves processing and does not add a new generation of lossy encoding, but it also leaves you with the source’s existing characteristics.
| Situation | Likely route | What to expect |
|---|---|---|
| Same stream layout, codecs, and time bases; output container accepts them | Concat demuxer with -c copy |
Fast join without re-encoding, subject to verification |
| Inputs differ in resolution, codec, tracks, or other relevant stream properties | Inspect and normalise, or use a concat filter with re-encoding | More control, but requires choosing output settings and processing the media |
| You are considering byte-level joining of ordinary MP4 or MKV files | Do not assume the concat protocol will work | The protocol is format-specific and not a general VOD join method |
| File plays, but a join has a timing or audio issue | Check source durations and boundary behaviour | Incorrect duration metadata or damaged input may be involved |
A stream-copy command cannot add filters, and it may fail when the destination container needs information that is unavailable in a source stream. A superficially successful output should still be checked at the joins. If the files are from different recording sessions, compare them before deciding that a copy operation is safe for your intended playback.
When re-encoding is necessary, there is no universal safe command for every gaming VOD set. The right filter graph and output settings depend on whether you have video only or audio, how many tracks exist, and what differences need normalising. A command copied from another channel might silently discard an audio track or produce an unsuitable output. Inspect first, select the output format and stream layout deliberately, then test a short segment before processing the full programme.
Send the output to a YouTube Live workflow
The command above creates joined.mp4; it does not initiate a broadcast. To stream the result, you need a separate YouTube Live workflow that supplies the encoded programme to the live endpoint using the appropriate ingest settings. YouTube’s official live streaming overview explains the platform’s live setup. Follow its current guidance for channel eligibility, stream configuration, and any account-specific requirements rather than relying on an old tutorial.
A local FFmpeg broadcast generally needs a live input or loop strategy, an encoder/output configuration, and a network connection that can sustain the chosen stream. The concat command alone handles none of those. Do not paste a stream key into an example that will be saved publicly or shared; treat it as a credential and use the official YouTube setup flow to obtain and manage it.
If your aim is a channel that continues while your Ubuntu desktop is off, the local concat operation does not provide that continuity. StreamNeo can remove the specific burden of leaving your computer running after you have prepared a suitable video: upload the file, provide your YouTube stream key, and the file runs as a YouTube Live broadcast without your own computer staying on. It is YouTube-only, so it is not a substitute if you need to broadcast to another platform. You still need to prepare and check the file, and you should review YouTube’s current rules for the content and channel.
Before committing, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.
FAQ
Does the concat list control the playback order?
Yes. FFmpeg follows the order of the file entries in the list, so put the intended first segment at the top and review the list before running the command. Do not rely on wildcard sorting unless you have checked the resulting order.
Can I use -c copy with any gaming VOD files?
No. The concat demuxer expects compatible streams, including matching codecs and time bases, and the output container must support the copied streams. Compare the inputs first; use a re-encoding workflow if they need normalising.
Does this command start a YouTube livestream?
No. It creates a joined local output file. A separate live workflow must send media to YouTube, using the current platform guidance and a properly protected stream key.
What should I do if FFmpeg reports a duration or timestamp problem?
Check the affected source file and the join in the output, especially if a file is truncated or has incorrect duration metadata. The concat demuxer can accept an explicit duration when you know a reliable value, but fixing or replacing a damaged input may be the better answer.