To loop a local playlist with FFmpeg, use -stream_loop -1 before the -i that reads the playlist. That asks FFmpeg to repeat that input indefinitely, but it does not turn a local M3U file into YouTube’s HLS ingest format.
The details depend on what your playlist actually contains and how its entries are encoded. The command below is an untested command shape, not a recipe that will work unchanged for every M3U file, FFmpeg build or YouTube channel.
A local playlist is not YouTube HLS ingest
A file ending in .m3u may be a local list of audio files, a list of URLs, or an HLS media playlist that refers to short media segments. The extension alone does not tell you which one you have. Before choosing an FFmpeg input format, open the file as text and check what its entries point to and whether it contains HLS-specific tags such as #EXT-X-TARGETDURATION and segment URLs.
A local music playlist is a source for FFmpeg: it tells FFmpeg which media to read. YouTube HLS ingestion is a way of delivering a live broadcast to YouTube, using a continuously updated playlist of media segments. These are different jobs, even if both involve a playlist file. YouTube’s HLS ingest instructions specify segment, playlist and transport requirements for an encoder that supports HLS ingest; they do not explain how to repeat a folder of local tracks.
For the ordinary YouTube live workflow shown here, FFmpeg reads media and sends an encoded stream to the ingest destination shown in YouTube Live Control Room. YouTube recommends RTMPS for that workflow. Its separate HLS method requires an HLS-capable encoder and has its own requirements, including TS segments lasting 1–4 seconds, HTTPS POST or PUT requests, and a rolling playlist with no more than five outstanding segments. YouTube also notes that HLS has higher latency than sending a continuous stream. Those constraints belong to HLS delivery, not to a local playlist input.
If you have an existing M3U file, do not assume that adding -f concat makes FFmpeg read it correctly. The concat demuxer expects its own file-list syntax. If you want to use concat input, create a text list in that format and verify that your installed FFmpeg can read it. For other M3U dialects, consult the FFmpeg documentation and test against the actual file. The FFmpeg reference documents demuxers and options, but it does not establish compatibility for every playlist file someone might call an M3U.
This distinction is useful if your goal is a radio-style stream: a source playlist can be local and simple, while the output still has to be a valid live broadcast. For a different approach to cycling through prerecorded material, see how to play videos in a random order with OBS. The application and playlist behaviour differ, but the same basic distinction remains: the media source is not the ingest protocol.
Prepare a concat playlist file
If your source media is a set of local files and you choose FFmpeg’s concat demuxer, make a separate text file such as playlist.txt. A basic file-list shape is:
file '/media/radio/track-one.mp3'
file '/media/radio/track-two.mp3'
file '/media/radio/track-three.mp3'
The paths in this example are illustrative. Use paths that exist on the machine running FFmpeg, and make sure the FFmpeg process has permission to read every file. Relative paths are interpreted in relation to the process’s working directory, which can differ from the directory you were looking at in a terminal. An absolute path can make that relationship clearer, especially when a scheduled task or service starts the process for you.
This example deliberately uses the concat demuxer’s file entries, not a claim that a conventional M3U playlist can be passed to concat unchanged. Playlist formats have their own escaping and metadata conventions. If a path contains spaces, quotes or other special characters, follow the syntax expected by the format you have selected rather than assuming shell quoting rules apply inside the playlist file.
The concat demuxer is most straightforward when successive files can be joined without awkward changes in stream layout or timestamps. Different codecs, sample rates, channel layouts, container formats or damaged files can complicate transitions. Test transitions between representative tracks instead of checking only whether the first file opens. The FFmpeg process may read an entry successfully yet still produce an audible gap, a decoding warning or an output problem when it moves to the next one.
If your existing playlist contains URLs, treat that as a separate input case. An online URL may expire, need authentication, redirect, or return a format that your build does not handle as expected. A list of URLs is not automatically a suitable concat file, and a local file list does not become an HLS ingest playlist just because one entry points to a stream. Confirm the media source and its access requirements before trying to run it continuously.
Keep the source material in a stable location while testing. Moving files after you write the list, changing the working directory, or relying on a mounted drive that is not available after a reboot can make a command that worked interactively fail later. If you are building a longer playlist from an archive, the podcast archive and Docker guide may help you think through how the process and files are organised, though its container setup is not required for this command.
Use FFmpeg’s input loop option
FFmpeg documents -stream_loop as an input option: 0 means no looping, and -1 requests infinite looping. In a command, the option belongs to the input whose contents you want to repeat. That is why the placement of the option matters as much as its value.
For a concat-demuxer text list, the general shape is:
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.txt \
-c:v libx264 -c:a aac -f flv "rtmps://YOUR_YOUTUBE_INGEST/YOUR_STREAM_KEY"
This is an untested command shape for explanation, not a tested, copy-and-run solution. It assumes playlist.txt uses the concat demuxer’s expected file-list format and that the selected media and output settings are suitable for your setup. Replace the placeholder destination with the RTMPS ingest URL and stream key currently supplied in YouTube Live Control Room. Do not publish a working stream key in a public script, screenshot, repository or log.
The -stream_loop -1 pair requests repeated reading of that input. It does not repair a malformed list, make incompatible tracks seamless, generate a missing video picture, or ensure that the destination accepts the stream. “Infinite” describes the requested input looping behaviour; it is not a promise that a process, computer, network or YouTube broadcast will never stop. A file can fail, a connection can drop, or the process can exit for a reason unrelated to the loop setting.
The -re option makes FFmpeg read file input at a real-time rate rather than consuming it as fast as possible. That is appropriate to consider when a file source is being used to feed a live stream. FFmpeg’s documentation includes an RTMP example that combines real-time pacing with H.264 video, AAC audio and FLV output. The example above uses a similar broad output shape, but you still need to check the installed build, selected codecs and actual media.
If your FFmpeg build rejects an option or behaves differently from the documentation, check the version and its available encoders and demuxers. Builds differ, and an option that exists in current reference documentation may not be available in the executable you are using. You can also run a short test to a local output before involving YouTube, which helps separate input and decoding problems from ingest problems.
Put each option before its matching input
FFmpeg command lines are read in order. Input options apply to the input that follows them, while output options apply to an output. For one playlist input, -stream_loop -1 belongs before -i playlist.txt. Placing it after that -i does not clearly request looping of the already-opened playlist; it may instead be interpreted in relation to a later input or have no intended effect.
A useful way to inspect a command is to mark its boundaries:
input options and format → -i source
output options → destination
In the example, -re, -stream_loop -1, -f concat and -safe 0 occur before -i playlist.txt. The codec selections and output format follow the input, before the destination URL. Do not shuffle options mechanically when troubleshooting. Check which input each option is meant to affect, and keep options next to that input so the command remains readable.
The -safe 0 setting in the example permits the concat demuxer to accept paths outside its restricted safe-path rules. Use it only when you understand and trust the playlist contents and paths. It is not a general security setting and should not be used to make untrusted playlist entries execute without inspection. If the command is used with a playlist assembled from outside your control, inspect it and its referenced files first.
A command with more than one input needs particular care. For example, if you add a still image as a video source and retain the playlist for audio, the loop option must be attached to the playlist input, not accidentally to the image. Explicit mapping then tells FFmpeg which audio and video streams to put into the output. The precise syntax depends on how the image and audio inputs are configured, so treat multi-input examples as a separate command to test, not a small edit you can safely infer from the one-input shape.
Add video and send the YouTube output
The shown command includes both -c:v libx264 and -c:a aac, so it assumes an output that contains video and audio. A collection of audio files by itself does not supply a picture. If your chosen live workflow requires video, provide a suitable video source, such as a static image, and map the audio and video streams explicitly. Confirm that the resulting output actually contains both streams before sending it to YouTube. Do not assume that an audio-only output will be accepted in your particular channel workflow; verify the current behaviour in YouTube Live Control Room.
YouTube’s encoder guidance recommends RTMPS and lists H.264 video with AAC or MP3 audio for the ordinary live stream path. It also gives advanced guidance including constant bitrate, a recommended two-second keyframe interval that should not exceed four seconds, and stereo audio at 44.1 kHz and 128 kbps. These are YouTube’s recommendations, not guarantees that any given file, encoder build or connection will behave well. Choose resolution and bitrate for the content and available upload connection, then test rather than infer quality from a command line alone.
The destination in the example is a placeholder, not a real ingest address. Copy the current server URL and stream key from Live Control Room, and keep those credentials private. If you regenerate the key or select a different ingest setting in YouTube, update the command accordingly. A mistyped URL, stale key or accidental whitespace can look like a codec failure when the actual problem is authentication or destination configuration.
YouTube transcodes live input for viewer formats, but that does not remove the need to send a valid input stream. Pay attention to the health indicators in Live Control Room during a private or unlisted test. If you are planning an always-on channel with a conventional encoder, the 24/7 OBS settings guide provides a useful comparison of the practical concerns around a continuously running setup. It does not change how FFmpeg’s playlist input works.
Test the stream and diagnose failures
Test with a short private or unlisted broadcast before relying on a playlist overnight. Use representative files, including a transition between entries, and check that playback advances, sound remains continuous enough for your purpose, and video reaches the viewer if your setup requires it. YouTube recommends testing with representative audio and video and monitoring stream health. A successful first connection does not prove that later entries, reconnects or long-running operation will work.
| What you see | What to check first | Why it matters |
|---|---|---|
| FFmpeg cannot open the list | File path, working directory and list syntax | The concat demuxer expects its own file-list format. |
| The first file plays, then playback stops or errors | The next entry, its permissions and media compatibility | A playlist can be valid at the start but fail at a boundary. |
| FFmpeg runs but the YouTube preview is unhealthy | Ingest URL/key, output codecs, bitrate and stream health | Input looping and accepted live output are separate issues. |
| The broadcast has sound but no picture | Whether a video input is present and mapped | Audio files do not provide a video stream. |
| The stream ends after a network interruption | Connection behaviour and process logs | -stream_loop repeats input; it is not a guarantee of reconnection. |
If FFmpeg reports that it cannot open playlist.txt, first confirm the actual working directory and file name. Then inspect each entry for a typo, inaccessible mount, quoting problem or unsupported path. If the list opens but one item fails, test that media file on its own and check what changes between it and the preceding item. A warning at the transition may point to a codec, timestamp or stream-layout difference rather than a YouTube issue.
If FFmpeg appears to be processing normally but YouTube does not show a healthy ingest, verify the exact destination and key in Live Control Room. Check the output’s audio and video streams and the current encoder guidance before changing playlist syntax. If a connection drops, FFmpeg’s documentation describes FIFO options that can attempt recovery after a temporary network failure. Recovery is an attempt, not a guarantee of uninterrupted service; observe whether it succeeds in your own environment.
For a stream that must run while you are away, the process has to remain available as well as the input. A laptop closing, a power cut, a router restart or a system sleep setting can stop an otherwise correct command. If your current machine or connection is unreliable, decide how you will monitor a test and what you will do after a process or network failure. The guide to handling OBS disconnects when changing connections covers a related operational problem, although its OBS-specific steps do not apply directly to FFmpeg.
A local looping command also keeps its own scope: it repeats the configured input rather than managing your channel’s schedule, rights or audience settings. Confirm that you have permission to stream the tracks and that your channel is configured as you intend. The sources here do not settle licensing questions or guarantee that a particular account will accept every output arrangement.
If maintaining a local FFmpeg process through power, connectivity and restart problems is the part you want to avoid, StreamNeo addresses that specific operational burden by running an uploaded video as a YouTube live stream without leaving your computer switched on. It is YouTube-only, so it is not a replacement when you specifically need FFmpeg to parse a local playlist or need another destination.
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 -stream_loop -1 work with every M3U file?
No. The option asks FFmpeg to repeat an input, but it does not establish that FFmpeg understands the file’s playlist dialect. Check the actual contents and use an input demuxer and format that match them; the concat example requires a concat-style file list, not an arbitrary M3U.
Why must the loop option go before -i?
FFmpeg treats -stream_loop as an input option, so it belongs before the input it should affect. Put it before -i playlist.txt for the playlist input, and check placement separately if your command contains more than one input.
Is a local M3U the same as YouTube HLS ingest?
No. A local playlist selects media for FFmpeg to read; YouTube HLS ingest is a separate delivery protocol with segment and rolling-playlist rules. An .m3u extension by itself does not tell you that the file is an HLS media playlist or that it is suitable for YouTube ingest.
Does the command guarantee a 24/7 stream?
No. It is an untested command shape and -stream_loop -1 only requests repeated input. You still need to verify the media, output, credentials, connection and process behaviour in a representative test, and no loop option guarantees that a broadcast will remain uninterrupted.