Your First Transcription Call
On this page
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 byvoxtral-mini-transcribe-3,voxtral-mini-transcribe-realtime-3, andvoxtral-mini-tts-3-0. Key changes: timestamps are segment-only (wordreturns a 400 error), diarization is possible in real time, real-time session settings are locked after the first audio chunk, andcontext_biasinputs 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
filedictionary helps with format detection - In production, add error handling (missing file, invalid format, network error)
response.textalways contains the full transcription as a string