A GStreamer timestamp warning when a file loops is not enough to identify a fix. The cause may be a timestamp reset, a segment transition, stream-event handling, or an element-specific constraint; you need the exact warning, pipeline, media details and GStreamer version to tell which.
Start by recording what happens to audio and video timestamps at the loop boundary, then check the active segment and event sequence. Validate YouTube encoder settings separately: they matter to ingest health, but changing them does not repair an incoherent local timeline.
Record the warning and pipeline
Capture the complete warning, including the element name, timestamp values if shown, and nearby log lines. “Non-monotonic DTS when looping a file” and a decoder warning about timestamps are not interchangeable diagnoses. A message from a muxer or RTMP output element points to a different stage than one emitted by a demuxer or decoder.
Record the GStreamer version and the full pipeline string, or a graph that shows every source, demuxer, parser, decoder, conversion element, muxer and sink. Include the file’s container and audio/video codecs. If you use application code to control playback, note how looping is triggered: a segment seek, an EOS callback, a restarted source, multifilesrc, concatenated files, or a restart of the whole pipeline.
Also note whether the warning happens on every pass, only after a seek, or after the channel has run for some time. That distinction can direct attention towards a repeatable boundary transition, a later stream-state change or another failure. Keep a short log from one pass before the warning and one after it, rather than relying on a paraphrase.
Do not begin by changing timestamp properties at random. An offset that hides a warning may create a gap, break audio/video alignment or move the problem to a downstream element. The literal message and the point where it appears should determine what values you inspect next.
Understand PTS and DTS
PTS is the presentation timestamp: when a decoded frame or audio buffer is meant to be presented. DTS is the decoding timestamp: when encoded data needs to be processed for decoding. They can differ, especially with compressed video that reorders frames. Either value can also be unknown.
GStreamer’s buffer reference describes DTS as usually monotonic, but does not require PTS to be monotonic in every stream. So a PTS sequence that moves backwards is not, on its own, proof of a bad stream. First establish which timestamp the warning names, which element reports it and whether that element has a specific ordering requirement.
Inspect the timestamps actually emitted by the demuxer or decoder and delivered to the muxer. Do not assume PTS and DTS should rise together, or that they must be equal. For each buffer, record PTS, DTS, duration and flags. A value of GST_CLOCK_TIME_NONE means the timestamp is not available; it is not a timestamp of zero.
The GstBuffer reference documents timestamp fields and the DISCONT flag. That flag marks a discontinuity, commonly after a seek or dropped buffer. It communicates stream state; it does not turn invalid timestamps into valid ones or establish a continuous timeline by itself.
A useful first question is whether the warning reflects a real regression in the field it names. Compare actual adjacent buffer values at the relevant element, not just a graph of perceived playback or the time shown in a player. If DTS is the concern, track DTS. If PTS is the concern, account for frame reordering and the active segment before concluding that presentation order is broken.
Inspect timestamps around the loop boundary
Log the final few audio and video buffers before a pass ends and the first few after the next pass begins. For each, capture PTS, DTS, duration, flags and, where possible, the active segment fields. Compare the values both at the demuxer or decoder output and at the muxer input. If they differ between those points, the element where they change is a more useful lead than the file alone.
Look for concrete patterns: a timestamp becoming unknown, a reset to zero, a repeated value, a gap, or a genuine regression in DTS. A file may naturally start its timestamps again at a new pass. Whether that is acceptable depends on how the pipeline represents the new segment and on what the downstream muxer expects; a reset alone does not prove what the correction should be.
Compare running time as well as raw timestamps. GStreamer maps buffer timestamps to running time using the preceding SEGMENT event. Raw timestamps from two different segments may not be directly comparable. The GStreamer synchronisation design explains how this mapping relates timestamps to pipeline running time.
Write down the last buffer’s values and the first buffer’s values on both streams. Then ask: are they in the expected segment, does the mapping produce the intended continuity, and does the element reporting the warning receive the same values you logged upstream? This keeps diagnosis tied to evidence instead of treating every boundary as a demand for an arbitrary timestamp offset.
Check segment and timeline behaviour
A file loop is a stream-state transition as well as a change in media position. GStreamer’s common event lifecycle is STREAM_START, then SEGMENT, then buffers, then EOS; after EOS, no more data is expected for that stream. If an application injects another pass after EOS, or restarts only part of the graph, it must account for that lifecycle rather than merely resetting timestamp numbers.
One documented approach for a continuous pipeline is a segment seek. With GST_SEEK_FLAG_SEGMENT, playback of the requested range completes with SEGMENT_DONE; the application can then issue another seek. The GStreamer seeking guide describes this pattern and the seek-related event flow. Confirm that all relevant streams participate coherently and that each element in the path handles the resulting events as expected.
A different design may restart a file source or the whole pipeline. In that case, inspect the STREAM_START, SEGMENT, flush and EOS behaviour at the boundary. The new pass may begin with media timestamps at an earlier point, so the surrounding pipeline has to establish the intended output timeline. Whether and how timestamps need rewriting depends on which element owns them and on the muxer’s documented requirements.
| Loop strategy | What stays alive | What to inspect at the boundary | Main trade-off |
|---|---|---|---|
| Segment seek | The pipeline can remain running | SEGMENT_DONE, the next seek, stream participation and segment mapping |
Requires the source and downstream elements to handle seeks coherently |
| Source or file restart | Some or all of the source path is restarted | New stream and segment events, flush and EOS behaviour, timestamp reset | A fresh pass can change stream state; continuity must be established downstream |
| Concatenation or multiple files | Often the surrounding output path remains active | Per-file timestamps, stream formats and transitions between inputs | Useful for a sequence, but each boundary still needs compatible timing |
This table is a way to compare designs, not a promise that one strategy fixes every warning. Accurate seeking can require scanning a file when it lacks an index, and the demuxer must support the relevant operation. Choose the loop model deliberately, then verify its actual event and timestamp behaviour in your pipeline.
Do not set DISCONT as a substitute for a valid segment or a suitable timeline. It may be appropriate after a seek or dropped data, but confirm what downstream elements do with it. Likewise, do not force PTS equal to DTS or apply an offset merely because values differ across the boundary.
Compare audio and video timing
Inspect audio and video separately before deciding that they are out of sync. Their buffers have different durations and their timestamps need not appear in matching steps. A video frame may have a PTS distinct from its DTS; an audio buffer covers a span of samples. Comparing one audio timestamp with one video timestamp without considering duration and segment mapping can give a misleading picture.
For each stream, compare the final buffers before the boundary and the first buffers after it. Check whether either timestamp is missing, whether a reset occurs in one stream but not the other, and whether running time remains consistent with the intended presentation. If only audio triggers the warning, focus on the audio path and the element named in the log. If only video does, do the same for the video path. If both change, inspect the shared seek, event handling or restart logic.
Also check whether both streams are included in the same loop operation. A seek or source restart that reaches video but not audio can produce a mismatch even when each stream’s timestamps appear plausible in isolation. Confirm that the pipeline’s segment transitions cover the streams you intend to broadcast, and verify the muxer receives the results you expect.
For a useful comparison, make a compact boundary record: stream name, buffer order, PTS, DTS, duration, flags, segment mapping and the reporting element. Add notes for the first buffers after the transition. This is more actionable than saying “the audio drifts” because it distinguishes a timing problem at the source from a change introduced later in the graph.
If you operate a recorded-video loop through OBS rather than a custom GStreamer pipeline, the controls and failure modes differ. The practical distinction is covered in this guide to OBS settings for looping devotional videos on YouTube Live. Do not carry a GStreamer-specific timestamp remedy over to an OBS scene without checking how that application handles playback.
Validate YouTube encoder settings separately
Once the local timeline is coherent, check the outbound encoder configuration against YouTube’s current guidance. YouTube recommends a two-second keyframe frequency and says not to exceed four seconds. Its live encoder settings guide also lists supported codecs and bitrate guidance for live ingest. Those recommendations are configuration checks, not evidence that a GStreamer loop boundary is correct.
For RTMP or RTMPS, YouTube’s guidance lists H.264, H.265 or AV1 video, AAC or MP3 audio, and CBR bitrate encoding; 5.1 audio is supported only with AAC. Confirm the protocol and settings you actually use against the official page, since guidance can change. Then send representative audio and video and check the stream-health feedback in Live Control Room.
A stream-health warning can identify an ingest or encoding issue, but it does not by itself reveal whether a local PTS/DTS transition, segment mapping or event lifecycle is wrong. Keep the checks separate: establish what the GStreamer graph delivers at the muxer, then verify the encoded output and ingest health. YouTube’s test guidance is a useful reminder to test the setup before relying on it for a live channel.
If your issue is actually an encoder bitrate choice rather than a loop-boundary warning, use a separate reference such as this YouTube bitrate guide for 720p loop streams. It addresses a different decision. Raising or lowering bitrate should not be treated as a repair for a timestamp warning unless the evidence points to an encoding problem.
Retest with a minimal reproduction
After collecting the evidence, reduce the pipeline without changing the part that reproduces the problem. Use the same media file, loop method and relevant GStreamer version. Remove unrelated overlays, transformations or output paths one at a time, and keep the element named in the warning if possible. The goal is to locate where the observed values or events first diverge, not to construct a different pipeline that no longer demonstrates the issue.
Test a single pass, then the transition, and then repeated passes. Log timestamps and events at the same points each time. If the warning disappears when a particular element is removed, add it back and inspect what it changes. If the reduced case still fails, you have a clearer report for the element’s documentation or support channel.
Before asking for a code-level diagnosis, assemble the exact warning, GStreamer version, media container and codecs, full pipeline or graph, loop mechanism, and the boundary log for both streams. Include which element emitted the warning and whether the relevant values are raw timestamps or running times. Without those details, a definitive fix would be guesswork.
For a channel that does not need a custom GStreamer pipeline, eliminating local file-loop orchestration may remove one source of overnight operational work. StreamNeo turns an uploaded video into a YouTube live stream that can run with your computer switched off, so you do not have to manage a local playback loop; it is not a GStreamer debugging tool and is YouTube-only. If you want to compare the costs and trade-offs of running a stream locally versus using a cloud option, this guide to choosing a cloud streaming service lays out the decision.
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 every PTS value have to increase?
No. GStreamer allows PTS not to be monotonic in every stream, and compressed video can have PTS and DTS values that differ. Check the field named by the warning, the active segment and the element reporting it before treating a sequence as invalid.
Will setting DISCONT fix a loop timestamp error?
Not by itself. The flag marks a discontinuity, often after a seek or dropped buffer, but does not supply valid timestamps or a suitable segment mapping. Verify that the flag, timestamps and downstream event handling match the intended transition.
Should I use a segment seek for every loop?
A segment seek is a documented GStreamer pattern for looping a range in a continuous pipeline, but it is not automatically right for every source and graph. Check whether the source supports accurate seeking and whether downstream elements handle SEGMENT_DONE and the next segment coherently.
Can YouTube’s encoder settings fix non-monotonic DTS?
Encoder settings are a separate validation step. Check YouTube’s current keyframe, codec and bitrate guidance after confirming the local timeline; changing those settings does not establish why a GStreamer element saw a timestamp regression.