How the Whisper API Integration Handles Files That Exceed the 25MB Limit
The Whisper API integration automatically splits oversized audio files into chunks under 24 MiB using FFmpeg, transcribes each segment separately via Groq or OpenAI endpoints, and reconstructs the full transcript with adjusted timestamps to maintain synchronization with the original video.
The bradautomates/claude-video repository implements a robust audio processing pipeline that respects the Whisper API's strict file size constraints. When extracted audio exceeds the 25MB upload threshold, the integration employs a pure-stdlib Python approach to chunk, transcribe, and reassemble segments without re-encoding the source media.
Understanding the 25MB Upload Ceiling and Safety Margin
Both Groq and OpenAI Whisper services enforce a roughly 25 MiB upload limit per request. In skills/watch/scripts/whisper.py, the code defines MAX_UPLOAD_BYTES = 24 * 1024 * 1024 at line 37 to maintain a 1 MiB safety margin. This conservative threshold prevents edge-case rejections due to HTTP overhead or payload wrapping, ensuring reliable uploads even with minor byte-counting variations between client and server.
The Six-Step Audio Chunking Pipeline
When the transcribe_video function detects oversized audio, it triggers a sophisticated segmentation workflow that preserves audio quality while respecting API limits.
1. Detecting Oversized Files
The entry point checks file size at lines 44-55. If audio_bytes <= MAX_UPLOAD_BYTES, the file uploads directly to the Whisper endpoint. Otherwise, the flow proceeds to the chunking logic to break the audio into compliant segments.
2. Planning Chunk Boundaries
The plan_chunks function (lines 40-62) calculates a list of (offset, duration) tuples using linear scaling based on constant-bitrate MP3 characteristics. This produces a segmentation plan where each chunk stays under the 24 MiB limit while distributing duration proportionally across the file.
3. Splitting Audio with FFmpeg
The split_audio function (lines 65-99) executes single-pass FFmpeg commands with -c copy for each planned slice. This extracts segments without re-encoding, preserving audio fidelity and processing speed. Chunks are written to a temporary subdirectory (audio_out.parent / "chunks") to avoid cluttering the working directory.
4. Transcribing Individual Chunks
The transcribe_chunks helper (lines 71-81) iterates through chunk files, calling the Whisper endpoint for each segment. It implements per-chunk exception handling, catching failures and logging them without aborting the entire batch.
5. Adjusting Timestamps with shift_segments
Since each chunk starts at 0 seconds relative to its own file, the shift_segments function (lines 32-47) adds the original temporal offset to every segment timestamp. This ensures the final concatenated transcript reflects the actual video timeline rather than resetting at each chunk boundary.
6. Aggregating Results
The system extends the master segment list with each chunk's shifted results. If every chunk fails, the function raises a clear Whisper failed on every audio chunk error. Otherwise, it returns the aggregated segments to the caller in skills/watch/scripts/watch.py.
Implementation Examples
Example 1: Standard Transcription (Under Limit)
from pathlib import Path
from skills.watch.scripts.whisper import transcribe_video
video_path = "sample.mp4"
audio_out = Path("audio.mp3")
segments, backend = transcribe_video(video_path, audio_out)
print(f"Used {backend} backend, got {len(segments)} segments")
Example 2: Automatic Chunking (Over Limit)
from pathlib import Path
from skills.watch.scripts.whisper import transcribe_video
video_path = "big_video.mp4" # Generates ~50 MiB audio
audio_out = Path("audio.mp3")
segments, backend = transcribe_video(video_path, audio_out)
# Console output shows chunking progress:
# [watch] audio: 50 MB exceeds 24 MB — splitting into 3 chunks…
# [watch] chunk 1/3 → 120 segments
# [watch] chunk 2/3 → 115 segments
# [watch] chunk 3/3 → 118 segments
print(f"Full transcript contains {len(segments)} segments")
Example 3: Handling Partial Failures
# If chunk 2 fails due to network timeout:
# [watch] chunk 2/3 failed — skipping (SystemExit: …)
# The function returns concatenated results of chunks 1 and 3 only,
# preserving partial progress rather than failing entirely
Error Handling and Resilience
The pipeline implements defensive design patterns suitable for long-running video processing. Per-chunk errors are logged and skipped rather than aborting the entire job, preventing temporary network glitches from invalidating hours of processing on large files. However, total failure protection ensures users receive explicit feedback when audio is completely corrupted or inaccessible.
Summary
- The integration reserves a 1 MiB safety margin, using 24 MiB as the effective limit instead of the full 25 MiB.
- FFmpeg
-c copysplits audio without quality loss or CPU-intensive re-encoding. - The
plan_chunksalgorithm uses linear scaling to calculate precise byte-boundaries for constant-bitrate MP3s. shift_segmentsensures reconstructed transcripts maintain accurate synchronization with the original video timeline.- Partial failures are tolerated and logged; total failure raises explicit exceptions to prevent silent data loss.
Frequently Asked Questions
Why does the code use 24 MiB instead of the full 25 MiB limit?
The 1 MiB buffer accounts for HTTP headers, JSON payload wrapping, and potential byte-counting discrepancies between client and server implementations. This conservative approach, defined at line 37 of skills/watch/scripts/whisper.py, prevents edge-case rejections at the API gateway while remaining well within the documented 25MB ceiling.
Does chunking affect transcription accuracy or timestamp precision?
No. Because split_audio uses FFmpeg's -c copy flag, the audio codec remains bit-for-bit identical to the original. The Whisper API receives identical acoustic data, just segmented temporally. The shift_segments function (lines 32-47) then adds the chunk's temporal offset to every word-level timestamp, ensuring the final transcript aligns perfectly with the original video timeline.
What happens if the network fails during processing of one chunk?
The transcribe_chunks function catches per-chunk exceptions and logs them with the pattern [watch] chunk X/Y failed — skipping. The final transcript contains only successfully transcribed segments. This resilience prevents a single network glitch from invalidating the entire job, though users should verify completeness if warnings appear in the logs.
Is video re-encoding required to handle large files?
No. Only the extracted audio track undergoes chunking via FFmpeg. The original video file remains untouched throughout the process, minimizing CPU usage, preserving video quality, and reducing overall processing time compared to solutions that re-encode the entire media file.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →