Communitygithub.com

TaherZiad/montage-crew

Schneidet Stille und Füllmaterial (Füllwörter, Wiederholungen, Fehlstarts) aus einem Sprecher-Video, BEVOR der Schnitt aufgebaut wird – rufe die gemessene /auto-trim-API auf, anstatt ffmpeg manuell zu verwenden, überprüfe die zurückgegebenen Kandidaten und erledige die eine Aufgabe, die nur ein Mensch/KI erledigen kann (wiederholte Aussagen erkennen). Lies dies, wenn der Brief „Tự động cắt ngắn video“ (AutoCut) aktiviert oder der Benutzer sich beschwert, dass das Video noch Füllmaterial/Stille enthält.

Was ist montage-crew?

Der Skill **TaherZiad/montage-crew** automatisiert das Schneiden von Stille und inhaltlichem Füllmaterial (Füllwörter, Wiederholungen, Fehlstarts) in Sprecher-Videos, bevor die weitere Bearbeitung (Szenen, Untertitel, Zooms) erfolgt. Er wird auf der **Montage-Crew**-Plattform eingesetzt und besteht aus zwei Hauptkomponenten: Server-gestützter Analyse (Messen des Rauschpegels, Erkennung von Kandidaten) und menschlicher Überprüfung (Freigabe oder Ablehnung der Kandidaten). Der Skill vermeidet die typischen Fallstricke von einfachen `silencedetect`-Ansätzen, indem er den Rauschpegel pro Datei misst und die Stille durch Transkription gegen Wortgrenzen absichert. Nach der Analyse überprüft der Nutzer jeden Kandidaten (Füllwörter, Stottern, Wiederholungen) und identifiziert zusätzlich semantisch wiederholte Aussagen (Step 3), die kein Detektor erkennt. Anschließend wird der Schnitt mit einem einzigen ffmpeg-Durchlauf durchgeführt, wobei alle Zeitstempel neu zugeordnet werden. Ein ausführlicher Bericht bestätigt die Qualität. Der Skill stellt sicher, dass der Schnitt vor dem Untertitel-Setup erfolgt, und verhindert so asynchrone Untertitel.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TaherZiad/montage-crew/tree/HEAD/skills/montage-crew/references/external/AIEV

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Auto-Cut – gemessene Stille & Füllmaterial-Trimmen

Grundsätze

  1. Schneide VOR dem Erstellen von Szenen/Untertiteln. Ein Schnitt danach wirft alle Zeitstempel (Untertitel, Zooms, SFX) durcheinander. Ausgabe dieses Schritts: assets/<quelle>.cut.mp4 + assets/transcript.cut.json – jeder spätere Schritt verwendet die geschnittene Version.
  2. Schneiden ist ZWINGEND, wenn der Brief autoCut aktiviert – es ist kein Vorschlag. Wenn nichts geschnitten werden kann, musst du im Bericht einen konkreten Grund nennen (das Video war bereits straff).
  3. Die Schwellwerte liegen auf dem Server, nicht in deinem Kopf. Führe NICHT selbst silencedetect aus und wähle KEINEN dB-Schwellwert nach Gefühl. Zwei gemessene Fakten haben diesen Workflow widerlegt:
    • Der richtige Schwellwert ist eine Eigenschaft der DATEI, keine Konstante. Bei einer echten Datei fand -40dB 0 Stille, -30dB 13, -25dB 21. Eine fest codierte Zahl ist entweder nutzlos oder verschluckt Sprache.
    • Lautstärke allein kann nicht zwischen „Pause“ und „leises Sprechen“ unterscheiden. Bei der gemessenen Quelldatei meldete silencedetect bei -30dB 48,6s „Stille“, aber nur 18,2s davon lagen in einer echten Lücke zwischen Wörtern; die anderen 30,4s befanden sich in Wörtern (Silbengrenzen, stimmlose vietnamesische Endungen c/t/p/ch). Das Schneiden allein anhand der Lautstärke verschluckt Sprache. Der Server übernimmt die Messung (autoTrim.ts) und die Kandidatengenerierung (deadWeight.ts). Du übernimmst die Überprüfung. Diese Aufteilung ist der Kern.
  4. Zwei Arten von Füllmaterial werden geschnitten: Stille (maschinell gemessen, durch das Transkript abgesichert) und inhaltliches Füllmaterial (Füllwörter, Stottern, wiederholte Takes – vom Server vorgeschlagen, von dir freigegeben; plus wiederholte AUSSAGEN, die nur du finden kannst – siehe Schritt 3).

Schritt 0 – Voraussetzung: ein Transkript mit Wort-Zeitstempeln

Die gesamte Absicherung hängt davon ab. Der Server sucht nach assets/transcript.raw.json, dann assets/transcript.json. Ohne eines läuft die Analyse zwar, kommt aber mit guarded: false zurück, die Füllmaterial-Liste ist leer und die Zahlen sind in beiden Richtungen Schätzwerte (er kann einen schlechten Schnitt durchlassen und einen guten ablehnen). Transkribiere zuerst – schneide niemals einen vietnamesischen Sprecher ohne Absicherung.

Schritt 1 – Analysieren (kostenlos, wiederholbar, ohne Kodierung)

POST http://localhost:6869/api/projects/<id>/auto-trim/analyze
body: {}                                   # oder { "source": "assets/face.mp4", "level": "tight" }

level ist natural | default | tight und standardmäßig auf brief.autoCutLevel gesetzt. Antwort:

  • silence – durationSec, der gewählte thresholdDb + thresholdNote (warum dieser Schwellwert gewonnen hat), gemessener noiseFloorDb, die silences die geschnitten werden, keepRanges, removedSec, die vollständige sweep-Tabelle und wordGuard (wie viele Sekunden das Transkript blockiert hat).
  • deadWeight – candidates[] mit kind (filler | stutter | repeat-take | hesitation), start/end, text, confidence, reason, context; plus totalSec und byKind.
  • guarded – true nur, wenn ein Transkript gefunden wurde. Wenn false, behebe das vor dem Schneiden.

Es wird nichts kodiert, du kannst es also so oft aufrufen, wie du möchtest (eine 217s-Quelle analysiert in etwa einer Sekunde).

Schritt 2 – überprüfe JEDEN Kandidaten (deine Aufgabe, nicht die der Maschine)

Die Liste ist deterministisch: gleiches Transkript, gleiche Kandidaten, gleiche Konfidenz. Was sie nicht kann, ist Bedeutung zu verstehen. Gehe sie einzeln durch und behalte nur die, die du verteidigen würdest:

  • Niedrige Konfidenz bedeutet „zuerst den Kontext lesen“, nicht „wahrscheinlich in Ordnung“. Vietnamesische Füllwörter überschneiden sich fast immer mit echten Wörtern. đó, ấy, thế, mà, là sind sowohl Füllpartikel als auch echte Demonstrativpronomen/Konjunktionen.
  • Verbindungssätze (hoặc là, tức là, bởi vì là, với lại là) sind die Falle. Gemessen an einem echten Transkript: „…có thể là ok ứng dụng nó / Hoặc là / Tham khảo để tìm cách…“ ist eine echte Alternative – das Wegschneiden zerstört einen Zweig des Satzes. Aber „Còn trường hợp mà mọi người có thể nghe / Hoặc là / Còn trường hợp mà người AI không ứng dụng được…“ ist ein abgebrochener Satz und sollte entfernt werden. Die Oberflächenform ist identisch; nur die Bedeutung trennt sie. Genau deshalb kommen diese mit einer niedrigen Basis-Konfidenz und einem Grund, der sagt: LIES DEN KONTEXT.
  • repeat-take-Kandidaten: Überprüfe, ob der spätere Take wirklich der vollständigere ist, bevor du ihn freigibst.
  • hesitation-Kandidaten sind reine Stille zwischen Wörtern – normalerweise sicher, aber überprüfe, ob du nicht eine bewusste Pause vor einem Höhepunkt entfernst.

Lehne großzügig ab. Ein zurückgelassenes Füllwort kostet 0,4s; ein geschnittenes echtes Wort macht den Satz unsinnig und der Zuschauer hört es sofort.

Schritt 3 – WIEDERHOLTE AUSSAGEN (nur du kannst sie finden – zwingend)

Kein Detektor erfasst dies, und es ist das Füllmaterial, über das sich Benutzer am meisten beschweren. Lies das Transkript als gesprochene Rede und analysiere es semantisch:

  1. Gruppiere Sätze, die die GLEICHE AUSSAGE machen – die Wörter müssen nicht übereinstimmen, nur der Inhalt. Ein Sprecher wiederholt eine Aussage oft 2-3 Mal: zuerst kurz/stolpernd, später vollständiger. Berücksichtige auch NICHT-benachbarte Sätze (macht Aussage A, schweift ab, kommt zu Aussage A detaillierter zurück).
  2. Behalte genau EINE Version pro Gruppe – die VOLLSTÄNDIGSTE:
    • Frühere kurze Version, spätere vollständigere Wiederholung -> behalte die spätere, schneide die frühere.
    • Späterer Satz ist nur ein kurzes Echo („đúng vậy, như tôi nói…“) -> behalte die frühere, schneide das Echo.
    • Zwei gleichwertige Versionen -> behalte die flüssigere Lieferung (weniger Stolperer, keine Füllwörter).
  3. Überprüfe den Fluss nach dem Schneiden: lies den erhaltenen Text von Anfang bis Ende. Wenn ein erhaltener Satz sich auf einen geschnittenen bezieht („như vừa nói“), behalte entweder beide oder wähle die Version ohne den Rückverweis.
  4. Wandle jede Entscheidung in einen Bereich {start, end} um und sende ihn mit den genehmigten Kandidaten in Schritt 4.
  5. Erstelle eine Tabelle vor dem Schneiden (füge sie in den Bericht ein): Zeitstempel | geschnittener Satz | Grund | erhaltener Satz – damit der Benutzer jede Entscheidung überprüfen kann.

Schritt 4 – Anwenden (geht durch die Render-Warteschlange)

POST http://localhost:6869/api/projects/<id>/auto-trim/apply
body: { "cutCandidates": [{ "start": 51.81, "end": 52.25 }, …] }   # NUR was du freigegeben hast
-> 202 { job }

Sende eine leere Liste, wenn du nichts freigegeben hast – die gemessenen Stille werden trotzdem geschnitten. Rufe dann GET /api/jobs/<jobId> auf, bis es abgeschlossen ist. Der Job:

  1. Analysiert erneut mit der Transkript-Absicherung, führt die Stillebereiche mit deinen freigegebenen Bereichen zusammen (Überlappungen werden zusammengeführt, sodass nichts doppelt gezählt wird).
  2. Verwirft jeden freigegebenen Bereich, der einen Wortmittelpunkt verschlucken würde – ein letztes Sicherheitsnetz über deiner Überprüfung, und es protokolliert jeden Bereich, den es ablehnt. Abgelehnte Bereiche im Log bedeuten, dass du etwas freigegeben hast, das auf echter Sprache sitzt; gehe zurück und lies diese Stelle erneut.
  3. Schneidet in EINEM ffmpeg-Durchlauf (trim/atrim + setpts/asetpts + concat), schreibt assets/<stamm>.cut.mp4.
  4. Ordnet jeden Zeitstempel in die geschnittene Zeitleiste neu zu -> assets/transcript.cut.json.
  5. Überprüft die AUSGABE mit den neu zugeordneten Wörtern und schreibt assets/auto-trim-report.json.

Wenn nichts zu schneiden ist, erstellt der Job bewusst KEINE .cut.mp4 (eine neu kodierte identische Kopie würde nur an Qualität verlieren) – output im Bericht ist null und du verwendest weiterhin die Quelle.

Schritt 5 – Lies den Bericht (der Job ist erst erledigt, wenn du es tust)

assets/auto-trim-report.json enthält: Dauer vorher/nachher, removed.silenceSec vs. removed.approvedSec, den gewählten Schwellwert und warum, abgelehnte Kandidaten und verification.

  • verdict: "pass" – das Ergebnis entspricht dem Profil für diese Stufe.
  • verdict: "fail" – der Job wurde trotzdem abgeschlossen und die Datei ist nutzbar, hat aber NICHT das Profil erfüllt. Das Log sagt dies explizit. Gib mehr Füllmaterial frei (Schritt 2/3) und führe „apply“ erneut aus, oder gib im endgültigen Bericht an, warum du es akzeptierst. Melde den Schnitt niemals als erledigt, während du einen Fehler ignorierst.

Die Bestehenskriterien sind nicht die alte Regel „keine Stille > 0,8s“ – Messungen haben gezeigt, dass diese Regel viel zu lasch ist. Eine echte Datei bestand sie, während sie 13 verbleibende Stille von 0,45–0,67s mit insgesamt 6,7s (4,2 % der Laufzeit) enthielt, was offensichtlich träge klingt. Die Profile begrenzen jetzt sowohl die längste einzelne Stille als auch das Gesamtverhältnis (default: 0,5s / 3 %).

Schritt 6 – Verwende die geschnittene Version überall

Ab hier lesen Untertitel, Tasten-Layout, SFX-Timing und Zooms assets/transcript.cut.json und die .cut.mp4. Die QC-Prüfung dead-air misst das zusammengebaute Video erneut am Transkript und SCHLÄGT FEHL, wenn brief.autoCut aktiv ist und die tote Luft immer noch über dem Profil liegt – das ist die Absicherung, nicht der Plan.

Der abschließende Bericht muss enthalten: die Schnitttabelle aus Schritt 3, die entfernten Sekunden aufgeteilt in Stille vs. freigegebenes Füllmaterial und das Verifizierungsurteil. Nimm die Zahlen aus auto-trim-report.json.

Bekannte Probleme

  • Verwenden des ALTEN Transkripts nach dem Schneiden -> Untertitel driften gegen Ende immer weiter aus dem Takt. Wechsle immer zu transcript.cut.json.
  • Nur Stille schneiden und wiederholte Aussagen ignorieren – das, was Benutzer „Füllmaterial“ nennen, ist meist Schritt 3.
  • Den gerenderten Entwurf anstelle der Quelle schneiden -> Qualitätsverlust durch eine zweite Kodierung. Schneide immer von der Quelle (der Server weigert sich, die Quelle zu überschreiben, und überspringt Dateien, die bereits *.cut.* heißen, wenn er einen Standard wählt).
  • Analysieren einer .cut.mp4, während das einzige Transkript das rohe ist -> die Absicherung ist auf die falsche Zeitleiste ausgerichtet. Gleiche die Quelldatei mit dem Transkript ab, das sie beschreibt.
  • SFX-/Erzähldateien mit eigener Vorlaufstille -> verwende data-media-start, um innerhalb von HyperFrames zu trimmen (siehe „SFX-Lautstärke und Vorlaufstille“ im Noti-TikTok-VN-Skill), kodiere eine Audiodatei nicht nur für 0,3s Vorlaufstille neu.
  • Zusammenfügen von geschnittenen Segmenten ohne Überblendung -> ein Klick an jeder Nahtstelle. Behoben in autoTrim.ts; die Regel steht unten und gilt für jeden neuen Code, der Audio schneidet oder verkettet.

Audio: 30ms-Überblendung an jeder Schnittkante (harte Regel)

Ein Schnitt landet mitten in der Wellenform. Das letzte Sample eines Segments und das erste Sample des nächsten sind unverwandt, daher ist die Nahtstelle ein vertikaler Sprung, und ein Sprung ist ein Klick. Die Ursache ist weder der Encoder noch die Quelle – es ist die Nahtstelle selbst, daher überlebt sie jede nachgelagerte Neukodierung.

Wie sehr es darauf ankommt, hängt davon ab, WO der Schnitt landet, und der Unterschied ist groß. Gemessen verlustfrei an einer echten 278s-Sprecher-Aufnahme, Vergleich desselben Schnitts mit und ohne Überblendung (größter Sample-zu-Sample-Sprung an der Nahtstelle; alles über ~0,02 ist hörbar):

Art der NahtstelleVorherNachher
Stille-Trimmen, 40 Nahtstellen (balanced)Median 0,0040, schlechteste 0,0113 – keine hörbarMedian 0,0000
Mitten im Sprechen, 4 Nahtstellen (Füllmaterial / wiederholte Aussagen)0,1195, 0,0744, 0,0232, 0,0064 – 3 von 4 hörbaralle ≤ 0,0008

Zum Vergleich: Der lauteste Sprung irgendwo in normaler Sprache in diesen Dateien war 0,06–0,13. Ein Sprung mitten im Sprechen ohne Überblendung kann also ein größerer Sprung sein als alles, was der Inhalt selbst erzeugt, während ein Stille-Sprung bei weitem nicht hörbar ist.

Überspringe die Überblendung nicht aufgrund der ersten Zeile. Reines Stille-Trimmen ist der Fall, in dem es zufällig nicht darauf ankommt; Schritt 3 (wiederholte Aussagen) und Clip-Extraktion schneiden direkt durch Sprache, und diese Nahtstellen klicken.

Behebung: Überblende beide Kanten jedes Segments über 30ms. Lang genug, um den Sprung zu beseitigen, viel zu kurz, um al s Überblendung hörbar zu sein. Verwende audioCutFade() in apps/server/src/util.ts; baue den Filter nicht selbst.

[0:a]atrim=start=S:end=E,asetpts=PTS-STARTPTS,afade=t=in:st=0:d=0.030,afade=t=out:st=D-0.030:d=0.030[aN]

Drei Dinge, die es stillschweigend unwirksam machen:

  • Reihenfolge. afade muss NACH asetpts=PTS-STARTPTS kommen. afade liest st von der eigenen Uhr des Streams; bei ursprünglichen Zeitstempeln liegt st=0 in der Vergangenheit und die Einblendung wird nie ausgelöst.
  • Länge. D ist die Segmentdauer, also ist der Start der Ausblendung D - 0.030. Begrenze die Ausblendung auf D/2, da sich sonst die beiden Überblendungen bei einem kurzen Segment überschneiden und es verschlucken.
  • Extrahieren eines Clips, nicht nur Zusammenfügen. Ein Clip, der aus einem längeren Video ausgeschnitten wird, hat dieselben beiden rohen Kanten, auch wenn nichts zusammengefügt wird – reframe.ts blendet sie über -af aus.

Ein Hinweis zum Selbstmessen: Vergleiche nicht zwei AAC-Kodierungen. Die Neukodierung verändert Samples überall, was die 40 echten Nahtstellen unter 294 zufälligen Differenzbereichen begrub und einen 54ms-Offset zwischen den beiden Dateien erzeugte. Rendere stattdessen beide Varianten direkt nach pcm_s16le – dann sind die beiden sample-ausgerichtet und die Nahtstellen sitzen genau an den kumulativen Segmentlängen.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

TaherZiad/montage-crew

Membangun motion graphic sinematik di browser (promo video, opener, intro, bumper, kinetic typography, explainer/video penjelasan bergambar 16:9 atau 9:16) memakai HTML + CSS + GSAP (+ Three.js bila perlu), dengan hasil yang bergerak seperti video sungguhan — bukan slide presentasi. Gunakan skill ini setiap kali user meminta "video promo", "opener", "intro animasi", "motion graphic", "bumper", "kinetic typography", "animasi teks sinematik", "explainer", "video penjelasan" (jurnalisme visual, kartun edukasi, kolase), atau menunjukkan referensi video promosi/explainer dan ingin dibuatkan versi web-nya — bahkan bila mereka tidak menyebut kata "motion graphic" secara eksplisit. Juga gunakan bila user mengeluh hasil animasi web "seperti PPT/presentasi" dan ingin lebih sinematik, atau ingin merender animasi web menjadi file video MP4, atau ingin explainer kartun/animasi dibangun LANGSUNG di After Effects lewat bridge/MCP Higgsfield.

TaherZiad/montage-crew

Agent 2 of the video editing pipeline. Finds and removes spoken mistakes — stutters, repeated words, false starts, and retakes (re-recorded lines) — from a talking-head recording. Use after cut-silences, when asked to cut mistakes, remove stutters / repeats / filler restarts, clean up flubs, or keep the best take. Works review-gated: it proposes every cut with context and a reason for approval, then renders only the approved cuts via ffmpeg. Requires a word-level transcript.

TaherZiad/montage-crew

Arabic short-video editor (any dialect). Edits talking-head videos and screen recordings, or builds an MG-led video from an idea with no footage - retakes and silences cut, Arabic RTL captions and hook, premium motion graphics, SFX, music, -14 LUFS master, cover - for 9:16, 16:9 or both. Delivers the MP4 plus a project for Resolve, Premiere, After Effects, CapCut or Final Cut. Asks a few questions on first use, keeps the user's brand kit, offers style cards, learns styles from videos, links and MG sites the user shows it, and learns the user's rules after each video. Use when the user asks to edit a video («منتجلي هذا الفيديو», «سوّي مونتاج», «أضف ترجمة», «قص الصمت», «بستايل …», "edit my video"), make a video from an idea («ما عندي فيديو، عندي فكرة», «فكرة فيديو عن…»), learn a style («تعلّم من هذا الفيديو», «هذا الموشن يعجبني»), save a brand («احفظ هويتي», «اقترح لي هوية») or change settings («غيّر إعداداتي»).

Verwandte Skills