Skip to content

Audio finishing

Speech recorded in a room is rarely ready to publish. It is too quiet or too loud for the platform, the air conditioning hums under it, a music bed either drowns it or is too shy to be heard, and the music stops before the voice does. Audio finishing is the set of steps a sound engineer applies before delivery. In Madoo they are six nodes that run locally, cost no credits, and each measures what it did: every one of them returns a report and a quality_check, so a workflow knows — not assumes — that the audio it delivers meets the target.

Platforms play everything at a set loudness, measured in LUFS (loudness units relative to full scale, over the whole programme): a file mixed louder is turned down, a quieter one sounds weak next to the rest. The other number is the true peak, in dBTP: the highest point the waveform reaches once decoded, which must stay a little under 0 so that no player clips it. A delivery target is therefore two numbers — for example −14 LUFS and −1 dBTP for social video and music streaming, −16 LUFS for podcasts, −23 LUFS for broadcast television.

Enhance Speech (audio/speech_enhance) cleans a voice locally: noise reduction, de-click, de-clip, de-esser, high- and low-pass filters, a gate and gentle compression. The profile sets them together — light keeps the room tone, podcast (the default) is balanced, dialogue is stronger for field recordings — and custom exposes every control. It does not remove echo or reverberation, nor separate a voice from music: that is a model’s job, done by ai/audio_isolation (paid).

Normalize Loudness (audio/loudness_normalize) brings audio to a loudness and a true-peak ceiling: podcast (−16 LUFS, −1.5 dBTP), broadcast (−23 LUFS, −1 dBTP), social (−14 LUFS, −1 dBTP), or custom values. The default two_pass mode measures the whole file first and then applies one correction, so the result is predictable. It returns the audio with its measurements before and after; with fail_on_target_miss (on by default) it refuses to publish a file that missed the target — turn it off to route the failed check to a gate instead.

Loop Music Bed (audio/loop) fits a music track to an exact duration — the length of a voice-over, taken from Media Technical Info — repeating it with crossfades (crossfade_ms) when it is shorter, cutting it when it is longer, with a fade in and a fade out that ends exactly on the last frame. It never changes the tempo.

Duck Background Audio (audio/duck) lowers a background (music) under a foreground (voice). The default phrase technique lowers the music for whole phrases: short pauses between words stay inside the phrase, so the music does not pump up and down with every word; it starts moving a little before the voice and comes back after it. voice_over (music 10 dB down under speech) is the default profile, subtle (6 dB) and aggressive (16 dB) the others; the compressor technique is a classic sidechain compressor that reacts to every word. output_duration: foreground ends the mix with the voice. If the background is absent — a branch without music — background_absent_behavior: pass_foreground lets the voice through alone.

Fit Audio Duration (audio/fit_duration) makes a clip last exactly as long as a slot — a line of a dub, a cue in an ad — by changing its tempo within bounds and keeping the pitch, then padding with silence or trimming when the bounds are not enough (tempo_then_pad, the default; tempo_then_trim; or tempo alone). natural_speech never slows or trims speech and reports how much it had to speed it up; the dubbing page explains it. A rate outside the bounds fails, is clamped or is applied with a warning, as on_out_of_range says.

Audio Quality Report (audio/quality_report) changes nothing: it measures integrated loudness, loudness range, true and sample peak, near-clipped samples, silence at the head and the tail, and dropouts, and checks them against a profile (dialogue, music, delivery) or explicit thresholds. It is the last step before a gate.

For simple edits there are also Trim, Split, Merge, Mix, Volume, Speed, Fade and Convert (audio/…), made for short clips; Mix sums two tracks at the volumes you give it.

  1. Clean the voice (Enhance Speech), then level it (Normalize Loudness, podcast): the voice enters the mix at a known level, whatever the recording.
  2. Fit the music to the voice (Loop Music Bed, with the voice’s duration from Media Technical Info): a bed shorter than the voice would otherwise stop in the middle — and the ducking check would not notice, because it measures the mix, not the music.
  3. Duck the music under the voice, ending with the voice.
  4. Normalize the mix to the delivery target, after the ducking: lowering the music takes about 3 LU off the mix, so a mix normalized before it arrives under the target.
  5. Measure it (Audio Quality Report) and send every check to a Quality Gate, with the audio on the gate’s value: the finished audio comes out of the gate only when every step passed.

Give every check its own check_id (voice-cleanup, voice-level, mix-loudness…). Two nodes of the same kind keep the same default id; a workflow whose gate would receive two checks with the same id is refused when it is validated, with DUPLICATE_CHECK_ID on the node to rename — before anything runs. How gates count checks, and why a check in warning blocks all_must_pass, is in Quality checks.

Work in WAV between steps (output_format: wav, lossless 24-bit, 48 kHz) and choose MP3 or AAC only for the file you deliver.

The audio finishing lab takes 48 seconds of an interview recorded by NASA and 60 seconds of a music bed, and makes a voice-over over music for a social video, at −14 LUFS. Next to it, the same two files are simply summed at fixed levels with Mix and measured the same way.

The lab: the voice-over goes to Voice length (Media Technical Info) and Clean the voice (Enhance Speech, podcast), then Level the voice (Normalize Loudness, podcast); the music bed goes to Fit the music to the voice (Loop Music Bed) with the voice’s duration; Music under every phrase (Duck, voice_over, phrase); Mix at −14 LUFS (Normalize Loudness, social); Measure the delivery (Audio Quality Report); Deliver only if all pass (Quality Gate) with five checks, giving the finished audio and the delivery report. Beside it, Naive mix (Mix) and Measure the naive mix.

Finished Naive mix
Loudness −14.1 LUFS (target −14 ± 2) −29.2 LUFS: 15 LU too quiet
True peak −1.2 dBTP −8.1 dBTP
Duration 48.0 s, ending with the voice 60.0 s: the music plays 12 s after the voice
The music under the voice 10 dB down during every phrase, back between answers constant
Gate passed, 5 of 5 checks would fail on loudness
Listen

Both results are MP3 copies of the run’s outputs for this page: finished, naive; the full measurements are in the run’s outputs. No credits.

Terminal window
node madoo-install-example.mjs lab-audio-finishing --api <your Madoo API URL> --key <key.json> --run --save mix

Replace the voice with your own recording and the music with your bed; for a podcast choose the podcast profile on the last normalization (−16 LUFS), for a TV spot broadcast (−23 LUFS).

Media: voice from “Artemis Media Resource — Interview Soundbites”, NASA (public domain; NASA does not endorse this documentation). Music: “Local Forecast – Elevator” Kevin MacLeod (incompetech.com), licensed under Creative Commons: By Attribution 4.0 License, http://creativecommons.org/licenses/by/4.0/.

The finished audio goes back onto the picture with Add Audio to Video in replace mode — see Editing video. To work on the soundtrack of a video, take it out first with Extract Audio.