Ein Video mit Sprecherstimme bauen
Eine durchgängige Anleitung, die mit einem LLM ein Skript schreibt, Clips generiert, ein Voiceover synthetisiert und beides zusammenführt — mit einem einzigen API-Schlüssel.
Dieses Tutorial verkettet drei Modelltypen in einem einzigen Skript: Ein Sprachmodell schreibt den Text, ein Videomodell erzeugt das Bildmaterial, und ein Sprachsynthese-Modell liest den Text vor. Ein realistisches Beispiel dafür, warum eine gemeinsame API und ein gemeinsames Guthaben über Modelltypen hinweg nützlich sind.
Was Sie brauchen: Python 3.9+, einen API-Schlüssel und ffmpeg, falls Sie Audio und Video am Ende muxen möchten.
Hier laufen echte Generierungsaufgaben, die echtes Guthaben kosten. Video ist der teure Teil — starten Sie beim Ausprobieren mit einer kurzen Dauer und nutzen Sie die Preisschätzung, wenn Sie vorab eine genaue Zahl möchten.
Einrichtung
pip install requests
export ATLASCLOUD_API_KEY="your-api-key"Schritt 1 — Gemeinsame Hilfsfunktionen
Jede Medienaufgabe folgt demselben Muster aus Einreichen und Pollen, also definieren wir es einmal.
import os, time, requests
API_KEY = os.environ["ATLASCLOUD_API_KEY"]
BASE = "https://api.atlascloud.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
TERMINAL = {"completed", "succeeded", "failed", "timeout"}
def submit(endpoint: str, model: str, **params) -> str:
"""Aufgabe einreichen. Beachten Sie: Die Parameter stehen flach, nicht in einem input-Objekt."""
r = requests.post(f"{BASE}/model/{endpoint}",
headers=HEADERS, json={"model": model, **params}, timeout=60)
r.raise_for_status()
return r.json()["data"]["id"]
def wait(prediction_id: str, timeout: int = 900) -> dict:
"""Pollen bis zum Endzustand, mit schrittweise wachsendem Intervall."""
deadline, delay = time.time() + timeout, 2.0
while time.time() < deadline:
r = requests.get(f"{BASE}/model/prediction/{prediction_id}",
headers=HEADERS, timeout=30)
r.raise_for_status()
data = r.json()["data"]
if data.get("status") in TERMINAL:
if data["status"] in ("failed", "timeout"):
raise RuntimeError(f"Aufgabe fehlgeschlagen: {data.get('error') or data['status']}")
return data
time.sleep(delay)
delay = min(delay * 1.5, 10.0)
raise TimeoutError(prediction_id)
def download(url: str, path: str) -> str:
r = requests.get(url, timeout=300)
r.raise_for_status()
with open(path, "wb") as f:
f.write(r.content)
return pathSchritt 2 — Den Text mit einem LLM schreiben
Sprachmodelle verwenden eine andere Basis-URL und arbeiten synchron, laufen also nicht über submit/wait.
def write_narration(topic: str) -> str:
r = requests.post(
"https://api.atlascloud.ai/v1/chat/completions",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "deepseek-ai/deepseek-v3.2",
"messages": [
{"role": "system",
"content": "You write narration for short videos. "
"Reply with two sentences of spoken narration and nothing else."},
{"role": "user", "content": f"Topic: {topic}"},
],
"max_tokens": 200,
},
timeout=120,
)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"].strip()
narration = write_narration("how ocean waves shape a coastline")
print(narration)Schritt 3 — Das Bildmaterial generieren
video_id = submit(
"generateVideo",
"alibaba/wan-2.5/text-to-video",
prompt="slow aerial shot of waves breaking against a rocky coastline at golden hour",
duration=5,
)
video = wait(video_id)
download(video["outputs"][0], "footage.mp4")Die Videogenerierung dauert Minuten, nicht Sekunden. Registrieren Sie im Produktivbetrieb einen Webhook und lassen Sie die Aufgabe zurückrufen, statt eine Polling-Schleife offen zu halten.
Schritt 4 — Das Voiceover synthetisieren
Der Text aus Schritt 2 wird hier zur Eingabe. Sprache, Musik und Transkription teilen sich denselben Endpunkt — welches Ergebnis Sie erhalten, entscheidet das Modell.
audio_id = submit(
"generateAudio",
"bytedance/seed-audio-1.0",
text=narration,
format="mp3",
sample_rate=44100,
speech_rate=-5, # Etwas langsamer, so ist die Erzählung besser verständlich
)
audio = wait(audio_id)
download(audio["outputs"][0], "voiceover.mp3")Den vollständigen Parametersatz, inklusive Stimmreferenzen, finden Sie unter Audio-Modelle.
Schritt 5 — Zusammenführen
ffmpeg -i footage.mp4 -i voiceover.mp3 \
-c:v copy -c:a aac -shortest narrated.mp4Optional — Untertitel generieren
Schicken Sie das Voiceover durch ein Transkriptionsmodell, um wortgenaue Zeitmarken für Untertitel zu erhalten.
stt_id = submit(
"generateAudio",
"bytedance/seed-asr-2.0",
audio_url=audio["outputs"][0], # Achtung: Das Feld heißt audio_url
enable_punc=True,
show_utterances=True,
)
stt = wait(stt_id)
# Bei Transkriptionsmodellen ist outputs[0] der Text selbst, keine Datei-URL
print(stt["outputs"][0])
for word in stt.get("stt_result", {}).get("words", [])[:10]:
print(word["start"], word["end"], word["text"])Transkriptionsmodelle erwarten audio_url, manche anderen Speech-to-Text-Modelle hingegen audio. Prüfen Sie die API-Referenz des Modells — ein falscher Feldname scheitert an der Validierung.
Wie es weitergeht
- Tauschen Sie das Videomodell gegen eines, das ein Referenzbild akzeptiert, und steuern Sie den Look über ein von Ihnen bereitgestelltes Standbild
- Wechseln Sie vom Polling zu Webhooks, damit lange Aufgaben Ihren Prozess nicht blockieren
- Erzeugen Sie mehrere Clips parallel und fügen Sie sie zu einer längeren Sequenz zusammen
- Ergänzen Sie eine Retry-Behandlung aus Fehler & Ratenbegrenzungen
Verwandte Themen
Last updated on