Difference Between Groq and OpenAI Whisper Backends in claude-video
The Groq and OpenAI Whisper backends differ only in endpoint URLs, model identifiers, API key environment variables, and User-Agent headers, while sharing identical audio chunking, retry logic, and response parsing implementations in skills/watch/scripts/whisper.py.
The claude-video repository provides a flexible transcription pipeline through its watch skill, supporting both Groq's Whisper-compatible API and OpenAI's native Whisper API within a single unified codebase. While the transcription workflow processes audio identically regardless of backend, four specific configuration distinctions determine which service handles your request and how the client authenticates.
Core Backend Configuration Differences
The transcription logic isolates backend-specific behavior to initialization parameters and headers, allowing the rest of the pipeline to remain service-agnostic.
Endpoint URLs and Model Selection
According to lines 29-34 in skills/watch/scripts/whisper.py, the two backends target different API endpoints and model identifiers:
- Groq Whisper: Sends requests to
https://api.groq.com/openai/v1/audio/transcriptionsusing thewhisper-large-v3model - OpenAI Whisper: Targets
https://api.openai.com/v1/audio/transcriptionswith thewhisper-1model
These values are defined as module-level constants and determine the destination for all multipart upload requests.
API Key Hierarchy and Environment Variables
The load_api_key function (lines 65-71 and 98-108) implements a preference-based fallback strategy for authentication:
- First checks for the
GROQ_API_KEYenvironment variable - Falls back to
OPENAI_API_KEYonly if the Groq key is absent
This hierarchy makes Groq the default backend when both keys are present, though users can override this behavior through CLI arguments.
User-Agent Header Requirements
The _post_whisper function (lines 45-51) transmits a custom User-Agent string (watch-skill/1.0 (+claude-code; python-urllib)) specifically to bypass Cloudflare's default blocking rules that target generic Python urllib clients. While the same header is sent to both services, it serves a functional purpose only for the Groq backend, which runs behind Cloudflare's edge network.
Shared Transcription Implementation
Despite configuration differences, the core audio processing pipeline remains identical for both backends, ensuring consistent behavior and maintainability.
Audio Processing Pipeline
The workflow processes audio through the same function sequence regardless of backend selection:
extract_audio(): Creates a mono 16kHz MP3 file that satisfies both services' 25 MiB upload limitplan_chunks(): Splits oversized audio into time-aligned segments based onMAX_UPLOAD_BYTESwhen files exceed the size restriction_build_multipart(): Constructs the request body using standard library tools without requiring external dependencies likerequests,groq, oropenaiSDKs_segments_from_response(): Normalizes the JSONsegmentsfield into a unified{start, end, text}format consumed by the rest of the pipeline
Retry Logic and Error Handling
Both backends share identical rate-limit handling in _post_whisper (lines 71-78). The code counts HTTP 429 responses and retries requests up to MAX_429_RETRIES times, applying the same backoff strategy regardless of whether the error originates from Groq or OpenAI infrastructure.
Practical Usage Examples
Configure and invoke the transcription pipeline using environment variables or CLI arguments to control backend selection.
Configuring API Keys
Store your preferred backend's API key in the user configuration file:
# ~/.config/watch/.env
GROQ_API_KEY="your-groq-key-here"
Alternatively, export the variable directly in your shell:
export GROQ_API_KEY="your-groq-key-here"
export OPENAI_API_KEY="your-openai-key-here"
When both variables are set, the system defaults to Groq unless explicitly overridden.
Selecting Backends via CLI
Run transcription with automatic backend selection (prefers Groq if GROQ_API_KEY is present):
python3 -m skills.watch.scripts.whisper /path/to/video.mp4
Force a specific backend using the watch CLI interface:
watch https://youtu.be/xyz --whisper openai
This bypasses the default preference hierarchy and routes the request to OpenAI's endpoint regardless of which environment variables are set.
Summary
- Both backends share identical chunking, retry, and parsing logic centralized in
skills/watch/scripts/whisper.py - Groq uses
whisper-large-v3atapi.groq.com, while OpenAI useswhisper-1atapi.openai.comas defined in lines 29-34 - The
load_api_keyfunction prioritizesGROQ_API_KEYoverOPENAI_API_KEYwhen both are available - A custom User-Agent header is required for Groq to bypass Cloudflare blocking rules
- Audio processing relies on
extract_audio(),plan_chunks(),_build_multipart(), and_segments_from_response()regardless of backend selection
Frequently Asked Questions
Which backend provides faster transcription speeds?
Groq typically offers lower latency for the whisper-large-v3 model compared to OpenAI's whisper-1, though the claude-video implementation adds no additional processing overhead beyond the network request itself. Actual performance depends on file size, network conditions, and current API load.
How do I force the use of OpenAI when Groq is configured?
Explicitly specify the backend using the CLI flag --whisper openai when invoking the watch command. This overrides the default preference hierarchy defined in load_api_key that otherwise prioritizes Groq when both GROQ_API_KEY and OPENAI_API_KEY environment variables are present.
Why does the Groq backend require a custom User-Agent header?
Groq's API runs behind Cloudflare, which blocks generic Python urllib user-agents by default. The custom header watch-skill/1.0 (+claude-code; python-urllib) defined in _post_whisper (lines 45-51) identifies the client as a legitimate transcription tool, allowing the request to reach Groq's inference servers.
What happens when audio files exceed the 25 MiB upload limit?
The plan_chunks() function automatically splits large files into segments under MAX_UPLOAD_BYTES, processing each chunk sequentially through the selected backend and concatenating results via _segments_from_response(). This chunking behavior is identical for both Groq and OpenAI backends.
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 →