Fix DTS repair escalation and idet parse regressions - #844
Merged
Conversation
The interlace detector required the three idet stat lines (Repeated Fields / Single frame / Multi frame) to be a single contiguous block. ffmpeg interleaves other stderr lines between them: on a source with non-monotonic DTS the -f null muxer emits "non monotonically increasing dts to muxer" warnings (idet uses -fflags +genpts), and a full-file scan decodes enough packets that a warning lands between the stat lines. The contiguous match then finds nothing, so the parse fails and the whole file is aborted, skipping the remux/re-encode that would repair it. Match each stat line independently and take the last of each: robust to interleaved warnings, and it still selects the final cumulative counts over idet's early all-zero pass. Log the raw idet output on a parse failure so any remaining unexpected case is diagnosable rather than guessed at. An idet failure stays a hard error that aborts the file: it is unexpected, so it should surface as a bug to fix, not be masked. Adds a regression test with warnings interspersed between the stat lines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A non-monotonic DTS verify failure only tried the lossless audio setts repair; when that did not apply (a video-stream or post-decode DTS) the file was marked RepairFailed with no further attempt. A full re-encode rebuilds the timestamps and does fix these, which the pre-3.21 pipeline relied on, so several files that used to repair now fail. Make the DTS path escalate through the standard repair tiers: surgical lossless setts, then a plain remux, then a re-encode, marking Repaired on the first tier whose re-verify is clean and RepairFailed only when all tiers fail. Add the missing remux tier to RepairAndReVerify so both the DTS and decode-error paths share the same surgical -> remux -> re-encode escalation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Time each file's task in ProcessDriver and report it on the "After" line, with the elapsed before the file name (file name last, being longest). Share one HH:mm:ss.fff formatter with the run summary so both read the same; hours come from TotalHours so a multi-day run does not wrap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses two media-processing regressions introduced in the 3.20 -> 3.21 transition (idet parsing and DTS repair escalation) and adds more consistent per-file timing diagnostics in the processing driver.
Changes:
- Make ffmpeg
idetparsing robust to interleaved stderr output by matching each stats line independently, and log the raw output on parse failure. - Escalate non-monotonic DTS repairs through the standard repair tiers (lossless setts -> remux -> re-encode) instead of stopping after setts failure.
- Add per-file elapsed timing (plus consistent duration formatting) to driver logging, with targeted tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| PlexCleaner/FfMpegIdetInfo.cs | Reworks idet parsing to tolerate interleaved warnings and improves failure diagnostics. |
| PlexCleaner/ProcessFile.cs | Adds a remux repair tier and escalates DTS repair through remux/re-encode fallbacks. |
| PlexCleaner/ProcessDriver.cs | Times per-file processing and introduces a shared FormatDuration() for consistent elapsed logging. |
| PlexCleanerTests/FfMpegIdetParsingTests.cs | Adds regression coverage for idet output with interleaved non-monotonic DTS warnings and updates parsing assertions. |
| PlexCleanerTests/ProcessDriverTests.cs | Adds unit coverage for FormatDuration() millisecond precision and multi-day hour accumulation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-ups from the 3.20→3.21 regression diff. Two files-flip-to-failed regressions plus a diagnostics/logging improvement.
1. idet parse robustness (interlace detection)
VC1 - National Lampoon's Christmas Vacationregressed to anError(Failed to parse idet output→Failed to count interlaced frames), aborting the file before it could be re-encoded.Root cause (confirmed against ground-truth ffmpeg output): the parser required the three idet stat lines contiguous. The idet command uses
InputOptions.Default(), which adds-fflags +genpts; on a source with non-monotonic DTS the-f nullmuxer emits"non monotonically increasing dts to muxer"warnings interleaved with the idet stats, and a full-file scan decodes enough packets that a warning lands between the stat lines →matches.Count == 0.Fix: match each stat line independently and take the last of each (robust to interleaving; still selects the final counts over idet's early all-zero pass). Log the raw idet output on a parse failure. An idet failure stays a hard error that aborts the file — it is unexpected, so it should surface as a bug, not be masked. Regression test added with warnings interspersed between the stat lines.
2. DTS repair escalation
Six files that were
Repaired, Verifiedpre-3.21 becameRepairFailed(50 First Dates, Kill Bill, Bitrate Love Island, Running Wild, Diplo, 90 Day). A non-monotonic DTS that the lossless audiosettsrepair couldn't fix (video-stream or post-decode) was markedRepairFailedwith no further attempt; a full re-encode fixes these and the pre-3.21 pipeline relied on it.Fix: the DTS path now escalates through the standard tiers — surgical lossless
setts→ plain remux → re-encode — markingRepairedon the first tier whose re-verify is clean,RepairFailedonly when all fail. Added the missing remux tier toRepairAndReVerifyso the DTS and decode-error paths share onesurgical → remux → re-encodeladder.3. Per-file processing time
Time each file's task in the driver and log it on the
Afterline (elapsed before the file name), sharing oneHH:mm:ss.fffformatter with the run summary (hours fromTotalHours, no multi-day wrap).Validation
Local build + develop image ffmpeg 8.0.1,
--parallel --testsnippets:ReMuxed, ReEncoded, Verified, no idet failure (was abort).Repaired, Verifiedviasetts→remux→re-encode(wasRepairFailed).217 tests pass; build + format clean.
🤖 Generated with Claude Code