DubClean Voice
Reference-conditioned removal of the original-language speech from a dubbed soundtrack.
Russian voice-over releases usually keep the English dialogue audible under the translation. DubClean Voice takes the speech of the dubbed track together with the speech of the original track β the reference β and returns the translation with the matched foreign speech removed.
The model is the speech-cleaning stage of DubClean, a local Windows service for rebuilding a dubbed soundtrack. It is published on its own so that the checkpoint can be inspected, reused and evaluated independently of that application.
| Task | reference-conditioned speech removal (audio-to-audio) |
| Input | two time-aligned mono speech stems, 24 kHz |
| Output | translated speech with the matched foreign speech removed, 24 kHz mono |
| Parameters | 3,883,906 (~15.5 MB fp32) |
| Architecture | complex-ratio-mask U-Net over STFT magnitudes |
| Training | 98,242 six-second examples, epoch 37 selected |
| License | AGPL-3.0-or-later |
Files
| File | Size | SHA-256 | Use |
|---|---|---|---|
dubclean_voice.pt |
46,909,206 B | FE1172C629C085F7ED8F7E264E2E37D4AEDE95C9448BB134EB9BAF8D5DEA53C9 |
production checkpoint, drop-in for a DubClean Portable install |
dubclean_voice_inference.pt |
15,611,318 B | 5B6ED6B0E319B0AED13289F1C47CD13BE78BFBC026F3A7F3BA981906E557A68D |
inference-only export: same weights, no optimizer state |
dubclean_voice.py |
architecture and checkpoint loader | ||
infer.py |
streaming command-line inference | ||
selftest.py |
offline check that the checkpoint loads and runs |
Both checkpoints hold bit-identical weights and produce identical output. The
production file additionally carries the AdamW optimizer state and the training
history of the run that produced it, and its SHA-256 is the one recorded in
DubClean Portable's portable_manifest.json. For plain inference prefer
dubclean_voice_inference.pt.
Quick start
pip install torch numpy scipy soundfile huggingface_hub
hf download Yaromanol/dubclean-voice --local-dir dubclean-voice
cd dubclean-voice
python selftest.py --checkpoint dubclean_voice_inference.pt
python infer.py \
--checkpoint dubclean_voice_inference.pt \
--mixture dubbed_speech.flac \
--reference original_speech.flac \
--output translated_speech_clean.flac
From Python:
import soundfile as sf
from dubclean_voice import load_model
from infer import read_mono, separate
model = load_model("dubclean_voice_inference.pt", device="cpu")
mixture = read_mono("dubbed_speech.flac") # translated speech + leaked foreign speech
reference = read_mono("original_speech.flac") # foreign speech to remove
voice = separate(model, mixture, reference, device="cpu")
sf.write("translated_speech_clean.flac", voice, 24000)
The model itself is a plain nn.Module:
output = model(mixture_tensor, reference_tensor) # float32 [B, T] at 24 kHz
output["voice"] # translated speech
output["reference"] # removed component = mixture - voice
What the inputs must be
This is the part that decides whether the model works at all.
- Speech stems, not raw film audio. Both inputs are the output of a speech extractor run over the two soundtracks β in DubClean, MossFormer2_SE_48K (Apache-2.0) over the original track and a DubClean-tuned variant over the dubbed track. Music and effects are removed beforehand and restored later. Feeding a full mix is out of domain.
- Time-aligned. The network compares the two signals frame by frame; the training data covers shifts up to about 150 ms and mild speed edits, and the dilated bottleneck gives some tolerance beyond that, but a systematic offset or a drifting timeline must be corrected first. DubClean aligns the two tracks (correlation and per-scene offsets) before this stage.
- The same scene. Mixture and reference are truncated to the shorter of the two. Passing unrelated audio as the reference is a trained-for negative case: the model is supposed to leave the mixture alone, not to invent removals.
- 24 kHz mono.
infer.pyresamples and downmixes for you. The output is band-limited to 12 kHz β inside DubClean the full-band music and effects come from a separate model, so the band limit applies only to the speech layer.
Architecture
STFT with n_fft=512, hop_length=256, Hann window, center=True β 257 bins
at 24 kHz. Six input planes are stacked from the mixture spectrum X and the
reference spectrum R:
log1p(12Β·|X|)andlog1p(12Β·|R|);- a time-averaged reference profile (long-term spectral shape of the reference);
- the spectral flux of the mixture;
- the log-magnitude difference;
- a normalized magnitude similarity between mixture and reference.
Phase relation never enters the network. A U-Net (base 16 channels β
16/32/64/96, bottleneck 128, skip connections) processes those planes; the
bottleneck holds ten identity-initialised residual blocks with time-axis
dilations 1,2,4,8,16,1,2,4,8,16, which is what carries tolerance to jitter and
local timing drift.
The two output planes form an unbounded complex ratio mask
mask = (1 + 2Β·tanh(a)) + iΒ·(2Β·tanh(b))
applied to the mixture spectrum, followed by iSTFT. The mask is deliberately not constrained to 0β¦1: cancelling speech that overlaps in time and frequency needs gains above one, negative real parts and a real phase correction. A narrow mask capped suppression at roughly 4β6 dB in earlier versions of this model.
The removed component is defined as mixture β voice, so the two outputs always
sum back to the input.
Inference is windowed: 6 s windows, 3 s hop, raised-cosine cross-fade. Memory
use does not grow with file length. On CPU (torch 2.5.1, Windows 10) the
reference implementation runs at roughly 8Γ real time; a GPU is faster but not
required.
Training data
The model was trained on semantic-balanced-replay-20260720-v1: 98,242
examples of 6.0 s at 24 kHz, split 82,241 / 8,001 / 8,000 into train /
validation / test.
Every example is synthesized from real speech clips: a translated-speech target, a foreign-speech component embedded under it, and the reference the model is conditioned on, mixed under a controlled factor plan (18 factors, 113 options β voice types, overlap, ducking, reference shift, speed edits, level ratios, backgrounds, extractor quality). Because the mixture is composed explicitly, the ground-truth target and the ground-truth removed component are exact.
Composition by supervision policy:
| Policy | Examples | Meaning |
|---|---|---|
remove_matched_en |
79,200 | remove the foreign speech that matches the reference |
preserve_ru |
13,074 | keep the translation untouched |
no_op |
3,343 | silence, background or no foreign speech β output the input |
preserve_all_speech |
2,625 | wrong or unrelated reference β remove nothing |
20% of the training split are negative cases (no_op, preserve_all_speech,
preserve_ru), replayed on purpose: a separator that also has to not act is
much safer on real films than one trained only on removals.
21 scenarios are represented, among them typical voice-over, monologue, dense dialogue, equal-level overlap, foreign speech louder than the translation, very low embedded foreign speech, partial or extra-phrase references, wrong reference, timing drift, local edit jumps, similar-sounding voices, speech-like background, and a 32,000-example "hard master" block in which the two tracks are pushed through independent mastering chains (5.1βstereo downmix, AC-3βAAC, broadcast versus release master, piecewise gain envelopes, time-varying ducking, micro-timing jitter, codec+EQ+dynamics chains).
Source material: speech clips extracted from film soundtracks held by the maintainer β 12,959 clips (~25 h) from 45 audio tracks of 25 works, Russian and English. Clips are split by source work (16 works train, 3 validation, 4 test), so validation and test films never contribute speech to training.
Individual titles are not published. See
TRAINING_DATA_DISCLOSURE.md: publishing this
model grants no rights to the films, translations or recordings behind the
dataset, and the dataset itself is not distributed.
Training procedure
- AdamW, weight decay 1e-5; the final continuation ran at lr 1e-5, batch 4 with 4 gradient-accumulation steps, on a single CUDA GPU.
- Loss: complex-spectrogram L1 on both outputs (1.0 / 0.6), waveform L1 (0.8 / 0.25), a small negative-SI-SDR term on the translated speech (0.002), a cosine leakage penalty against the removed component (0.10), and a residual energy term normalized by the foreign-speech energy (1.00). The last term is what makes "removed nothing" expensive when there is something to remove, while staying harmless on no-op cases.
- Early stopping on validation loss, patience 2. Epoch 37 (91,323 steps) was selected; epochs 38 and 39 were worse and training stopped.
Evaluation
Metrics on the held-out splits of the synthetic benchmark, at the selected
epoch. EN suppression is 10Β·log10( MSE(mixture β target) / MSE(output β target) ) β how much of the error against the clean translation is removed.
RU SI-SDR is the scale-invariant SDR of the output against the clean
translation, i.e. how intact the translation stays.
| Validation | Test | |
|---|---|---|
| EN suppression | 7.41 dB | 7.54 dB |
| RU SI-SDR | 25.94 dB | 24.23 dB |
| SI-SDR improvement | 6.58 dB | 7.15 dB |
| Loss | 0.2736 | 0.3249 |
By channel condition (validation, 40 examples each):
| Condition | EN suppression | RU SI-SDR |
|---|---|---|
| independently randomised mastering (legacy) | 8.45 dB | 22.30 dB |
| drift + local edit | 9.02 dB | 12.87 dB |
| broadcast vs release master | 7.79 dB | 11.18 dB |
| AC-3 5.1 β AAC stereo | 7.64 dB | 13.78 dB |
| extractor pair asymmetry | 7.49 dB | 12.39 dB |
| micro-timing jitter | 6.89 dB | 11.38 dB |
| piecewise gain envelope | 6.64 dB | 10.15 dB |
| time-varying ducking | 6.56 dB | 18.23 dB |
| independent downmix | 6.33 dB | 11.38 dB |
| compound codec + EQ + dynamics | 6.07 dB | 12.29 dB |
| very low embedded foreign speech | 4.51 dB | 24.68 dB |
Acceptance run for the release, on top of the table above:
- hard-master bucket: 6.90 dB suppression at 13.83 dB RU SI-SDR;
- safety bucket (nothing to remove): 107.6 dB RU SI-SDR β on no-op material the model is effectively a passthrough;
- 25 real dubbed-film samples were rendered through the full application and reviewed by ear; no failures were recorded against the previous production checkpoint.
These numbers are a synthetic benchmark. Read them as a comparison between checkpoints, not as a promise about a particular film.
Limitations and failure modes
- A dub mastered from a different source can be unremovable. If the translated release was mixed from a different master than the original track you hold, the embedded foreign speech is not phase- or timbre-coherent with your reference, and suppression measured on real films can fall to ~0 dB with the model behaving correctly. This is a property of the material, not a bug β check a preview scene before processing a whole film.
- Alignment is a precondition. Uncorrected offsets beyond a few hundred milliseconds, edit differences or a drifting timeline break the frame-by-frame comparison.
- The extractor is part of the domain. The model was trained on extractor output, including its artifacts; with a different speech extractor, expect a domain shift, and note that the extractor itself can damage the translated speech before this model ever sees it.
- Language pair. Trained on Russian voice-over above English originals. Other pairs are untested.
- Bandwidth. 24 kHz internally; the speech layer comes back band-limited to 12 kHz.
- Not a standalone dub cleaner. Alone it processes speech stems. Producing a finished soundtrack additionally needs alignment, music/effects restoration and remixing β that is what the DubClean application does around it.
- Short events. The reported metrics come from long-form buckets; very short isolated utterances were not measured separately in this run.
Intended use
Restoring the speech layer of a dubbed soundtrack you have a lawful basis to process β personal archives, restoration work, dubbing and localisation research, and evaluation of reference-conditioned separation.
Out of scope: passing off the output as an official release, and any use of source material you have no right to process. The AGPL grants rights to this model and its code only. It grants nothing over films, translations, recordings or subtitles.
The DubClean pipeline
original track βββΊ speech extractor βββββββββββββββΊ reference (EN speech)
β
dubbed track βββΊ speech extractor βββΊ alignment βββΊ mixture (RU + leaked EN)
β
βΌ
DubClean Voice β this model
β
clean RU speech ββββΌβββΊ remix βββΊ soundtrack
β
dubbed track βββΊ DubClean M&E βββΊ music and effects
DubClean M&E, the companion model that rebuilds speech-free music and
effects, is part of the DubClean application and is not published here.
License and rights
The weights and the code in this repository are AGPL-3.0-or-later. The full
text is in LICENSE; scope and exclusions are in
MODEL_LICENSE.md; attribution and third-party notes are in
NOTICE.
If you run a modified version of this model as a network service, the AGPL
requires you to offer the corresponding source to its users. For terms outside
the AGPL, see PROPRIETARY_LICENSING.md.
Media processed with DubClean is not licensed by DubClean, and processing it does not place it under the AGPL.
Citation
@software{dubclean_voice_2026,
title = {DubClean Voice: reference-conditioned removal of original-language
speech from dubbed soundtracks},
author = {DubClean contributors},
year = {2026},
note = {AGPL-3.0-or-later},
url = {https://huggingface.co/Yaromanol/dubclean-voice}
}
Russian version of this card: README_RU.md.
- Downloads last month
- -