OpenAI Whisper API: Developer Guide for Speech-to-Text

OpenAI Whisper API: A Practical Guide for Developers

Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.

If you’re building anything that touches audio or video — auto-generated subtitles, podcast transcripts, searchable meeting recordings — the OpenAI Whisper API is one of the fastest ways to get production-grade speech-to-text without babysitting a GPU. This guide walks through setup, real code, Docker-based deployment, and how to fold Whisper into a streaming media pipeline.

What Is the OpenAI Whisper API

Whisper started as an open-source model from OpenAI trained on 680,000 hours of multilingual audio. The hosted OpenAI Whisper API wraps that model behind a simple HTTPS endpoint, so you send an audio file and get back a transcript — no model weights, no GPU drivers, no CUDA version hell.

It supports:

  • Transcription in the original spoken language
  • Translation directly into English
  • Multiple output formats (json, text, srt, vtt, verbose_json)
  • Word- and segment-level timestamps for caption generation
  • Automatic language detection across 90+ languages
  • For teams already running Docker-based infrastructure (see our Docker Compose guide for media servers), Whisper slots in as just another containerized service that calls out to an external API — no local inference workload required.

    How Whisper Differs from Self-Hosted Models

    The open-source Whisper model can be run locally with ffmpeg preprocessing and a Python inference script, but that means owning GPU costs, model loading time, and scaling logic yourself. The API version trades a per-minute usage fee for zero infrastructure management. If you’re processing a handful of files a day, the API is almost always cheaper than a standing GPU instance. If you’re transcribing thousands of hours monthly, self-hosting on a dedicated GPU box starts to make financial sense — more on that tradeoff later.

    Setting Up Your Environment

    You’ll need an OpenAI account with billing enabled and an API key. Store it as an environment variable — never hardcode it in source control.

    export OPENAI_API_KEY="sk-your-key-here"

    Installing Dependencies and Getting an API Key

    Grab your key from the OpenAI platform dashboard, then install the official Python SDK:

    python3 -m venv venv
    source venv/bin/activate
    pip install openai python-dotenv

    If you’re working with video files rather than raw audio, you’ll also need ffmpeg to extract the audio track first:

    sudo apt update && sudo apt install -y ffmpeg

    Making Your First Transcription Request

    Here’s a minimal script that transcribes an audio file and prints the text:

    import os
    from openai import OpenAI
    
    client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
    
    with open("episode-01.mp3", "rb") as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="verbose_json",
            timestamp_granularities=["segment"]
        )
    
    print(transcript.text)
    for segment in transcript.segments:
        print(f"[{segment.start:.2f}s - {segment.end:.2f}s] {segment.text}")

    Using verbose_json gives you segment-level timestamps, which is exactly what you need to generate .srt or .vtt caption files for a video player.

    Generating SRT Captions Directly

    You can skip manual formatting entirely by requesting the srt format:

    with open("episode-01.mp3", "rb") as audio_file:
        srt_output = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="srt"
        )
    
    with open("episode-01.srt", "w") as f:
        f.write(srt_output)

    That .srt file drops straight into Plex, Jellyfin, or any HTML5 video player with <track> support.

    Docker-Based Deployment for Production Pipelines

    For a repeatable production setup, wrap the transcription logic in a small containerized worker rather than running scripts by hand. This fits naturally alongside the rest of a Docker-based stack — if you haven’t containerized your media pipeline yet, our Docker Compose guide for media servers is a good starting point.

    FROM python:3.11-slim
    
    RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
    
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    
    COPY worker.py .
    
    CMD ["python", "worker.py"]

    # docker-compose.yml
    services:
      whisper-worker:
        build: .
        environment:
          - OPENAI_API_KEY=${OPENAI_API_KEY}
        volumes:
          - ./incoming:/app/incoming
          - ./captions:/app/captions
        restart: unless-stopped

    The worker polls an incoming/ directory, transcribes new files, and writes captions to captions/ — a pattern that’s easy to hook into any media ingestion pipeline.

    Handling Large Audio Files and Chunking

    The API caps uploads at 25 MB per request. For long-form content — full podcast episodes, lecture recordings, or livestream VODs — you need to split the audio first. Use ffmpeg to chunk into fixed-length segments before sending each one:

    ffmpeg -i full-episode.mp3 -f segment -segment_time 600 -c copy chunk_%03d.mp3

    Then loop over the chunks, transcribe each, and stitch the resulting text (or timestamped segments) back together, adjusting timestamps by the cumulative offset of each chunk.

    Adding Captions to Streaming Video Workflows

    If you’re running a self-hosted streaming setup — Jellyfin, Plex, or a custom player — auto-generated captions are one of the highest-value, lowest-effort additions you can make. A typical pipeline looks like:

    1. Extract audio from the source video with ffmpeg
    2. Send the audio to the Whisper API for transcription
    3. Save the returned .srt alongside the video file
    4. Let your media server auto-detect the sidecar subtitle file

    ffmpeg -i movie.mkv -vn -acodec mp3 movie-audio.mp3

    This is especially useful for archived home-theater libraries where original subtitle tracks were never included, or for creators who need burned-in captions for accessibility compliance.

    Cost Optimization and Rate Limits

    Whisper API pricing is billed per minute of audio processed, not per API call. A few practical ways to keep costs down:

  • Downsample audio to mono 16kHz before uploading — it doesn’t affect transcription quality but reduces file size and upload time
  • Batch process during off-peak hours if you’re running a queue-based worker
  • Cache transcripts — don’t re-transcribe the same file if it hasn’t changed
  • Use language hints when you know the source language, which slightly speeds up processing
  • Rate limits are account-tier dependent, so if you’re running a high-volume pipeline, implement exponential backoff on 429 responses rather than hammering retries.

    Self-Hosting vs API: When to Use Which

    Running open-source Whisper locally makes sense once your volume justifies dedicated GPU hardware. Below a certain threshold, the API is simpler and cheaper. As a rough rule of thumb:

  • Under ~50 hours/month of audio: use the API, skip the infrastructure
  • 50–500 hours/month: API is still usually cheaper unless you already have idle GPU capacity
  • 500+ hours/month: a dedicated GPU VPS running the open-source model often pays for itself within weeks
  • If you land in that last bucket, both DigitalOcean and Hetzner offer GPU-backed instances well suited to running Whisper locally at scale, and either is a solid choice if you’re already comfortable managing your own Docker stack — check out our best VPS providers for streaming servers breakdown for a deeper comparison.

    Deploying Your Transcription Service

    For the worker pattern described above, you don’t need anything exotic — a small 2-4 vCPU instance is plenty, since the actual transcription happens on OpenAI’s infrastructure, not yours. Your container just handles file movement, chunking, and API calls.

    If you’re standing up a new box specifically for this kind of media automation, DigitalOcean’s Droplets are quick to provision and integrate cleanly with Docker Compose out of the box. Hetzner tends to win on raw price-per-core if your workload is more CPU-bound (heavy ffmpeg transcoding alongside the transcription queue).

    Recommended: Ready to put this into practice? DigitalOcean is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.

    FAQ

    Does the Whisper API support real-time streaming transcription?
    No. The hosted API is request/response only — you send a complete audio file and get a transcript back. For live/real-time captioning, you’d need to chunk a live stream into short segments and transcribe them in near-real-time, which introduces latency, or use a different real-time speech service.

    What audio formats does the API accept?
    MP3, MP4, MPEG, MPGA, M4A, WAV, and WEBM are all supported directly. If your source is a video container like MKV, extract the audio track with ffmpeg first.

    How accurate is Whisper compared to other transcription services?
    Whisper generally performs very well on clear English audio and holds up better than most competitors on accented speech and background noise, though accuracy on noisy or overlapping-speaker audio still degrades like any ASR system.

    Can I use the Whisper API for copyrighted movie or show audio?
    Technically yes for personal captioning of content you legally own, but redistributing generated captions for copyrighted material you don’t have rights to can raise legal issues — check your local regulations before publishing.

    Is there a free tier for the Whisper API?
    No dedicated free tier exists for the API itself, though new OpenAI accounts sometimes receive trial credits. Budget for per-minute usage costs in any production plan.

    What’s the maximum file size per request?
    25 MB per upload. Longer files need to be chunked with ffmpeg before sending, as covered earlier in this guide.

    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *