If the videos in your playlist have different frame rates, use a decode, filter and re-encode pipeline when you need one dependable output cadence. Do not expect -re or packet-copy concatenation to fix the difference: -re controls reading speed, while the concat demuxer has strict matching requirements.
The practical method is to inspect every file, decide whether the output should be constant or variable frame rate, normalise the video and audio, then pace the finished input in real time for YouTube Live. The examples below assume you already have local files, permission to retransmit them, and an FFmpeg build that supports the options shown.
Choose the right way to join the files
There are two different FFmpeg approaches to joining a playlist. The concat demuxer joins packets from a sequence of files and can work with stream copying. The concat filter decodes the inputs, joins them as frames and audio samples, and normally re-encodes the result.
That distinction matters when one file is 25 fps, another is 30 fps, and a third is 29.97 fps. A packet-copy join does not inspect and rebuild every frame to create a new common cadence. It expects the files to have matching stream properties, including the relevant codecs, stream layout and time bases. FFmpeg’s concat demuxer documentation also explains that file durations are used to advance timestamps, so inaccurate duration metadata can create transition artefacts or gaps.
The concat filter is the more useful starting point when the files differ in frame rate, dimensions, pixel format, audio layout or other stream properties. It gives you a place to scale, pad, convert, resample and set the output timing before the final encode. The cost is additional processing and another generation of encoding.
| Method | Use it when | Main trade-off |
|---|---|---|
| Concat filter and re-encode | The files have different frame rates or other stream properties, or the output needs normalisation | More CPU or GPU work and one more encode generation, but much more control |
| Concat demuxer and stream copy | The files have matching streams, codecs, time bases and compatible timing | Little processing, but strict compatibility and more risk at transitions |
| Constant frame rate output | Your delivery pipeline needs one regular cadence | Frames can be duplicated or dropped to reach the selected rate |
| Variable frame rate output | Preserving each source’s timestamp pattern is more important than one fixed cadence | The receiving pipeline and playback devices must handle changing timestamps correctly |
A useful related decision is whether FFmpeg or a visual tool suits your workflow. The FFmpeg or OBS comparison for 24/7 YouTube streaming explains where command-line control helps and where a graphical workflow may be easier to operate.
Use the demuxer only after checking the files, not simply because -c copy looks faster. If the clips are first re-encoded into common stream properties, a later packet-copy join may become practical. Even then, inspect the result at every boundary.
Inspect the playlist inputs and their frame rates
Before writing a filter graph, make a small inventory of the playlist. The ordered list might be a text file, a shell variable or a script-generated sequence, but FFmpeg cannot infer your editorial intent. It also cannot solve playlist access, authentication, DRM or rights questions for you. Work with media files that you have supplied to the pipeline.
For a first look at one file, run:
ffprobe -hide_banner -i clip-01.mp4
For a more compact machine-readable summary, use:
ffprobe -v error \
-show_entries stream=index,codec_type,codec_name,width,height,pix_fmt,avg_frame_rate,r_frame_rate,time_base,duration \
-show_entries format=duration \
-of json clip-01.mp4
Repeat this for each file, or have a small script collect the results. Record at least these properties:
- video width and height
- video codec and pixel format
- average and nominal frame rate
- time base and duration
- audio codec, sample rate, channel layout and duration
- whether every file actually contains an audio stream
Do not focus only on the displayed fps. Two files can both say 30 fps while differing in dimensions, pixel format, time base or audio layout. Conversely, different nominal rates do not automatically mean every source must be permanently converted before you decide what the live output should be.
For example, you might find a 25 fps devotional clip at 1920×1080, a 30 fps title card at 1280×720, and a 29.97 fps ambience loop with stereo audio. The output decision could be a constant 30 fps stream with the smaller video scaled and padded, or a variable-rate result that retains more of the source timing. Those are different delivery choices, not merely different command syntax.
Check audio at the same time. The concat filter expects a consistent set of streams for each segment. A playlist in which some files have stereo audio and others have no audio needs an explicit policy. You can add silence to silent clips, create a consistent audio stream during preprocessing, or split the playlist into groups that share the same layout. The illustrative filter below assumes every input has one compatible audio stream.
Do not use the upload guidance for a different purpose. YouTube’s video upload encoding recommendations discuss preserving the recorded frame rate for uploaded content. That does not establish that a mixed-frame-rate live playlist must retain each source cadence unchanged.
Normalise clips with a decode, filter and encode pipeline
When mixed inputs need one controlled result, decode each file, apply the same video and audio treatment, concatenate the filtered streams, and encode the output. FFmpeg’s FAQ recommends the concat filter when re-encoding is needed.
Here is an illustrative two-file pattern. It assumes both files contain one video stream and one audio stream, and that the intended output is 1280×720 video with stereo audio. It is not a universal command: the number of inputs, stream mappings, aspect-ratio policy and audio treatment must match your actual files.
ffmpeg -i clip-01.mp4 -i clip-02.mp4 \
-filter_complex "\
[0:v]scale=1280:720:force_original_aspect_ratio=decrease,\
pad=1280:720:(ow-iw)/2:(oh-ih)/2,\
format=yuv420p,setsar=1[v0];\
[1:v]scale=1280:720:force_original_aspect_ratio=decrease,\
pad=1280:720:(ow-iw)/2:(oh-ih)/2,\
format=yuv420p,setsar=1[v1];\
[0:a]aformat=sample_rates=48000:channel_layouts=stereo[a0];\
[1:a]aformat=sample_rates=48000:channel_layouts=stereo[a1];\
[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-c:v libx264 -c:a aac \
-fps_mode cfr -r 30 \
-pix_fmt yuv420p -ar 48000 -ac 2 \
normalised.mp4
The scale and pad stages make the geometry consistent without cropping the source. If cropping is preferable for your channel, change that policy deliberately rather than copying these dimensions. format=yuv420p creates a common pixel format for a broad range of playback paths, while setsar=1 removes an unwanted sample-aspect-ratio difference.
The audio stages are equally important. They make the example’s sample rate and channel layout explicit, but they do not create audio where none exists. If a clip has no audio stream, [1:a] cannot be produced. Add a silent audio source for that segment, preprocess the clip, or use a generated filter graph that handles both cases. Do not quietly assume that every file has the same stream layout.
The concat=n=2:v=1:a=1 part is tied to two video and two audio segments. For a longer playlist, generate the labels and segment count from the actual manifest rather than hand-editing a very long command. That also reduces the chance of mapping a clip’s audio to the wrong video.
A second decision is the output cadence. In this example, -fps_mode cfr -r 30 asks FFmpeg to produce a constant 30 fps output. FFmpeg’s stream selection and frame-rate mode documentation describes constant frame rate mode as duplicating or dropping frames to reach the requested cadence. That can make downstream delivery more predictable, but it is not free: a 25 fps source may receive repeated frames, while a source with a higher cadence may lose frames.
The alternative is a variable frame rate policy. With -fps_mode vfr, FFmpeg uses frame timestamps and avoids creating duplicate timestamps, subject to the input and filter graph. With passthrough, demuxer timestamps are retained. These modes can preserve more of the source timing, but you must test the resulting timestamps and confirm that the live destination behaves as expected.
Choose one policy for the output after inspecting the material. Do not force every source to a common recorded frame rate merely because their displayed rates differ, and do not describe -re as a frame-rate converter. Frame-rate conversion is done by the filtering and output timing stages, not by real-time input pacing.
Set the output cadence and live ingest settings
Once the media has been normalised, build the live output around the selected cadence. A common H.264 and AAC pattern might look like this:
ffmpeg -re -i normalised.mp4 \
-c:v libx264 -preset medium -pix_fmt yuv420p \
-r 30 -fps_mode cfr \
-b:v 4500k -maxrate 4500k -bufsize 9000k \
-g 60 -keyint_min 60 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-f flv "rtmps://YOUR_INGEST_URL/YOUR_STREAM_KEY"
Treat the bitrate in that command as an example placeholder, not a recommendation for every resolution. YouTube’s live encoder settings list RTMP or RTMPS, supported video codecs, audio codecs, frame-rate guidance and bitrate ranges by output choice. As listed on YouTube’s site in September 2026, its live guidance supports output up to 60 fps and recommends a two-second keyframe frequency that should not exceed four seconds. Check the current page before choosing the resolution, codec and bitrate for your channel.
The example’s -g 60 corresponds to a two-second GOP at 30 fps. If you choose another output cadence, derive the GOP from that cadence instead of copying the number. Your available upload connection also needs room for the selected video and audio bitrate, plus normal network variation. A generic bitrate cannot guarantee a healthy ingest.
YouTube lists H.264, H.265 and AV1 among supported live video codecs as listed on its site in September 2026, but support alone does not make every codec the easiest choice for your particular FFmpeg build, computer or workflow. H.264 with AAC is a straightforward baseline for the illustrative RTMP or RTMPS command. Confirm the destination URL and stream settings in YouTube Live Control Room, and keep the stream key private.
If you are running a devotional, local information or ambience channel overnight, the encode is only one part of reliability. The input files need predictable timestamps, the output needs a deliberate cadence, and the network needs enough sustained upload capacity. A guide to making a 24/7 YouTube live stream from pre-recorded videos covers the broader operational decisions around a file-based channel.
For a local FFmpeg process, you will also need a plan for failures. A dropped network connection, a corrupt source file or a process that exits at the end of the input can stop the broadcast. If your concern is an unattended channel rather than a one-off test, read the practical advice on fixing a church YouTube live stream that keeps disconnecting in India, including the distinction between an encoding problem and an internet problem.
Pace file input in real time with -re
A local file normally reads as quickly as the computer can decode it. That is useful when creating an output file, but it is not the behaviour you want when sending a file to a live ingest endpoint. Put -re before the relevant input so FFmpeg reads it at approximately its native playback rate:
ffmpeg -re -i normalised.mp4 ...
FFmpeg’s command-line documentation describes -re as reading the input at its native frame rate and equates it with -readrate 1. It is an input option, so its position matters when a command has several inputs. Apply it to the file input that is intended to feed the live output.
-re does not change 25 fps into 30 fps, make variable frame rate material constant, or repair a timestamp discontinuity. The filter graph and output frame-rate policy do that work. If the normalised file is 30 fps, -re paces that 30 fps file; it does not decide that cadence for you.
There is a trade-off when using -re with complex inputs. If decoding or filtering cannot keep up with the requested pace, FFmpeg may fall behind. Watch the console output and the receiving platform rather than assuming that a successful process means a healthy broadcast. Conversely, omitting -re can make the file arrive much faster than real time, which is unsuitable for an ordinary live playlist.
For a sequence of files, decide where concatenation occurs. You can first create a normalised playlist file and then pace that single output, or build a filter graph that reads the source files and sends the joined result directly to the live muxer. The latter is convenient for a short, known list; the former is usually easier to inspect, resume and test.
If you need to change the programme while a channel is already running, do not treat a live file swap as a simple frame-rate issue. The guide to changing the video on an active 24/7 YouTube live stream addresses the operational side of making a controlled change.
When the repeated work is mainly keeping a file-based YouTube broadcast running while your own computer is switched off, StreamNeo removes the local process, real-time pacing and overnight restart work after you upload the file and provide the YouTube stream key. It remains your responsibility to check that you have permission to use the material and that the prepared file behaves as intended.
Validate transitions and stream health
Do not judge the pipeline only by watching the first minute. Mixed-frame-rate problems often appear at the boundary between clips, where timestamps, audio duration or geometry change.
Start with a short test containing the hardest transitions: a 25 fps clip into a 30 fps clip, a clip with a different resolution, a quiet audio section after a loud one, and any file that was previously reported as having unusual duration metadata. Check the normalised file with ffprobe, then play it from slightly before each transition.
Look for these symptoms:
- a visible pause, jump or repeated image at the cut
- audio that leads or trails the video after a transition
- a sudden aspect-ratio change or stretched picture
- silence, crackle or a channel-layout change
- video that runs faster or slower than the intended programme
- timestamps that stop advancing or move backwards
- the output ending earlier than the expected combined duration
You can inspect packet and frame timestamps with a focused probe, for example:
ffprobe -v error -select_streams v:0 \
-show_frames -show_entries frame=best_effort_timestamp_time,pkt_duration_time \
-of csv normalised.mp4
You do not need to read every row by hand. Look around the transition and confirm that timestamps continue forward and frame durations are plausible. Also inspect audio timestamps if the transition appears out of sync. A file with a misleading duration can be especially troublesome for the concat demuxer because later timestamps are based on the declared duration.
Then test the actual live route with a private or otherwise appropriate YouTube broadcast. Use representative movement and audio, not only a static title card. YouTube recommends testing before the event with audio and movement similar to the planned stream, and monitoring stream health during the event. Its stream health guidance should be checked for the current indicators and troubleshooting steps.
Watch both FFmpeg’s console and Live Control Room. On the local side, check whether encoding falls behind or reports repeated timestamp warnings. On YouTube’s side, check whether the incoming stream remains connected and whether the reported health changes when a difficult clip begins. A clean local command does not prove that the ingest connection or destination is healthy.
If the test fails, change one variable at a time. First verify the source and audio layout, then simplify the filter graph, then confirm the output cadence, and only afterwards adjust bitrate or encoder speed. Changing the frame rate, resolution and bitrate simultaneously makes it difficult to know which change helped.
A constant frame rate can make delivery easier to reason about, but it cannot conceal a bad source. If frames are dropped or duplicated in a way that creates visible judder, try another output cadence that suits the majority of the playlist, or retain variable timing if the destination and your tests support it. The correct choice depends on the files and the delivery path, not on a universal preset.
Keep the workflow repeatable overnight
Write down the assumptions behind the working command: input dimensions, audio presence, selected output cadence, encoder, bitrate range, GOP calculation and destination protocol. Store the stream key outside the command file where possible, and do not put it into screenshots, public scripts or support posts.
For a longer playlist, generate a report before encoding. Flag files with missing audio, unusual dimensions, a different pixel format, very short duration, or a frame rate outside the intended output plan. A small amount of preparation is easier than diagnosing a failed transition after the channel has been live for several hours.
Keep the original media and the normalised copies separate. If you later choose a different cadence, you can regenerate the output without losing the source. Name the normalised file with its dimensions and frame-rate policy, such as playlist-720p-cfr30.mp4, so that the command’s assumptions are visible.
Finally, rehearse the restart path. Start the stream with a short representative file, stop it cleanly, reconnect it, and observe what happens when the network is briefly unavailable. If you are operating from a home connection in India or elsewhere, test at the time of day when the channel will normally run. A pipeline that works at midday may still need a different operational plan overnight.
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
Can FFmpeg combine videos with different frame rates?
Yes, but choose the method based on the stream properties and the output you need. The concat filter decodes and re-encodes, which lets you normalise geometry, audio and cadence. The concat demuxer can avoid re-encoding only when the files meet its stricter compatibility requirements.
Does -re convert 25 fps video to 30 fps?
No. -re paces input reading at approximately real time. Use the filter graph and an explicit output frame-rate policy such as constant frame rate mode when you need a chosen cadence.
Should I use constant or variable frame rate for YouTube Live?
Use constant frame rate when a regular delivery cadence makes your encoder and ingest path easier to test. Consider variable frame rate when retaining source timestamps is important and your complete playback path handles it, then test transitions and stream health with representative files.
Can I use -c copy for a mixed-frame-rate playlist?
Only after confirming that the files have compatible streams, codecs, time bases and timing. Different frame rates are a warning to inspect the inputs rather than proof that packet-copy concatenation will be safe, and inaccurate duration metadata can cause artefacts at boundaries.