beginner12 min readPart 1 of 1

OpenAI Whisper API Tutorial: Speech to Text in Python (API and Local)

Transcribe audio to text in Python with OpenAI's speech-to-text API: gpt-transcribe and the deprecated whisper-1, prompts and keywords, streaming, timestamps and SRT subtitles, files over 25 MB, and running Whisper locally.

TechLogHub
·

Prerequisites

  • •Python 3.9 or newer
  • •An OpenAI API key (for the API sections)
  • •ffmpeg installed for compressing, splitting and local transcription
  • •A GPU is recommended but not required for local Whisper

What You'll Learn

  • Transcribe audio files with the OpenAI speech-to-text API in Python
  • Improve accuracy with prompts, keywords and language hints
  • Stream transcripts and generate timestamps and SRT subtitles
  • Process recordings larger than the 25 MB upload limit
  • Run Whisper locally with openai-whisper or faster-whisper and choose between local and API

OpenAI's speech-to-text API turns audio files into text in a few lines of Python, and the open source Whisper model can do the same on your own hardware. This tutorial covers both: how to call the OpenAI Whisper API and its newer transcription models, how to handle long recordings, timestamps and subtitles, and when running Whisper locally makes more sense.

Whisper API in 2026: what changed

"Whisper API" usually means the whisper-1 model on OpenAI's /v1/audio/transcriptions endpoint. That endpoint is still the way to transcribe files, but the models behind it have moved on:

  • gpt-transcribe is the model OpenAI currently recommends for file transcription. It supports streaming, a prompt, a keywords list for names and jargon, and multiple expected languages.
  • whisper-1, gpt-4o-transcribe, gpt-4o-mini-transcribe and gpt-4o-transcribe-diarize are deprecated, and OpenAI has announced they will shut down on February 26, 2027. The translations endpoint, which uses whisper-1 to translate audio into English, is deprecated on the same timeline.
  • whisper-1 remains the only model with word-level and segment timestamps through timestamp_granularities, so it still matters for subtitles until it is retired.
  • The code below uses gpt-transcribe for plain transcription and whisper-1 only where you need timestamps. Check OpenAI's speech-to-text guide for the latest model list before you deploy.

    Step 1: set up the SDK

    You need an OpenAI API key in the OPENAI_API_KEY environment variable and the official Python SDK. If you have not done this before, the OpenAI API Python tutorial explains keys and billing.

    pip install --upgrade openai
    export OPENAI_API_KEY="sk-proj-your-key-here"

    Supported input formats are mp3, mp4, mpeg, mpga, m4a, wav and webm, and each upload can be at most 25 MB.

    Step 2: transcribe an audio file

    from openai import OpenAI
    client = OpenAI()
    with open("meeting.mp3", "rb") as audio_file:
        transcription = client.audio.transcriptions.create(
            model="gpt-transcribe",
            file=audio_file,
        )
    print(transcription.text)

    The response contains the transcript text, and with gpt-transcribe also a languages list with the detected language codes. Always open the file in binary mode ("rb").

    Step 3: improve accuracy with a prompt and keywords

    Speech models struggle most with product names, acronyms and people's names. Give the model context with a prompt, and with gpt-transcribe a list of keywords and expected languages. The SDK passes newer fields through extra_body:

    with open("support-call.wav", "rb") as audio_file:
        result = client.audio.transcriptions.create(
            model="gpt-transcribe",
            file=audio_file,
            prompt="Customer support call about the TechLogHub Pro plan and invoice AC-42.",
            extra_body={
                "keywords": ["TechLogHub", "AC-42", "Kubernetes", "Priya Sharma"],
                "languages": ["en", "hi"],
            },
        )
    print(result.text)

    Keep each keyword on one line. Do not send the older single language field together with languages. If you know the audio is in one language, passing it still helps accuracy and speed.

    Step 4: stream the transcript

    For long files, streaming lets you show text as soon as it is ready instead of waiting for the full transcript:

    with open("lecture.mp3", "rb") as audio_file:
        stream = client.audio.transcriptions.create(
            model="gpt-transcribe",
            file=audio_file,
            stream=True,
        )
        for event in stream:
            if event.type == "transcript.text.delta":
                print(event.delta, end="", flush=True)
            elif event.type == "transcript.text.done":
                print()
                print("Detected languages:", event.languages)

    Streaming here applies to a completed file. For live microphone audio, OpenAI's Realtime API handles transcription over a WebSocket or WebRTC session instead. whisper-1 does not support streaming.

    Step 5: timestamps and subtitles with whisper-1

    To build subtitles or jump to the moment a word was spoken, request timestamps from whisper-1 while it remains available:

    with open("talk.mp3", "rb") as audio_file:
        result = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="verbose_json",
            timestamp_granularities=["word", "segment"],
        )
    for word in result.words[:10]:
        print(f"{word.start:6.2f}s  {word.word}")

    whisper-1 can also return subtitle files directly. With response_format set to "srt" or "vtt", the SDK returns a string you can save:

    with open("talk.mp3", "rb") as audio_file:
        srt = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="srt",
        )
    with open("talk.srt", "w", encoding="utf-8") as f:
        f.write(srt)

    Because whisper-1 is scheduled to shut down, plan a replacement for timestamp features: either a diarization or timestamp-capable model from OpenAI's current list, or the local Whisper options below, which produce timestamps and SRT files for free.

    Step 6: handle files larger than 25 MB

    Two simple strategies cover most cases. First, compress: speech does not need CD quality, and mono 16 kHz MP3 at 32 to 64 kbps keeps accuracy while shrinking files dramatically. An hour of audio at 32 kbps is roughly 14 MB.

    ffmpeg -i meeting.wav -ac 1 -ar 16000 -b:a 32k meeting.mp3

    Second, split long recordings into chunks, ideally at silences, so sentences are not cut in half. ffmpeg's segment muxer splits by time:

    mkdir -p chunks
    ffmpeg -i podcast.mp3 -f segment -segment_time 600 -c copy chunks/part_%03d.mp3

    Then transcribe the chunks in order and join the text:

    from pathlib import Path
    from openai import OpenAI
    client = OpenAI()
    parts = []
    for chunk in sorted(Path("chunks").glob("part_*.mp3")):
        with open(chunk, "rb") as f:
            result = client.audio.transcriptions.create(model="gpt-transcribe", file=f)
        parts.append(result.text.strip())
        print("done:", chunk.name)
    Path("podcast.txt").write_text(" ".join(parts), encoding="utf-8")

    Passing the last sentence of the previous chunk as the prompt for the next one helps keep names and style consistent across boundaries.

    Practical tips for better transcripts

  • Record clean audio. A decent microphone close to the speaker beats any model setting. Reduce background music and echo where you can.
  • Convert to mono. Stereo adds size without helping recognition, and 16 kHz is enough for speech.
  • Trim silence. Long silent stretches waste upload size and can occasionally cause repeated or invented phrases; ffmpeg's silenceremove filter or a voice activity detector removes them.
  • Use the prompt for spelling, not instructions. The prompt is context the model conditions on, so include the correct spellings of names and terms rather than commands such as "transcribe carefully".
  • Post-process with an LLM. A cheap text model can add paragraphs, fix casing in product names and produce a summary or action items from the raw transcript.
  • Log failures and retry. Network errors and 429 rate-limit responses happen on long batch jobs; the SDK retries automatically, but record which chunks failed so you can resume without re-transcribing everything.
  • Check the result on a sample. Before processing an archive, transcribe a few representative minutes with two models or settings and compare them on the words that matter to you.
  • Run Whisper locally instead

    Whisper is also an open source model released by OpenAI under the MIT licence, so you can run it on your own machine with no per-minute cost and no audio leaving your network. The reference package needs Python and ffmpeg:

    pip install -U openai-whisper
    whisper meeting.mp3 --model turbo --language en --output_format srt

    The CLI writes a subtitle file next to the audio. From Python:

    import whisper
    model = whisper.load_model("turbo")
    result = model.transcribe("meeting.mp3")
    print(result["text"])
    for seg in result["segments"][:5]:
        print(round(seg["start"], 1), round(seg["end"], 1), seg["text"])

    Model sizes trade speed for accuracy. The official README lists roughly 1 GB of VRAM for tiny and base, 2 GB for small, 5 GB for medium, 6 GB for turbo and 10 GB for large. turbo is an optimised large-v3 variant that is much faster with a small accuracy cost, and it is a good default on a modern GPU. On CPUs or for higher throughput, use faster-whisper, a CTranslate2 reimplementation that is several times faster and supports 8-bit quantization:

    from faster_whisper import WhisperModel
    model = WhisperModel("large-v3", device="cuda", compute_type="float16")
    segments, info = model.transcribe("meeting.mp3", beam_size=5)
    print("Language:", info.language)
    for s in segments:
        print(f"{s.start:7.1f}s  {s.text}")

    On Macs and edge devices, whisper.cpp runs quantized Whisper models efficiently on Apple Silicon and CPUs.

    Whisper API vs local Whisper: which to choose

  • Cost: the API bills per use, so it is cheap for occasional files; local Whisper costs nothing per minute once you have the hardware, which wins for large archives.
  • Privacy: local transcription keeps audio on your machines, which can simplify compliance for medical, legal or internal recordings.
  • Hardware and ops: the API needs no GPU and scales instantly; local Whisper needs a GPU for good speed and someone to maintain it.
  • Features: the API's newer models add streaming, keywords and multilingual hints and keep improving; local Whisper gives you timestamps, SRT output and full control, including fine-tuning.
  • Longevity: hosted model names get deprecated, as whisper-1 shows, while an open source model you have downloaded keeps working.
  • A common pattern is local Whisper or faster-whisper for bulk and sensitive audio, and the API for apps that need fast, scalable transcription without running GPUs.

    Next steps

    Feed transcripts into an LLM to summarise meetings or extract action items with the OpenAI API Python tutorial, index them for search with embeddings, or keep the whole pipeline on your own hardware by pairing local Whisper with a model from the run an LLM locally tutorial. If you are choosing an AI provider for the rest of your stack, see OpenAI API vs Anthropic API vs Gemini API.

    whisper apiopenai whisperspeech to textpythontranscriptionai

    Keep the references coming

    One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.