Files
8-cut/docs/plans/2026-04-06-8cut-design.md
T
Ethanfel 6573fa6e05 feat: mpv Wayland embedding, timeline redesign, UX polish
mpv embedding:
- Replace wid/QOpenGLWidget with QOffscreenSurface + QOpenGLFramebufferObject
  + QPainter readback — works on Wayland/KDE without sub-surface compositing
- Force desktop OpenGL 3.3 core profile before QApplication (fixes black output on GLES)
- Timer-based render polling (16 ms) replaces signal-flood from mpv C thread;
  fixes playback animation and scrubbing preview
- Fix AB-loop: set ab-loop-a/b to "no" on stop (0 means infinite in mpv)

Timeline:
- Full redesign: time ruler with adaptive major/minor ticks, playhead triangle
  handle, selection region with edge lines, numbered marker badges
- Height 160 px; layout collapsed from 4 rows to 2 below timeline
- Markers appear immediately on export (optimistic update before ffmpeg finishes)
- Right-click marker → context menu to delete from DB

Hotkeys:
- Replace keyPressEvent with QShortcut(ApplicationShortcut) so keys work
  regardless of focused widget; MpvWidget gets NoFocus policy

Export:
- WebP: switch lossless→lossy quality 85, compression_level 1 (~10x faster)
- Add -threads 0 for full CPU utilisation during decode/filter
- Remember last export folder across sessions via QSettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:22:58 +02:00

47 lines
2.1 KiB
Markdown

# 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.