diff --git a/machinery/src/video/mp4.go b/machinery/src/video/mp4.go index 938e2e3..faaa783 100644 --- a/machinery/src/video/mp4.go +++ b/machinery/src/video/mp4.go @@ -66,6 +66,7 @@ type MP4 struct { FragmentStartRawPTS uint64 // Raw PTS for timing when to flush fragments FragmentStartDTS uint64 // Accumulated VideoTotalDuration at fragment start (matches tfdt) LastKeyframeRawPTS uint64 // Raw PTS of the most recently seen keyframe (in any fragment) + LastKeyframeGapMs uint64 // Gap (ms) between the previous two consecutive keyframes MoofBoxes int64 // Number of moof boxes in the file MoofBoxSizes []int64 // Sizes of each moof box SegmentDurations []uint64 // Duration of each segment in timescale units @@ -326,13 +327,23 @@ func (mp4 *MP4) AddSampleToTrack(trackID uint32, isKeyframe bool, data []byte, p // fragment with a "media corruption" error because the inner IDR resets // frame_num/POC inside what they expect to be a single GOP. Force a // fragment boundary whenever two consecutive keyframes arrive much - // closer than a normal GOP (here: < 500 ms apart). This isolates the - // seam IDR into its own fragment so each fragment stays a clean GOP. - if !shouldFlush && trackID == uint32(mp4.VideoTrack) && mp4.Start && - mp4.LastKeyframeRawPTS > 0 && pts > mp4.LastKeyframeRawPTS && - pts-mp4.LastKeyframeRawPTS < MinNormalGOPMs { - log.Log.Warning(fmt.Sprintf("mp4.AddSampleToTrack(): forcing fragment flush at unexpectedly close keyframe (gap=%d ms, fragment elapsed=%d ms) - likely upstream loop/restart discontinuity", pts-mp4.LastKeyframeRawPTS, elapsed)) - shouldFlush = true + // closer than a normal GOP. + // + // We only flag this as a seam when it is a *sudden* anomaly: the + // previous keyframe gap must have been healthy (>= MinNormalGOPMs). + // This avoids false positives on cameras that legitimately emit + // short-interval IDRs (short GOP, motion-triggered recovery IDRs, + // all-intra streams) where every keyframe would otherwise be flagged + // in a cascade, producing many tiny fragments and log spam. + if trackID == uint32(mp4.VideoTrack) && mp4.Start && + mp4.LastKeyframeRawPTS > 0 && pts > mp4.LastKeyframeRawPTS { + gap := pts - mp4.LastKeyframeRawPTS + if !shouldFlush && gap < MinNormalGOPMs && + (mp4.LastKeyframeGapMs == 0 || mp4.LastKeyframeGapMs >= MinNormalGOPMs) { + log.Log.Warning(fmt.Sprintf("mp4.AddSampleToTrack(): forcing fragment flush at unexpectedly close keyframe (gap=%d ms, fragment elapsed=%d ms) - likely upstream loop/restart discontinuity", gap, elapsed)) + shouldFlush = true + } + mp4.LastKeyframeGapMs = gap } if trackID == uint32(mp4.VideoTrack) { mp4.LastKeyframeRawPTS = pts