Was macht resolve-cut?
Sie montieren, rendern und prüfen Videos in DaVinci Resolve Studio über gespeicherte Skripte mit Parametern. Sie schreiben die Montage nicht in jeder Sitzung neu: Sie rufen die Skripte auf, lesen, was sie zurückgeben, und überprüfen das Ergebnis mit Zahlen und Einzelbildern. Der Geschmack bleibt menschlich: Die Person entscheidet, was bleibt, Sie führen aus und messen.
$SKILL unten ist der Ordner dieses Skills (in dem diese Datei lebt). Skripte in scripts/resolve/ laufen in Resolve über run.py; Skripte in scripts/media/ sind einfaches Python mit ffmpeg. Jedes Skript hat --help.
Bevor Sie beginnen
- Resolve antwortet:
python3 "$SKILL/scripts/resolve/run.py" - '{}' <<< 'result = resolve.GetVersionString()'. Exit-Code 2 bedeutet, dass Resolve geschlossen ist, es sich um die kostenlose Edition handelt oder unter Einstellungen > System > Allgemein > Externes Scripting verwenden nicht auf Lokal gesetzt ist. ffmpeg -version,python3 -c "import numpy, PIL"undELEVENLABS_API_KEY(Umgebungsvariable oder./.env).- Wenn das Projekt eine Notizdatei führt (
VIDEO_NOTES.mdoder ähnlich), lesen Sie sie: was die Person zuvor genehmigt und abgelehnt hat. Fragen Sie nicht zweimal nach derselben Korrektur. - Arbeitsordner: Alles, was Sie schreiben (Transkripte, Dossier, Einzelbilder, Render), geht in einen Arbeitsordner, niemals in den Rohmaterial-Ordner.
Der Ablauf
1. Transkribieren. Wortgenaue Transkripte, eine JSON pro Clip:
python3 "$SKILL/scripts/media/transcribe.py" <clips-Ordner> --out work/transcripts [--language por].
Das Transkript ist die Grundlage für alles: Auswahl der Takes, Schnitt an Bildgrenzen und Prüfung des endgültigen Mixes.
2. Dossier. Das gesamte Material in einer kompakten Textdatei, einmal lesen:
python3 "$SKILL/scripts/media/dossier.py" <clips-Ordner> --transcripts work/transcripts --out work/dossier.md [--sheets].
Es listet jeden Satz mit seiner Zeit auf und markiert «repeats C0076 20.2», wenn ein Satz wie ein früherer beginnt: ein weiterer Versuch derselben Zeile. Mit einem Skript behalten Sie die letzte vollständige Aufnahme jedes Absatzes; lassen Sie Zögern, Fehlstarts und wiederholte Versuche weg. Öffnen Sie einen Clip nur, um zu entscheiden:
python3 "$SKILL/scripts/media/inspect_range.py" <clip> <t0> <t1> --words work/transcripts/<clip>.json (Einzelbilder, Wellenform und Wörter in einem Bild).
3. Schnittliste. Schreiben Sie work/plan.json mit den ausgewählten Takes in der Reihenfolge
({"Lesson 01 v1": [["01a", "C0081", 1.9, 12.6], ["01b", "C0083", 5.4, 23.8], ...]}: Take, Clip, von, bis in Sekunden des Clips), dann:
python3 "$SKILL/scripts/media/cut_list.py" work/plan.json work/transcripts <clips-Ordner> work/cuts.json.
Schnitte landen auf der leisesten Bildgrenze neben den Wörtern, Pausen über 1 s werden verkürzt, und Segmente wechseln sich mit Zoom 1 / 1,2 ab, sodass Schnitte zwischen Takes nicht springen. Bei einem Fehlstart ohne Lücke („ko- contar“) erzwingen Sie das Bild mit {"in_frame": N} oder {"out_frame": N}. Notizen für den Editor: add_markers.py.
4. In Resolve montieren. Ein schwerer Vorgang pro Aufruf, und lesen Sie jedes result, bevor Sie den nächsten ausführen:
R="$SKILL/scripts/resolve/run.py"
python3 "$R" "$SKILL/scripts/resolve/project.py" '{"name": "Lesson 01", "width": 1920, "height": 1080, "fps": "25"}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "import", "bin": "Raw", "media": "/abs/clips", "files": ["C0081.MP4"]}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "timeline", "bin": "Raw", "cuts": "/abs/work/cuts.json", "timeline": "Lesson 01 v1", "zoom": {"center": [0.45, 0.37]}, "voice_isolation": 50}'
zoom.center gibt an, wo sich das Gesicht befindet (Bruchteil des Bildes), sodass die Vergrößerung es an Ort und Stelle hält. Überprüfen Sie, ob frames == expected ist und failures leer ist.
5. Vor dem Rendern ansehen. frames.py exportiert Einzelbilder direkt aus der Timeline in unter einer Sekunde
({"timeline": "Lesson 01 v1", "frames": [100, 500], "folder": "/abs/work/frames", "max": 960}). Schauen Sie sich ein normales und ein vergrößertes Bild an.
6. Rendern.
python3 "$R" "$SKILL/scripts/resolve/render.py" '{"phase": "start", "timeline": "Lesson 01 v1", "folder": "/abs/out", "name": "lesson-01", "preset": "reel", "width": 1920, "height": 1080, "mark": [0, <frames - 1>]}',
dann alle 10 s {"phase": "status", "job": "<id>"} abfragen, bis JobStatus Complete ist. Warten Sie, bis der Render abgeschlossen ist, bevor Sie antworten: Ein unbeaufsichtigter Durchlauf, der seinen Turn bei „Render gestartet“ beendet, hat niemanden, der ihn überprüft.
7. Verifizieren. python3 "$SKILL/scripts/media/qc.py" out/lesson-01.mp4 --expected <frames> --transcribe
(--ref gegen die letzte genehmigte Version hinzufügen, --frames für ein Blatt, --simulate für Instagram). Lesen Sie das Transkript des endgültigen Mixes an jedem Schnitt: Wiederholte Wörter („entscheiden, entscheiden“), abgeschnittene Wörter und Wörter an der falschen Stelle sind die Mängel, die eine Schnittliste verursacht. Bestätigen Sie einen verdächtigen Schnitt an der Wellenform (inspect_range.py), bevor Sie ihn verschieben, reparieren Sie die Schnittliste, montieren Sie eine neue Version (v2) und rendern Sie erneut. Maximal 3 Runden, jeder Mangel mit seiner genauen Zeit benannt. Nennen Sie es nie erledigt, weil es „richtig aussieht“: Zitieren Sie die Zahlen.
8. Ausliefern. loudness.py, wenn der Mix nicht im Zielbereich liegt (linearer Gain und ein Limiter, niemals loudnorm), dann
deliver.py export.mp4 clean.mp4 [--no-editlist] [--copy <ordner>]: keine Timecode-Spur, keine Metadaten, moov zuerst, Kopie Byte für Byte verglichen.
9. Überprüfen, nachdem die Person genehmigt hat. Notieren Sie in der Notizdatei, was sie genehmigt und abgelehnt hat, in ihren Worten, eine Zeile pro Punkt; jede neue Falle mit ihrem Datum; und jede Routine, die Sie mehr als einmal von Hand ausgeführt haben, wird zu einem Skript mit Parametern neben diesen.
Skripte in Resolve ausführen
run.pyverbindet sich mit dem geöffneten Resolve und führt ein Skript mitresolve,project,P(das JSON) und__file__aus, dann gibt esresultals JSON aus. Es kostet weitaus weniger Token, als dasselbe Skript über einen MCP zu schreiben.- Mit einem MCP-Server stattdessen (offizielles
run_script_unsafe):P = {...}; __file__ = "<absoluter Pfad des Skripts>"; exec(open(__file__, encoding="utf-8").read()). Die Sandbox liest Dateien ohneencodingals ASCII, und Namen bleiben zwischen Aufrufen erhalten: Die Skripte verwenden Variablen mit Präfix. - Speichern Sie vor und nach dem Schreiben (
GetProjectManager().SaveProject()); es gibt kein Rückgängig. Jede neue Version auf einer Kopie der Timeline erstellen (DuplicateTimeline, die auch Fusion-Comps kopiert). - Schlagen Sie die API nach, anstatt zu raten: die offizielle MCP
search_scripting_api,get_scripting_docsundget_whats_new(einmal pro Sitzung) oder Blackmagics README im OrdnerDeveloper/Scriptingvon Resolve (Hilfe > Dokumentation > Entwickler). - Neue Operation, die sich wiederholen wird? Schreiben Sie sie einmal als Skript mit einem
P-Dict und einemresultneben diesen.
Auslieferungsziele
| Ziel | Bild | Ton |
|---|---|---|
| Reels, Stories, Shorts, TikTok | 1440x2560 mit der Aufnahme-Bildrate, H.264 High bei etwa 20 Mbit/s real, Rec.709 Tags (1-1-1), faststart | -14 LUFS, True Peak unter -1,5 dBTP |
| Lektionen und Kurse | wie aufgenommen (1920x1080 oder 3840x2160) | -16 LUFS, True Peak bis zu -1 dBTP |
| YouTube | der 4K-Master (1080p-Uploads verlieren Qualität), MP4 ohne Edit-Listen | Der Mix des Masters |
| 1920x1080 und 1080x1920 mit 16 Mbit/s, mit SRT | Der Mix des Masters |
Verifizierte Fallen
Gemessen auf macOS mit Resolve Studio 21.1.1 und 21.1.2, Oktober und November 2026.
Maschine
- Ein ffmpeg gleichzeitig, mit
nice -n 15und-threads 2: 96 parallele ffmpeg-Prozesse haben den Mac eingefroren und einen Neustart erzwungen. - In zsh teilt
$varnicht in Wörter auf (ffmpeg $argsbricht): Argumentlisten in Python erstellen. - Ausgaben in den Arbeitsordner schreiben: Ein Helfer, der Bilder neben dem Clip gespeichert hat, hat in den Rohmaterial-Ordner geschrieben.
Resolve Einrichtung und API
- Resolve 21.1 hat Python Scripting zu Studio verschoben:
run.pyund beide MCP-Server benötigen DaVinci Resolve Studio. - Externes Scripting muss auf Lokal gesetzt sein (Einstellungen > System > Allgemein), sonst gibt
scriptapp("Resolve")None zurück. StartRenderingist der letzte Aufruf eines Skripts: Alles andere gibt None zurück, bis der Render endet.- Die Projekt-Bildrate wird beim Erstellen der ersten Timeline festgelegt: setzen Sie sie vorher (
project.py). - Auflösung:
SetSettingeinen Schlüssel nach dem anderen,useCustomSettingszuerst. - Das MCP-Timeout (standardmäßig 10 s, maximal 60 s) gibt einen Fehler zurück, aber das Skript läuft in Resolve weiter: Überprüfen Sie den Status, bevor Sie es erneut ausführen.
- Es gibt kein Trimmen, Verschieben oder Slip: Löschen Sie das Element und fügen Sie es mit
startFrame,endFrame(exklusive) undrecordFrameerneut hinzu. startFramezählt ab dem ersten Bild der Datei, auch mit Kamera-Timecode.GetSourceStartFrameliest manchmal ein Bild zu früh (866 liest 865), während die Platzierung richtig ist: Lesen Sie den In-Point mitGetLeftOffset.AddMarkerbehält einen Marker pro Bild.ReplaceCliplöscht die Metadaten des Clips.SetTrackEnablegibt True zurück und ändert bei einigen Timelines nichts: Deaktivieren Sie die Clips mitSetClipEnabledund bestätigen Sie auf einem exportierten Bild.SetClipEnabledauf einer Timeline, die nicht die aktuelle ist, gibt False zurück: ZuerstSetCurrentTimeline, dann mitGetClipEnabledbestätigen.DeleteClips(items, True)rippelt jede Spur: Löschen Sie zuerst, ohne Ripple, was den Schnitt kreuzt (Stems, Untertitel).- Voice Isolation funktioniert per Skript:
TimelineItem.SetVoiceIsolationState({"isEnabled": True, "amount": 100})hat den Raumhall um 3 bis 4 dB gesenkt;Timeline.SetVoiceIsolationState(track, {...})setzt einen Regler für eine ganze Spur. - Die API kann keine ResolveFX-Parameter setzen (Face Refinement, Blemish Removal): Eine Person setzt sie, oder Sie steuern die UI über Barrierefreiheit.
- Bei gesperrtem Bildschirm oder minimiertem Resolve verschwindet das Fenster aus der Barrierefreiheit, aber die API arbeitet weiter: Mit exportierten Bildern überprüfen.
- Super Scale ist eine Media-Pool-Eigenschaft:
SetClipProperty("Super Scale", 2); eine Ersatzdatei muss erneut gesetzt werden. - LUTs für
Graph.SetLUTwerden im System-LUT-Ordner von Resolve in einem Unterordner abgelegt, übergeben durch relativen Pfad nachRefreshLUTList(). - Ändern der Seiten während Resolve abspielt, lässt es hängen;
item.GetFusionCompByIndex(1).Execute(lua)bearbeitet eine Kompilation, ohne die Fusion-Seite zu öffnen.
Import und Medien
- Ein ProRes pro Importaufruf: Mehrere ProRes 4444 (und einmal zwei neue ProRes 422) in einem Aufruf haben Resolve 21.1 zum Absturz gebracht (
UiMpController,std::out_of_range). Kamera-MP4s, 22 in einem Aufruf, waren in Ordnung. - Nach diesem Absturz meldet ein verwaister
ResolvePython-Prozess dem MCPlaunch_resolve, dass Resolve läuft: Töten Sie ihn und öffnen Sie Resolve erneut. ImportMediamit einer Liste von Pfaden: Die Form mit Dictionaries gab None für MP4 auf 21.1 zurück.- Resolve speichert die Decodierung nach Pfad zwischen: Eine Datei, die Sie erneut rendern, bekommt einen neuen Namen.
- PCM 24-Bit Little-Endian in MOV wird als weißes Rauschen gelesen: Verwenden Sie
pcm_s24be. - iPhone HEVC hat den macOS-Decoder zum Absturz gebracht: Bearbeiten Sie von ProRes aus.
- iPhone HDR (HLG, Dolby Vision): Unser eigenes Tonemapping sah verwaschen aus und wurde zweimal abgelehnt. Fragen Sie zu Beginn nach einem SDR-Export.
- Ein 1-Bild
.movwird als 150-Bild-Standbild importiert: Geben Sie ihm mindestens 3 Bilder und trimmen Sie es auf der Timeline. - Gerades Alpha: Resolve liest Alpha un-premultipliziert, sodass ein Overlay, das mit ffmpeg
overlayauf einer transparenten Leinwand erstellt wurde, dunkel erscheint; positionieren Sie es mitpad=W:H:x:y:[email protected].
Rendern
- Mit
SelectAllFramesgibtStartRenderingmanchmal False zurück: Setzen SieMarkIn/MarkOut(render.pymark), was auch die Tonenden abschneidet, die eine Timeline verlängern. - Ein H.264-Job, der direkt nach einem reiner Audio-Job erstellt wurde, kam ohne Video: Laden Sie ein Preset vor
SetRenderSettingsund überprüfen Sie mit ffprobe den Videostream. VideoQualityist eine Obergrenze, kein Durchschnitt: 20000 ergab 14,7 Mbit/s und 27300 ergab 20,7 Mbit/s bei 1440x2560.- „Force sizing to highest quality“ ist kein
SetRenderSettings-Schlüssel, wird aber in einem Render-Preset (ForceHighestQualitySizing) transportiert. ExportRenderPreset(name, path)behandeltpathals Ordner;ImportRenderPresetbenennt das Preset nach der Datei.- Presets speichern eine Bildrate: Setzen Sie
FrameRatevon der Timeline, oder eine 29,97-Timeline wird konvertiert gerendert (render.py macht das). ExportFrame(21.1.2) gab 4 Bilder bei 1440x2560 in 0,75 s aus, innerhalb von 41 bis 46 dB des Renders: Überprüfen Sie Bilder ohne Rendern.
Ton und Transkripte
- Ein Schnitt zwischen zwei Takes kann ein wiederholtes Wort verbinden („entscheiden, entscheiden“): Transkribieren Sie den finalen Mix und suchen Sie nach Duplikaten. Korrigieren Sie, ohne die Länge zu ändern: Beenden Sie das erste Stück vor dem Wort, beginnen Sie das zweite früher in der Pause des guten Takes.
- Das Transkript hört keine Flüstern und Atemzüge: Schnittpunkte kommen vom eigenen Ton der Kamera (
cut_list.py). - Scribe hat einmal ein Wort 3 s zu früh platziert, nach einem Klatschen und einem Flüstern: Bestätigen Sie auf der Wellenform, bevor Sie einen Schnitt verschieben.
- MP3-Soundeffekte landen etwa 60 ms zu spät (der Encoder-Delay wird nicht kompensiert): Verwenden Sie WAV für alles, was auf ein Bild treffen muss.
- loudnorm in einem Durchlauf ist dynamisch und ändert den genehmigten Mix; in zwei Durchläufen fällt es stillschweigend auf dynamisch zurück: Verwenden Sie
loudness.py.
Aufnahmen und Plattformen
- 25 fps auf Instagram: Dienen mit 25 (ffprobe der ausgelieferten Dateien, November 2026). Das Ruckeln kommt von ProMotion iPhones, die keinen 25- oder 50-Hz-Modus haben. Behalten Sie 25-fps-Material bei 25 (die Konvertierung auf 30 wiederholt eines von fünf Bildern); neues Material mit 29,97 und einem 1/50-Verschluss aufnehmen.
- Flimmern unter 50-Hz-Lichtern hängt vom Verschluss ab, nicht von der Bildrate: 1/50 und 1/100 flimmern nicht; 1/60 bei 30 fps tut es.
- Instagram kodiert auf dem Telefon und erneut auf dem Server erneut: Die grundlegende Auslieferung liegt bei etwa 720x1280 mit 1,4 Mbit/s, der Ton normalisiert auf etwa -14 LUFS, daher gewinnt ein Master über -14 nichts.
qc.py --simulatezeigt, was überlebt. - CRF in ffmpeg unterbelichtet dunkle Hintergründe: Ein Reel blieb bei 6,8 Mbit/s. Prüfen Sie die tatsächliche Bitrate vor der Auslieferung.
- Ein unbeaufsichtigter
claude -p-Durchlauf beendet seinen Turn, wenn der Render startet, es sei denn, die Eingabeaufforderung sagt, dass er warten soll.
Skripte
| Skript | Was es tut |
|---|---|
scripts/media/transcribe.py | Scribe Wort-für-Wort JSON pro Clip (Schlüssel über stdin, niemals in der Prozessliste) |
scripts/media/dossier.py | Jeder Clip als kompakter Text: Sätze mit Zeiten, Pausen, wiederholte Versuche, optionale Einzelbildblätter |
scripts/media/inspect_range.py | Ein Bild eines Bereichs: Einzelbilder, Wellenform, Wörter mit Zeiten |
scripts/media/cut_list.py | Take-Auswahl zu Schnittliste mit Bildgenauigkeit und Zoom-Variation |
scripts/media/qc.py | Finale Datei auf Bildanzahl, Lautstärke, wiederholte Wörter, Simulation der Plattform prüfen |
scripts/resolve/run.py | Python mit resolve, project, P und file in Resolve ausführen |
scripts/resolve/project.py | Projekt mit Name, Auflösung, Bildrate erstellen |
scripts/resolve/assemble.py | Medien importieren, Timeline aus Schnittliste montieren |
scripts/resolve/render.py | Timeline rendern, Status abfragen |
scripts/resolve/frames.py | Einzelbilder direkt aus Timeline exportieren |
scripts/resolve/deliver.py | Exportierte Datei säubern: Metadaten, Edit-Listen entfernen; optional kopieren |
scripts/resolve/loudness.py | Lautstärke mit linearem Gain und Limiter korrigieren |
scripts/resolve/add_markers.py | Marker nach Schnittliste setzen |
Allgemeine Parameter
Die meisten Skripte erwarten die folgenden Parameter als JSON über die Umgebungsvariable P oder über einen Dateipfad:
| Parameter | Typ | Beschreibung |
|---|---|---|
name | String | Projektname oder Timelinename |
width | Integer | Breite des Projekts/Bildes |
height | Integer | Höhe des Projekts/Bildes |
fps | String | Bildrate (z.B. "25", "29.97") |
bin | String | Medienpool-Ordner |
media | String | Pfad zum Medienordner |
files | Liste | Dateinamen für Import |
cuts | String | Pfad zur Schnittliste JSON |
timeline | String | Timelinename |
zoom | Object | Zoom-Einstellungen ({"center": [0.45, 0.37]}) |
voice_isolation | Integer | Stärke der Sprachisolierung (0-100) |
folder | String | Ausgabeordner |
name | String | Ausgabedateiname |
preset | String | Render-Preset ("reel", "lesson", "youtube", "linkedin") |
mark | Liste | Mark In/Out für Render |
Hinweise
- Das Skill erwartet, dass DaVinci Resolve Studio bereits läuft und externes Scripting aktiviert ist.
- Alle Skripte geben ihre Ergebnisse als JSON auf stdout aus. Lesen Sie
resultnach jedem Aufruf. - Die Arbeitsordner müssen absolute Pfade sein. Relative Pfade können zu Fehlern führen.
- Bei Fehlern geben die Skripte einen Exit-Code ungleich 0 und eine Fehlermeldung auf stderr aus.