I am trying to send an MP4 video through Pion WebRTC to the browser.
Using FFmpeg, I split it into an Opus OGG stream and an Annex-B H.264 video stream. While the video works fine, the audio keeps cutting in and out. It plays fine for a few seconds, then stops for a second, and continues.
This is the FFmpeg command I use for audio:
ffmpeg -i demo.mp4 -c:a libopus -vn -page_duration 20000 demo.ogg
And this is my transmitter (shortened):
var lastGranule uint64
for {
pageData, pageHeader, err := ogg.ParseNextPage() // Uses Pion OggReader
// Taken from the play-from-disk example
sampleCount := float64(pageHeader.GranulePosition - lastGranule)
lastGranule = pageHeader.GranulePosition
sampleDuration := time.Duration((sampleCount/48000)*1000) * time.Millisecond
err = audioTrack.WriteSample(media.Sample{Data: pageData, Duration: sampleDuration})
util.HandleError(err)
time.Sleep(sampleDuration)
}
I tried hardcoding the delay to 15ms, which fixes the issue that it's cutting out, but then it randomly plays way too fast or starts skipping. Since I had glitchy video before updating my FFmpeg command (add keyframes and remove b-frames), I assume this is also an encoder problem.
What could be the cause for this?
Update: Using WebRTC logging in Chrome, I discovered the following log lines that occurred frequently:
[27216:21992:0809/141533.175:WARNING:rtcp_receiver.cc(452)] 30 RTCP blocks were skipped due to being malformed or of unrecognized/unsupported type, during the past 10 second period.
This is probably the reason for the cutouts, although I can't figure out why it receives malformed data.
The problem in the end was an inaccuracy in the Sleep time caused by issue #44343 in Go itself. It caused the samples not to be sent at a constant rate, but at a rate that randomly was between 5 and 15ms off, resulting in a choppy stream.
Sean DuBois and me fixed this in the latest play-from-disk
and play-from-disk-h264
examples in the Pion repository by replacing the for
-loop and Sleep()
with a Ticker
, which is more accurate.