Commit Graph

48 Commits

Author SHA1 Message Date
Ethanfel 191d1cf299 fix: move SELVA_CATEGORIES to module level, harden append_to_tsv, fix tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 18:48:46 +02:00
Ethanfel c76eb9ec84 feat: add label/category annotation fields and TSV export for SELVA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 18:45:29 +02:00
Ethanfel 8fb8782e65 fix: use correct venv path on Windows (Scripts/python.exe) 2026-04-06 18:30:37 +02:00
Ethanfel e62a712de2 perf: skip redundant repaints, cache fps, O(1) playlist dedup, fix worker leak
- TimelineWidget.set_cursor: skip update() when clamped value is
  unchanged (e.g. clicking at the boundary repeatedly).
- MainWindow: cache container_fps in self._fps on file load; keyPressEvent
  reads the cached value instead of hitting the mpv property on every key.
- PlaylistWidget: add _path_set (set[str]) alongside _paths (list[str])
  so duplicate detection in add_files is O(1) instead of O(N).
- SettingsDialog._on_install: quit+wait any previous SetupWorker before
  starting a new one, preventing leaked threads and duplicate signal
  connections on repeated installs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 18:18:31 +02:00
Ethanfel 16e0bc231c perf: playlist O(1) updates, marker hover cache, crop pen cache, keyboard debounce, export marker fast-path
- PlaylistWidget._select: only update the two items whose label changes
  (old current → plain name, new current → add ▶) instead of rewriting
  every item in the playlist.
- TimelineWidget: pre-compute (t/duration, path) fractions in
  _hover_cache on set_markers/set_duration so mouseMoveEvent avoids
  dividing by duration on every pixel of mouse movement.
- CropBarWidget: cache QPen in __init__ instead of recreating per frame.
- _step_cursor: update label/state immediately and start the timeline's
  existing _seek_timer instead of calling _on_cursor_changed directly,
  so held arrow keys are debounced the same as mouse drag.
- _refresh_markers: call _get_markers_for(filename) directly after
  export (exact match known) and only fall back to fuzzy find_similar
  when no exact-match rows exist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 18:07:58 +02:00
Ethanfel 4c44d78c37 perf: seek debounce, cached paint resources, async DB lookup, regex pre-compile
- TimelineWidget: debounce cursor_changed signal with 16ms timer so
  mpv.seek is called at most ~60/s during drag; flush on mouseRelease.
  Cache QPen/QFont objects in __init__ instead of recreating per frame.
- _normalize_filename: compile _QUALITY_RE and _SEP_RE once at module
  level instead of on every call.
- ProcessedDB: add check_same_thread=False; add _get_markers_for() to
  avoid a second find_similar pass; store db path.
- _DBWorker(QThread): runs find_similar + _get_markers_for off the main
  thread. _after_load starts the worker instead of blocking; stale
  results discarded if the user loads a different file first.
- MainWindow: reuse self._settings instead of creating a new QSettings
  instance in the mask row setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 18:04:18 +02:00
Ethanfel b57131a3d9 feat: keyboard navigation for timeline
Arrow keys / J / L: step one frame; Shift = 1 second jump
Space / P: toggle play/pause
K: pause and return to cursor
E: trigger export
M: jump to next export marker (wraps)

Keys are suppressed when a text field has focus.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:35:46 +02:00
Ethanfel 9652b249ba feat: extract audio alongside WebP image sequence
Adds build_audio_extract_command and runs it in ExportWorker after the
frame sequence completes. Audio written to <sequence_dir>.wav (lossless
pcm_s16le). Extraction failure (no audio stream) is silently ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:20:40 +02:00
Ethanfel fe3e642dfa fix: guard mask generation against WebP sequence export path 2026-04-06 17:19:03 +02:00
Ethanfel 855797a1b3 docs: clarify _last_export_path holds dir path for WebP sequence 2026-04-06 16:07:44 +02:00
Ethanfel f9649f7584 feat: wire WebP sequence format into export flow 2026-04-06 16:05:26 +02:00
Ethanfel 13c8a8aeab style: rename fmt_idx to idx in _cmb_format setup 2026-04-06 16:04:30 +02:00
Ethanfel c163b298c4 feat: add format combo (MP4 / WebP sequence) to export row 2026-04-06 16:02:26 +02:00
Ethanfel d3c4dea597 fix: guard makedirs in ExportWorker.run inside try/except 2026-04-06 16:01:16 +02:00
Ethanfel f86442322f feat: ExportWorker supports image_sequence mode 2026-04-06 15:59:17 +02:00
Ethanfel 1ab18e6ab5 fix: use -c:v and explicit -an in image_sequence ffmpeg command 2026-04-06 15:58:33 +02:00
Ethanfel 93028d9ac7 feat: build_sequence_dir and image_sequence flag for build_ffmpeg_command
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 15:56:16 +02:00
Ethanfel 3c6f83de5a feat: wire mask generation and settings into MainWindow 2026-04-06 15:39:07 +02:00
Ethanfel ccc1e04acb feat: MaskWorker, SetupWorker, SettingsDialog 2026-04-06 15:37:12 +02:00
Ethanfel 9bc65a2b25 feat: add build_mask_output_dir utility 2026-04-06 15:34:08 +02:00
Ethanfel 29b404ec23 feat: wire portrait crop into MainWindow 2026-04-06 13:53:55 +02:00
Ethanfel d8c7642f15 feat: CropBarWidget for portrait crop positioning 2026-04-06 13:51:56 +02:00
Ethanfel 1a43c4725d feat: portrait crop filter in build_ffmpeg_command
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:51:02 +02:00
Ethanfel 625ca2d21c feat: resize short-side field with QSettings persistence 2026-04-06 13:33:13 +02:00
Ethanfel 798c5ff4f4 feat: add short_side resize to build_ffmpeg_command 2026-04-06 13:31:58 +02:00
Ethanfel 207518902f feat: wire timeline markers into MainWindow 2026-04-06 13:11:05 +02:00
Ethanfel 5960a2fe78 feat: timeline markers with hover tooltip 2026-04-06 13:10:12 +02:00
Ethanfel 63d48a968c feat: DB schema v2 — store start_time and output_path, add get_markers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:08:49 +02:00
Ethanfel bcde41c4fc fix: list item selection styling, advance() guard against no selection 2026-04-06 12:59:18 +02:00
Ethanfel f93fea2a22 fix: clear stale DB warning, allow playlist panel to resize 2026-04-06 12:55:58 +02:00
Ethanfel ccdb50c6a4 feat: wire playlist and DB into MainWindow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:53:41 +02:00
Ethanfel 75fd43577e feat: PlaylistWidget with drop support and auto-advance
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:51:46 +02:00
Ethanfel dab4b26ce1 fix: utcnow deprecation, DB unique constraint and index, regex comment 2026-04-06 12:50:53 +02:00
Ethanfel 558fa23da4 feat: ProcessedDB and _normalize_filename with tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:42:03 +02:00
Ethanfel c5f508ffb9 fix: remove redundant _reset_counter call in _pick_folder 2026-04-06 12:27:51 +02:00
Ethanfel 1fb69b10fb fix: Wayland XCB force, AB-loop clamp, folder textChanged, drop validation 2026-04-06 12:26:08 +02:00
Ethanfel 73abd5429a feat: dark theme, complete 8-cut tool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:22:49 +02:00
Ethanfel 9981cc84c1 docs: clarify format_time truncation and counter reset behavior 2026-04-06 12:22:17 +02:00
Ethanfel 322d89b688 feat: complete MainWindow UI with playback and export
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:19:54 +02:00
Ethanfel ad1a4283e8 feat: MpvWidget with seek and AB-loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:12:53 +02:00
Ethanfel ba736fe532 fix: end QPainter in finally block to prevent resource leak 2026-04-06 12:11:39 +02:00
Ethanfel f0313b10a8 feat: TimelineWidget with cursor and 8s highlight 2026-04-06 12:09:35 +02:00
Ethanfel 8a97c3c7c2 fix: ffmpeg command type hint, -ss comment, FileNotFoundError handler 2026-04-06 12:08:42 +02:00
Ethanfel f6832f58a6 feat: ExportWorker with ffmpeg command builder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:06:32 +02:00
Ethanfel 68f9a01d2b fix: format_time rollover, move sys.path to conftest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 11:16:52 +02:00
Ethanfel 5819ea2970 feat: add utility functions with tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 11:14:01 +02:00
Ethanfel a3e2cb4d3b chore: remove unused import, add .gitignore 2026-04-06 11:12:55 +02:00
Ethanfel 7c46ec3ae7 feat: project skeleton 2026-04-06 11:11:25 +02:00