Use GStreamer’s tee to split a shared media path into two queued branches: one for segmented local recording with splitmuxsink, and one for YouTube Live through an FLV muxer and rtmpsink. splitmuxsink creates local files; it does not send the YouTube stream.
Treat the pipeline below as a topology, not a universal copy-and-run command. The source, audio and video layout, codecs, installed plugins, machine capacity and current YouTube ingest instructions all affect the working pipeline.
Plan the recording and streaming branches
The design has one shared input and two outputs. Capture and any processing that is genuinely common to both outputs happen before a tee. Each branch needs its own queue, so a slow file write or network send has room to proceed independently rather than immediately blocking the other path.
The recording branch ends at splitmuxsink. It muxes the incoming stream into files and starts another file when a configured time or size threshold is reached. The live branch must supply YouTube-compatible audio and video, mux them as FLV, and send that data over RTMP with rtmpsink. GStreamer’s tee documentation describes the element as a one-to-many pipe fitting; its splitmuxsink documentation covers segmented file output.
A schematic single-stream example is:
[source] . [shared capture / conversion / encoding as appropriate] . tee name=t
t. . queue . splitmuxsink location="record-%05d.mp4" max-size-time=<nanoseconds>
t. . queue . [stream-specific encode or parse chain] . flvmux . rtmpsink location="<YouTube RTMP URL>/<stream-key>"
This sketch leaves out important details deliberately. A camera may expose separate audio and video pads, while a file source may already contain encoded streams. A muxer may require compatible input caps, and a live branch may need parsing or encoding that the recording branch does not. Your application may also supply the server address and stream key separately or combine them for the sink. Confirm the exact form using YouTube’s current encoder instructions and a local test.
Decide early whether the recording must preserve the source quality, whether the live copy needs a different format, and how long local segments should be. These are separate requirements, not a single encoder preset. A useful design note records the source formats, the recording container, the intended split rule, the live branch’s required caps, and where the credential is stored.
Build the shared capture and encode path
Start with the source alone. Confirm that GStreamer can read it, that audio and video are present when expected, and that timestamps advance. Then add only the conversions or encoding needed by both destinations. A USB capture device, a camera source and a media file each expose different pads and formats, so begin from the actual source rather than borrowing a pipeline written for another device.
Encoding before the tee can avoid doing the same encode twice. It is a reasonable choice if one encoded stream meets the needs of both outputs and is accepted by both downstream chains. But the recording container and the FLV live muxer may impose different codec or parsing needs, and preserving a source stream for local archive may not match the live output requirement.
Encoding after the tee makes each branch independent. That can help when the archive should keep a high-quality or source-compatible version while YouTube receives a separately encoded live version. It also means more work for the processor or hardware encoder, and separate encoders can introduce timing or resource pressure. There is no universally right placement: test the exact source and target machine.
Do not infer a resolution, frame rate, bitrate or keyframe interval from this schematic. The official GStreamer references explain elements and properties, not a suitable profile for every channel. Select settings based on the media you actually have, the upload path, storage needs and YouTube’s current guidance. If a live branch has to convert or encode, measure that workload while the recording branch is active, not in isolation.
Add a tee and queues for both outputs
A tee fans data out to multiple branches, but each branch should start with a queue. Without branch buffering, a downstream stall can propagate backwards through the shared path. A queue decouples scheduling to a degree; it does not create unlimited capacity or guarantee that either output survives a persistent bottleneck.
Keep the branch boundaries clear when assembling the real pipeline. Link the tee’s requested source pads to separate queues, then link each queue to its own downstream elements. If audio and video are separate streams, you may need a tee in each path or a more deliberate arrangement that keeps the related streams synchronised into each muxer. The single-line sketch does not solve that multi-pad wiring for you.
Observe queue levels and pipeline bus messages during testing. A growing queue indicates that a downstream consumer is not keeping up. For example, if local storage becomes slow while the network branch is active, the recording queue may fill and eventually affect capture. Likewise, unstable upload or a slow live encoder can build pressure on the streaming queue. Queue limits and leaky behaviour are application choices with consequences: dropping buffers may preserve responsiveness but can lose content, while waiting can back-pressure upstream.
If you are adapting an established desktop workflow, the distinction between a local program loop and the encoded outputs matters. The guide to looping multiple videos in OBS without a transition gap is useful for playlist behaviour, but a GStreamer tee still needs deliberate branch and muxer handling. A tee copies flow to branches; it does not synchronise, encode or make incompatible caps compatible by itself.
Configure splitmuxsink for local segments
Set a location pattern that produces a distinct filename for each fragment, such as record-%05d.mp4, and choose a time or byte threshold appropriate to the recording workflow. max-size-time is expressed in nanoseconds and max-size-bytes in bytes. A value of zero disables the corresponding threshold. The element uses muxer and sink components to write files; its documented defaults are mp4mux and filesink, but those may not suit every input or archive format.
Splitting is tied to muxing and video keyframes, not arbitrary exact wall-clock instants. The GStreamer documentation notes that the split occurs at video keyframe boundaries. A nominal time or size limit can therefore be exceeded by a GOP, and the minimum part size is one GOP. If you need the video fragments to play independently, the video needs closed GOPs. Check the resulting files in a player or media inspection tool rather than assuming that a numbered series is automatically a clean edit.
If predictable duration boundaries matter, use an encoder configuration with a sufficiently regular keyframe interval and test the actual fragment durations. send-keyframe-requests can request a keyframe at each time threshold, but the documentation says it requires max-size-bytes=0 to be effective. This is a property to evaluate in a relevant pipeline, not a substitute for checking the encoder’s behaviour and output.
The async-finalize option lets the previous muxer and sink finish a fragment asynchronously while a new pair begins. In this mode, configure muxer-factory and sink-factory rather than direct muxer and sink object properties. It can alter how finalisation work overlaps with recording, but it cannot remove a sustained storage bottleneck or guarantee a complete file after a forced process stop.
Plan for orderly shutdown. A clean pipeline transition gives the muxer a chance to finalise the current file; a crash or power loss may leave the last segment incomplete. Inspect several completed segments, including one produced after a split and the final segment after a clean stop. If retention matters, decide how old files are moved or removed without interfering with files still being written.
Mux and send the live branch to YouTube
The live branch has a different endpoint from the recording branch. It must arrive at flvmux with compatible audio and video inputs, and the resulting FLV data goes to rtmpsink. The rtmpsink reference shows the FLV muxer upstream of the sink and describes sending data to a streaming server using RTMP. The RTMP plugin documentation likewise identifies the sink as sending FLV over RTMP.
Whether to encode before the tee or separately in this branch depends on what the source already provides and what the two outputs require. If the source is already encoded, parsers may be needed to shape the data for downstream elements; if it is raw, the live path needs appropriate encoders. Confirm negotiation in the actual pipeline and check that flvmux accepts the selected stream caps. A successful file branch does not prove that the live chain can mux or connect.
The live path also has its own failure modes: an encoder may not keep up, the FLV muxer may reject incompatible caps, or the network connection may fail. Review GStreamer’s bus errors and element state, and keep the local recording test distinct from the YouTube ingest test. Do not assume that successful RTMP connection means the archive is valid, or that a valid archive proves the live audience is receiving a stable broadcast.
If your actual goal is a continuous channel from a pre-rendered playlist rather than a custom live capture graph, compare the maintenance model before committing to a complex local pipeline. A cloud service reliability discussion for nonstop playlist streams addresses a different operating pattern. StreamNeo removes the specific burden of leaving a computer on to push an uploaded file continuously, but it is YouTube-only and does not replace a GStreamer setup where you need live capture or simultaneous local segmented recording.
Use the ingest URL and key from Live Control Room
Create or prepare the live event in YouTube Studio and use the current encoder instructions shown for that workflow. YouTube Help says live streaming must be enabled on a verified channel; for a first activation, enabling it can take at least 24 hours after the request. Check the current YouTube live streaming instructions before scheduling a test, because account steps and displayed ingest details are the authoritative source for your channel.
Use the RTMP server URL and stream key supplied by YouTube. Treat the key like a password: do not put a real key in a published command, source repository, shared screenshot or routine log. Keep it in a protected configuration mechanism suitable for the environment running the pipeline, and replace it if it is exposed. The schematic’s <YouTube RTMP URL>/<stream-key> is a placeholder, not evidence that every current endpoint uses that exact concatenation.
YouTube’s encoder workflow may show more than one connection option. Match the selected endpoint to the sink and protocol you are actually using, and verify the precise URL format from the current instructions. The GStreamer rtmpsink expects an RTMP destination; it does not retrieve your credentials or choose the correct YouTube event for you.
Before a public or scheduled session, run a private or otherwise controlled test if available in the account workflow. Confirm that YouTube receives the intended audio and video, that the preview is current, and that the event is in the state you expect. Your pipeline can be locally healthy while the wrong event, endpoint or key is configured.
Test both outputs and monitor resource use
Build in stages. First run the source and shared processing path alone, checking audio/video timestamps and negotiated caps. Then add splitmuxsink and let it create multiple completed segments. Open them, inspect their duration and continuity, and verify the filename sequence and finalisation behaviour after a clean stop.
Next add the queued live branch and test the FLV-to-RTMP path with the current YouTube server URL and stream key. Watch the YouTube preview and review local bus output for negotiation or connection errors. Only after each branch works alone should you run both together for a meaningful period on the target machine and network.
During the combined test, monitor encoder load, dropped buffers, queue growth, storage throughput, upload stability and bus errors. There is no universal capacity threshold in the cited element documentation. A machine that works for a short test may still struggle when storage activity, network conditions or source complexity change. Test the actual channel material and intended operating conditions, rather than relying on a profile copied from a different system.
If problems appear, change one part at a time. For queue growth, determine which downstream branch is slow. For damaged segments, examine the recording branch, keyframe structure and shutdown path. For a rejected live stream, inspect caps, muxing and the current YouTube endpoint details. This keeps the diagnosis tied to evidence rather than changing encoder, muxer and network settings together.
For a long-running channel, compare how much operational work the local machine needs with other available methods. A VPS-based FFmpeg approach for a Hindi bhajan stream may fit a file-looping workflow better than a custom capture graph, while GStreamer is useful when you specifically need its media pipeline and local segment outputs. Your choice should follow the source and maintenance requirement, not a claim that one tool is universally more reliable.
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 splitmuxsink send my stream to YouTube?
No. splitmuxsink writes segmented local files. Use a separate tee branch with an FLV muxing stage and rtmpsink for the RTMP live output.
Can I use one encoder for both branches?
Possibly, if the encoded stream is suitable for both the recording muxer and the live FLV chain. If the outputs need different formats or qualities, branch before encoding and encode separately, while checking the extra processing load on your machine.
Will every segment match the exact time limit?
Not necessarily. Video splits are tied to keyframe boundaries, so a GOP can carry a fragment beyond a nominal threshold. Check the actual segments and ensure the GOP structure suits independent playback if that is required.
What if the stream key or RTMP URL does not work?
Check the current encoder details in YouTube Studio, confirm the event and endpoint, and verify how your application passes the URL to rtmpsink. Keep the key private, and diagnose the live branch separately from the local recording branch.