Skip to content

Add lossless DTS timestamp repair and verify reclassification - #833

Merged
ptr727 merged 10 commits into
developfrom
feature/dts-timestamp-repair
Jul 13, 2026
Merged

Add lossless DTS timestamp repair and verify reclassification#833
ptr727 merged 10 commits into
developfrom
feature/dts-timestamp-repair

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Summary

Verify no longer fails on benign non-monotonic DTS muxer warnings (see #827). ffmpeg -f null can exit 0 yet emit Application provided invalid, non monotonically increasing dts to muxer for files that decode and play correctly; the old "any stderr means failure" rule made these a permanent VerifyFailed/RepairFailed, and a re-encode could not fix it because Matroska stores no DTS and ffmpeg re-derives a non-monotonic timeline on read.

Changes

  • Verify reclassification (fail-closed):VerifyClassifier partitions the -f null stderr line by line as it streams (O(1) memory - a non-monotonic-DTS file emits one warning per packet). Only a recognized benign timestamp warning passes; anything else, including an unrecognized line, fails. Verify is deterministic (Clean/TimestampOnly/DecodeError); AutoRepair gates only whether the failure is repaired.
  • Lossless timestamp repair: a TimestampOnly failure is repaired with the setts bitstream filter (stream copy, no re-encode), gated by a byte-identical per-stream streamhash check, as the first repair tier ahead of the re-encode tier used for genuine decode corruption.
  • Consolidated packet analysis: the bitrate and per-stream DTS-monotonicity analyses now share a single ffprobe -show_packets pass.
  • analyze_frames closed captions: closed-caption detection uses ffprobe -analyze_frames -show_entries stream=closed_captions, retiring the movie=...[out0+subcc] lavfi filter and its QuickScan snippet-remux workaround.
  • New DtsTimestampRepair plugin: revisits files an older version marked RepairFailed, clears the flag when the failure was a benign timestamp issue, and losslessly repairs the timestamps when the DTS is demux-visible.
  • Version floor bumped to 3.21; README and HISTORY updated.

Testing

  • 207 unit tests pass (VerifyClassifier, DtsInfo, ClosedCaptions JSON, plugin loader); CSharpier, dotnet format style, markdownlint, shellcheck, cspell all clean.
  • End-to-end on real tooling: process on a demux-visible DTS file (system ffmpeg 7.1.5) -> Repaired, Verified; a post-decode DTS file -> Verified with no media change; the plugin on a seeded RepairFailed copy -> flag cleared, Verified+Repaired.
  • analyze_frames CC path validated end-to-end against ffmpeg 8.0.1 -> ClearedCaptions, Verified.

🤖 Generated with Claude Code

Verify no longer fails on benign non-monotonic DTS muxer warnings.
ffmpeg -f null can exit 0 yet emit "non monotonically increasing dts to
muxer" for files that decode and play; the old "any stderr fails" rule
made these a permanent VerifyFailed/RepairFailed that a re-encode could
not fix. Verify now classifies stderr line by line (streamed, so memory
stays bounded), fail-closed: only a recognized benign timestamp warning
passes, anything else fails. A timestamp-only result is a repairable
failure, cleaned losslessly with the setts bitstream filter and gated by
a byte-identical stream-hash check, ahead of the re-encode tier used for
genuine decode corruption.
Also consolidates the bitrate and DTS packet analyses into one
show_packets pass, switches closed-caption detection to ffprobe
analyze_frames, and adds the DtsTimestampRepair example plugin that
retroactively clears RepairFailed files an older version gave up on.
See #827.
CopilotAI review requested due to automatic review settings July 13, 2026 16:30

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates PlexCleaner's verify/repair pipeline to distinguish benign FFmpeg muxer timestamp warnings from real decode corruption, adds a lossless timestamp-repair tier, and modernizes closed-caption detection, with supporting tests, plugin example, and release docs/version bump.

Changes:

  • Add VerifyResult + VerifyClassifier and switch FFmpeg verify to streamed stderr classification (bounded memory).
  • Add lossless timestamp repair (setts + streamhash regression gate) and consolidate packet analysis into a single ffprobe -show_packets pass.
  • Switch closed-caption detection to ffprobe -analyze_frames and add the DtsTimestampRepair example plugin + tests/docs updates.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
version.jsonBumps version floor to 3.21.
README.mdAdds 3.21 release notes + docs for non-monotonic DTS repair and the new plugin example.
HISTORY.mdAdds detailed 3.21 changelog entry for verify reclassification, timestamp repair, and CC probe changes.
cspell.jsonAdds new technical terms used by the changes (e.g., setts, streamhash).
PlexCleaner/VerifyResult.csIntroduces deterministic verify classification enum.
PlexCleaner/VerifyClassifier.csImplements fail-closed stderr line classification (timestamp-only vs decode error).
PlexCleaner/FfMpegTool.csReturns VerifyResult, streams stderr classification, adds SetTimestamps + GetStreamHashes.
PlexCleaner/MediaTool.csAdds stderr streaming execution helper used by verify classification.
PlexCleaner/ProcessFile.csIntegrates verify classification, timestamp-only repair tier, packet analysis consolidation, and new CC probe path.
PlexCleaner/DtsInfo.csAdds per-stream DTS monotonicity tracking used to gate timestamp repair.
PlexCleaner/FfProbeTool.csReplaces lavfi subcc approach with -analyze_frames CC detection; consolidates packet probe entrypoint.
PlexCleaner/FfProbeBuilder.csAdds ReadIntervalFrames() helper for quick-scan bounding in CC probing.
PlexCleaner/FfMpegBuilder.csAdds -bsf:a builder support for setts.
PlexCleaner/FfMpegToolJsonSchema.csAdds JSON schema types for closed-captions probe output.
PlexCleaner/Program.csIntroduces a quick-scan frame-count constant for CC probing.
PlexCleaner.slnxAdds the new plugin project to the solution.
Plugins/DtsTimestampRepair/DtsTimestampRepairPlugin.csAdds example plugin to revisit legacy RepairFailed timestamp-only cases.
Plugins/DtsTimestampRepair/DtsTimestampRepair.csprojAdds plugin project definition referencing PlexCleaner.
PlexCleanerTests/VerifyClassifierTests.csAdds unit tests for stderr classification + streamed accumulator behavior.
PlexCleanerTests/DtsInfoTests.csAdds unit tests for DTS monotonicity detection.
PlexCleanerTests/ClosedCaptionsProbeTests.csAdds unit tests for the new closed-captions probe JSON parsing.
PlexCleanerTests/PluginLoaderTests.csExtends plugin-loader tests to cover the new example plugin.
PlexCleanerTests/PlexCleanerTests.csprojAdds the new plugin project reference so tests can load it.
PlexCleanerTests/FileNameEscapingTests.csRemoves tests for the retired lavfi movie=...[out0+subcc] escaping path.

Comment threadPlexCleaner/ProcessFile.cs Outdated
Comment threadPlexCleaner/ProcessFile.cs
Address Copilot review:
- The lossless timestamp repair rewrites the media, so log the decision
once at Warning before the rewrite, per the AGENTS.md logging taxonomy,
so it shows at --loglevel Warning.
- A non-monotonic DTS is a correctable verify failure, not a pass; reword
README and HISTORY so they no longer imply verify passes it.
CopilotAI review requested due to automatic review settings July 13, 2026 17:06

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/FfProbeTool.cs Outdated
A malformed or empty ffprobe stdout made ClosedCaptionsProbe.FromJson
throw and crash processing; catch and log like GetMediaPropsFromJson,
returning false instead.
CopilotAI review requested due to automatic review settings July 13, 2026 17:13

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Comment threadPlexCleaner/ProcessFile.cs
Comment threadPlexCleaner/FfMpegTool.cs
- Log a non-monotonic DTS (TimestampOnly) verify outcome so the
standalone verify command shows why it failed.
- Omit the empty error field when a silent non-zero ffmpeg exit has no
captured error line, matching LogFailedResult.
CopilotAI review requested due to automatic review settings July 13, 2026 17:22

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/ProcessFile.cs Outdated
TryLosslessTimestampRepair returned false for both a benign demux-clean
file and a genuine repair failure, so a demux-visible DTS whose setts
rewrite failed was wrongly marked Verified and never retried. Split the
outcome into NotApplicable, Repaired, and Failed: Failed now sets
VerifyFailed/RepairFailed, and cancellation leaves the state untouched.
CopilotAI review requested due to automatic review settings July 13, 2026 17:33

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/FfMpegTool.cs
CopilotAI review requested due to automatic review settings July 13, 2026 17:42

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/ProcessFile.cs Outdated
CopilotAI review requested due to automatic review settings July 13, 2026 17:48

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/ProcessFile.cs
CopilotAI review requested due to automatic review settings July 13, 2026 17:55

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/ProcessFile.cs Outdated
Accepting a timestamp-only re-verify marked a file Verified even though
it still fails verification, so a future run would skip it as already
verified and hide the remaining failure.
CopilotAI review requested due to automatic review settings July 13, 2026 18:03

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.

Comment threadPlexCleaner/FfMpegTool.cs Outdated
Previously a non-zero exit with only the benign DTS warning on stderr
stayed TimestampOnly; fail closed and classify any non-zero exit as a
decode error.
CopilotAI review requested due to automatic review settings July 13, 2026 18:10

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit ecf952a into developJul 13, 2026
13 checks passed
ptr727 added a commit that referenced this pull request Jul 13, 2026
A non-monotonic DTS that verify detects but the lossless setts repair cannot fix now stays RepairFailed instead of being cleared to Verified. Only a successful lossless repair or a clean re-verify clears the flag. Follow-up to #833.
ptr727 added a commit that referenced this pull request Jul 13, 2026
ffmpeg's 'Last message repeated N times' line was misclassified as a decode error, so a duplicate-DTS file was wrongly failed instead of losslessly repaired. Ignore those markers. Also log the unique decode-error lines (deduped by a normalized key, capped) so a failure reports every distinct error. Follow-up to #833/#834.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@ptr727