Skip to content
streamneo.
Streaming Settings12 min read

GStreamer YouTube Playlist Stream with Subtitles: Burn In SRT Captions Using textoverlay

Connect an SRT file to GStreamer textoverlay, check subtitle timing, and distinguish visible playback captions from a saved encoded video.

sn.
StreamNeoPublished 7 October 2026
Worth sharing?

For a GStreamer-readable video and a matching SRT file, textoverlay can render each caption over the video during playback. The documented graph displays that overlay; it does not by itself encode or save a permanently captioned video.

The YouTube playlist part is a separate concern. The GStreamer references used here do not establish that a YouTube playlist URL can be opened or advanced directly by this pipeline, so treat resolving playlist entries into readable media as an upstream step and verify it in your own environment.

Check your GStreamer version and available elements

GStreamer is a collection of elements and tools, and the elements available to a command depend on the installed build and plugins. Before adapting an example, check which gst-launch-1.0 you are running and whether the required elements—textoverlay, subparse, decodebin3, videoconvert, and autovideosink—are available there. A command copied from current documentation may not work unchanged on an older distribution or a minimal installation.

You can inspect the tool version with gst-launch-1.0 --version. To inspect a particular element's properties and pads, use gst-inspect-1.0 textoverlay, then repeat for subparse or decodebin3 if needed. These commands report what is installed locally; they are more useful than assuming every system has the same element set or property defaults. The GStreamer textoverlay reference describes the element, while the gst-launch documentation explains the command-line tool and named-pad linking.

If an inspection command says an element cannot be found, do not keep changing the pipeline syntax at random. First identify the missing plugin or choose a playback method supported by the installation. A machine intended to run unattended should be tested with the exact package set and account that will operate it; a pipeline that works in a developer shell may fail after a service starts with a different environment.

Prepare the video and matching SRT file

Use a video file that GStreamer can read and an external SRT file whose cues describe that video. In the example below, the names movie.avi and movie.srt are placeholders. Replace them with the actual paths, taking care with spaces and shell quoting. The subtitle file should be plain SRT with numbered cues and start/end time ranges, followed by the text for each cue.

For example, a cue might start at 00:00:04,000 and end at 00:00:07,000, with a short line of text between those times. The cue numbering is not a cue to display numbered captions: it identifies the entries in the file. What matters for synchronisation is that the cue time range corresponds to the scene in the video. A structurally valid SRT can still be a poor match if it was prepared for a different cut, frame rate conversion, intro, or edit.

Keep the video and SRT together while testing, and note whether either begins with an offset or has been trimmed. If the source video starts with a logo or a silent leader that is absent from the subtitle timing, later captions may appear consistently early or late. That is usually a timing or source mismatch, not a failure of textoverlay to display text.

If your actual input is an online playlist, keep retrieval separate from caption rendering. The GStreamer playback documentation describes generic URI and playback behaviour, but the reviewed references do not verify direct YouTube watch-URL extraction, playlist iteration, authentication, or availability. Resolve each playlist entry to a media URI that your pipeline can read, then provide the corresponding subtitle file for that item. Do not assume that putting a playlist page URL in a GStreamer uri property will perform those steps.

For a channel that rotates files, the playlist controller also needs to keep each video paired with its own subtitle file. A practical operating note can record the media path, subtitle path, and whether their start points match. If you are changing items while a YouTube broadcast remains active, the separate mechanics in keeping a live stream active while replacing its playlist are relevant, but do not replace testing the GStreamer input and SRT pairing.

Understand textoverlay's video and text inputs

textoverlay has a video input and a text input. The video side carries decoded frames; the text side can receive timestamped subtitle buffers. The official example connects decoded video to overlay.video_sink and parsed subtitles to overlay.text_sink. The element renders text over the frames as they pass through, using the timestamps on the video and text streams to decide when a cue belongs on screen.

That distinction is central to the word “burn in”. In ordinary playback language, people sometimes use it to mean that the captions are visibly drawn over the picture. In file-production language, it usually means that the picture has been altered and saved with those letters permanently part of the video image. The documented example demonstrates the first meaning only: it is a playback pipeline ending in a video sink, not an encode-and-save job.

The textoverlay element can also be used with static text through its text property when the text sink is not linked. That is different from an SRT stream, which supplies cue text over time. For this task, subparse reads and parses the subtitle file, so the text pad receives timed subtitle data rather than one fixed label. The documentation notes that text wrapping is enabled by default; if a cue has awkward line breaks or is too long, inspect the subtitle content and the installed element's available properties rather than assuming a universal layout setting.

A simpler alternative may be enough when you only want playback with an external subtitle file: GStreamer documents playbin3 with uri and suburi. That delegates more of playback and subtitle handling to the player instead of wiring the overlay pads yourself. Choose the explicit textoverlay graph when you need to understand or control the path between parsing, video, and overlay; choose player-managed playback when its subtitle behaviour is sufficient. Neither approach establishes a YouTube playlist resolver.

The official command-line example is a useful starting point:

gst-launch-1.0 textoverlay name=overlay . videoconvert . videoscale . autovideosink \
  filesrc location=movie.avi . decodebin3 . videoconvert . overlay.video_sink \
  filesrc location=movie.srt . subparse . overlay.text_sink

Read it as two input branches meeting at the named overlay element. The video branch reads a file, asks decodebin3 to select and run a decoder, converts the decoded output, and connects it to the overlay's video pad. The subtitle branch reads the SRT file, passes it through subparse, and connects the resulting timed text to the overlay's text pad. After compositing, the output is converted and scaled before being sent to autovideosink for display.

The name=overlay part gives the element a name that later links can refer to. The strings overlay.video_sink and overlay.text_sink are named-pad references, not filenames. This explicit wiring is why the example is easier to reason about than a single high-level player command: you can see which branch supplies pictures and which supplies text. It is also more exposed to differences in local decoders, sinks, plugin availability, and media formats.

Start with a short local file rather than an entire channel playlist. If the pipeline reports that a pad cannot be linked, inspect the relevant elements and the media's actual streams; the source file may have a format that your local decoder path does not expose as expected. The GStreamer playback tutorials provide background on common playback pipelines and are useful context when the explicit graph needs adaptation.

A player-managed configuration may be shorter, but it gives you less direct visibility into the subtitle branch. In either case, test the result in a local playback session before tying it to a long-running broadcast. If your broader workflow uses a shell script to keep a video loop running, the Linux shell-script loop guide is relevant to orchestration, not proof that the subtitle graph itself handles playlist retrieval or restarts.

Match subtitle timing to video timestamps

textoverlay relies on timestamps rather than simply displaying the next SRT line as soon as it is read. subparse turns the SRT cues into timed text; the overlay compares those times with the video stream and shows the cue for its specified interval. When timing is correct, captions appear over the scene they describe and disappear at the cue's end.

This also explains why a pipeline can run without errors and still look wrong. If all captions appear late by roughly the same amount, check for a consistent offset between the file and subtitle track. If the mismatch grows over the duration, the subtitles may have been authored for a different edit or timing basis. If only certain lines are wrong, inspect those cue boundaries and text. These are diagnostic clues, not guarantees about the cause.

For an initial test, pick a few moments you can identify in the video: an early cue, one around the middle, and one later on. Watch the cue start and end at each point. That gives you more information than checking only the opening seconds, where even a track that drifts later may appear correct. Keep the test playback at its ordinary speed and avoid judging timing from a seek operation alone, because a seek can affect how the player reaches a timestamp.

If you use playbin3 instead, the external subtitle URI is supplied with suburi alongside the media uri, according to the documented player interface. This can reduce graph wiring, but it does not change the need for a matching file and timing check. For more elaborate subtitle handling, GStreamer also documents subtitleoverlay, including controls such as subtitle encoding and timestamp offset; check the documentation and your installed version before relying on a property or default.

Test the visible overlay in playback

The sample command ends in autovideosink, so its purpose is to show the rendered result on a display. Run it first in a normal interactive session where you can see the video. Confirm that picture appears, that the expected SRT text is visible, and that captions enter and leave at the expected moments. If only the picture appears, check that the subtitle file path is correct and that the text branch reaches overlay.text_sink.

Make the test representative of the actual material. Include cues with longer lines, punctuation, non-English characters if your channel uses them, and any unusual line breaks. Font rendering and character encoding may vary with the installed plugins and system configuration. The subtitleoverlay documentation describes an encoding fallback path, but that should not be treated as a guarantee that every SRT text file will render correctly on every machine. Inspect the local configuration and use a small sample from your own content.

A visible overlay during local playback is evidence that the parsing and display path works for that test. It is not evidence that an output file has been written, that a YouTube live encoder is connected, or that an entire playlist can advance without intervention. Those are separate stages with separate failure modes. For an always-on channel, use a representative overnight-style test of the complete workflow before relying on it: media changes, subtitle pairing, output path, and recovery should all be observed in the arrangement you intend to operate.

That distinction matters particularly when the viewing computer is also expected to run a continuous broadcast. If you need to leave a computer on for playback and encoding, weigh its power and maintenance needs against a hosted workflow. A Beelink mini PC cost breakdown can help frame the local-computer side of that choice. Where the specific burden is keeping a source machine running for a file-based channel, StreamNeo removes that particular requirement by taking an uploaded video and running it as a YouTube live stream while your own computer is off; it does not replace preparing or verifying the subtitle source for a GStreamer pipeline.

Add encoding or muxing only if you need a saved file

If your goal is a permanently captioned output file, add a separate production stage after the overlay and verify it as a separate pipeline. The overlay must feed an appropriate video encoder, the encoded stream must be placed in a suitable container by a muxer, and the muxer must write to an output sink. The right encoder and container depend on your target format and environment; they are not included in the cited subtitle example, so do not infer a complete export command from it.

A saved file should be checked independently. Reopen it with a player, inspect several caption moments, and verify the image and audio. Confirm that the file has the expected duration and that captions are visibly part of the picture if that is the result you want. Merely adding filesink to the displayed example would not, by itself, add encoding or muxing: a video stream needs to be encoded and packaged in the intended output format.

There is a different choice if you want selectable captions rather than text permanently drawn into the image. That requires preserving a subtitle track in a suitable container and confirming support in the playback destination; it is not the same as the textoverlay rendering path. Decide whether viewers should be able to turn captions on and off, or whether the text must always be visible in the picture, before building the output graph.

For a live YouTube broadcast, producing a locally rendered file is still not the same as sending a live stream. A separate live-output pipeline needs to encode and deliver media using the settings and stream destination you have configured. Check current official YouTube guidance for the live setup you use, and do not assume that a working local preview means the broadcast is reaching YouTube. Likewise, if you are considering a cloud-run file loop, compare that operating model with your own hardware and playlist requirements rather than treating caption rendering as an automatic feature of the broadcast.

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 the documented textoverlay command create a captioned video file?

No. It draws parsed subtitle text over video for playback and sends the result to a display sink. To create a saved video with captions permanently in the picture, construct and verify a separate graph with encoding, muxing, and an output sink.

Can I put a YouTube playlist URL directly into this command?

The reviewed GStreamer documentation does not verify direct YouTube playlist URL resolution or playlist advancement. Treat resolving each entry to a readable media URI as a separate upstream task, then test the actual retrieval and subtitle pairing in your environment.

What should I try if the subtitle text is missing?

Check the SRT path, confirm that subparse and textoverlay are available, and verify the text branch ends at overlay.text_sink. Then check that the SRT is valid and that its cue times overlap the video's timestamps. An element or property may differ by installed GStreamer version, so inspect the local installation rather than assuming it matches an example.

Is playbin3 an alternative to textoverlay?

Yes, for simpler playback with an external subtitle file, GStreamer documents playbin3 with a media uri and subtitle suburi. It leaves more subtitle handling to the player; it does not demonstrate a YouTube playlist workflow or create a permanently captioned export.

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 Streaming Settings guides ↗ · All topics ↗