Context
A conference recorded on several microphones (speakers, room, music) produces hours of raw multitrack audio. Most editing time goes into locating material — who speaks when, on which track, where the silences are — before any cutting.
Open-source speech tooling (Whisper and its derivatives, pyannote, Silero VAD) solves transcription and “who spoke when” well, but stops at text. The question addressed here is whether that analysis can be delivered as an editing object: a multitrack timeline in AAF, the interchange format that audio workstations open natively, with tracks qualified and dead time removed.
Before → after
One real job processed end to end: a conference recorded on 16 tracks. Everything on the right-hand side was produced automatically, with no manual cut; figures are read from the job’s analysis database and from the delivered AAF.
| Input (raw recording) | Generated output (AAF timeline) | |
|---|---|---|
| Tracks | 16 × 1 h 32 min 54 s (≈ 24 h 46 min of audio to review) | 16 tracks kept in the AAF, 6 carrying clips |
| Track roles | 4 speech · 2 music (one auto-flagged as ambience) · 10 silent | 10 silent tracks left empty, no manual triage |
| Material | 204 speech regions and 5 music passages detected | 41 clips (37 speech, 4 music) |
| Cuts | — | 40 hard cuts between sources, of which 33 microphone switches |
| Transitions | — | 0 crossfades: straight cuts, each speech clip extended by a 0.3 s tail |
| Dead time | — | 3 gaps ≥ 4.5 s rippled out (36.9 s); timeline 1 h 32 min 17 s |

Top: the 16 input tracks over the full recording, coloured by the detected role and activity; the four speech microphones are active almost all the time because each one also picks up its neighbours. Bottom: the generated edit, one lane per track as in the AAF — a single source is kept at any moment, ticks mark the 40 source switches, hatched areas in the top panel are the removed dead time.
Speech clips are few and long (median 79 s, longest 10 min 11 s): the montage follows the active speaker rather than chopping on every breath, and micro-switches shorter than 0.8 s are absorbed by the anti-flicker smoothing. Ten clips are still shorter than 6 s — short interjections, the first place to look when checking the edit.
Approach
Methods
Transcription. Whisper large-v3 via faster-whisper (CTranslate2), run on
fixed-length chunks inside an isolated, persistent worker process: the model is
loaded once, and a native crash only loses one chunk, which is reported rather
than silently dropped. Decoding uses beam search with Silero VAD filtering and
condition_on_previous_text disabled to limit repetition loops.
Word timing and speakers. Word-level timestamps come from WhisperX forced alignment (wav2vec2). Speaker turns come from pyannote diarisation and are assigned to words by temporal overlap.
Post-processing. Pure filters remove known Whisper hallucinations (stock subtitle credits, “thanks for watching”-type phrases, music-only segments), non-Latin output on French audio and duplicates, then merge consecutive same-speaker segments.
Track qualification and montage. Each track is classified as speech, music or silent by combining frame energy, VAD coverage and transcript statistics. The montage selects, for every 100 ms frame, the microphone with the highest signal-to-noise ratio above its own noise floor (reducing cross-talk “bleed”), applies anti-flicker smoothing and ripples out global dead time.
Synchronisation. Separate recorders are aligned by matching distinctive words across transcripts (robust median of offsets), after a coarse clock-based placement corrected for clock drift.
Export. The edit list is written as a multitrack AAF with pyaaf2, either
embedding the audio or linking to it.
Deployment. A web portal accepts jobs and a separate compute worker polls it over HTTPS. Clients upload only compressed analysis copies together with a manifest of their original files; the delivered AAF references the original WAV names, so the editor relinks full-quality sources locally and the originals never leave the client’s machine.
Results
Benchmark (bench_stt.py) on real conference audio: one-minute speech windows
selected by VAD on four speech tracks, Whisper large-v3 throughout, Apple
Silicon laptop, warm timings excluding model loading. No ground-truth
transcript was available, so quality figures are divergence from a
pseudo-reference (WhisperX output), not absolute error.
| Pipeline (CPU) | Real-time factor |
|---|---|
| openai-whisper | 0.43 |
| WhisperX | 0.51 |
| WhisperX + forced alignment | 0.54 |
| openai-whisper + word timestamps | 0.57 |
| faster-whisper (beam 5 + VAD) | 0.66 |
| faster-whisper + word timestamps | 0.70 |
- Word timing: native word timestamps deviate from forced alignment by a median of ~205 ms (faster-whisper) and ~210 ms (openai-whisper); forced alignment adds about 1.2 s per minute of audio.
- Transcript divergence: 7–11 % word-level divergence between pipelines, mostly punctuation, segmentation and normalisation on manual inspection.
- Repetitions: 1–2 % repeated content; no hallucinated passages observed on these clips.
- Track detection: the three music/silence tracks of the seven-track recording were identified by VAD and skipped automatically.
Limitations & next steps
- Quality is measured against a pseudo-reference; a manually transcribed test set is needed to report true word error rate and diarisation error rate.
- Benchmark clips are short (one minute per track) and all single-speaker windows, so diarisation accuracy on multi-speaker overlap is not yet quantified.
- CTranslate2 has no Metal backend: on Apple Silicon, faster-whisper and WhisperX run on CPU, while CUDA is used where available. Device choice per stage was benchmarked rather than assumed; a CUDA comparison remains to be measured.
- AAF export targets Logic Pro import; other editors have not been systematically tested.
Stack
Python · faster-whisper · CTranslate2 · WhisperX · pyannote.audio · Silero VAD · PyTorch (MPS / CUDA) · ffmpeg · pyaaf2 · SQLite · PHP · MySQL