-r flag and remove B-frames with -bf 0. These adjustments ensure the output stream has predictable timing, allowing RTSP clients to decode the video without buffer underflow or synchronization errors.
Understanding Non-Monotonous DTS
DTS stands for Decode Time Stamp. In a valid video stream, these timestamps must be monotonically increasing, meaning each subsequent frame's DTS must be greater than or equal to the previous one. When FFmpeg encounters a situation where the calculated DTS decreases or jumps unpredictably, it halts processing to prevent downstream players from desynchronizing audio and video.
This issue is particularly common when converting container formats like MP4 to streaming protocols like RTSP. The source MP4 file may contain Variable Frame Rate (VFR) content, such as screen recordings or certain camera feeds, where the time between frames varies. Additionally, modern codecs often use B-frames (Bidirectional frames) which reference both past and future frames, complicating the DTS ordering. RTSP servers expect a steady, linear stream of data, making them sensitive to these irregularities.
Why MP4 Files Cause This Issue
MP4 files are highly flexible containers that can store video with complex temporal structures. Unlike raw streams, they allow for:
- Variable Frame Rates: Frames are not spaced evenly in time.
- B-Frames: These frames are displayed out of order relative to their decoding order, requiring careful rearrangement of timestamps.
- Keyframe Intervals: Irregular keyframe placement can disrupt the stream structure if not handled correctly by the encoder.
When FFmpeg reads these complex structures, it attempts to map them to a linear timeline. If the mapping logic fails to account for all edge cases in the source file, it produces non-monotonic DTS values, triggering the error.
Solution 1: Force Constant Frame Rate
The most effective way to fix non-monotonous DTS is to force FFmpeg to output a Constant Frame Rate (CFR). This ensures that every frame is spaced exactly at the same interval, eliminating timing jitter. You can achieve this by adding the -r flag followed by the desired frame rate (e.g., 30 or 60).
ffmpeg -i input.mp4 -c:v libx264 -r 30 -f rtsp rtsp://localhost:8554/stream
In this command, -r 30 tells FFmpeg to output 30 frames per second consistently. If the source has a different frame rate, FFmpeg will either drop duplicate frames or repeat frames to maintain the 30fps rhythm. This regularization of time intervals resolves the DTS calculation errors because the decoder knows exactly when each frame should arrive.
Solution 2: Remove B-Frames
B-frames are another major contributor to DTS issues. They require the decoder to have access to future frames before displaying the current one, which creates complex dependency chains. RTSP streaming benefits from simpler prediction modes. You can disable B-frames by adding -bf 0 to your FFmpeg command.
ffmpeg -i input.mp4 -c:v libx264 -bf 0 -f rtsp rtsp://localhost:8554/stream
By setting -bf 0, you instruct the H.264 encoder to only use I-frames (Intra) and P-frames (Predictive). This simplifies the decoding process significantly. While it may slightly increase bitrate due to reduced compression efficiency, it guarantees a linear DTS flow. This method is especially useful for live streaming scenarios where low latency and stability are prioritized over maximum compression.
Solution 3: Use Muxing Options for RTSP
RTSP has specific requirements for how data is packaged. Using appropriate muxer options can help FFmpeg manage timestamps more effectively. The -fflags +genpts option forces FFmpeg to generate new PTS/DTS values based on the packet duration, rather than relying on the source file's potentially flawed timestamps. Combine this with -movflags +frag_keyframe if you are using fragmented MP4 containers, though for standard RTSP, simple muxing flags often suffice.
ffmpeg -i input.mp4 -c:v libx264 -r 30 -bf 0 -fflags +genpts -f rtsp rtsp://localhost:8554/stream
This comprehensive approach addresses multiple potential causes simultaneously. It forces a constant frame rate, removes complex B-frames, and regenerates timestamps from scratch. This combination is robust against various types of source file anomalies.
Related Streaming Considerations
When troubleshooting RTSP streams, it is important to consider the entire pipeline. For instance, if you are converting other formats like HEVC, similar timestamp issues may arise. See How to Convert HEVC MP4 to HLS Stream with ffmpeg for insights into handling complex codec timestamps. Additionally, audio synchronization is critical; if your audio track also experiences playback issues after fixing the video DTS, refer to Fixing AAC Audio Tracks That Won't Play After FFmpeg Transcode to ensure both tracks remain aligned.
If you are integrating this stream into a web application, you might encounter client-side buffering errors. Check Streaming RTSP URL Video Using Node.js: Troubleshooting FFmpeg Errors for debugging strategies related to network delivery and player compatibility.
Frequently Asked Questions
Why does my RTSP stream freeze after starting?
Freezing usually indicates that the client cannot keep up with the incoming data rate or that timestamps are misaligned. Ensure you are using a constant frame rate (-r) and check your network bandwidth. If the bitrate is too high, reduce it with -b:v.
Can I use H.265 (HEVC) instead of H.264 for RTSP?
Yes, but many older RTSP clients and hardware decoders do not support HEVC. H.264 remains the standard for broad compatibility. If you must use HEVC, ensure your client supports it and apply the same DTS fixes.
Does removing B-frames affect video quality?
Removing B-frames can slightly reduce compression efficiency, leading to a larger file size or higher bitrate for the same visual quality. However, for real-time streaming, the trade-off is often worth it for the increased stability and lower latency.
What if the source video has no audio?
If the source lacks audio, FFmpeg might still try to create an empty audio stream, which can cause sync issues. Use -an to explicitly disable audio encoding if you only need video, preventing unnecessary timestamp calculations for missing audio packets.
How do I verify the DTS values in the output?
You can use ffprobe to inspect the stream properties. Run ffprobe -show_packets output.ts to view individual packet timestamps. Look for any negative delta values or decreasing sequences, which indicate persistent DTS problems.