Bachelorarbeit Pipeline: Automatisierte Highlight-Erkennung & 9:16-Aufbereitung

Diese Repository enthält eine vollständige, skriptbasierte Pipeline, um aus Langvideos automatisch SocialMediataugliche 9:16Highlights zu erzeugen inkl. Transkription, KIgestützter ClipSelektion, Gesichts/Mundaktivitätsanalyse, AutoCropping, Untertitel (WordCaps) und finalem Export.

Inhaltsverzeichnis


Features

  • Transkription mit WortZeitstempeln (Whisper, chunked ohne GrenzDoppler)
  • LLMgestützte ClipSelektion (Viralität/Emotionalität etc. in SQLite gespeichert)
  • FaceDetection (YOLOv8face) & Mundaktivität (MediaPipe)
  • Stabiles 9:16AutoCropping (Median + EMA, Deadband, SzenenschnittErkennung, SwitchCooldown)
  • WordCaps Untertitel (ASS generiert, per ffmpeg eingebrannt)
  • BatchExport der Highlights (MoviePy, Längen/GrenzChecks)

Ordnerstruktur

Die Pfade werden zentral in config.py definiert:

PROJECT_ROOT/
├─ data/
│  ├─ input/                 # Eingabevideo(s)
│  ├─ transkripte/           # Whisper-Outputs (*_segments.json, *_timed.txt ...)
│  ├─ segments/              # LLM-Clip-Auswahl, DB etc.
│  ├─ output/
│  │  └─ raw_clips/          # Roh-Highlight-Clips (aus cutClips.py)
│  ├─ face_data_combined/    # faces.json je Clip (YOLO + MediaPipe)
│  └─ face_crop_centers/     # (optional) Center-Listen
├─ output/
│  ├─ output_9x16_final/         # Auto-cropped 9:16 Videos
│  ├─ output_9x16_final_subbed_word/  # 9:16 mit eingebrannten Word-Caps
│  └─ debug/                     # Debug-Previews/Artefakte
├─ models/                    # YOLO-Weights (z. B. yolov8n-face.pt)
├─ whisper-cache/            # Whisper Modell-Cache
└─ src/... (optional projektspezifisch)

Beim ersten Start legt config.py fehlende Verzeichnisse automatisch an.

Voraussetzungen

SystemTools

  • ffmpeg (inkl. ffprobe) im PATH

Python

  • Python 3.10+ empfohlen
  • Pakete (Beispiel):
    openai-whisper, torch, ffmpeg-python, ultralytics, opencv-python, mediapipe, moviepy, tqdm, numpy, regex
  • Optional/abhängig vom Codepfad: pydub, scikit-image (falls in Erweiterungen verwendet)

Modelle & Keys

  • Whisper: lädt Modelle automatisch in whisper-cache/ (steuerbar via WHISPER_MODEL)
  • YOLOv8face: models/yolov8n-face.pt (oder größeres Modell)
  • OpenAI API Key (für segment_transcript.py & rateCluster.py): export OPENAI_API_KEY=...
    • DefaultModell ggf. per export OPENAI_MODEL=gpt-4o setzen

Installation

# 1) Python-Umgebung
python3 -m venv .venv
source .venv/bin/activate

# 2) Systemabhängigkeiten
# ffmpeg installieren (Mac: brew install ffmpeg, Ubuntu: apt install ffmpeg)

# 3) Python-Pakete (Beispiel)
pip install --upgrade pip
pip install openai-whisper torch ffmpeg-python ultralytics opencv-python mediapipe moviepy tqdm numpy regex

# 4) Modelle/Dateien
# YOLO-Weights:
#   Download yolov8n-face.pt → ./models/yolov8n-face.pt
# API Key für LLM:
export OPENAI_API_KEY="sk-..."
export OPENAI_MODEL="gpt-4o"

Schnellstart (empfohlener Workflow)

  1. Eingabe ablegen
    Lege dein Langvideo in data/input/ (z.B. meinvideo.mp4).

  2. Transkription (Whisper, chunked & doppler-sicher)

python transcription.py --input data/input/meinvideo.mp4 --model small --lang de

→ erzeugt *_segments.json + *_timed.txt in data/transkripte/.

  1. Clips mit LLM selektieren & in DB speichern
export OPENAI_API_KEY="..."; export OPENAI_MODEL="gpt-4o"
python segment_transcript.py --base meinvideo --block 60 --min 6.0 --max 30.0

→ schreibt Clips in SQLite (data/clips_openai.db o. ä.)

  1. Highlights aus dem Originalvideo schneiden
python cutClips.py --file meinvideo.mp4 --limit 10 --order score

→ exportiert highlight_*.mp4 nach data/output/raw_clips/

  1. FaceDetection + Mundaktivität
python main_detect_faces.py --model models/yolov8n-face.pt     --input-dir data/output/raw_clips --output-dir data/face_data_combined     --frame-skip 1 --downscale 0.5
  1. Targets je Frame bauen (Zentren/Größe glätten)
python make_segments.py --pattern "highlight_*.mp4" --fps 0 --smooth 7 --overwrite
  1. 9:16 AutoCrop anwenden
python main_apply_crop.py --pattern "highlight_*.mp4" --median 7 --ema 0.5     --deadband 16 --cut_detect --mux_audio --overwrite

→ fertige 9:16Clips in output/output_9x16_final/

  1. WordCaps Untertitel einbrennen (optional)
python add_subtitles.py --clips_dir output/output_9x16_final     --out_dir output/output_9x16_final_subbed_word --model small --limit 20

→ fertige Videos mit eingebrannten WordCaps in output/output_9x16_final_subbed_word/

💡 Du kannst viele Parameter (Fensterbreiten, Deadband, Erkennungsschwellen, Limits) über die CLI anpassen.

Skripte & CLI

transcription.py

ChunkedTranskription mit Wortzeitstempeln.

--input PATH        # Eingabevideo/-audio (Default: erstes File in data/input/)
--outdir PATH       # Ausgabeverzeichnis (Default: data/transkripte/)
--model NAME        # Whisper-Modell (tiny/base/small/medium/large; env: WHISPER_MODEL)
--lang CODE         # Sprachcode (z.B. de) oder leer/None für Auto-Detect
--chunk FLOAT       # Chunk-Länge in s (Default 60)
--overlap FLOAT     # Überlappung in s (Default 2.0)
--min-dur FLOAT     # Mindest-Segmentdauer (s)
--max-gap FLOAT     # Max. Zeit-Gap beim Mergen (s)
--fp16              # Nur sinnvoll mit GPU

segment_transcript.py

LLMSelektion & Speichern in SQLite.

--base STR          # Basename der Transkriptdateien (z.B. 'meinvideo')
--block FLOAT       # Blocklänge s für den Prompt
--min FLOAT         # minimale Clip-Länge s
--max FLOAT         # maximale Clip-Länge s
# env: OPENAI_API_KEY, OPENAI_MODEL (z. B. gpt-4o)

cutClips.py

Schneidet ausgewählte Highlights als Einzelclips.

--file NAME         # Name der Input-Datei in data/input (Default: erstes Video)
--limit INT         # Anzahl zu exportierender Clips (Default 10)
--order {score,start} # Sortierung: Score (absteigend) oder Startzeit

main_detect_faces.py

YOLOv8face + MediaPipe → faces.json pro Clip.

--input-dir PATH    # Default: data/output/raw_clips
--output-dir PATH   # Default: data/face_data_combined
--model PATH        # YOLOv8-face Weights (Default: models/yolov8n-face.pt)
--conf-thresh FLOAT # Default 0.35
--frame-skip INT    # z. B. 1 = jeden Frame, 2 = jeden von zwei ...
--downscale FLOAT   # Frame-Downscale vor YOLO (0..1, z. B. 0.5)
--expansion FLOAT   # Margin Pass 1 (relativ)
--expansion2 FLOAT  # Margin Pass 2 (relativ)
--min-crop INT      # minimale Croplänge (px)
--faces-upscale INT # min. Kantenlänge für FaceMesh (kleine Crops hochskalieren)
--imgsz INT         # YOLO input size (Default 448)
--max-det INT       # Max Detects / Frame
--use-refine        # MediaPipe refine_landmarks aktivieren

make_segments.py

Erzeugt *_target_by_frame.json (Zentren+Side pro Frame) aus Face/CenterDaten.

--pattern STR       # Dateimuster in raw_clips (Default: highlight_*.mp4)
--fps FLOAT         # FPS erzwingen (0 = aus Video lesen)
--smooth INT        # MA-Fensterbreite (ungerade)
--overwrite         # bestehende target_by_frame.json überschreiben

main_apply_crop.py

Wendet 9:16Crop mit Glättung/Szenenschnitt an.

--pattern STR       # Dateimuster in raw_clips (Default: *.mp4)
--out_w INT         # Output-Breite (Default 1080)
--out_h INT         # Output-Höhe (Default 1920)
--zoom_pad FLOAT    # Zoom-Pad (0..1)
--median INT        # Median-Fenster (>=3, ungerade)
--ema FLOAT         # EMA-Alpha (0..1)
--deadband FLOAT    # Totband in Pixel
--switch_cd INT     # Cooldown-Frames nach Trackwechsel
--cut_detect        # Szenenschnitt-Erkennung aktivieren
--cut_corr FLOAT    # Schwellwert Korrelation (0..1)
--cut_cd INT        # Cooldown-Frames nach Cut
--mux_audio         # Original-Audio unterlegen
--debug             # Debug-Overlay anzeigen
--debug_scale FLOAT # Debug-Preview skaliert rendern
--overwrite         # vorhandene Ausgaben überschreiben

add_subtitles.py

Generiert WordCaps mit Whisper & brennt sie ein.

--clips_dir PATH    # Quelle (Default: output/output_9x16_final)
--out_dir PATH      # Ziel   (Default: output/output_9x16_final_subbed_word)
--pattern STR       # z. B. *.mp4
--limit INT         # Nur die ersten N Clips
--model NAME        # Whisper-Modell (tiny/base/small/medium/large)
--lang CODE         # Sprachcode oder Auto

rateCluster.py (optional)

Lässt LLM Scores (Viralität, Emotion, Humor, Provokation) nachtragen.

Modelliere StandardModell via OPENAI_MODEL (z.B. gpt-4o).


Tipps & Troubleshooting

  • Modelle/Performance
    • CPUonly ist möglich (Whisper/YOLO langsamer). Auf Apple Silicon wird automatisch MPS genutzt; auf NVIDIA CUDA.
    • --frame-skip und --downscale in main_detect_faces.py beschleunigen die FaceDetection deutlich.
  • ffmpegMuxing prüfen (main_apply_crop.py --mux_audio): Falls Ton fehlt, ffmpeg-Installation checken. Rückgabecode im Log prüfen.
  • Fehlende Dateien
    • Kein Input? → data/input/ prüfen.
    • Fehlende TranskriptPaare? → *_timed.txt und *_segments.json müssen existieren (aus transcription.py).
    • Fehlende Faces? → Pfad zu models/yolov8n-face.pt korrekt?
  • Datenbank
    • Highlights liegen in SQLite (siehe config.py: DB_PATH). Bei Wiederholungen kann ein DELETE FROM highlights; VACUUM; sinnvoll sein.
  • Cache/Verzeichnisse
    • WhisperCache via XDG_CACHE_HOMEwhisper-cache/ neben dem Projekt. Speicherplatz beachten.

Reproduzierbarkeit

  • Lege eine requirements.txt mit exakten Versionen an (Freeze deiner funktionierenden Umgebung).
  • Dokumentiere verwendete ModellVersionsstände (YOLO Weights, WhisperModellgröße, OPENAI_MODEL).
  • Fixiere RandomSeeds, falls nötig (hier meist deterministisch durch externe Modelle/Bibliotheken).

Lizenz / Danksagung

  • Verwendung von OpenAI Whisper, Ultralytics YOLOv8, MediaPipe, OpenCV, MoviePy, ffmpeg.
  • Die jeweiligen Lizenzen der Bibliotheken beachten.
Description
No description provided
Readme 1.4 GiB
Languages
Python 100%