FFmpeg’s concat demuxer can play a podcast playlist in sequence, but its text script does not reconcile incompatible streams, codecs or time bases. Check and, where necessary, normalize your episodes before relying on the playlist for a long YouTube Live broadcast.
The method is most useful when the files already have matching stream layouts and technical properties, and you want FFmpeg to read them in order without re-encoding. If they differ, prepare compatible versions first or use a workflow that re-encodes them; a playlist alone cannot fix them.
What the concat demuxer does
The concat demuxer presents a sequence of media files as one virtual input. You write a plain-text script naming each file, and FFmpeg reads the packets from one file after another. That makes it useful for an ordered podcast rotation: an introduction, several recorded episodes, and perhaps a closing segment.
The script is not an editing timeline and does not convert the contents. It does not resize video, change an audio sample rate, add a missing audio track, or make different codecs match. FFmpeg’s concat demuxer documentation says the files must have the same streams, codecs and time bases. Treat that as a condition to check, not a problem the playlist will solve for you.
There are several FFmpeg approaches with similar names. The concat demuxer is a packet-level virtual input; the concat filter joins decoded streams and can be used when re-encoding; and the concat protocol joins data at the file level, with different restrictions. They are not interchangeable. The FFmpeg FAQ on concatenation explains the distinction between demuxer and filter approaches.
If all episodes already match and avoiding a generation of re-encoding matters, the demuxer is a reasonable starting point. If the source recordings came from different editors, export settings or recording devices, allow time for a preparation stage. A successful FFmpeg run is not by itself proof that every transition will look or sound right, or that YouTube will receive a stable stream.
Check stream, codec and time-base compatibility
Inspect every episode before composing the playlist. ffprobe is FFmpeg’s companion tool for reporting streams and media properties. For an individual file, a useful first inspection is:
ffprobe -v error -show_streams -show_format episode-01.mp4
Repeat it for the files you intend to join. Compare whether each has video, audio, or both; the order and number of streams; video and audio codecs; pixel dimensions and frame rates; audio sample rate and channel layout; and the reported time bases. The demuxer’s core requirement is matching streams, codecs and time bases. Other differences, such as resolution or channel layout, are also signals to test carefully and may call for a normalized output profile rather than stream copy.
| What to compare | Why it matters | What to do if it differs |
|---|---|---|
| Stream count and order | The virtual input expects corresponding streams across files. | Add or remove streams in prepared copies so the set and order match. |
| Video and audio codecs | The demuxer does not turn one codec into another. | Transcode to a common video and audio codec. |
| Time bases and timestamps | Packet timing is chained from one file to the next. | Prepare consistent outputs and test transitions; investigate timestamp warnings. |
| Dimensions and frame rate | A YouTube output profile should behave consistently across the sequence. | Scale and set a common frame rate during preparation if needed. |
| Audio sample rate and layout | A transition between stereo, mono or differing rates can expose discontinuities. | Resample and map audio to the layout you intend to deliver. |
| Duration accuracy | FFmpeg uses file durations when shifting later timestamps. | Check unusual durations and consider an explicit duration only when verified. |
For example, an episode exported as H.264 video with AAC stereo audio is not automatically interchangeable with an audio-only MP3 episode, even if both are podcast content. Decide whether the live programme needs a visual slate on audio-only portions, then make prepared files with the same stream arrangement. You cannot add that slate by listing the MP3 beside an MP4.
Time bases and durations deserve particular attention in a long sequence. The demuxer shifts timestamps so that later files follow the previous file according to its duration. If a reported duration is inaccurate, later timing can be wrong and an apparent gap or artifact may occur. An explicit duration directive can override a file’s reported duration, but it should be based on checked media timing rather than guesswork.
Normalize or transcode incompatible episodes
When files do not meet the compatibility checks, make normalized intermediate files before building the playlist. Choose a common output profile for the programme: for example, one video codec, one audio codec, one frame size and frame rate, and one audio sample rate and channel layout. The right profile depends on the source material and the encoder you can run; it is not a universal preset.
A basic re-encoding command for a video episode might look like this, with output settings adjusted to your material and FFmpeg build:
ffmpeg -i episode-source.mp4 \
-vf "scale=1280:720,fps=30" \
-c:v libx264 -c:a aac -ar 44100 -ac 2 \
episode-normalized.mp4
This is an example of a preparation pattern, not a promise that every source will fit without adjustment. Check the output with ffprobe. If a source has no audio or no video, decide how to create the missing stream, such as a consistent still or slate and silence, before joining it with files that have both. A simple transcode command cannot infer editorial intent.
The trade-off is time and quality. Re-encoding takes processing time and another encode can affect picture or sound, while stream copy preserves the encoded packets but cannot harmonize incompatible inputs. If you need to join sources that differ and re-encoding is acceptable, the concat filter is another route because it operates on decoded streams. It requires an explicit plan for matching frame sizes, timestamps and audio, then encoding the result. Do a short test before preparing a very long programme.
Keep the original recordings separate from the normalized copies. Use clear names, such as episode-01-source.mp4 and episode-01-normalized.mp4, and make the playlist refer only to the copies you have inspected. That reduces the chance of silently replacing a source or mixing prepared and unprepared episodes.
Write the concat playlist script
Create a UTF-8 plain-text file named, for example, playlist.ffconcat. The header must be the first line exactly as shown for FFmpeg to recognise the format automatically; do not put a blank line or byte-order mark before it.
ffconcat version 1.0
file 'episode-01-normalized.mp4'
file 'episode-02-normalized.mp4'
file 'episode-03-normalized.mp4'
Each file line identifies the next input. Relative paths are convenient if the playlist and media files are kept together, but FFmpeg resolves them relative to the process’s working directory. Run the command from a known directory or use paths you have checked. Spaces and special characters need to be represented using the concat script’s quoting and escaping rules; for a first test, simple filenames make errors easier to spot.
The demuxer enables its safe option by default. A filename or path outside its accepted safe form may be rejected. The option -safe 0 relaxes that check, which is why examples often include it, but do not use it as a reflex. Use it only with a playlist and files you control and trust. A script that points to arbitrary paths is not something to run casually.
You can add a duration line after a file entry when the source duration reported by FFmpeg is known to be wrong and you have checked the correct value. The directive affects timestamp placement for following material; it is not a trimming command. If the list needs accurate seeking across the virtual sequence, explicit durations for every file may be useful, but they must be reliable. First try the playlist without overrides and inspect any timing problem rather than inserting estimated values.
Run FFmpeg with the playlist input
For an initial local test, send the sequence to a file or a local playback target before adding YouTube credentials. A minimal invocation is:
ffmpeg -f concat -safe 0 -i playlist.ffconcat -c copy test-output.mkv
Here -f concat selects the demuxer and -i supplies its script. -safe 0 is shown only if your controlled paths require it. -c copy avoids re-encoding, but it is suitable only when the inputs and output container are compatible. It does not bypass the demuxer’s matching-stream requirements. If FFmpeg reports stream or timestamp errors, stop and resolve those rather than assuming the output is sound.
For a YouTube-bound output, encoding to a consistent profile can be simpler to reason about than copying a mix of source packets. This illustrative pattern reads the playlist in real time and encodes H.264 video and AAC audio:
ffmpeg -re -f concat -safe 0 -i playlist.ffconcat \
-c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k \
-r 30 -g 60 -c:a aac -b:a 128k -ar 44100 \
-f flv "$YOUTUBE_INGEST_URL/$STREAM_KEY"
The values are an example, not a universal bitrate recommendation or a tested guarantee. In this example, a GOP of 60 frames at 30 frames per second illustrates a two-second keyframe interval. YouTube’s current encoder settings and bitrate guidance varies by codec, resolution and frame rate. Its page lists 5 Mbps minimum and 14 Mbps recommended for H.264 at 1080p30, and recommends a two-second keyframe interval, not exceeding four seconds. Check that current table and select settings for your actual output and available upload capacity.
The command’s options before -i describe the input, while options after it configure output. -re asks FFmpeg to read at native rate rather than sending a file as fast as possible. The final -f flv selects the streaming muxer; the destination is the ingest address and stream key provided in YouTube Live Control Room. Check the FFmpeg build for the selected encoder and test the exact command with representative files before scheduling a public event.
Connect FFmpeg output to YouTube Live
In YouTube Live Control Room, create or select the intended live stream and copy the ingest URL and stream key shown for it. YouTube recommends RTMPS, the secure form of RTMP; use the secure endpoint supplied in the current interface. You can read YouTube’s encoder setup instructions for the current steps and platform controls.
Treat the stream key like a password. Do not publish it in a tutorial screenshot, source repository or command copied into a shared document. The shell example uses environment-variable placeholders so the key is not literally embedded in the article; those placeholders do not create credentials. Set them in a private environment or enter the destination through a method appropriate to your operating system. If a key is exposed, reset it in YouTube rather than assuming nobody has seen it.
The YouTube stream’s privacy, scheduling and auto-start or auto-stop settings are separate from FFmpeg’s concat options. Decide whether the broadcast is private or public, whether it is scheduled, and how you intend to end it. Review those controls in Live Control Room; FFmpeg sending packets does not set them on your behalf.
For a channel you need to leave running while your computer is off, consider where the FFmpeg process will operate and how you will notice and recover from a disconnect. A local laptop depends on its power, network and sleep settings. The folder-of-videos FFmpeg guide for Ubuntu Server explores a different operating arrangement, while the recorded-video rotation guide covers the continuity problem from a playlist perspective. StreamNeo addresses the specific burden of keeping a prepared file broadcast running after your own computer is off: it takes an uploaded video and runs it as a YouTube live stream, with monitoring and restart if the broadcast drops.
Preflight the sequence and stream health
Do not test only the first few seconds of the first file. A clean opening can hide a failed transition, missing audio in a later episode or a duration error that shifts timestamps. Start FFmpeg with the exact playlist and output profile you plan to use, then inspect the transitions that are most likely to differ: the first join, the longest file, and any episode with a different source history.
Use this preflight sequence:
- Record the FFmpeg version with
ffmpeg -version, then inspect each source and prepared file withffprobe. - Check the playlist header, entry order, spelling and path resolution from the directory where FFmpeg will run.
- Test both stream-copy and encoding only if the chosen method calls for them; read warnings rather than treating a zero exit code as a quality check.
- Listen across transitions for silence, clipped starts, channel changes or an abrupt change in loudness. Watch for a frozen frame, black gap or unexpected change in framing.
- Confirm the upload connection can sustain the selected output bitrate with practical headroom for network variation.
- Open the encoder preview in Live Control Room and verify that picture and audio arrive before starting the public event.
- Monitor YouTube’s stream-health messages during the broadcast, and keep the source playlist and media files available if recovery is needed.
YouTube recommends testing with audio and movement similar to the actual stream and watching stream health while live. A podcast with a static cover image is not a complete test if the real programme includes moving waveform graphics or video clips. Check the actual production pattern, including its audio level and transitions.
Keep a local master or backup of the final sequence. YouTube’s encoder setup guidance says streams under 12 hours are automatically archived, but verify current platform behaviour and account settings before treating that archive as your only copy. Archiving is a platform feature, not a substitute for retaining files you may need to correct or re-run.
A playlist test cannot guarantee that an internet connection, encoder or YouTube ingest will stay healthy overnight. It can catch avoidable input and transition problems before viewers encounter them. For more on rotating recorded material without a visible interruption, compare the considerations in a continuous recorded-showcase workflow.
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
Why does FFmpeg concat fail when my podcast episodes have different formats?
The concat demuxer expects corresponding streams, codecs and time bases across its files; it does not convert mismatches. Inspect the inputs with ffprobe, then prepare normalized copies or use a concat-filter workflow that re-encodes where needed. Test the resulting sequence before sending it to YouTube.
Does the playlist script transcode the episodes?
No. It describes an ordered sequence of files for FFmpeg to read as a virtual input. Transcoding is a separate operation; use it to make incompatible episodes share a suitable output profile before relying on the demuxer.
Can I use -c copy for a YouTube podcast stream?
Possibly, if the files have compatible streams and codecs and the output is suitable for YouTube’s ingest expectations. Stream copy avoids re-encoding but cannot reconcile mixed assets. If you need to change codecs or output characteristics, encode a consistent output and check YouTube’s current settings guidance.
Does a successful FFmpeg command mean the stream is stable?
No. It confirms only that FFmpeg completed the operation it was given; it does not certify the transitions, upload connection or YouTube ingest. Preview the feed in Live Control Room, check picture and audio, and monitor stream health during the event.