For a YouTube loop stream, constant frame rate (CFR) means producing video at one chosen frame cadence, such as 30 frames per second. In FFmpeg, looping a file, pacing it like a live source, and making its output CFR are separate jobs, so configure and test each deliberately.
The template below is a starting point, not a command guaranteed to work unchanged with every file or computer. Check the input, choose a cadence that suits the material, and confirm both the encoded output and YouTube ingest before relying on it overnight.
Understand the jobs each option performs
A file on disk can be read faster than its recorded duration. That is useful for conversion, but not for a live broadcast: the encoder should deliver the material at approximately the pace at which it would be watched. FFmpeg's -re reads input at its native rate, which is useful when sending a file as a live-style stream. It does not repeat the file and does not set the output frame rate.
-stream_loop -1 tells FFmpeg to repeat the input indefinitely. It addresses what happens when the file reaches its end, not how quickly frames are sent. A loop can still have variable frame timing unless you configure an output cadence.
CFR is that cadence: a specified number of frames per second over time. If a source has too many frames for the chosen rate, conversion can drop frames; if it has too few, conversion can duplicate them. The result has a regular output cadence, but that does not create new visual detail. A still devotional image, for example, may not benefit from being converted to a higher rate merely because the number is larger.
FFmpeg offers more than one place to express cadence. The fps video filter converts frames inside the filter graph. An output combination such as -fps_mode:v cfr -r:v 30 requests constant-rate output synchronisation at the chosen rate. The right choice depends on where you want conversion to happen and whether other filters are already in the chain. Pick one deliberate conversion point rather than stacking options without a reason.
The official FFmpeg documentation describes input looping, real-time reading, output frame-rate options and per-stream synchronisation. Its filter documentation covers the fps filter. Consult the documentation for the FFmpeg version installed on your system, especially if a command copied from an older guide uses -vsync: the current documentation marks that global option deprecated and describes -fps_mode as the per-stream alternative.
Prepare the file and choose a target rate
First decide what the stream is meant to look and sound like. Use the frame rate of the source and the movement in the content as starting points. A slideshow or slow ambience loop may not need the same cadence as a video with frequent movement. YouTube's live encoder guidance asks you to specify resolution, frame rate and bitrate in your encoder and lists rates up to 60 fps; that is an available range, not a recommendation to convert every file to its highest value.
Inspect the file before encoding. FFprobe, distributed with FFmpeg, can show video and audio streams as well as frame-rate metadata. For example:
ffprobe -v error -show_streams -of json loop.mp4
Look for the video stream's dimensions and its reported frame-rate fields. r_frame_rate and avg_frame_rate can help reveal an obvious mismatch, but metadata is not a full account of how smoothly the video plays. Files assembled from different clips, variable-frame-rate phone footage, and exports with unusual timestamps deserve a visual review as well.
Confirm that the file has the audio you intend to send. Some loops have no audio stream; others contain music or narration. The optional audio mapping in the template below allows the command to continue if no audio stream is present, but it cannot invent a soundtrack or correct an unsuitable track. If a video has several audio streams, decide which one should be used rather than assuming the first is right.
If you need to prepare a playlist rather than repeat one file, the workflow is different. The guide to streaming a pre-recorded video playlist with OBS covers that alternative. If you are specifically choosing a cadence for animated material, compare the considerations in choosing a YouTube Live frame rate for a pre-recorded animation loop.
Use a safe loop command template
This template separates the input-side jobs from the output cadence and leaves credentials visibly as placeholders:
ffmpeg -stream_loop -1 -re -i loop.mp4 \
-map 0:v:0 -map 0:a? \
-vf "fps=30" \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac \
-f flv "rtmp://a.rtmp.youtube.com/live2/STREAM_KEY"
Replace loop.mp4 with the path to your file and replace 30 with your intended frame rate. Replace the output address and STREAM_KEY with the connection details from your own YouTube Live setup; never publish a real key in a guide, screenshot, public command history, or support post. The address shown is a placeholder form, and you should check YouTube's current live setup instructions for the destination details that apply to your channel.
The input options come before -i because they apply to the input: -stream_loop -1 repeats that input and -re paces its reading. -map 0:v:0 selects the first video stream from input zero. -map 0:a? requests an audio stream when one exists, with the ? making the mapping optional. The output is encoded, rather than copied, so the video filter can alter the frame cadence.
This is a command shape, not a universal recipe. Your FFmpeg build may not include the named encoder, the input may have no usable video, or the file may require different handling. Paths with spaces need shell-appropriate quoting. Test the exact command in the environment where it will run, and investigate errors rather than removing options at random.
Set CFR and map audio deliberately
In the template, -vf "fps=30" places cadence conversion in the video filter graph. The filter produces the target rate by dropping or duplicating frames where necessary. If the command already applies filters, add the frame-rate conversion in a considered position in the graph and check the resulting output; filter order can matter for other transformations.
You can instead express CFR at the output synchronisation stage:
ffmpeg -stream_loop -1 -re -i loop.mp4 \
-map 0:v:0 -map 0:a? \
-fps_mode:v cfr -r:v 30 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -f flv "rtmp://a.rtmp.youtube.com/live2/STREAM_KEY"
Here -fps_mode:v cfr asks FFmpeg to synchronise the video output to a constant frame rate, while -r:v 30 states the target rate. These options belong to the output side. Use either this approach or the fps filter as your intentional conversion point for a straightforward transcode; avoid adding both just to make the command appear more explicit. Test with your file and FFmpeg version to see that the output has the intended cadence.
Do not move -r before -i as a shortcut. Input -r and output -r do different things. For raw inputs without reliable timestamps, input -r can tell FFmpeg to assume a constant input rate and ignore stored timestamps. On ordinary timestamped video, that is not a substitute for output conversion and can misrepresent how the source is timed. FFmpeg's documentation explains the placement and behaviour of these options.
The audio mapping is intentionally independent from the video conversion. -c:a aac encodes mapped audio as AAC; it does not select the correct track or repair clipping, silence, or sync problems. If the source has no audio, optional mapping avoids a failure caused solely by the absent stream. If it has multiple tracks, map the intended stream explicitly after inspecting it.
Adjust encoding to capacity and ingest
A live transcode must keep up with playback in real time. Encoding at the chosen resolution and frame rate requires CPU or hardware-encoder capacity, and a machine that cannot sustain the work may fall behind even if the command is syntactically valid. Watch FFmpeg's progress output during a representative test. If it repeatedly cannot encode at real-time speed, reduce the workload or choose a suitable encoding method before leaving it unattended.
Resolution, frame rate, video bitrate, audio bitrate and keyframe behaviour form a profile that must also suit YouTube's current ingest guidance. The sample command intentionally does not prescribe a bitrate: the appropriate value depends on output resolution, content and current platform requirements. Check the current YouTube encoder settings rather than taking a value from an old post. A lower cadence or resolution may be a reasonable trade-off when the source has little movement or the encoding machine is constrained, but inspect the result at normal playback size.
libx264 is a common software encoder name in FFmpeg builds, not a promise that every installed build supports it or that software encoding is the best choice on your machine. Hardware encoders, where available, can reduce CPU work, but have their own build, quality and configuration considerations. Keep the first test simple enough to diagnose; change one relevant setting at a time and note whether the encoder sustains pace.
For a 24/7 loop, the computer and its connection must remain available and the process must recover sensibly if interrupted. People comparing local and hosted approaches may find the Linux VPS playlist-streaming guide useful for understanding a different operating arrangement. It does not change the FFmpeg CFR settings: whichever environment you use, validate the actual encoded output and ingest path.
Protect the stream key
Treat a YouTube stream key as a credential. Anyone who obtains it may be able to send a stream to the associated destination, so do not put a real key in an article, public repository, video tutorial, or support screenshot. The placeholder in the examples is deliberately not a usable secret.
Avoid pasting a live command containing the key into a public chat or issue. Shell history and process listings may also expose command-line arguments depending on the operating system and setup. Use a private, access-controlled method appropriate to your environment, and remove or rotate a key if you have exposed it. Check YouTube's current channel controls for managing stream keys and permissions.
If you need a file-based broadcast without leaving your own computer running, StreamNeo removes that specific operational chore: you upload the video, provide your YouTube stream key, and the broadcast continues with your computer switched off. Keep the key private there as well, and remember that this is a YouTube-only approach rather than an FFmpeg feature.
Validate the output and test the whole path
Before a long broadcast, encode a short representative test. Include the kinds of movement, scene changes and audio present in the actual loop, and send it through the intended ingest path if possible. YouTube recommends testing with representative audio and movement and monitoring stream health during an event. A local file that plays correctly is not by itself proof that the encoder sustains real time or that YouTube receives a healthy stream.
Inspect the encoded output with FFprobe, for example:
ffprobe -v error -show_streams -of json test-output.flv
Review the output video stream's frame-rate metadata and compare it with the intended rate. Depending on the container and how the file was produced, metadata fields may not tell the whole story. Confirm with playback and, where possible, frame or timestamp inspection; look for visible judder, unexpected repeated frames, dropped motion, audio drift, or black gaps at the loop boundary.
Then test the live result in YouTube Live control room and check the stream health feedback. Verify that the incoming resolution and frame rate are as intended, the audio is present and in sync, and the picture remains stable through a loop boundary. Keep the test private or unlisted as appropriate to your channel plan. A clean probe report cannot establish ingest health or guarantee that a long-running stream will remain uninterrupted.
If playback looks wrong, isolate the stage before changing several things at once. Confirm the input timestamps and stream selection first; then check the chosen target rate and the output metadata; finally review encoding speed and YouTube's health indicators. If the output already has the intended constant cadence, extra conversion may add work without improving it. For audio-specific problems, the audio-sync troubleshooting guide for recorded lesson streams offers a separate diagnostic path.
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
How do I set constant frame rate in FFmpeg?
Choose a target rate and apply one deliberate conversion method. For a filter-graph conversion, use -vf "fps=30" with the number changed to your target; for output synchronisation, use -fps_mode:v cfr -r:v 30. Encode and inspect the actual output rather than assuming the command alone proves CFR.
How do I loop a video on YouTube Live with FFmpeg?
Use -stream_loop -1 before the input to repeat it and -re before the input to pace file reading for live-style output. Those options do not set CFR, so configure cadence separately and use the correct YouTube ingest details and a private stream key. Test the complete encode and ingest path before leaving it running.
Should I use -r, -vf fps, or -fps_mode cfr?
For a simple transcode, use the fps filter when you want conversion in the filter graph, or use output -fps_mode:v cfr with output -r:v when you want explicit output synchronisation. Do not confuse output -r with input -r, which has a different role and placement. Choose one conversion point and validate it with your source and FFmpeg version.
Does CFR guarantee smooth playback on YouTube?
No. CFR specifies a regular output cadence, but it cannot ensure that the encoder keeps up, that the source looks smooth after frames are dropped or duplicated, or that ingest is healthy. Review the video and audio and monitor YouTube's live health feedback during a representative test.