Skip to main content
Lesson 5 of 16 · Voxtral Audio: Transcription and Speech-to-Text

Your First Transcription Call

Lesson 5 of 16 Updated November 3, 2026 Developer
On this page
  1. Your first transcription with Voxtral
  2. Prepare the environment
  3. Transcribing a local file
  4. Transcribing from a URL
  5. Moving to a robust version
  6. What the response contains
  7. Key takeaways

Course updated November 3, 2026 for Voxtral 3, based on Mistral’s Migrate from Voxtral 2 guide: Voxtral 2 models (voxtral-mini-2602, voxtral-mini-transcribe-realtime-2602, voxtral-mini-tts-2603), deprecated on October 31, 2026 and removed on April 30, 2027, are replaced in examples by voxtral-mini-transcribe-3, voxtral-mini-transcribe-realtime-3, and voxtral-mini-tts-3-0. Key changes: timestamps are segment-only (word returns a 400 error), diarization is possible in real time, real-time session settings are locked after the first audio chunk, and context_bias inputs are free-form (phrases with spaces). Sources: Migrate from Voxtral 2 · Speech to Text.

Your first transcription with Voxtral

Enough theory. In this lesson, you will make your first complete call to the offline transcription API: a local audio file goes to Voxtral Mini Transcribe 3, and you process the returned text. The code fits in a few lines, but we will then build up to a robust version suitable for unattended operation.

Prepare the environment

The Mistral SDK installs with a single command. The verification step that follows saves you from hunting down an import error later.

# Install the Mistral SDK
pip install mistralai

# Verify the installation
python -c "from mistralai.client import Mistral; print('SDK installed')"

You will need a Mistral API key. Create one at console.mistral.ai and store it in an environment variable rather than hardcoding it:

export MISTRAL_API_KEY="your-api-key-here"

Transcribing a local file

Here is the complete code to transcribe a local audio file:

import os
from mistralai.client import Mistral

# Initialize the client
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

# Open and transcribe the audio file
with open("mon_audio.mp3", "rb") as f:
    response = client.audio.transcriptions.complete(
        model="voxtral-mini-transcribe-3",
        file={"content": f, "file_name": "mon_audio.mp3"}
    )

# Display the result
print("=== Transcription ===")
print(response.text)

That is it. In four lines of active code, you get the full transcription of your audio file.

Let us walk through these four lines. Mistral(api_key=...) creates the client with your API key; this is the object you will reuse for all subsequent calls. open("mon_audio.mp3", "rb") opens the file in binary mode, which is mandatory for audio—omitting the b causes a decoding error that is difficult to interpret. The file={"content": f, "file_name": "..."} parameter expects a dictionary containing the file object and its name; this name is not decorative, it helps the server detect the format. Finally, response.text contains the full transcription as a string.

Transcribing from a URL

If your audio file is already hosted online, use file_url instead of file:

import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

response = client.audio.transcriptions.complete(
    model="voxtral-mini-transcribe-3",
    file_url="https://example.com/mon_audio.mp3"
)

print(response.text)

The URL must be publicly accessible. The Mistral server will download the file directly, which avoids routing the audio through your machine when it is already in the cloud—a significant bandwidth saving for a catalog of several hundred files.

Moving to a robust version

The minimal script works for a test. In production, you need to handle missing files, unexpected formats, missing keys, and network errors. The following script performs these checks before the call, then saves the result.

import os
import sys
from pathlib import Path
from mistralai.client import Mistral

def transcrire_audio(chemin_fichier: str) -> str:
    """Transcribes an audio file with Voxtral Mini Transcribe 3."""

    # Check that the file exists
    fichier = Path(chemin_fichier)
    if not fichier.exists():
        raise FileNotFoundError(f"Fichier introuvable : {chemin_fichier}")

    # Check the extension
    extensions_valides = {".mp3", ".wav", ".flac", ".ogg", ".m4a", ".webm"}
    if fichier.suffix.lower() not in extensions_valides:
        raise ValueError(
            f"Format non supporté : {fichier.suffix}. "
            f"Formats valides : {', '.join(extensions_valides)}"
        )

    # Check size (practical limit: ~200 MB)
    taille_mo = fichier.stat().st_size / (1024 * 1024)
    if taille_mo > 200:
        print(f"Attention : fichier volumineux ({taille_mo:.1f} Mo)")

    # Initialize the client
    api_key = os.environ.get("MISTRAL_API_KEY")
    if not api_key:
        raise EnvironmentError("Variable MISTRAL_API_KEY non définie")

    client = Mistral(api_key=api_key)

    # Transcribe
    try:
        with open(chemin_fichier, "rb") as f:
            response = client.audio.transcriptions.complete(
                model="voxtral-mini-transcribe-3",
                file={"content": f, "file_name": fichier.name}
            )
        return response.text
    except Exception as e:
        raise RuntimeError(f"Erreur de transcription : {e}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage : python transcrire.py <fichier_audio>")
        sys.exit(1)

    chemin = sys.argv[1]
    print(f"Transcription de : {chemin}")
    print("-" * 50)

    texte = transcrire_audio(chemin)
    print(texte)

    # Save to text file
    sortie = Path(chemin).stem + "_transcription.txt"
    Path(sortie).write_text(texte, encoding="utf-8")
    print(f"\nTranscription sauvegardée dans : {sortie}")

Run it from the terminal by passing the file path:

python transcribe.py meeting_march15.mp3

The script checks the file, transcribes it, displays the result, and automatically saves it to a .txt file with the same base name. You now have the skeleton for batch processing: loop over a directory, and your audio archive becomes a searchable text archive.

What the response contains

The response object is not limited to text. It also provides the duration of the processed audio and the language recognized by the model—two useful pieces of information for logging your jobs and detecting files that are not in the expected language.

# Full text
print(response.text)

# Audio duration (in seconds)
print(f"Durée : {response.duration:.1f}s")

# Detected language
print(f"Langue : {response.language}")

The best way to gauge the model’s quality is to test it on your own voice. Record a voice message lasting thirty seconds to two minutes, run the script above, and compare the result word-for-word with what you said: you will immediately see where the rare errors lie, almost always on proper nouns. Then repeat the exercise with a file in another language, without changing the code, to observe automatic language detection in action.

Key takeaways

  • The minimal call requires 4 lines: client, file open, API call, read result
  • Two send modes: local file (file) or URL (file_url)
  • The file name in the file dictionary helps with format detection
  • In production, add error handling (missing file, invalid format, network error)
  • response.text always contains the full transcription as a string