Skip to content
streamneo.
Setup Guides12 min read

How to Use Cron to Switch Playlists in an FFmpeg YouTube Livestream

Use cron to schedule playlist changes by stopping and relaunching FFmpeg, with practical guidance on timing, YouTube events and testing.

sn.
StreamNeoPublished 4 October 2026
Worth sharing?

Cron cannot replace the input playlist inside an FFmpeg process that is already running. The straightforward scheduled method is to have cron run a wrapper that selects the next list, stops the current FFmpeg process cleanly, and starts a new FFmpeg invocation with that list.

That process transition is separate from YouTube Studio scheduling. Studio provides the broadcast and the ingest details; your local schedule decides which media FFmpeg sends. A restart can interrupt the incoming feed, so test how it behaves with the specific YouTube event you plan to use.

What cron can and cannot change

Cron is a clock and command launcher. At a scheduled time, it starts a command under the account that owns the crontab. It does not attach to FFmpeg and alter the process’s current input. If FFmpeg is reading one concat list, changing the list on disk does not make the already-running invocation switch to another list.

For Linux Cronie, a user crontab has five time and date fields followed by a command, and entries are checked each minute. The default shell is /bin/sh; do not assume that aliases, shell functions, or environment variables from your interactive terminal will be available. Use explicit paths and set any environment your script needs. Other cron implementations may differ. See the crontab man page for the documented behaviour of that implementation.

The practical meaning of “switch playlists” in this guide is therefore: at a boundary, stop one FFmpeg job and start another with a different input list. The change is a restart, not a live mutation. That is easier to reason about than hoping that an input file reloads, but it can create a gap or affect the broadcast while the new encoder connection starts.

If you need the outgoing feed to remain connected while media changes, that is a separate pipeline design. It requires a switching mechanism built and tested for that purpose; cron and the concat demuxer alone do not provide an in-process playlist reload feature. Choose the simpler restart pattern only when its transition is acceptable.

Plan playlist selection by schedule

Start by writing down the schedule in the timezone you actually intend to use. For example, you might send a morning devotional block and then a daytime bhajan block. Decide which playlist should be active at each boundary, what should happen if a scheduled run is missed, and whether a repeated run should be harmless or should restart the stream again.

On Linux Cronie, CRON_TZ can set the timezone used to interpret the schedule. Daylight-saving transitions need attention: a local time that does not occur may be skipped, while a repeated local time may run twice. Logs use the cron daemon’s local timezone, which can differ from the schedule timezone. If your channel serves viewers in India, state the intended timezone explicitly rather than relying on the machine’s default. Check your system’s cron documentation before applying Cronie-specific details elsewhere.

Prefer a schedule that has a clear answer for each moment. One approach is a wrapper called with a named block, such as morning or evening, which maps that name to a fixed playlist path. Another is to have one script read the current schedule and choose the active list. The named-block approach is easier to inspect; the schedule-reading approach avoids editing many cron entries when the programme changes. In either case, the selected file should be predictable and validated before the current process is stopped.

A restart also raises a broadcast question: do you intend one YouTube event to continue through an ingest interruption, or should each block have its own event? The local cron schedule cannot decide that for YouTube Studio. If you are planning a sequence of music blocks, compare the scheduling considerations in how to schedule songs for a 24/7 YouTube radio stream. For video playlists, the guide to streaming a playlist of videos on YouTube Live may help you establish the media side before adding process restarts.

Write a wrapper to stop the current FFmpeg process

The wrapper is the bridge between the calendar and FFmpeg. It should receive or determine the block to play, check that the associated list exists, stop the old encoder, wait for it to exit, then launch the replacement. It should also prevent a second copy of the wrapper from running over the first. A lock or another process-supervision method can provide that guard; it matters particularly when a cron run is repeated or delayed.

Use absolute paths for the FFmpeg executable, list files, logs, and any state or lock file. Cron’s environment is deliberately modest compared with an interactive shell, so a command that succeeds in a terminal may fail when run by cron because it cannot find a binary or file. Have the wrapper log the selected block, the time it started, the stop result, and the replacement process result. Do not write the YouTube stream key into a log.

There is no single universally safe stop command for every setup. If FFmpeg is managed by a service supervisor, use that supervisor’s stop and start controls rather than guessing a process ID. If you manage it directly, keep a reliable PID or process handle and send a normal termination request, then wait for the process to exit before starting the next one. Avoid broad commands that kill every process named ffmpeg: another job on the same machine could be affected.

A wrapper should fail safely. If the next playlist is missing or empty, do not stop a healthy current stream and leave nothing to replace it. Validate the file first; on an invalid selection, log the problem and preserve the running process or follow a deliberately chosen fallback. Likewise, if the old process does not exit within the period you allow, do not blindly launch a second encoder. Report the failure and make the recovery action explicit.

The following is a structural sketch, not a copy-and-run script. The stop and launch functions need to match your process manager and system:

#./bin/sh
set -eu

FFMPEG=/usr/bin/ffmpeg
LIST=/srv/channel/lists/morning.ffconcat
LOG=/var/log/channel/playlist-switch.log

# Check the selected list and acquire a single-run lock here.
# Ask the current managed FFmpeg job to stop, then wait for exit.
# Start the replacement and record its exit status and logs.

Keep the script owned and readable only by the account that needs it. A stream key is a credential used to send a feed to your channel, so protect it as you would other account credentials. You can supply it through a protected configuration mechanism rather than embedding it in a world-readable script or printing it in command logs. Test your chosen method: process arguments and diagnostic output can expose secrets depending on how a command is constructed.

Launch FFmpeg with the replacement list

The concat demuxer is one way to make a playlist of files an FFmpeg input. It reads a list of media paths in sequence and presents them as a concatenated input. Each block can have its own list, which means the wrapper can select a different list for the next FFmpeg invocation. Use the FFmpeg concat demuxer documentation for the current syntax, escaping rules, and directives; paths containing quotes or unusual characters need care.

A minimal list has the form below, but its entries must be real paths accessible to the account running FFmpeg:

file '/srv/channel/video/intro.mp4'
file '/srv/channel/video/main.mp4'

The files should have compatible streams, including codecs and time bases, for the concat demuxer to handle them as a continuous input. Matching the container alone is not enough to establish compatibility. Differences in stream layout or inaccurate stored durations can cause timestamp gaps or visible and audible artefacts. FFmpeg’s documented duration directive can override a file’s stored duration when appropriate, but do not add estimates without checking the media and the documentation.

Your new FFmpeg command will also include the output settings needed for your channel and the YouTube ingest URL and key. Keep those settings consistent across blocks unless you have a reason to change them. The wrapper’s job is to choose the input list and coordinate the process transition; it should not silently change resolution, audio mapping, or encoder behaviour at the same time. Change one class of settings at a time so failures are easier to diagnose.

If your videos have different audio levels or timing, check them before scheduling a boundary. A block switch will not fix media problems that already exist inside a list. The guidance on preventing audio and video drift in an FFmpeg YouTube loop stream is useful when you are checking whether the files behave as expected together.

Keep shutdown and restart orderly

At a boundary, the order matters: validate the next input, request a clean stop of the old process, wait for exit, then launch the new invocation. Starting a replacement before the old encoder has stopped can produce overlapping attempts to send to the same destination. Stopping first can leave a short interruption while the replacement connects. Neither outcome should be assumed harmless; observe the transition in a test broadcast.

Use one authority to manage the FFmpeg process. Mixing a service manager, a shell background job, and cron without a clear ownership model makes it difficult to know which process is current or who restarts it. If the process exits unexpectedly, decide whether the supervisor should restart the same block, whether the wrapper should select the block that is currently scheduled, or whether an operator should intervene. A watchdog that always restarts an old command can undo a playlist change if it is not coordinated with the schedule.

Record enough information to reconstruct a failed transition: the intended block, the chosen list, the old process’s exit, the new process start, and relevant FFmpeg errors. Rotate or limit logs so they do not grow without attention, and keep credentials out of them. A clear log line such as “evening list selected” is more useful than a command dump containing a key.

Cron’s day and time fields also deserve deliberate review. Under Linux Cronie, if both day-of-month and day-of-week fields are restricted, either field can match and trigger the command. That can surprise you if you read the fields as requiring both conditions. Keep the schedule simple, inspect the installed crontab, and run the wrapper manually under the same account before relying on it unattended.

Configure the YouTube event and encoder

YouTube Studio and cron have different jobs. Studio creates or schedules the live event and provides the stream URL and key; FFmpeg sends audio and video to that ingest destination. YouTube’s encoder setup instructions describe entering those details in an encoder and checking the Live Control Room preview. The Studio event schedule does not select a local concat list, and changing the list does not create or schedule an event.

Before you build the wrapper around a particular event, decide whether a restart and reconnect fits that event’s operation. Stopping the encoder means the content being sent stops. The official documentation does not settle every design choice about whether a particular reconnection should remain part of an event or how a channel should coordinate multiple events; check the current Studio guidance and test your own workflow. Do not treat an FFmpeg restart as a command to create a new YouTube broadcast.

Use YouTube’s current live encoder guidance for supported protocols and settings. Its recommendations include RTMP or RTMPS, constant bitrate, supported video and audio codecs, and a two-second keyframe interval, with a maximum of four seconds. Bitrate depends on the resolution, frame rate, and codec, so use the current table for the exact combination you intend to send rather than copying a value from a different setup. YouTube describes RTMPS as RTMP over TLS/SSL; its RTMPS guidance explains the encrypted ingest option.

Test with representative content: a quiet devotional track may reveal audio problems that a moving video does not, while a high-motion scene can expose encoding or bandwidth trouble. Watch the Live Control Room preview and stream health instead of assuming that a successful FFmpeg process means viewers receive a healthy feed. YouTube’s encoder guidance says streams under 12 hours are automatically archived; do not assume that the same archive guidance applies to longer continuous broadcasts. Verify current platform instructions for your event.

Test a playlist change before relying on it

First test each list on its own. Confirm that every file exists and is readable by the cron account, the order is right, audio is present, and the files play through their expected endings. Then test the wrapper without a live key if you can: confirm that it selects the intended list, refuses a missing list, stops only the managed FFmpeg job, and does not permit overlapping runs.

Next, test a real transition at a time when you can watch it. Observe the old process stop, the new one start, the Live Control Room preview, audio continuity, and stream health. Note whether Studio continues to show the event as expected after the ingest reconnects. A local log alone cannot tell you what the platform accepted or what viewers saw.

Finally, test the schedule itself. Run the job under cron’s account and environment, check its timezone, and inspect timestamps in both the cron and wrapper logs. If you need a reliable overnight channel, repeat the test around the actual kind of boundary you intend to use, including a daylight-saving transition where relevant to your chosen timezone. Keep an operator’s recovery plan: know how to restore the previous list or start the intended block manually if the scheduled change fails.

A restart-based schedule is most suitable when the list boundaries are known and a brief ingest interruption is acceptable. If uninterrupted switching is essential, plan and test a continuous switching pipeline instead of treating a cron restart as seamless. Where keeping a single encoder running is the priority, compare the underlying trade-offs with approaches to streaming a slideshow continuously to YouTube from a VPS, while recognising that a slideshow pipeline is not automatically a playlist-switching solution.

When the transition and event behaviour are understood, choose an operating approach that fits how much process management you want to own.

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 cron change an FFmpeg playlist while it is running?

No. Cron starts commands on a schedule; it does not replace an input inside a running FFmpeg process. For this pattern, a scheduled wrapper stops the existing process and launches a new invocation with the next list.

Will restarting FFmpeg schedule a new YouTube broadcast?

No. YouTube Studio handles creation or scheduling of the event, and FFmpeg sends the feed to the URL and key supplied for it. A restart changes the encoder process, not the Studio event schedule.

Will viewers see a gap when FFmpeg restarts?

They may, because stopping one encoder and starting another can interrupt the incoming feed while the replacement connects. Test the transition against your own event and monitor the Live Control Room; do not promise a seamless switch based only on a local process restart.

How do I avoid two FFmpeg jobs starting at once?

Have a single process manager or wrapper own the job, and make the wrapper reject a second simultaneous run with a lock or equivalent guard. Validate the next list, stop the managed process, wait for its exit, and only then start the replacement.

YOU’VE REACHED THE END

Keep the ideas coming.

More guides, useful tools and a little help for your next broadcast.

Back to the journal ↗
YOUR NEXT READ

A little more to explore.

More Setup Guides guides ↗ · All topics ↗