Spracherkennung mit Whisper
whisper-large-v3-turbo ist über denselben /v1/audio/transcriptions-Endpunkt wie die OpenAI Whisper API zugänglich, sodass jeder für OpenAI geschriebene Code durch Änderung der base_url direkt übernommen werden kann. Unterstützte Formate, Sprachcodes und Inferenzparameter auf der Whisper-Modellseite.
Einrichtung
user@local $ pip install openai
user@local $ export OPENAI_API_KEY="sk-…"
Für das Aufteilen großer Dateien (über 25 MB):
user@local $ pip install pydub
# pydub benötigt ffmpeg
user@local $ brew install ffmpeg # macOS
user@local $ apt-get install ffmpeg # Debian/Ubuntu
Grundlegende Transkription
import os
from openai import OpenAI
client = OpenAI(base_url="https://llm.aihosting.mittwald.de/v1")
with open("aufnahme.mp3", "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=f,
language="de", # Immer explizit setzen — Standard ist "de"
response_format="json",
temperature=1.0,
)
print(result.text)
Mehrere Sprachen
dateien_und_sprachen = [
("meeting_de.mp3", "de"),
("interview_fr.wav", "fr"),
("podcast_en.ogg", "en"),
("vortrag_ja.flac", "ja"),
]
for dateiname, sprache in dateien_und_sprachen:
with open(dateiname, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=f,
language=sprache,
response_format="json",
temperature=1.0,
)
print(f"[{sprache}] {result.text[:120]}")
Große Dateien (> 25 MB)
Die API akzeptiert Dateien bis zu 25 MB. Größere Aufnahmen mit pydub an Stille-Stellen aufteilen, damit jeder Abschnitt sicher unter dem Limit bleibt und keine Wörter mittendrin geschnitten werden:
from pydub import AudioSegment
from pydub.silence import split_on_silence
from io import BytesIO
def grosse_datei_transkribieren(path: str, language: str = "de") -> str:
"""Datei beliebiger Größe transkribieren durch Aufteilen an Stille-Stellen."""
audio = AudioSegment.from_file(path)
# An Pausen von mehr als 700 ms mit Stille unter -40 dBFS aufteilen
chunks = split_on_silence(
audio,
min_silence_len=700,
silence_thresh=-40,
keep_silence=300, # 300 ms Stille an jeder Kante für Kontext beibehalten
)
# Fallback: wenn keine Stille gefunden, in feste 60-Sekunden-Abschnitte aufteilen
if not chunks:
chunk_ms = 60_000
chunks = [audio[i: i + chunk_ms] for i in range(0, len(audio), chunk_ms)]
transkripte: list[str] = []
for chunk in chunks:
buf = BytesIO()
chunk.export(buf, format="mp3")
buf.seek(0)
buf.name = "chunk.mp3" # openai SDK liest das .name-Attribut für den MIME-Typ
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=buf,
language=language,
response_format="json",
temperature=1.0,
)
transkripte.append(result.text)
return " ".join(transkripte)
volltext = grosse_datei_transkribieren("langes_interview.mp3", language="de")
print(volltext)
Transkription + Zusammenfassungs-Pipeline
Whisper mit einem Chat-Modell verknüpfen, um direkt von Audio zu einer schriftlichen Zusammenfassung zu gelangen:
def transkribieren_und_zusammenfassen(audio_path: str, language: str = "de") -> dict:
# Schritt 1: Transkribieren
with open(audio_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=f,
language=language,
response_format="json",
temperature=1.0,
)
transkript = result.text
# Schritt 2: Zusammenfassen
zusammenfassung_resp = client.chat.completions.create(
model="Qwen3.6-35B-A3B-FP8",
messages=[
{
"role": "system",
"content": "Fasse das Transkript prägnant zusammen. Verwende Stichpunkte für die wichtigsten Themen.",
},
{"role": "user", "content": transkript},
],
temperature=0.7,
max_tokens=512,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
return {
"transkript": transkript,
"zusammenfassung": zusammenfassung_resp.choices[0].message.content,
}
ausgabe = transkribieren_und_zusammenfassen("team_standup.mp3", language="de")
print("Transkript:\n", ausgabe["transkript"])
print("\nZusammenfassung:\n", ausgabe["zusammenfassung"])
Drop-in-Ersatz für OpenAI
Bestehender Code für die OpenAI Whisper API benötigt nur eine base_url-Änderung:
# Vorher (OpenAI)
client = OpenAI()
# Nachher (mittwald AI Hosting)
client = OpenAI(base_url="https://llm.aihosting.mittwald.de/v1")
Der gesamte übrige Code – Dateiverarbeitung, response_format, language, temperature – bleibt identisch.
Zeitstempel und Spracherkennung mit verbose_json
response_format="verbose_json" gibt segmentgenaue Zeitstempel, die erkannte Sprache und die Gesamtdauer zurück:
with open("aufnahme.mp3", "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=f,
language="de",
response_format="verbose_json",
temperature=1.0,
)
print(result.text)
print(f"Sprache: {result.language}")
print(f"Dauer: {result.duration}s")
for seg in (result.segments or []):
print(f" [{seg['start']:.1f}s–{seg['end']:.1f}s] {seg['text']}")