d91beef0fd314250d8d9b94de86dfea019a8bd96
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
dc3527ab05 |
fix(dub): stereo, full-band music bed — separate the HQ extraction, pin the mix to stereo (#1138)
* fix(dub): stereo, full-band music bed — separate the HQ extraction, pin the mix to stereo Owner asked for a channels/Hz/samples comparison of a dub against its original to tune generation toward the source. The measurements found a class, not a knob: L/R correlation: original 0.754, dub 1.000 (mono in a stereo container) stereo width (S/M): 0.375 vs 0.003 LUFS: -17.8 vs -17.2 (already fine) Two stacked causes: 1. INGEST: Demucs separated audio.wav — the 16 kHz MONO extraction made for ASR. The music bed therefore inherited mono AND an 8 kHz bandwidth ceiling at its source (Demucs upsamples to 44.1 kHz internally, so the stems LOOKED like 44.1k stereo files while carrying neither). Ingest now extracts a second full-quality file (44.1 kHz stereo, pcm_s16le) just for separation; ASR keeps its 16 kHz mono file; Demucs cost is ~unchanged (it resampled to 44.1 kHz internally either way). Best-effort: if the HQ extraction fails, separation falls back to the ASR file — exactly the old behavior. The stem-move path follows the input's basename. 2. MIX: amix negotiates ONE channel layout across inputs, and the synthesized voice is mono — so even a true-stereo bed was collapsed at the mix. bed_mix_filter now pins BOTH legs to stereo (aformat=channel_layouts=stereo); upmixing the mono voice duplicates it dead-center, which is where dubbed dialogue belongs anyway. Verified with real ffmpeg: the new graph preserves a stereo bed's width through the mix (and the ingest test pins that demucs receives audio_hq.wav with -ac 2 -ar 44100 while ASR keeps -ac 1 -ar 16000). Both tests fail with their half of the fix reverted. Full suite: 2989 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(dub): pre-HQ stem caches are not reused (review) Greptile P1, real: the content-hash cache restores a previous job's stems for the same video and skips Demucs — so every video processed BEFORE the HQ-extraction change would keep its 16 kHz-mono-derived bed forever, and the fix would never apply to exactly the videos users re-upload to hear the difference. find_cached_job now requires the audio_hq.wav marker in the cached job dir; older candidates are skipped with a log line and separation reruns once at full quality. Regression test covers both directions of the gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: mergetest <nizam4103@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b64f53b0af |
feat: pipeline error transparency — no more silent "unknown error" (plan-04, closes #131) (#136)
* docs(plan-04): spec + plan for pipeline error transparency (#131) speckit spec/plan/research/data-model/contract/quickstart for plan-04. Grounds the fix in the real code map: shared failure-event builder (backend/core/failure.py) feeding tasks.py + dub_pipeline.py + dub_core.py, non-empty reason guarantee, sanitized diagnostic block, frontend renderer with docs deeplink. Closes-target: #131 (children #122, #63). Design only — no code changes yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(pipeline): structured, non-empty failure events + logged tracebacks (#131) plan-04 backend: no more silent "unknown error". A shared failure helper guarantees a non-empty reason at every emit site and a sanitized, copyable diagnostic block. - backend/core/failure.py: build_failure()/build_failure_event() (reason falls back to the exception class name), sanitize() (reuses the logging_filter HF-token regex + redacts *TOKEN*/*KEY*/*SECRET* env values + home→~), diagnostic() (reuses the env capture), classify() reusing the error_docs_map 5-class taxonomy for the docs deeplink + hint. - core/tasks.py worker: structured event instead of bare str(e); keeps the logged traceback. - services/dub_pipeline.py: enrich download/extract error yields; ADD the missing outer `except Exception` (the #122 path — unhandled ingest errors were never surfaced with stage context); surface the previously-silent demucs/scene/thumbnail degradations as non-fatal `warning` events. - api/routers/batch.py: guaranteed non-empty batch failure reason. SSE payload is additive (legacy `error`/`stage`/`detail` keys preserved), so existing frontends keep working and already show the specific reason. Tests (TDD, fail-before/pass-after): 14 cases — non-empty-reason guarantee, redaction, diagnostic sanitization, and the 3 Test-matrix triggers (worker / extract / url). 483 passed, 0 regressions. Closes #131. Refs #122, #63. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(dub-ui): show specific cause + docs deeplink + copyable diagnostic (#131) plan-04 frontend. The backend now sends a structured, non-empty failure; surface it to the user instead of "extract: unknown error". - dubSlice: DubFailure type + dubFailure state/setter. - useDubWorkflow: capture the structured failure on the SSE error event (reason/error_class/stage/hint/docs_topic/diagnostic); clear on new runs. - DubTab: DubFailureNotice renders the actionable hint, an "Open docs" deeplink (via the existing errorDocsMap classifier), and a "Copy diagnostic" button — shown beneath the error badge in both failure banners. typecheck + build clean; 66 frontend tests pass. Refs #131, #122, #63. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(failure): annotate intentional best-effort excepts (CodeQL) The new security workflow's CodeQL flagged 5 bare `except: pass` blocks. All are deliberate best-effort guards (sanitize/diagnostic must never throw on the failure path; the test cancels the worker to tear it down). Added explanatory comments per CodeQL's py/empty-except rule. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |