MiniMax H3 Audio Perceptual Drift Audit / 音色远近漂移审计 (Advanced/T8)
Catching the 'voice suddenly sounds far away' failure
- reference_audio
- candidate_audio
- candidate_audio
- pass_audit
- decision
- maximum_spectral_drift
- maximum_level_delta_db
- suspected_start_seconds
- suspected_end_seconds
- report_json
You've heard it in a hundred dual-sampled H3 clips: the dialogue starts right, then mid-scene the voice gets thinner, quieter, like the character stepped to the back of the room, then comes back. That's perceptual drift - the spectral envelope and level of the generated audio sliding away from the reference over time. MiniMaxH3AudioPerceptualDriftAuditT8Advanced is the node that flags those segments for you, because on a long clip your ears stop trusting themselves by minute two.
It's a CPU-only, report-only comparison. Give it a synchronized reference_audio (your clean source) and a candidate_audio (the generated result on the same timeline), and it walks the pair in analysis windows, marking windows where the candidate persistently drifts in spectral shape or loudness relative to the reference. Then it returns a PASS or ABSTAIN with the suspected start/end seconds so you can jump straight to the bad part instead of scrubbing.
The settings that matter
- analysis_window_ms (500) and hop_ms (100) - how granular the sweep is. Smaller windows catch short glitches but produce noisier verdicts; 500/100 is a good default for speech.
- spectral_drift_threshold (0.3) and level_delta_threshold_db (4) - how much change counts as drift. The author's own validation found real audible drift in a pure two-pass clip triggering ABSTAIN somewhere in the 1.4–3.6 second range, while a normal one-pass and a 80% mix passed. So the defaults are calibrated against actual ears, not invented.
- persistent_window_count (3) - a single stray window doesn't fail the audit; the drift has to persist across this many windows. That's the "this isn't a blip, it's a slide" filter.
- active_rms_floor_dbfs (−50) - quiet/silent regions don't count toward drift, so pauses don't produce false alarms.
The outputs are the useful part: pass_audit (BOOLEAN), decision (STRING), maximum_spectral_drift, maximum_level_delta_db, and suspected_start_seconds / suspected_end_seconds. The candidate_audio passes through untouched - audit only, no repair, same philosophy as its sibling Integrity Audit.
What it can't do
Read the description's own limit: it does not diagnose distance, reverb or speaker identity. It's an acoustic red-flag detector, not a forensic tool. If the drift is actually a voice swap or a reverb catastrophe, this node will mark it suspicious but won't tell you why. Treat it as a triage step: ABSTAIN → go listen to that window, then decide whether to re-run with lock_source or remix. The README frames it as a "second pair of ears" for the fixed-material claims it validates - it flags, humans judge.
Install
It lives in T8/MiniMax H3/Audio/Advanced of the T8mars pack:
cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/comfyui-minimax-h3-audio-T8
Restart ComfyUI. No pip extras, no model files, pure CPU signal analysis. Use it after any remix_source or dual-clock run where you're shipping someone's voice as a deliverable - it's cheap insurance that the character stays in the same room for the whole take.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| reference_audio | AUDIO | — | |
| candidate_audio | AUDIO | — | |
| analysis_window_ms | FLOAT | 500100–2000 | — |
| hop_ms | FLOAT | 10020–1000 | — |
| active_rms_floor_dbfs | FLOAT | -50-100–0 | — |
| spectral_drift_threshold | FLOAT | 0.300.01–4 | — |
| level_delta_threshold_db | FLOAT | 4.00.1–40 | — |
| persistent_window_count | INT | 31–100 | — |
| max_duration_delta_ms | FLOAT | 21.00–10000 | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| candidate_audio | AUDIO | — |
| pass_audit | BOOLEAN | — |
| decision | STRING | — |
| maximum_spectral_drift | FLOAT | — |
| maximum_level_delta_db | FLOAT | — |
| suspected_start_seconds | FLOAT | — |
| suspected_end_seconds | FLOAT | — |
| report_json | STRING | — |