Keep the playlist items as separate, ordered files until you have chosen how to join them. If their streams are compatible, FFmpeg’s concat demuxer can join them without re-encoding and create one chapter per file; if they are not, use a re-encoding workflow and handle chapter metadata deliberately.
Do not assume a successful join means the chapters will appear in every player. Check the finished file’s chapter table and test chapter navigation in the application where you plan to use it.
Keep playlist videos separate and ordered
The first job is not encoding. It is preserving which item came first, which came next, and which downloads belong to the playlist. Keep every downloaded item separate until you have checked the list and settled on the output method. Joining too early makes a missing or misplaced segment harder to spot and can leave you with no simple way to retry one failed download.
Use filenames that record the playlist index as well as a readable title. yt-dlp supports output templates, including fields for playlist index and title; see its output-template and playlist options when setting up a download. A filename such as 003 - Morning Bhajan.mp4 is easier to inspect than a series of titles with no explicit sequence. The index is a useful label, not proof that every expected item downloaded: compare the files with the playlist or your saved manifest before joining.
For a long download, keep a record of completed items. yt-dlp’s download archive can help it skip items already downloaded on a later run. Preserve the source files, the ordered file list, and the command you used together, rather than relying on a terminal history that may be lost. This is a recovery arrangement, not a promise that every interrupted job will resume without checking.
Playlist download and playlist concatenation are separate choices. yt-dlp’s --concat-playlist can concatenate downloads under documented conditions, but its project notes that the files need matching codecs and numbers of streams. Do not treat that switch as a guarantee of the single master file and per-item chapter table you intend to make. If you need explicit chapter creation and a verifiable FFmpeg output, download separate items and control the join yourself.
A playlist that contains a mix of music videos, still-image tracks, or different source formats may not behave like one uniform file. Make the decision using actual stream information rather than titles or file extensions. If this playlist will feed an ongoing YouTube channel, the separate-file discipline also makes it easier to replace a single item later. It is a different problem from keeping a live broadcast running; for that, the practical choices in switching videos automatically in OBS concern playback scheduling rather than preparing a joined master.
Inspect streams before choosing a join
The concat demuxer is the efficient path only when the inputs have compatible stream layouts, codecs, and time bases. In practical terms, check that files have the same kinds of streams in the same arrangement and that their formats are suitable for a direct join. Two files that both end in .mp4 can still differ in ways that matter; matching extensions alone is not a compatibility test.
Use ffprobe to inspect each file’s streams, codec names, dimensions, audio properties, time bases, and duration. You can examine a sample with a command such as:
ffprobe -v error -show_streams -show_format "001 - Opening.mp4"
Repeat this for the other items, or save the output and compare it. Pay attention to missing audio, extra subtitle or data streams, differing resolutions, and variable or unknown duration information. If you find a mismatch, do not force a stream-copy join and hope the result is clean. Choose a common output profile and use a concat-filter workflow that re-encodes instead.
The trade-off is straightforward. A compatible demuxer join avoids another lossy generation and generally asks less of the computer, but it depends on matching inputs and reliable durations. A concat filter with re-encoding can normalise varied inputs to a chosen resolution, frame rate, codec, and audio layout, but takes more processing time and may reduce quality. There is no generic runtime estimate that applies to every playlist; duration, resolution, codecs, settings, and hardware all affect it.
FFmpeg’s concat demuxer documentation describes the file-list approach, its compatibility expectations, and chapter_per_file. Its FAQ on concatenating media distinguishes the demuxer route from the concat-filter route when re-encoding is needed. Read those pages alongside your own probe results rather than choosing on the basis of a filename or a tutorial command copied from a different set of sources.
Build an ordered concat demuxer list
When inspection says the inputs are compatible, make a text manifest with one file line per item, in playlist order. For example:
ffconcat version 1.0
file '001 - Opening.mp4'
file '002 - Morning Bhajan.mp4'
file '003 - Closing.mp4'
Keep the manifest beside the source files and output. Review it as a human-readable checklist: first item, last item, any gaps in the playlist indexes, and any duplicate entries. The concat demuxer processes the entries in the order given, not the order you intended when downloading. Alphabetical order can put item 10 before item 2 if names do not use a stable index format, which is one reason to inspect the manifest explicitly.
Names with quotes, backslashes, or unusual characters need escaping according to concat-script syntax. Relative paths and a manifest in a controlled working directory reduce ambiguity. The demuxer’s safe-path behaviour is enabled by default; safe=0 permits arbitrary paths, so only use it with a list you control and have checked. Do not use it as a reflexive fix for a manifest that points somewhere unexpected.
A basic stream-copy join with per-file chapters can be invoked like this, subject to the installed FFmpeg build and the actual inputs:
ffmpeg -f concat -chapter_per_file 1 -i inputs.ffconcat -map 0 -c copy joined.mkv
Treat this as a pattern, not a universal command. Check the output container’s chapter support and adjust stream selection if your files carry tracks you do not want. If the command reports stream or timestamp issues, return to compatibility and duration checks rather than assuming the warning is harmless.
Duration accuracy matters. The demuxer uses segment durations to offset later timestamps and form chapter boundaries. FFmpeg warns that an inaccurate duration can shift following timestamps and lead to gaps or artefacts. Unknown duration information can make reliable boundary calculation impossible for the affected entry. Check the probe output and, if necessary, provide accurate duration information in the concat list as documented by FFmpeg. Do not invent a duration to make the manifest look complete.
Add one chapter per file with chapter_per_file
The concat demuxer’s chapter_per_file option creates a chapter for each input file. Its chapter name comes from the file’s title metadata when available and otherwise from the filename. This is useful when one playlist item should correspond to one navigable chapter in the master. A descriptive filename can therefore give you a useful fallback title, but check the resulting names instead of relying on that fallback blindly.
The option belongs to the concat demuxer, so it is relevant to the compatible-input workflow above. It is not a general promise that every join, filter, or re-encode will create the same chapter table. If you are using the concat filter or another workflow, plan the chapter source and boundary times explicitly.
Chapter starts are cumulative. If the first file runs for 12 minutes and the next runs for 18 minutes, the second chapter should begin after the first segment ends, and the third after both have ended. Those figures are only an illustration of addition, not a recommended segment length. Use measured or otherwise reliable segment durations, and verify boundaries against the actual joined output. A wrong duration can cause chapter starts to drift away from the content they are meant to identify.
If the first file has embedded chapters, consider whether those are the chapters you want. The concat option creates a chapter per file, while FFmpeg’s normal chapter mapping can also carry chapter data from an input. Avoid mixing assumptions about per-file chapters and copied source chapters. Decide whether your goal is one chapter per playlist item, detailed chapters already present within an item, or a custom table, then inspect what the output contains.
Re-encode incompatible inputs and handle chapter metadata
When codecs, stream layouts, or time bases differ, use a concat-filter workflow and encode to one consistent output profile. This lets you choose a common resolution, frame rate, video codec, and audio layout rather than trying to stream-copy incompatible material. The filter route is more demanding and can introduce another lossy generation, so keep the originals until the output has been checked.
A re-encode does not by itself mean chapter metadata is lost. FFmpeg normally maps chapters from the first input that contains chapters. The -map_chapters option lets you select a chapter source explicitly; a negative input index disables chapter copying. Consult the FFmpeg documentation for chapter mapping and metadata and be specific when there is any ambiguity about which input supplies the chapter table.
That default behaviour is distinct from creating one new chapter for every playlist item. If the inputs have no useful chapters, or you want one chapter for each joined segment, calculate the cumulative boundaries and author them. Do not expect the concat filter to infer the intended playlist-item table merely because it received several inputs. Likewise, do not assume existing chapters in the first input describe the boundaries of the whole concatenated programme.
FFmpeg’s FFMETADATA format can carry explicit chapters. A metadata file begins with ;FFMETADATA and can include a [CHAPTER] section with a time base, start, end, and title, for example:
;FFMETADATA1
[CHAPTER]
TIMEBASE=1/1000
START=0
END=720000
title=Opening
[CHAPTER]
TIMEBASE=1/1000
START=720000
END=1800000
title=Morning Bhajan
The example uses millisecond units and illustrative boundaries only. Your values must match the actual joined programme. For each chapter, keep start and end values coherent, non-overlapping, and aligned with the intended segment. If the joined file has been filtered or its durations have changed, calculate against the encoded output timeline rather than blindly reusing source durations.
Map the metadata or chapter source into the output as appropriate for your command, and verify the outcome. Chapter mapping and global metadata mapping are related but distinct; specifying one mapping can affect automatic mapping of that kind. Keep a copy of the metadata file and the command alongside the output so you can adjust a title or boundary without reconstructing the whole job.
The workflow below is useful when an uploaded video needs a single, deliberate chapter table before it becomes part of a continuous channel. If running FFmpeg through the night is the recurring operational burden rather than preparing the file itself, StreamNeo removes that specific need to leave your own computer running for a file-based YouTube live broadcast. It does not replace the work of preparing and checking the video or its chapter data.
Check the output chapter table
After the join or encode finishes, inspect the output rather than inferring success from a zero exit status. Use ffprobe to show chapters and streams:
ffprobe -v error -show_chapters -show_streams -show_format joined.mkv
Review each chapter’s start, end, and title. Confirm that the first chapter starts where intended, later boundaries follow the segment order, and the final end does not cut off the last item. Compare the table against your manifest and duration notes. A chapter named after a filename may be technically present but unhelpful to a viewer, so check spelling and make titles meaningful.
Also inspect the actual stream inventory and total duration. An output can have the expected chapter count but still have a missing audio stream, an unexpected subtitle track, a truncated ending, or a timestamp problem. Play the beginning, a transition between representative items, and the end in a media player. Seek directly to chapters and confirm that navigation lands near the expected content.
Container support and player presentation are separate from FFmpeg’s internal chapter data. A file may contain chapter entries while a particular player does not display a chapter menu, or may present names differently. Test the file in the target application or upload workflow and check its current documentation before treating chapters as visible to viewers. Do not describe chapter data as automatically preserved in every container, concat, or re-encode route.
Keep the verified output separate from temporary or partial files. Retain the originals, manifest, metadata file if used, and command log until you have watched enough of the result to be confident it is the intended master. If you need to revise a chapter, the manifest and metadata let you audit which source item and boundary it came from. For creators preparing a recorded class or study loop, setting video quality for a recorded YouTube stream is a separate decision from chapter encoding, but both benefit from testing the actual file before a long broadcast.
For a devotional playlist assembled from audio files rather than existing videos, the source preparation differs; see the 24/7 Kannada songs stream workflow. In either case, an ordered input record and a final playback check are more useful than assuming the exported file matches the playlist.
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 chapter_per_file work with any FFmpeg concat method?
No. It is an option for the concat demuxer’s compatible-input workflow, not a blanket feature of every concat filter or re-encode. If you use another method, define or select the chapter source deliberately and inspect the output table.
Will a re-encode remove all existing chapters?
Not necessarily. FFmpeg normally maps chapters from the first input that contains them, and -map_chapters can choose a source or disable chapter copying. Check the chosen input’s chapters and the output, especially when you want new playlist-item boundaries rather than the first file’s original chapters.
Why are chapter times wrong after a concat?
A common cause is inaccurate or unknown segment durations. The demuxer uses durations to offset later timestamps and set boundaries, so bad values can shift following content. Compare the output table and playback transitions with reliable durations, then correct the source duration information or author chapter boundaries explicitly.
Do chapter markers always appear on YouTube or in every player?
No universal display behaviour should be assumed. Verify that the output contains chapters, then test the target player or upload workflow and consult current official documentation for its supported behaviour. A successful FFmpeg encode alone does not establish that every interface will expose chapter navigation.