mixing.transcript¶
Transcript-driven media editing.
Speech-to-text via ElevenLabs Scribe, filler-word detection, and timeline-aware cuts of audio/video. Produces editable transcripts (plain prose, SRT, word-level JSON) and applies cuts via ffmpeg.
The HTTP client uses stdlib only (no requests or elevenlabs SDK
dependency), so the package adds no required deps. The runtime needs
ffmpeg on PATH for media operations, and an ElevenLabs API key (env
var ELEVENLABS_API_KEY or explicit api_key=) for transcription.
Quick start:
>>> from mixing.transcript import remove_fillers
>>> result = remove_fillers("input.mov", "out/")
>>> print(result.cleaned_media)
Lower-level building blocks:
>>> from mixing.transcript import (
... transcribe, build_cuts, keeps_from_cuts,
... words_to_srt, words_to_prose, apply_keeps,
... )
Functions
|
Transcribe |
Default on-disk cache for Scribe responses. |
|
|
Return |
|
Compute time ranges to REMOVE. |
|
Return ranges to KEEP given the cut ranges and total duration. |
|
Lowercase and strip non-alpha so |
|
Back-compat aliases — historically these names lived in different modules. |
|
Render an SRT from a Scribe word list (no filler removal, no remapping). |
|
SRT aligned to a post-cut timeline. |
|
Render a Scribe word list as plain prose, with paragraph breaks on long pauses. |
|
Map |
|
Extract a mono mp3 from |
|
Re-encode |
|
Return |
|
End-to-end filler removal. |
Classes
|
Paths and computed ranges produced by |
- class mixing.transcript.FillerRemovalResult(cleaned_media, transcript_md, transcript_srt, cleaned_md, cleaned_srt, scribe_json, cuts_json, keeps_json, duration, cuts=list(), keeps=list())[source]¶
Bases:
objectPaths and computed ranges produced by
remove_fillers().
- mixing.transcript.apply_keeps(input_path, output_path, keeps, *, video_codec='libx264', audio_codec='aac', crf=20, preset='medium', audio_bitrate='160k', faststart=True, overwrite=True)[source]¶
Re-encode
input_pathkeeping only the listed time ranges.- Parameters:
output_path (
Union[str,Path]) – Output file (extension picks the container).keeps (
Sequence[dict]) –[{"start": float, "end": float}, ...]time ranges in seconds.audio_bitrate (
str) – Re-encode knobs forwarded to ffmpeg.faststart (
bool) – Add-movflags +faststart(mp4 web-streaming).overwrite (
bool) – Pass-yto ffmpeg.
- Return type:
- Returns:
The output path.
- mixing.transcript.build_cuts(words, *, fillers=frozenset({'ah', 'eh', 'er', 'erm', 'hmm', 'mhm', 'mm', 'mmm', 'uh', 'uhh', 'uhm', 'um', 'umm'}), audio_events=frozenset({'(coughs)'}), absorb_trailing_space=True, merge_gap=0.08)[source]¶
Compute time ranges to REMOVE.
- Parameters:
- Return type:
- Returns:
List of
{"start": float, "end": float, "label": str}dicts, sorted by start time and non-overlapping.
- mixing.transcript.default_cache_dir()[source]¶
Default on-disk cache for Scribe responses.
Honors
$MIXING_TRANSCRIPT_CACHE_DIR, then$XDG_CACHE_HOME, then~/.cache/. Final segment is alwaysmixing/transcript.- Return type:
- mixing.transcript.extract_audio(input_path, output_path, *, sample_rate=16000, channels=1, bitrate='96k', overwrite=True)[source]¶
Extract a mono mp3 from
input_path(suitable for STT).Returns the output path.
- Return type:
- mixing.transcript.fmt_srt_time(seconds)¶
Format a time in seconds as an SRT timestamp
HH:MM:SS,mmm.Milliseconds are rounded (not truncated), with carry handled correctly, and negative inputs clamp to zero.
>>> seconds_to_srt_time(2592.187) '00:43:12,187' >>> seconds_to_srt_time(1.5) '00:00:01,500' >>> seconds_to_srt_time(-3) '00:00:00,000'- Return type:
- mixing.transcript.is_filler(item, *, fillers=frozenset({'ah', 'eh', 'er', 'erm', 'hmm', 'mhm', 'mm', 'mmm', 'uh', 'uhh', 'uhm', 'um', 'umm'}), audio_events=frozenset({'(coughs)'}))[source]¶
Return
Trueifitemis a filler word or a removable audio event.- Return type:
- mixing.transcript.keeps_from_cuts(cuts, duration)[source]¶
Return ranges to KEEP given the cut ranges and total duration.
- mixing.transcript.normalize_token(text)[source]¶
Lowercase and strip non-alpha so
"Uh,"->"uh".- Return type:
- mixing.transcript.remap_time_after_cuts(t, cuts)[source]¶
Map
tfrom the original timeline onto the post-cut timeline.If
tfalls inside a cut, snaps to the moment that cut would have started in the post-cut timeline.- Return type:
- mixing.transcript.remove_fillers(input_media, output_dir, *, output_media=None, fillers=frozenset({'ah', 'eh', 'er', 'erm', 'hmm', 'mhm', 'mm', 'mmm', 'uh', 'uhh', 'uhm', 'um', 'umm'}), audio_events=frozenset({'(coughs)'}), api_key=None, scribe_kwargs=None, apply_keeps_kwargs=None, keep_intermediate=True, scribe_data=None)[source]¶
End-to-end filler removal.
- Parameters:
input_media (
Union[str,Path]) – Video or audio file to clean.output_dir (
Union[str,Path]) – Directory to write transcripts and intermediate files into. Created if missing.output_media (
Union[str,Path,None]) – Output cleaned media path. Defaults tooutput_dir / f"{stem}.cleaned.mp4".audio_events (
Iterable[str]) – Override the default filler / event sets.api_key (
str|None) – ElevenLabs API key (else envELEVENLABS_API_KEY).scribe_kwargs (
Optional[Mapping[str,object]]) – Extra kwargs forwarded totranscribe().apply_keeps_kwargs (
Optional[Mapping[str,object]]) – Extra kwargs forwarded toapply_keeps().keep_intermediate (
bool) – IfFalse, delete the extracted audio file.scribe_data (
dict|None) – If provided, skip the network call and use this dict (must match Scribe’s response shape). Useful for tests / replays.
- Return type:
- Returns:
A
FillerRemovalResultwith file paths and the computed cut/keep ranges.
- mixing.transcript.srt_for_media(media, *, srt_path=None, reuse=True, refresh=False, cache=True, max_chars=80, **transcribe_kwargs)[source]¶
Return
(srt_text, srt_path)formedia, transcribing if needed.- Parameters:
media (
Union[str,Path]) – Audio or video file (Scribe extracts audio from video).srt_path (
Union[str,Path,None]) – Where the SRT lives/should be written. Defaults to the media path with an.srtsuffix.reuse (
bool) – WhenTrue(default) and the SRT already exists, read and return it without re-transcribing.refresh (
bool) – Force re-transcription even if the SRT exists (overwrites it).cache (
bool) – Pass-through tomixing.transcript.transcribe()’s on-disk response cache.max_chars (
int) – Max characters per SRT cue when generating.transcribe_kwargs – Extra args forwarded to
transcribe(e.g.language_code,diarize).
- Return type:
- Returns:
The SRT text and the path it lives at.
- mixing.transcript.transcribe(audio, *, api_key=None, model_id='scribe_v1', timestamps_granularity='word', tag_audio_events=True, diarize=False, language_code=None, extra_fields=None, timeout=600.0, cache=False, refresh=False)[source]¶
Transcribe
audiowith ElevenLabs Scribe.- Parameters:
audio (
Union[str,Path,bytes]) – Path to an audio/video file, or raw bytes.api_key (
str|None) – API key. Falls back to env varELEVENLABS_API_KEY.model_id (
str) – Scribe model id (currentlyscribe_v1).timestamps_granularity (
str) –"word"(default),"character", or"none".tag_audio_events (
bool) – Whether to surface(laughs)/(coughs)etc.diarize (
bool) – Speaker diarization on/off.language_code (
str|None) – Optional BCP-47 hint to skip language detection.extra_fields (
Optional[Mapping[str,str]]) – Additional multipart fields to send (forward compatible).timeout (
float) – Total request timeout in seconds.cache (
Union[bool,str,Path]) –False(default) → no cache.True→ usedefault_cache_dir(). A path → use that directory. The cache key is the SHA-256 of the audio bytes plus all request parameters that affect the response.refresh (
bool) – WhenTrueandcacheis enabled, force a re-call and overwrite the cached entry. Useful for invalidating stale entries when Scribe upgrades its model.
- Return type:
- Returns:
The raw JSON response from ElevenLabs (a dict). When
timestamps_granularity="word"(default), the response contains a"words"list where each entry has at minimum{"text", "start", "end", "type", "confidence"}. Non-word events (type != "word") include(laughs)etc. whentag_audio_events=True.- Raises:
RuntimeError – No API key supplied and
ELEVENLABS_API_KEYunset.HTTPError – Request failed (4xx/5xx).
- mixing.transcript.words_to_prose(words, *, paragraph_pause=1.2, drop_fillers=False, fillers=frozenset({'ah', 'eh', 'er', 'erm', 'hmm', 'mhm', 'mm', 'mmm', 'uh', 'uhh', 'uhm', 'um', 'umm'}), audio_events=frozenset({'(coughs)'}))[source]¶
Render a Scribe word list as plain prose, with paragraph breaks on long pauses.
- Parameters:
- Return type:
- mixing.transcript.words_to_srt(words, *, max_chars=80, sentence_endings='.?!')[source]¶
Render an SRT from a Scribe word list (no filler removal, no remapping).
- Return type:
- mixing.transcript.words_to_srt_remapped(words, cuts, *, max_chars=80, sentence_endings='.?!', drop_fillers=True, fillers=frozenset({'ah', 'eh', 'er', 'erm', 'hmm', 'mhm', 'mm', 'mmm', 'uh', 'uhh', 'uhm', 'um', 'umm'}), audio_events=frozenset({'(coughs)'}))[source]¶
SRT aligned to a post-cut timeline.
Each word’s timestamp is shifted earlier by the cumulative duration of all cuts that ended before it, so the resulting SRT drops in over the cleaned media.
- Return type:
Modules
Filler-word detection over Scribe-shaped word lists. |
|
Transcript output formats: SRT, plain prose, time remapping. |
|
ffmpeg-backed audio extraction and timeline-cut application. |
|
Reuse-or-create the SRT that lives next to a media file. |
|
High-level filler-removal pipeline. |
|
ElevenLabs Scribe (speech-to-text) HTTP client. |