SRT Streaming – ZLMediaKit TS Demuxer Crash
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 18/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Domain
- audio-video-rtc, mobile-dev
Research direction
The crash is an assertion in ts_demuxer_input in libmpeg/source/mpeg-ts-dec.c (line 261) on the ZLMediaKit side, preceded by packet-loss logs from SrtTransport.cpp (handleDataPacket) and TSDecoder.cpp (line 69). On the client, the muxing setup is in SrtSender.kt (setTrackConfig, sendAudioFrame). Start by reproducing with the ZLMediaKit Docker image and capturing the TS packets around the lost-packet range. Done means identifying which TS invariant the demuxer rejects, and the issue has no assignee and no maintainer answer.
Written by the indexing model from the issue text.
Description
Environment
- Client Library: RootEncoder (Pedro's library)
- Server: ZLMediaKit (latest
masterbranch, Docker) - Docker Image:
zlmediakit/zlmediakit:master - Protocol: SRT with MPEG-TS muxing
- Codec: H.264 (also tested with H.265)
- Platform: Android (tested Android 11+)
Issue Description
SRT streaming using MPEG-TS causes ZLMediaKit to crash after approximately 4–5 minutes of streaming.
The server terminates due to an assertion failure inside the TS demuxer.
Assertion failed: (0), function ts_demuxer_input,
file /opt/media/ZLMediaKit/3rdpart/media-server/libmpeg/source/mpeg-ts-dec.c,
line 261
Error Details
ZLMediaKit Log
2026-01-20 17:28:52.692 T [MediaServer] [1-event poller 5] SrtTransport.cpp:776 handleDataPacket | pkt lost 1770381322->1770382164
2026-01-20 17:28:52.692 W [MediaServer] [1-event poller 5] TSDecoder.cpp:69 operator() | ts packet lost, dts:25771715 pts:25771715 bytes:14465
2026-01-20 17:28:55.275 T [MediaServer] [1-event poller 5] UdpServer.cpp:342 operator() | 60-57(192.168.1.36:59624) SRT::SrtSession on err: 6(Assertion failed: (0), function ts_demuxer_input, file /opt/media/ZLMediaKit/3rdpart/media-server/libmpeg/source/mpeg-ts-dec.c, line 261.)
- Stream duration before crash: ~291 seconds
Configuration
Video Encoder (Android)
- Resolution: 720p (1280×720)
- FPS: 30
- Bitrate: 2.5 Mbps
- GOP: 2 seconds (60 frames)
- Codec: H.264 (also tested H.265)
- Audio: Disabled (video-only stream)
SRT Client
- Latency: 300ms
- Cache: 1200 frames
- CheckServerAlive:
true
Code Implementation
SrtSender.kt (video-only TS)
private fun setTrackConfig(videoEnabled: Boolean, audioEnabled: Boolean) {
Pid.reset()
service.clearTracks()
if (videoEnabled) service.addTrack(commandsManager.videoCodec.toCodec())
service.generatePmt()
psiManager.updateService(service)
Log.i(TAG, "Track config: video=$videoEnabled, audio=false (forced video-only for SRT)")
}
override suspend fun sendAudioFrame(mediaFrame: MediaFrame) {
Log.d(TAG, "Skipping audio packet for video-only SRT stream")
return
}
Reproduction Steps
- Configure
GenericStreamwith H.264 encoder (720p @ 30fps, 2.5Mbps) - Set SRT URL:
srt://server:9000?streamid=publish:app/stream - Start streaming
- Stream runs normally for 4–5 minutes
- ZLMediaKit crashes with TS demuxer assertion failure
Observations
- RTMP streaming with identical encoder settings is stable for 1–5 hours
- SRT streaming crashes consistently after 4–5 minutes
- Issue reproduces with:
- H.264 and H.265
- Bitrates from 1.5 Mbps to 5 Mbps
- Resolutions from 360p to 720p
Analysis / Suspected Causes
PCR Timing Issues
val pcr = if (isAudio && !mpegTsPayload.isKeyFrame)
null
else
TimeUtils.getCurrentTimeMicro()
For video-only streams, PCR may not be continuous or frequent enough for strict TS demuxers.
Adaptation Field Flags
randomAccessIndicatoris only set for keyframes
Continuity Counter
- Potential overflow or reset issues during long streams
PTS / DTS Drift
- Timestamp drift may accumulate over time
Potential Fixes
Fix 1: Always Include PCR for Video-Only Streams
val pcr = TimeUtils.getCurrentTimeMicro()
Fix 2: Enforce PCR Interval (e.g. every 100ms)
private var lastPcrTime = 0L
private val pcrInterval = 100_000L
val currentTime = TimeUtils.getCurrentTimeMicro()
val pcr = if (currentTime - lastPcrTime >= pcrInterval) {
lastPcrTime = currentTime
currentTime
} else null
Fix 3: Validate Continuity Counter Wrap
pesContinuity = (pesContinuity + 1) and 0xF
if (pesContinuity == 0) {
Log.w(TAG, "PES continuity counter wrapped")
}
Workarounds
- Use RTMP instead of SRT (stable for hours)
- Patch ZLMediaKit TS demuxer to skip invalid packets instead of asserting
Expected Behavior
SRT streaming should remain stable for hours without TS demuxer crashes.
Questions
- Is this a known compatibility issue with ZLMediaKit’s TS demuxer?
- Does ZLMediaKit expect stricter PCR / continuity rules for MPEG-TS over SRT?
- Should TS packet generation be adjusted to be more conservative?
- Dominant language
- Kotlin
- Stars
- 3k
- Forks
- 946
- Avg merge
- 5d 1h
- Merged PRs (30d)
- 6
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pedroSG94/RootEncoder
-
Scheme-less stream URLs throw NullPointerException instead of URISyntaxExceptionPossibly taken @blihio claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
pedroSG94/RootEncoder#2218 ·
Maintainers usually reply within 3 days
-
Nullable GIF input causes NullPointerException in GifStreamObject.loadPossibly taken @blihio claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
pedroSG94/RootEncoder#2216 ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
pedroSG94/RootEncoder#2213 ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 43/100
pedroSG94/RootEncoder#2220 ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
pedroSG94/RootEncoder#2207 · 1 reaction ·
Maintainers usually reply within 3 days
All issues in pedroSG94/RootEncoder
Similar issues
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
Maintainers usually reply within 1 day
-
afk-ok area:agents size:S
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
enorm-labs/event-junkie#3523 ·
Maintainers usually reply within 1 day
-
submit-adaption submit-adaption-pre
Difficulty 1/5 Under an hour Newbie friendliness 82/100
BetterAndroid/android-notification-icon-project#750 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
lysine-dev/okhttp#9797 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
openbase/planetsudo.engine#107 ·
Maintainers usually reply within 1 day