Runway-Bildraten-Erhöhung: So prüfen Sie das fertige Video
Vollständiger Ablauf von Vorbereitung und Upload eines lokalen Videos über enhance_frame_rate, Task-Abfrage und Speicherung bis zur FPS- und Sync-Prüfung.
Inhalt

Sie können ein fertiges lokales Video haben, ohne bereits eine Runway-Ausgabe mit erhöhter Bildrate zu besitzen. Vor der Abnahme müssen Sie die Datei vorbereiten und hochladen, targetFramerate senden, auf den Task warten und das Ergebnis speichern. Dieser Leitfaden zeigt die vollständige REST-Kette und prüft danach Bildrate, Bewegungsartefakte, Schnitte und Audio-Synchronität.
Runway hat enhance_frame_rate am 17. September 2026 zu Runway Dev hinzugefügt. Der Vorgang nutzt den video upscale endpoint und akzeptiert 24, 25, 30, 48, 50, 60, 120, 23_98 (23,98 fps), 29_97 (29,97 fps) und 59_94 (59,94 fps); eine Eingabe ist auf 300 Sekunden begrenzt, und die Ankündigung nennt 1 credit pro 2 Sekunden.
Nehmen Sie das Ergebnis nicht allein deshalb ab, weil es flüssiger aussieht. Wählen Sie zuerst die exakte Zielkadenz, prüfen Sie danach Metadaten, riskante Bewegungen, Schnitte sowie die Synchronität am Anfang, in der Mitte und am Ende und testen Sie anschließend in der realen Timeline und Zielplattform.
Zuerst die Lieferkadenz wählen; ohne genaue Vorgabe nicht verarbeiten
Wählen Sie vor dem Senden den exakten Wert aus Timeline-, Sender-, Werbeplattform- oder Kundenvorgabe. 29_97 und 30 sowie 59_94 und 60 wirken fast gleich, doch eine falsche Ersetzung kann bei langen Programmen, Broadcast und gemischten Quellen einen neuen Transcode oder kompletten Durchlauf erzwingen.
| Ziel | Typische Entscheidungsgrundlage | Vor der Übergabe bestätigen |
|---|---|---|
23_98 / 24 | Timeline oder Auftraggeber verlangt Filmkadenz | Ob exakt 23,98 statt ganzzahlig 24 gefordert ist |
25 / 50 | 25/50-fps-Produktionskette oder regionale Vorgabe | Timeline, Untertitel, Audio und übriges Material nutzen dieselbe Kadenz |
29_97 / 30 | Das Zielsystem nennt ausdrücklich einen der Werte | Nicht ohne Freigabe gegeneinander austauschen |
59_94 / 60 | Bewegungsreiches Material oder Plattform mit HFR-Vorgabe | Flüssigere Wiedergabe bedeutet nicht, dass verlorene Details wiederhergestellt sind |
48 / 120 | Spezielle Timeline, Zeitlupe oder HFR-Ausgabe | Nur verwenden, wenn der Downstream es verlangt; höher ist nicht automatisch besser |
Steht im Briefing nur „flüssiger machen“, fragen Sie nach der endgültigen Lieferspezifikation. Sonst entsteht möglicherweise eine technisch gültige 60-fps-Datei, die dennoch nicht sauber in eine 59,94-fps-Timeline gehört.
Quelldaten sichern, damit sich Fehler später zuordnen lassen
Dokumentieren Sie vor der Verarbeitung Bildrate, Dauer, Codec und Audiospuren der Quelle. Ohne diese Referenz lässt sich eine fehlende Spur, geänderte Dauer oder eingefrorene Schlusssequenz nur schwer der Quelle, der Runway-Ausgabe oder einem späteren Transcode zuordnen.
- Dateiname, Dauer, Abmessungen, Codec und ursprüngliche Bildrate.
- Ob die Quelle konstante Bildrate (CFR) oder variable Bildrate (VFR) nutzt.
- Anzahl der Audiospuren, sample rate, Kanäle und ungefähre Dauer.
- Zielbildrate und Herkunft der Anforderung, etwa „Kunde verlangt
59_94“. - Drei bis fünf riskante Timecodes: schnelle Schwenks, Hände, feine Linien, Verdeckungskanten, Blitze, Übergänge, Untertitel oder UI.
- Mindestens drei Audio-Sync-Anker am Anfang, in der Mitte und am Ende.
Diese Referenz verhindert, dass die Kontrolle bei „wirkt flüssiger“ endet, während geänderte Dauer, fehlende Spur oder Lieferinkompatibilität übersehen werden.
Zuerst prüfen, ob das lokale Video in den Ablauf passt
Prüfen Sie Format, Dauer und Größe vor dem API-Aufruf. Eine enhance_frame_rate-Eingabe darf höchstens 300 Sekunden lang sein; ein ephemeral upload muss zwischen 512 Byte und 200 MB liegen. Verwenden Sie bevorzugt unterstützte Container und Codecs wie MP4 mit H.264, H.265 oder AV1 und teilen Sie längere Programme an natürlichen Schnitten.
Liegt das Video bereits in Object Storage, kann seine HTTPS-URL direkt als videoUri dienen. Sie muss einen Domainnamen statt einer IP verwenden, HEAD unterstützen, korrekte Content-Type- und Content-Length-Header liefern und darf nicht von Redirects abhängen; das URL-Limit für Video beträgt 32 MB. Für eine normale lokale Masterdatei vermeidet der ephemeral upload diese Hosting-Anforderungen.
Bestätigen Sie außerdem gekaufte credits im Konto. Die Veröffentlichung nennt 1 credit pro 2 Sekunden, erklärt aber keine Rundung angebrochener Einheiten. Speichern Sie deshalb estimatedCost aus der Einreichung und den endgültigen cost des Tasks.
Mit diesem Skript hochladen, senden, warten und herunterladen
Das REST-Beispiel hält alle kritischen Schritte sichtbar. Es fragt den API Key verdeckt ab, prüft lokale Dauer und Größe, erstellt einen ephemeral upload, überträgt die Datei, startet den Bildraten-Task, fragt alle fünf Sekunden ab und lädt die erfolgreiche Ausgabe herunter.
Installieren Sie die Python-Abhängigkeit und stellen Sie ffprobe bereit:
python3 -m pip install requests
Speichern Sie den folgenden Code als runway_fps.py:
from __future__ import annotations
import getpass, json, os, random, subprocess, sys, time
from pathlib import Path
import requests
API = "https://api.dev.runwayml.com"
FPS = {"24", "25", "30", "48", "50", "60", "120", "23_98", "29_97", "59_94"}
RETRYABLE = {429, 502, 503, 504}
def api(session, method, path, body=None):
for attempt in range(6):
response = session.request(method, API + path, json=body, timeout=60)
if response.status_code < 400:
return response
if response.status_code in RETRYABLE and attempt < 5:
time.sleep((2**attempt) * (1 + random.random() * 0.5))
continue
raise RuntimeError(f"HTTP {response.status_code}: {response.text}")
raise RuntimeError("RETRY_LIMIT_REACHED")
def main():
if len(sys.argv) not in {3, 4}:
raise SystemExit("python runway_fps.py INPUT_VIDEO TARGET_FPS [OUTPUT_VIDEO]")
source = Path(sys.argv[1])
target = sys.argv[2]
output = Path(sys.argv[3]) if len(sys.argv) == 4 else Path(f"runway-{target}fps.mp4")
if target not in FPS:
raise SystemExit(f"UNSUPPORTED_TARGET_FRAMERATE: {target}")
if not source.is_file():
raise SystemExit(f"INPUT_NOT_FOUND: {source}")
if not 512 <= source.stat().st_size <= 200 * 1024 * 1024:
raise SystemExit(f"INVALID_UPLOAD_SIZE_BYTES: {source.stat().st_size}")
duration = float(subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1", str(source)],
check=True, capture_output=True, text=True,
).stdout.strip())
if not 0 < duration <= 300:
raise SystemExit(f"INVALID_DURATION_SECONDS: {duration}")
key = os.getenv("RUNWAYML_API_SECRET") or getpass.getpass("RUNWAYML_API_SECRET: ")
session = requests.Session()
session.headers.update({
"Authorization": f"Bearer {key}",
"X-Runway-Version": "2024-11-06",
"Content-Type": "application/json",
})
upload_init = api(session, "POST", "/v1/uploads", {
"filename": source.name,
"type": "ephemeral",
}).json()
with source.open("rb") as handle:
upload = requests.post(
upload_init["uploadUrl"],
data=upload_init["fields"],
files={"file": (source.name, handle)},
timeout=300,
)
if upload.status_code >= 400:
raise RuntimeError(
f"UPLOAD_FAILED_REQUEST_NEW_UPLOAD: HTTP {upload.status_code}: {upload.text}"
)
created = api(session, "POST", "/v1/video_upscale", {
"model": "enhance_frame_rate",
"videoUri": upload_init["runwayUri"],
"targetFramerate": target,
}).json()
task_id = created["id"]
print(json.dumps({"id": task_id, "estimatedCost": created.get("estimatedCost")}, indent=2))
while True:
task = api(session, "GET", f"/v1/tasks/{task_id}").json()
status = task["status"]
if status in {"PENDING", "THROTTLED", "RUNNING"}:
time.sleep(5)
continue
if status == "SUCCEEDED":
urls = task.get("output") or []
if not urls:
raise RuntimeError("SUCCEEDED_WITHOUT_OUTPUT")
with requests.get(urls[0], stream=True, timeout=300) as download:
download.raise_for_status()
with output.open("wb") as saved:
for chunk in download.iter_content(1024 * 1024):
if chunk:
saved.write(chunk)
break
if status == "FAILED":
raise RuntimeError(json.dumps({
"status": status,
"failure": task.get("failure"),
"failureCode": task.get("failureCode"),
"cost": task.get("cost"),
}, ensure_ascii=False))
if status == "CANCELLED":
raise RuntimeError(json.dumps({"status": status, "cost": task.get("cost")}))
raise RuntimeError(f"UNKNOWN_TASK_STATUS: {status}")
subprocess.run([
"ffprobe", "-v", "error", "-show_entries",
"stream=codec_name,width,height,r_frame_rate,avg_frame_rate,time_base,duration:format=duration",
"-of", "json", str(output),
], check=True)
print(output.resolve())
if __name__ == "__main__":
main()
Beispiel: input.mp4 in 60 fps umwandeln und als output-60fps.mp4 speichern:
python3 runway_fps.py input.mp4 60 output-60fps.mp4
Geben Sie den Schlüssel erst bei RUNWAYML_API_SECRET: ein. Er wird nicht angezeigt, gelangt nicht in die Shell-History und wird nicht in eine Datei geschrieben. Eine bereits sicher gesetzte Umgebungsvariable wird direkt gelesen.
Die drei API-Stufen des Skripts verstehen
Die Generierung ist erst abgeschlossen, wenn alle drei Stufen erfolgreich sind. Feldnamen sind case-sensitive; im REST-JSON müssen videoUri und targetFramerate stehen.
| Stufe | Request | Pflichtinhalt | Erfolgssignal |
|---|---|---|---|
| Upload initialisieren | POST https://api.dev.runwayml.com/v1/uploads | filename, type: "ephemeral" | uploadUrl, fields, runwayUri werden geliefert |
| Bildrate senden | POST https://api.dev.runwayml.com/v1/video_upscale | model: "enhance_frame_rate", videoUri, targetFramerate | Task-id und estimatedCost werden geliefert |
| Task lesen | GET https://api.dev.runwayml.com/v1/tasks/{id} | Task-ID im Pfad | status: "SUCCEEDED" und nicht leeres output |
Senden Sie nach der Initialisierung einen multipart POST an uploadUrl, übernehmen Sie alle Werte aus fields und hängen Sie das Video als Feld file an. Erst nach erfolgreicher Übertragung ist runwayUri verwendbar; die URI gilt 24 Stunden.
Nach Erfolg sofort herunterladen und dauerhaft speichern
Warten Sie bei PENDING, THROTTLED oder RUNNING weiter. Runway weist darauf hin, für denselben Task nicht häufiger als alle fünf Sekunden mit Aktualisierungen zu rechnen. Lesen Sie output[0] nur bei SUCCEEDED; FAILED und CANCELLED sind nicht erfolgreiche Endzustände.
Ausgabe-URLs verfallen meist innerhalb von 24–48 Stunden. Laden Sie die Datei sofort in eigenen persistenten Speicher und geben Sie die temporäre URL nicht als finale Lieferadresse weiter. Ist sie abgelaufen, rufen Sie denselben Task erneut ab, bevor Sie eine neue kostenpflichtige Generierung starten. Ein erfolgreicher Download bestätigt nur den API-Task; die folgenden Abnahmetests bleiben nötig.
Fehler nach Typ behandeln statt alles blind zu wiederholen
Scheitert der multipart POST an uploadUrl, verwenden Sie den presigned upload nicht erneut, sondern rufen /v1/uploads neu auf. Bei 400, 401, 404 oder 405 korrigieren Sie Eingabe, Schlüssel, Ressource oder Methode. Das Beispiel wiederholt nur 429, 502, 503 und 504 mit exponentiellem Backoff und jitter.
Bei FAILED speichern Sie failure, failureCode und cost: SAFETY.* nicht wiederholen; bei ASSET.INVALID zuerst das Medium korrigieren; vor INTERNAL.BAD_OUTPUT.* Eingabeprobleme untersuchen; INPUT_PREPROCESSING.INTERNAL, INTERNAL, fehlenden Code oder THIRD_PARTY.UNAVAILABLE nach Wartezeit erneut versuchen. Keine identische Anfrage endlos wiederholen.
Schritt 1: Mit ffprobe bestätigen, dass die Datei das Ziel erreicht
Prüfen Sie mit ffprobe mittlere Bildrate, time base, tatsächliche Framezahl, Dauer und Audiospuren, bevor Sie das Bild beurteilen. Ein einzelnes FPS-Feld im Betriebssystem oder Player reicht für die Abnahme nicht aus.
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,time_base,duration \
-of json output.mp4
ffprobe -v error -select_streams v:0 -count_frames \
-show_entries stream=nb_read_frames,avg_frame_rate,r_frame_rate,duration \
-of json output.mp4
ffprobe -v error \
-show_entries format=duration:stream=index,codec_type,codec_name,sample_rate,channels,duration \
-of json output.mp4
Prüfen Sie:
avg_frame_rateentspricht dem Ziel oder einer gleichwertigen rationalen Darstellung.r_frame_rateundavg_frame_ratestehen nicht unerklärt im Widerspruch; eine große Differenz erfordert eine VFR-Prüfung.- Bei einer CFR-nahen Datei liegt
nb_read_framesungefähr bei Dauer mal Ziel-fps. - Die Ausgabedauer entspricht der Quelle; am Ende fehlen keine Frames und es wurde kein eingefrorener Nachlauf ergänzt.
- Abmessungen, Codec und Audiospuren erfüllen die Lieferspezifikation.
- Audio- und Videodauer unterscheiden sich nicht unerwartet stark.
Bei 29,97 und 59,94 zeigen Werkzeuge häufig 30000/1001 und 60000/1001. Die Bruchdarstellung ist kein Fehler.
Schritt 2: Zuerst die fehleranfälligsten Einstellungen prüfen
Beginnen Sie mit schnellen Bewegungen, Verdeckungskanten, feinem Text und Schnittpunkten, weil Interpolationsfehler dort am schnellsten sichtbar werden. Kontrollieren Sie Folgendes bei 100 %, Frame für Frame oder mit reduzierter Geschwindigkeit:
- schnelle Schwenks, Kamerafahrten und schnelle Objekte;
- Hände, Finger, Haare, Brillenfassungen und Lippen;
- Zäune, Jalousien, Gitter, kleine Schrift und feine UI-Linien;
- Vordergrundobjekte, die Hintergrundkanten verdecken oder freigeben;
- Wasser, Rauch, Partikel, Blätter und hochfrequente Texturen;
- Blitze, harte Schnitte, Überblendungen und Frames um einen Einstellungswechsel.
Suchen Sie reproduzierbare Defekte statt eines vagen Schärfeeindrucks: Doppelkonturen, Ghosting, verbogene Kanten, für einen Frame verschwindende Objekte, pulsierende Texturen, deformierte Gliedmaßen, Mischbilder am Schnitt oder zitternden statischen Text.
Notieren Sie bei jedem Problem exakten Timecode, Zielrate sowie Quell- und Ausgabeausschnitt. So lässt sich ein vorhandener Quelldefekt von einem neuen Problem oder einem Decoder-Unterschied trennen.
Schritt 3: Synchronität am Anfang, in der Mitte und am Ende prüfen
Ein synchroner Anfang beweist nicht, dass die ganze Datei synchron bleibt; prüfen Sie Anfang, Mitte und Ende, um festen Versatz von zunehmendem Drift zu unterscheiden. Gehen Sie so vor:
- Suchen Sie am Anfang einen klaren Anker, etwa Klatschen, Plosivlaut, Aufprall, Landung oder Bildschnitt.
- Wiederholen Sie die Prüfung in der Mitte und am Ende.
- Ähnlicher Versatz an allen drei Stellen deutet auf feste Verzögerung hin.
- Ein zum Ende wachsender Fehler weist eher auf Dauer, time base oder Bildrateninterpretation hin.
- Bei Lip Sync prüfen Sie Anfang, Mitte und Ende einer zusammenhängenden Aussage, nicht nur eine Silbe.
Die Veröffentlichung beschreibt die Audioverarbeitung nicht. Nehmen Sie daher nicht an, dass die Spur immer unverändert bleibt oder automatisch synchron ist. Entscheidend ist die gelieferte Datei.
Schritt 4: In realer Timeline und Zielplattform erneut testen
Testen Sie die Datei immer in der tatsächlichen Schnitt-Timeline und Zielplattform, weil ein NLE oder zweiter Transcode die Kadenz neu interpretieren, die Geschwindigkeit ändern oder eine Audiospur verlieren kann. Führen Sie mindestens diese beiden Prüfungen durch:
- Legen Sie die Datei in die vorgesehene Timeline und prüfen Sie, dass das NLE sie nicht neu interpretiert, verlangsamt/beschleunigt oder eine Audiospur verliert.
- Testen Sie sie auf der finalen Plattform oder dem Zielgerät und bestätigen Sie, dass ein zweiter Transcode Kadenz, Untertitel und Synchronität nicht verändert hat.
Transcodiert die Plattform erneut, bewahren Sie sowohl die Runway-Ausgabe als auch die Plattformversion auf. Untersuchen Sie beide getrennt, bevor Sie ein Problem der vorgelagerten Datei zuschreiben.
Mit dieser Tabelle bestehen, nacharbeiten oder Quellsegment behalten
Geben Sie die Datei nur frei, wenn alle kritischen Punkte die Liefervorgabe erfüllen. Scheitert nur eine Einstellung, verarbeiten Sie dieses Segment neu oder behalten Sie das Quellmaterial, bevor Sie das gesamte Programm erneut ausführen.
| Prüfung | Bestehensbedingung | Maßnahme bei Fehler |
|---|---|---|
| Zielbildrate | Exakte Kadenz; 29,97/59,94 werden nicht als 30/60 behandelt | Ziel oder Timeline-Interpretation korrigieren |
| Dauer und Frames | Dauer entspricht Quelle; bei CFR liegt die Zahl nahe am Soll | VFR, Abschneiden, Freeze-Tail und time base untersuchen |
| Abmessungen und Codec | Entsprechen Editor- oder Kanalvorgabe | Gemäß Spezifikation neu muxen oder transcodieren |
| Schnelle Bewegung | Keine inakzeptablen Doppelbilder, Verbiegungen oder Aussetzer | Timecodes markieren; anderes Ziel testen oder Quellsegment behalten |
| Schnitte und Blitze | Keine Misch-, Wiederholungsframes oder auffälliges Flackern | An natürlichem Schnitt teilen, neu verarbeiten und Naht prüfen |
| Text und UI | Glyphen, feine Linien und statische Overlays bleiben stabil | Grafiken in der Postproduktion neu auflegen |
| Audio-Sync | Kein sichtbarer Versatz/Drift am Anfang, in der Mitte und am Ende | Dauer/time base vergleichen, dann neu ausrichten oder transcodieren |
| Dateiintegrität | Vollständig decodierbar, Ende und Spuren intakt | Neu herunterladen, neu muxen oder Task wiederholen |
In diesen Fällen nicht von 60 auf 120 fps erhöhen
Bleiben Sie bei der niedrigsten Bildrate, die die Liefervorgabe erfüllt, wenn 120 fps nur Dateigröße und Folgeaufwand erhöhen. Erhöhen Sie die Bildrate in folgenden Fällen nicht:
- das Ziel nur 24, 25, 29,97 oder 30 fps verlangt;
- die Quelle bereits starkes Ghosting, Kompressionsblöcke oder motion blur enthält;
- Untertitel, UI oder feine Linien instabiler werden;
- ein Sync-Problem noch ungeklärt ist;
- die Zielplattform ohnehin auf eine niedrigere Bildrate transcodiert;
- kein sichtbarer Nutzen entsteht, aber Speicher-, Decodier- oder Transcode-Aufwand steigt.
Bildrate ist ein Lieferparameter, kein isolierter Qualitätswert. Bestanden ist die Datei, wenn sie die geforderte Kadenz ohne inakzeptable neue Defekte erfüllt — nicht, wenn sie die höchste Zahl trägt.
Die Übergabe in zehn Schritten abschließen
Die Reihenfolge mit wenig Nacharbeit lautet Spezifikation und Referenz, Upload und Senden, Warten und Speichern, danach technische, visuelle und reale Prüfung.
- Exaktes
targetFramerateaus der Downstream-Spezifikation wählen. - Rate, Dauer, Audio und Risiko-Timecodes mit
ffprobesichern und maximal 300 Sekunden bestätigen. - Für eine lokale Datei
POST /v1/uploadsaufrufen unduploadUrl,fields,runwayUrispeichern. - Multipart-Formular an
uploadUrlsenden; bei Fehler einen neuen Upload anfordern. POST /v1/video_upscalemitmodel,videoUri,targetFramerateaufrufen.- Task-
idundestimatedCostspeichern. - Alle fünf Sekunden
GET /v1/tasks/{id}bis zum Endstatus aufrufen. - Bei
SUCCEEDEDoutputherunterladen und dauerhaft speichern;FAILEDoderCANCELLEDnach Fehlertyp behandeln. - Tatsächliche Kadenz, Dauer, Artefakte, Schnitte und Audio mit
ffprobeund Frame-Prüfung kontrollieren. - Vor Übergabe in echter Timeline und Zielplattform testen.
Offizielle Quellen: Models, Inputs, Uploads, Video upscale API Reference, Task API Reference, Outputs, HTTP errors, Task failures und API Changelog. Schnittstellenfelder und Schritte wurden am 26. September 2026 geprüft.