chunkscribe
Split long audio at natural pauses and transcribe it with the OpenAI API.
Transcription endpoints cap uploads at 25 MB, which forces you to chunk anything
longer than roughly ten minutes. Cutting on a fixed clock clips words mid-syllable
at every boundary. chunkscribe cuts at silences instead: you set a target
duration, and it extends to the next qualifying pause.
Install
pip install chunkscribe
Set your key in a .env file beside the audio, or in the environment:
OPENAI_API_KEY=sk-...
WAV input needs nothing else. Other formats require pip install chunkscribe[mp3]
and an ffmpeg binary on PATH.
Use
chunkscribe SOURCE [OUTPUT] [options]
Inspect the split before spending anything:
chunkscribe lecture.wav --dry-run
14 chunks, 176.3 min of speech, ~$1.06
part_000.wav 0.0 → 9.7 min ( 9.7 min, 18.6 MB)
part_001.wav 9.8 → 19.2 min ( 9.4 min, 18.0 MB)
...
Then run it:
chunkscribe lecture.wav transcript.txt --language en --timestamps
Omit OUTPUT to write alongside the input as .txt.
Options
| Flag | Default | |
|---|---|---|
--dry-run |
off | split and report, no API calls |
-f, --overwrite |
off | replace an existing output file |
-q, --quiet |
off | suppress the per-chunk listing |
--workdir DIR |
.chunkscribe/ |
cache location |
--min-dur SEC |
420 | earliest legal cut point |
--max-dur SEC |
600 | hard ceiling; keeps chunks under 25 MB |
--max-silence SEC |
0.6 | pause length that qualifies as a cut |
--energy N |
50 | speech/silence threshold |
--model NAME |
gpt-4o-transcribe |
|
--language ISO |
autodetect | e.g. en |
--prompt TERMS |
— | seed names, jargon, expected spellings |
--timestamps |
off | prefix each chunk with its source offset |
Tuning the split
Run --dry-run and read the chunk list. Two failure modes:
One region, or very few. --energy is too low, so room tone counts as speech
and no pause ever qualifies. Raise it to 55–60.
Most chunks land on exactly --max-dur. No qualifying pause is being found,
so every cut is a blind ceiling cut. Raise --max-silence to 0.4, or lower
--energy. A warning fires automatically when this happens to more than half
the chunks.
A three-hour lecture typically settles at 18–25 regions.
Caching and resume
Chunk audio and per-chunk transcripts are cached under --workdir. Interrupt a
run and re-issue the same command: completed chunks are reused and cost nothing.
The cache directory name includes a fingerprint of the split settings, so
changing --energy or --min-dur writes to a fresh directory rather than
pairing new boundaries with stale transcripts. Old directories are never
cleaned up automatically — rm -rf .chunkscribe/ when you're done.
Accuracy notes
--prompt seeds the first chunk's vocabulary. After that each chunk is primed
with the tail of the previous transcript, which keeps names and terminology
consistent across boundaries. Put rare terms in --prompt even if they appear
late; the carry-over window is only 800 characters.
Because transcription is sequential to preserve that carry-over, a long file takes a while. Parallelising would be faster and less consistent.
Silences longer than --max-silence are dropped between regions, so chunk
durations won't sum to the full runtime. That's expected. Timestamps come from
each region's true offset in the source, not from accumulated durations.
Python API
from pathlib import Path
from chunkscribe import transcribe, SplitConfig
text = transcribe(
"lecture.wav",
split_cfg=SplitConfig(min_dur=300, max_dur=540, energy_threshold=55),
timestamps=True,
)
Path("transcript.txt").write_text(text, encoding="utf-8")
Lower-level pieces, if you want the chunk boundaries themselves:
from chunkscribe import SplitConfig, TranscribeConfig, split, transcribe_chunks, render, workdir_for
cfg = SplitConfig()
chunks = split(Path("lecture.wav"), workdir_for(Path("lecture.wav"), cfg), cfg)
for c in chunks:
print(c.index, c.start, c.end, c.size)
results = transcribe_chunks(chunks, TranscribeConfig(language="en"))
print(render(results, timestamps=True))
Exit codes
0 success · 1 split failure · 2 bad arguments · 130 interrupted
Cost
The --dry-run estimate uses a hardcoded per-minute rate. Verify it against
current OpenAI pricing before relying on it.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chunkscribe-0.1.0.tar.gz.
File metadata
- Download URL: chunkscribe-0.1.0.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31a7be6b556459a47402c8263720f465021927ff73c9e5e44bfce72fb0fc43bc
|
|
| MD5 |
a9ea5521a738a7625452ccd6e39de031
|
|
| BLAKE2b-256 |
0ed3368a6d52fe131c12819dd7c016a2e72654df66bb2062851a6f2150d7e560
|
File details
Details for the file chunkscribe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: chunkscribe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5caa798e872f38199d3662a95af26cc52e562af450ed5b12a11bc13136f2e65e
|
|
| MD5 |
232ae60b5e61d677071300871dd18d4e
|
|
| BLAKE2b-256 |
0b9bc5fb917e4137180335559a34cc7bbdce72c9e85abb05b70ee7f33a65bbe6
|