Nodes/ComfyUI_zura_nodes/Zura · Blend Audio Words (combined editor)
ComfyUI Node

Zura · Blend Audio Words (combined editor)

The one-node version of Zura's dialogue editor — and when to skip it

By ZURAVFX·Created about a month ago·Updated a day ago· 2
Zura · Blend Audio Words (combined editor)
  • generated_audio
  • edit
  • finished_audio
  • receipt
◄selection_mode▾►
◄generated_start0.000►
◄generated_end0.500►
◄timing▾►
◄fade_ms12►
◄projectDialogue_Edit►

What this node actually is

You have a line of dialogue you want to change one word of. Not re-record it, not regenerate the whole scene - swap "Tuesday" for "Thursday" and leave every other sample alone. That's the job this corner of the Zura Nodes pack was built for, and it's one of the more useful things in it: LongCat-AudioDiT clones the voice and speaks the new sentence, then you bolt only the changed words back into the original waveform.

ZuraAudioDialogueFinish - displayed as Zura · Blend Audio Words (combined editor) - is the older, one-node version of that blend step. It holds the word selection and the splice in the same node: pick a range on the generated take, pick the range it replaces in the source, hit Run, get a WAV.

My honest advice up front: if you're starting fresh, use the pack's four-stage template instead (ZuraAudioDialogueSource → the LongCat take → ZuraAudioDialogueSelect → ZuraAudioDialogueOutput). The author's own docs call this one "the older combined editor … remains available for existing workflows," which is a polite way of saying it's kept for graphs that already exist. It's not broken, it's just less pleasant: the selection and the expensive blend share a node, so every experiment re-runs the whole thing.

How the splice works

The real logic lives in audio_dialogue.py, and it's more careful than most audio-splicing code I've seen in a custom node.

The source is decoded through ffmpeg (no binary, no node). The take arrives as a ComfyUI AUDIO and gets converted to the source's rate and channel count; then the slice from generated_start–generated_end is cut, RMS-matched to the source slice it replaces with a bounded gain (0.25×–4×, capped so it can't clip), faded at both joins with a squared-sine ramp of fade_ms, and dropped in: before untouched, take, after untouched.

Sample-exact, not "close enough" - the code asserts the pre- and post-selection regions are bit-identical to the original.

The timing widget is the decision that trips people up:

  • Natural duration (no stretch) inserts the take at whatever length it came out and shifts the rest of the audio to make room. The line after it moves later.
  • Keep timing (up to 15% fit) keeps the timeline fixed using a pitch-preserving atempo stretch - but only if the take is within 85–115% of the selection length. Outside that it refuses outright rather than smear your dialogue.

The inputs you'll touch

Wire generated_audio from your LongCat voice node and edit from ZuraAudioDialogueSource. Set selection_mode to Manual IN/OUT and dial generated_start/generated_end by ear on the take - that is the reliable path.

Auto changed words is the tempting one: it transcribes the take with Parakeet, diffs the recognised words against your original transcript, and finds the changed span for you. It only works if Parakeet is configured (separate Python env, model files, a parakeet.local.json next to the pack) and only if your edit is one continuous replacement - no deletions, no scattered fixes.

Then timing, fade_ms (12 ms is a sane default; raise it if you hear a click), and project, which is just the output folder label.

Outputs are finished_audio (a normal AUDIO, feed it to Preview Audio or a save node) and receipt, a JSON string with the sample ranges, the gain applied, the duration ratio and whether a stretch happened. It's an output node, so it writes to disk itself: output/zura_voice/<label>_<date>_<id>/ gets dialogue_edit.wav (float WAV at the source rate and channel count), replacement_take.wav, and edit_receipt.json.

Install

ComfyUI Manager → search Zura Nodes → install the entry published by ZURAVFX, then restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
cd ComfyUI_zura_nodes && pip install -r requirements.txt

requirements.txt pulls soundfile, av and friends, but the dependency that actually bites is ffmpeg/ffprobe on your PATH. The voice model is a separate one-time LongCat 3.5B install via Setup_LongCat_Windows.cmd or python setup_longcat.py --install; importing the node downloads nothing.

Where people get burned

Auto mode fails quietly, then hands you your own audio back. If Parakeet isn't set up or the changed words aren't unambiguous, this node doesn't crash - it copies the original through and writes a receipt with "status": "Select replacement words". If your "finished" audio sounds exactly like the source, read the receipt before you re-render anything.

Keep timing refuses anything over 15%. That's a feature. Change the LongCat pace or move your handles instead of wishing it stretched further.

Touch the source file and it stops. The edit payload carries a size+mtime hash of your audio; edit or move it and you get "The source changed. Load its waveform again."

One more thing: this pack has essentially no community footprint - I went looking for forum threads and found none - so the in-repo DIALOGUE_EDITING.md is your best map. It's short, and unusually honest about what's tested.

CategoryZura/audio editing

Inputs (8)

NameTypeDefaultDescription
generated_audioAUDIO—
editZURA_AUDIO_EDIT—
selection_modeCOMBO2 options: Auto changed words, Manual IN/OUT
generated_startFLOAT0.000—
generated_endFLOAT0.500—
timingCOMBO2 options: Natural duration (no stretch), Keep timing (up to 15% fit)
fade_msFLOAT120–100—
projectSTRINGDialogue_Edit—

Outputs (2)

NameTypeDescription
finished_audioAUDIO—
receiptSTRING—