6573fa6e05
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>
2.1 KiB
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:
- Drop zone / loaded file path display
- mpv video embed (preview)
- Custom timeline widget with draggable cursor
- Playback controls + cursor position display
- 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
- Command:
Architecture
Single file main.py (~300-400 lines):
MainWindow(QMainWindow)— owns all state: file path, cursor (seconds), base name, output folder, export counterTimelineWidget(QWidget)— custompaintEventdraws bar + cursor line;mousePressEvent/mouseMoveEventfor scrubbingMpvWidget(QWidget)— embeds mpv using window ID (wid), exposesload(path),seek(t),play_loop(a, b),pause()ExportWorker(QThread)— runs ffmpeg subprocess, emitsfinished(path)orerror(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.