diff --git a/machinery/src/video/mp4.go b/machinery/src/video/mp4.go index faaa783..938e2e3 100644 --- a/machinery/src/video/mp4.go +++ b/machinery/src/video/mp4.go @@ -66,7 +66,6 @@ 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 @@ -327,23 +326,13 @@ 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. - // - // 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 + // 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 } if trackID == uint32(mp4.VideoTrack) { mp4.LastKeyframeRawPTS = pts