# 8-cut Design ## Overview A Linux desktop tool for dropping a video clip, setting a start point on a timeline, and exporting exactly 8 seconds to a numbered output file. ## Stack - **Python + PyQt6** — native desktop window, drag & drop, custom timeline widget - **python-mpv** — embedded video playback with audio, frame-accurate seeking, AB loop for 8s preview - **ffmpeg** — export via subprocess, always re-encodes to guarantee exactly 8s with no freeze frames ## Layout Single window, top to bottom: 1. Drop zone / loaded file path display 2. mpv video embed (preview) 3. Custom timeline widget with draggable cursor 4. Playback controls + cursor position display 5. Export controls: base name input, folder picker, next filename preview, Export button ## Behavior - **Drag & drop** a video file onto the window to load it - **Timeline**: click or drag to reposition cursor; shows current frame when paused - **Play 8s**: mpv seeks to cursor position, plays 8 seconds, loops back using mpv AB-loop (`ab-loop-a` = cursor, `ab-loop-b` = cursor + 8s) - **Pause**: shows current frame at cursor position - **Export**: runs ffmpeg in a QThread (non-blocking UI) - Command: `ffmpeg -ss {start} -i {input} -t 8 -c:v libx264 -c:a aac {output}` - Output: `{folder}/{basename}_{NNN:03d}.mp4` - Counter auto-increments after each successful export - Counter resets if base name or folder changes ## Architecture Single file `main.py` (~300-400 lines): - `MainWindow(QMainWindow)` — owns all state: file path, cursor (seconds), base name, output folder, export counter - `TimelineWidget(QWidget)` — custom `paintEvent` draws bar + cursor line; `mousePressEvent`/`mouseMoveEvent` for scrubbing - `MpvWidget(QWidget)` — embeds mpv using window ID (`wid`), exposes `load(path)`, `seek(t)`, `play_loop(a, b)`, `pause()` - `ExportWorker(QThread)` — runs ffmpeg subprocess, emits `finished(path)` or `error(msg)` signal ## Export guarantees Always re-encode (never stream copy) to avoid freeze frames caused by keyframe misalignment at the cut point. Output is always exactly 8.000 seconds.