Files
8-cut/docs/plans/2026-04-06-8cut-design.md
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

2.1 KiB

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.