Video-Logo-/Untertitelentfernung (video-watermark-remover)
Mit ProPainter werden fest positionierte Logos, Eckenlogos und Untertitel (die im Bild eingebrannt sind) aus Videos repariert. Es wird nur der ROI um das Element herum ausgeschnitten und repariert, dann mit einer weichen Kante wieder ins Originalvideo eingefügt. Pixel außerhalb des ROI bleiben unverändert.
⚠ ProPainter steht unter der S-Lab License 1.0: Nur für nicht-kommerzielle Zwecke. Für kommerzielle Nutzung muss der Autor kontaktiert werden. Nur für Material verwenden, das du verwenden darfst.
0. Umgebung (erste Nutzung)
Die Skripte befinden sich im Ordner scripts/. Das Arbeitsverzeichnis muss das Skill-Verzeichnis sein (in dem sich SKILL.md befindet).
python scripts/setup_env.py # Prüft ffmpeg / PyTorch (CUDA), klont eine feste Version von ProPainter, erzeugt config.json
python scripts/selftest.py # Erstellt ein Testvideo, führt den gesamten Workflow durch, vergleicht mit Ground Truth, gibt PASS/FAIL aus
- Wenn
config.jsonnicht existiert, gibtsetup_env.pyHinweise, was fehlt und wie es installiert wird. PyTorch muss vom Benutzer entsprechend seiner Grafikkarte als CUDA-Version installiert werden. - Wenn der Selbsttest fehlschlägt, nicht fortfahren – zuerst die Umgebung gemäß der Hinweise reparieren.
- Im Folgenden bezieht sich
pythonauf den Interpreter, der inconfig.jsonvonsetup_env.pyeingetragen wurde (also die Umgebung, die beim Setup verwendet wurde).
Was der Benutzer bereitstellen muss
| Element | Erforderlich | Beschreibung |
|---|---|---|
| Videodatei | ✅ | Eine oder mehrere Dateien |
| Was entfernt werden soll | ✅ | In Klartext: „Senderlogo oben links“, „großes Logo in der Mitte“, „Untertitel unten“ |
| Positionshinweis | Optional | Nur nötig, wenn es mehrere ähnliche Elemente gibt |
| Zeitbereich | Optional | Standardmäßig automatische Erkennung; nur nötig, wenn ein Teil erhalten bleiben soll |
| Nachfolgende Absichten | Empfohlen zu fragen | Ob ein neues Logo überlagert, Untertitel neu eingesetzt werden oder neue Untertitel einen Hintergrundbalken haben. Mit Balken reicht einfaches Weichzeichnen, kein Inpainting nötig |
Fehlende Pflichtfelder nachfragen; optionale Felder nicht ausfragen.
Fähigkeiten und Grenzen (vor Arbeitsbeginn prüfen, Abweichungen dem Benutzer mitteilen)
- ✅ Fest positionierte Logos, Eckenlogos, Senderlogos, auch halbtransparente, ein-/ausblendende, die in Überblendungen oder Übergängen verschwimmen.
- ✅ Fest positionierte, horizontal zentrierte, einzeilige Untertitel (im Bild eingebrannt), weiße oder dunkle Schrift, mit oder ohne Schlagschatten.
- ⚠️ Bewegte oder skalierte Logos, Laufschriften, mehrzeilige Untertitel, nicht zentrierte Untertitel: Die Skripte können sie nicht automatisch verfolgen. Der Benutzer muss Zeitbereiche angeben und dann mit
--block,--grow-frommanuell arbeiten – das Ergebnis wird schlechter. - ⚠️ Text, der bereits im Bild ist (Schilder, Bildschirmtexte), der mit dem zu entfernenden Element überlappt, wird mit entfernt. Darauf muss in der Erkennungsliste hingewiesen werden.
- Erfordert eine NVIDIA-GPU mit mindestens 4 GB freiem VRAM. Läuft auch mit CPU, aber extrem langsam.
Arbeitsablauf (8 Schritte, in dieser Reihenfolge)
Zwischendateien werden im temporären Arbeitsverzeichnis $W gespeichert. Das Endergebnis liegt neben dem Originalvideo, Qualitätskontrollbilder im Ordner <Video-Verzeichnis>/qc/.
1. Erkundung
python scripts/probe.py IN1.mp4 [IN2.mp4] --out-dir $W
Betrachtet die extrahierten Einzelbilder und beurteilt:
- Wo befindet sich das Element?
- Ist es ein Eckenlogo oder ein großes, zentriertes Logo?
- Gibt es Einblendungen (notiert den stabilen Frame-Bereich des Logos), Schwarzblenden, Skalierungs- oder Weichzeichnungsübergänge?
- Gibt es Untertitel?
2. Lokalisierung (statisches Logo)
python scripts/locate_static.py --video IN1.mp4@Startframe:Endframe [--video IN2.mp4@a:b] --out-dir $W
- Start- und Endframes sollten Einblendungen, Schwarzblenden und Übergänge vermeiden.
- Wenn dasselbe Logo in mehreren Quellen vorkommt, alle zusammen übergeben. Das Skript nimmt nur Pixel, die in allen Quellen statisch sind – so werden zufällig statische Blöcke im Hintergrund ausgeschlossen.
- Betrachte
static_rel.png(je schwärzer, desto statischer). Basierend darauf werden der grobe Rahmen (--box) und ein Schwellwert festgelegt: 0,3–0,5 für Vollflächenlogos, 0,6–0,75 für halbtransparente Logos.
3. Maske erstellen und vom Benutzer bestätigen lassen
Statisches Logo:
python scripts/mask_logo.py --rel $W/static_rel.npy --box x0,y0,x1,y1 --thresh 0.5 \
[--block Rechteck] [--clear Bereich --block Bereich] --preview IN1.mp4@Frame [--preview IN2.mp4@Frame] --out-dir $W
- Feine Elemente (Text, Strahlen, Linien) werden Strich für Strich maskiert – die echten Hintergrundpixel zwischen den Strichen dienen dem Modell als Referenz.
- Nur in zwei Fällen
--block(Rechteck) verwenden: bei massiven, flächigen Logos oder bei sehr kleinen Buchstaben, die sich nicht fein genug maskieren lassen (z. B. eine sehr kleine englische Zeile). - ❌ Feine Elemente nicht mit einem großen Rechteck abdecken. Wenn die Kamera langsam hineinzoomt, bleibt fast kein echter Hintergrund unter der abgedeckten Fläche sichtbar – das Modell muss dann Pixel erfinden, was zu einer „Schuppentextur“ führt.
- Prüfe auf der Vorschau, ob die Kanten und Enden des Elements abgedeckt sind. Nicht erfasste Teile werden beim Inpainting ins Bild hineingezogen und hinterlassen bunte Striche.
Untertitel:
python scripts/mask_subtitle.py IN.mp4 --out-dir $W [--rows y0,y1] [--dark] [--shadow 0,0]
- Ohne
--rowswird automatisch im unteren 40 % des Bildes nach Untertitelzeilen gesucht. Bei Fehlern manuell angeben. - Achte auf Warnungen im Output, dass der Untertitel „nah am Bildrand“ ist.
Dem Benutzer zur Bestätigung vorlegen: Zeige mask_preview.png oder subtitle_mask_preview.png sowie eine Erkennungsliste. Verwende die von mask_logo.py ausgegebenen Koordinaten, z. B.:
① Senderlogo oben links: Reparaturrahmen (21,15)–(124,50), erscheint durchgehend ② Untertitel unten: y485–524, insgesamt 47 Sätze ③ Bei 1:34 liegt ein Schild im Bild innerhalb des Reparaturbereichs – es wird mit entfernt
Erst nach Bestätigung durch den Benutzer in Schritt 5 gehen.
4. Segmentierung
python scripts/shots.py IN.mp4 --out $W/bounds.json [--extra 178]
Harte Schnitte und Ein-/Ausblendungen werden getrennt. Ohne Segmentierung entstehen in statischen Szenen durch das Ausleihen von Pixeln aus benachbarten Szenen „pillenförmige Farbklumpen“.
5+6. Inpainting + Zusammensetzen
Lange Videos im Hintergrund laufen lassen, regelmäßig ins Log schauen und aktiv den Fortschritt melden.
python scripts/inpaint.py --video IN.mp4 (--mask $W/mask.npy | --masks $W/masks.npz) --bounds $W/bounds.json \
--workdir $W/run --out OUT.mp4 [--mask-dilation 2] [--grow-from 178:14] [--workers 2]
--mask-dilation: Standard 2; für halbtransparente, leuchtende Logos 4.--grow-from Frame:Pixel: Ab einem bestimmten Frame die Maske um weitere Pixel erweitern, um Logos in Skalierungs- oder Weichzeichnungsübergängen abzudecken.- Wenn im selben Video sowohl Logo als auch Untertitel entfernt werden sollen, in zwei Durchläufen: Der zweite Durchlauf verwendet als
--videodas Ergebnis des ersten. Die beiden ROIs nicht zu einem großen Rahmen zusammenfassen. - Bei Unterbrechung einfach denselben Befehl erneut ausführen; bereits fertige Segmente werden übersprungen.
- Die Ausgabedatei wird
Originalname-nologo.mp4oderOriginalname-nologo-nosub.mp4genannt. Das Skript überschreibt keine Originaldateien. - Zeitbedarf (RTX 3060, 2 parallele Durchläufe): 960×540, 126 Sekunden Video, Logo oben links ca. 17 Minuten, Untertitel ca. 21 Minuten; 5 Sekunden großes, zentriertes Logo ca. 1 Minute.
7. Qualitätskontrolle
python scripts/qc.py --orig IN.mp4 --out OUT.mp4 (--mask .. | --masks ..) --bounds $W/bounds.json --workdir $W/run \
[--residue blue] [--times 3,12,20] --out-dir <Videoverzeichnis>/qc/xxx
Numerische Metriken:
- Nachzieheffekte: Die Varianz des Ergebnisvideos sollte ungefähr der Varianz des äußeren Bereichs entsprechen.
- Flackern: Der Median des Verhältnisses sollte bei 1 oder darunter liegen, nur sehr wenige Ausreißer-Frames.
- Nahtstellen: Verhältnis etwa 1.
- Abweichung außerhalb des Bereichs: < 2.
- Restfarbe: Sinkt nahe 0.
- Vollständig schwarze Frames: 0.
⚠ Auch wenn alle numerischen Werte OK sind, können lokale Probleme auftreten – jede sheet_XX.png muss visuell überprüft werden (Farbklumpen, Schuppentextur, Restbuchstaben, bunte Linien). Bei Problemen zum entsprechenden Schritt zurückgehen:
- Farbklumpen: Mit
shots.py --extrazusätzliche Schnittpunkte hinzufügen. - Schuppentextur: Auf Strich-für-Strich-Maskierung umstellen.
- Restlinien:
--blockergänzen.
Nach der Korrektur nur die betroffenen Teile erneut ausführen und erneut qualitätsprüfen.
8. Abgabe
- Gib die absoluten Pfade des Ergebnisvideos und der Vergleichsbilder an und zeige
before_after.pngdem Benutzer. - Wenn mehrere Teile zusammengefügt werden müssen:
python scripts/concat.py A.mp4 B.mp4 C.mp4 --out FULL.mp4. Das Skript prüft, ob die Gesamtframezahl der Summe der Teile entspricht. - Koordinatendokument schreiben – Vorlage unter
references/positions-template.md. Für jedes Element drei Ebenen: Ursprünglicher Bereich des Elements, tatsächlicher Reparaturbereich, äußerster, mit Weichzeichnung versehener Rand (also der Bereich, den ein neues Logo abdecken sollte). Für Untertitel denunion_boxaussubtitle_info.jsonverwenden. - Bekannte Mängel nach Zeitpunkten auflisten, nicht verheimlichen.
Harte Regeln (alle auf Erfahrung basiert)
- Breite und Höhe des ROI müssen ≥160 sein. Bei einer Höhe von 96 liefert ProPainter im Maskenbereich reines Schwarz, selbst mit fp32.
inpaint.pystellt dies bei der automatischen ROI-Auswahl bereits sicher. - Übergänge müssen getrennt werden. Nur harte Schnitte zu segmentieren übersieht Ein-/Ausblendungen – ProPainter leiht dann Pixel aus benachbarten Szenen, was zu Farbklumpen führt. Eine Vergrößerung der Maske oder die Verwendung von fp32 behebt das nicht.
- Feine Elemente werden Strich für Strich maskiert, nicht mit einem großen Block abgedeckt.
- Untertitel zentriert symmetrisch zuschneiden und für denselben Satz dieselbe Maske verwenden. Ohne symmetrischen Zuschnitt werden helle Hintergrundstreifen mit maskiert. Unterschiedliche Masken für denselben Satz führen zu Flackern, insbesondere beim Einblenden.
- Numerische Metriken übersehen Probleme – jede
sheet_XX.pngmuss visuell überprüft werden. - Vor dem Inpainting den Benutzer die Maske bestätigen lassen. Keine Originaldateien überschreiben, keine Benutzerdateien löschen.
- Hintergrundprozesse öffnen keine Fenster (Skripte bereits integriert). Lange Aufgaben im Hintergrund ausführen und aktiv Fortschritt melden.