[Support]:Recording (Review) playback stalls on Safari and iOS because the VOD HLS playlist references about three times as many fragments as actually carry media #23452
Replies: 2 comments
-
|
This is a well-documented and thoroughly analyzed bug report. Your diagnosis aligns with a similar issue reported in the beta where the In that related discussion, the root cause was identified as the VOD/clip endpoint generating segments with minimal content (styp, sidx, empty moof, no mdat) that strict Apple decoders cannot process. (1) Your analysis showing that two of every three fragments are 164-byte empty fMP4 fragments—and that Safari stalls when reaching these data-less segments—matches the pattern described in the beta support discussion. (1) The VOD endpoints you're using follow this pattern: This returns an HLS playlist for the specified timestamp range, and you append Your workaround observations are consistent with the documented behavior—the Export workflow concatenates recordings server-side into a single MP4, bypassing the HLS segment stitching that produces the empty fragments. This appears to be a bug in Frigate's HLS playlist generation for the review/VOD endpoints, specifically affecting how segments are stitched together. The expected behavior, as noted in the related discussion, would be to either skip empty segments or merge them with the next segment. (1) I don't have documentation on a fix or workaround beyond what you've already discovered (using Export instead of Review playback). This would need to be addressed in Frigate's VOD segment generation code. 📚 Sources:
Have another question? Just tag @inkeep. |
Beta Was this translation helpful? Give feedback.
-
|
This seems likely to be a very specific combination of issues, I have multiple Hikvision cameras and no playback issues on iOS. Usually when we see lots of segments with no data, it's due to timestamp corruption in the segments causing bad segment encapsulation, something we see most with reolink cameras (though still quite uncommon in general). I'll see if we can come up with some ffprobe commands that might narrow down what might be going wrong in this case. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Checklist
Describe the problem you are having
On iOS (Safari + every native iOS Frigate companion app I tested - i have no non-iOS devices currently available), recording
playback under
/reviewstalls after ~5–15 s with a decode error. The interesting bit: the same files, served via different Frigate playback code paths on the same iOS device, work without issue.This strongly suggests the bug is in Frigate's recording-review HLS playlist generation rather than the underlying recordings, the camera streams, the codec, the container, or client-side decoder strictness. I assume this is the same issue as #7031 and Issue #18695 sounds similar, too. This seems to be dependent on the encoder in the camera. For some encodings stitching seems to fail
While diagnosing I think I found the cause. The review playlist (index-v1.m3u8) lists 296 fMP4 segments, each with a normal EXTINF duration, but only every third .m4s fragment actually contains media. The other two of every three are 164-byte empty fMP4 fragments (styp, sidx, and an empty moof, with no mdat). It seems a strict Apple decoder stalls once playback reaches one of these data-less fragments.
Environment
0.17.1-416a9b7docker top):(The
-bsf:v h264_metadata=video_full_range_flag=0is to fix a separateyuvj420p→yuv420pissue that affected playback before the review-stitching problem was isolated. Tested both with and without that filter; the stitching bug behaves the same either way.)Steps to reproduce
1781108096.452104-4wj1zmm 2026-06-10 16:14:56.452 UTC to 2026-06-10 16:15:03.082 UTC./review?id=1781108096.452104-4wj1zmon iOS Safari (or Lumen, Kapal, etc.)3.. Playback starts and then stalls after a short time without recovering. Scrubbing forward stalls again.
The stall point is not fixed. One screen capture stalls after about one second, another after about ten seconds. That variability is itself informative; see the analysis further down.
What works fine on the same iOS device
Exportworkflow — exports the same time window as a single server-side-concatenated mp4. Plays without error on the same iPad. created via.curl -X POST \ "http://100.64.0.17:5000/api/export/terasse/start/1781108096.452/end/1781108103.082" \ -H "Content-Type: application/json" \ -d '{"playback":"realtime","name":"ios-bug-terasse"}'What does NOT work
Reviewplayback (HLS playlist stitching 10-s segments) — stalls in Safari, Lumen for Frigate, Kapal and Viewu, all on iOS 18.7.8.Version
0.17.1-416a9b7
In which browser(s) are you experiencing the issue with?
Safari on iOS 18.7.8.
Frigate config file
docker-compose file or Docker CLI command
Relevant Frigate log output
Throughout a stalling session every request returns 200 or 206, and Frigate logs no errors or warnings. A representative sequence for the example event , from the Safari client: GET /vod/terasse/start/1781107200/end/1781110800/master.m3u8 200 165 GET /vod/terasse/start/1781107200/end/1781110800/index-v1.m3u8 200 1248 GET /vod/terasse/start/1781107200/end/1781110800/init-v1.mp4 200 739 GET /vod/terasse/start/1781107200/end/1781110800/seg-85-v1.m4s 200 14037059 GET /vod/terasse/start/1781107200/end/1781110800/seg-88-v1.m4s 200 14223397The client requests seg-85 and then seg-88 (and later seg-106 and then seg-109): a stride of three, which skips the empty fragments in between. The full one-hour access-log excerpt of a stalling session is linked at the end.
Operating system
Debian
Install method
Home Assistant Add-on
Network connection
Wired
Camera make and model
Hikvision DS-2CD2345G0P-I and others from the same era
Screenshots of the Frigate UI's System metrics pages
The playlist references far more fragments than carry media. For the example hour, index-v1.m3u8 lists 296 segments. It has a single EXT-X-MAP pointing at init-v1.mp4, no EXT-X-DISCONTINUITY tags, an EXT-X-TARGETDURATION of 33, and EXTINF durations between 6.0 and 32.8 seconds (183 of them exactly 10.
0). The head of the playlist:
Two of every three fragments are empty. The content lengths of the fragments around the event:
The 164-byte fragments are structurally valid fMP4 but carry no samples: a styp box, a sidx, and a moof with an mfhd, and no mdat. ffprobe confirms this. With init-v1.mp4 prepended, seg-85 decodes 463 frames with packet PTS from 848.92 to 879.28 seconds, that is about 30 seconds of media at 2688x1520; seg-86 yields zero packets.
The media-bearing fragments use continuous, absolute PTS. seg-85 spans 848.92 to 879.28 seconds of the hour and does not reset to zero, so PTS continuity across the real fragments is intact. This is not a case of missing EXT-X-DISCONTINUITY tags.The server side is clean.
Every request returns 200 or 206 and Frigate logs nothing during playback, so the failure is entirely on the client decoder.
The Export path, which concatenates the same recordings server-side into one continuous mp4, plays them without trouble on the same device.
Any other information that may be helpful
Hypotheses, not confirmed
The empty fragments are the most likely cause of the stall. The playlist's timeline includes nominal-duration segments that contain no samples, and a strict player that reaches one has nothing to render. This also fits the variable stall point. Depending on where the seek for the event lands within the cadence of one media fragment followed by two empty ones, the player renders anywhere from about a second up to the remainder of the current media fragment before it reaches the next empty one and stops. I have not proven the exact client behaviour.
Things tried and ruled out.
Things tried and ruled out.
Sample material, all public, for event 1781108096.452104-4wj1zm (camera terasse, 2026-06-10 16:14:56 to 16:15:03 UTC):
terasse/15.42.mp4
The event on our instance, behind authentication, for reference: https://nvr.foxel.org/review?id=1781108096.452104-4wj1zm
I hope this is helpful; I'm not really into video containers and codecs.
Beta Was this translation helpful? Give feedback.
All reactions