Mirror the manual export path: re-export and auto-export now read the
active tab's LTX-2 params via _ltx2_export_params() and override
short_side/duration plus thread target_fps/snap32/frames through to
ExportWorker. Foley tabs return None and keep byte-identical behavior.
For auto-export, params are captured at batch-build time so queued
batches keep their own geometry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
".../AlexisCrystal/" + "_copy" was producing ".../AlexisCrystal/_copy"; rstrip
the trailing separator first → ".../AlexisCrystal_copy". Regression test uses a
trailing-slash source folder.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Constructing MainWindow loads and (on close) re-saves the playlist tabs; a test
that mutated tab state could persist into the user's real session. Redirect
QSettings to a temp dir at import time.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New tab copies the source tab's video list + separators, gets a unique
"<name> copy" label and an adapted own export folder ("<folder>_copy"), and
inherits the tab-named-folder flag. No files are moved or copied — you export
into the new tab's folder. Keeps Foley/variant datasets separate without the
file-shuffling that a misexport used to require.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bump APP_VERSION to 1.1 with a "What's new" entry covering the menu bar,
tabbed control deck, side-by-side panels, status bar, and visual polish.
Add an Interface section to the README. Shortcuts unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pinning 2 of 3 panels previously showed a 3rd "leftover" tab-column, which
read as all-three-pinned and was confusing. Now the split view shows exactly
the pinned panels (pin 2 -> 2 columns, pin 3 -> 3). Adds an always-available
View > Side-by-side panels submenu of checkable toggles as the way to pin a
panel while already in split view (the right-click-tab gesture only works in
tabbed mode). Tests assert exactly-N-columns and the menu-pin path; the win
fixture now resets deck state so tests don't depend on persisted layout.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test_deck_stack_exists: _deck_stack present; default shows _control_deck.
- test_pinning_two_panels_switches_to_split: pin 2 panels + refresh →
stack shows _deck_split_container.
Pin via _pinned flags directly (not the toggle handler) so no QSettings
write leaks into other function-scoped windows; existing 6 tests run in
default/tabbed state and still pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirror the playlist pin→side-by-side pattern for the Export / Crop &
Track / Scan control-deck panels. Right-click a deck tab → "Show
side-by-side"; pinning 2+ panels lays them out as resizable QSplitter
columns, with any unpinned panel kept reachable in a leftover tab-column.
The ✕ header returns a panel to tabs. State persists across launches via
the deck_pinned QSettings key.
- _DeckTabBar: minimal QTabBar emitting pin_toggle_requested(idx).
- _build_control_deck wraps _control_deck + a split container in a
QStackedWidget (_deck_stack), mounted in right_layout in its place;
sets _pinned/_label/_deck_key on each page; builds _deck_panels.
- _refresh_deck_layout / _detach_deck_panels / _clear_deck_split /
_on_deck_pin_toggle / _on_deck_unpin / _save_deck_layout, guarded by
_deck_loading. Reparented pages are setVisible(True) so they don't
render blank (same gotcha the playlist documents).
- Restore block at the end of __init__ reads deck_pinned (str/list).
- Height-pin now targets _deck_stack and fits the tallest split-mode
column (22px header + content) so split mode never clips.
Default (nothing pinned) behaves exactly like the prior tabbed deck.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pin deck panels (Export/Crop/Scan) side-by-side as resizable columns,
mirroring the playlist pin pattern; unpinned panels stay reachable as a
tab-column. Spec for the multi-pane feature.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds MainWindow._build_menubar building File/Edit/Scan/View/Help menus
whose actions reuse the existing handler methods. Profile combo and the
? shortcuts button move from top_bar into a TopRightCorner widget. Adds
_show_about and _rebuild_remove_subprofile_menu helpers. Bidirectional
sync for Hide exported / Show hidden; forward-only sync for Review mode
(reverse added in a later stage).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tabbed control deck reorg of MainWindow: menu bar for rare actions,
always-visible transport bar, 3-tab control deck (Export / Crop & Track /
Scan), real status bar, plus a visual-polish pass. No behavior, shortcut,
or core/ changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Subcategory marker groups cycled through only 5 colors, so the 6th repeated.
Generate 24 colors across the hue wheel, interleaved (coprime step) so
consecutive groups are ~105 deg apart and colors only repeat after 24.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When autoclip (A / back button) or a wheel scroll reduces the clip span, seek
playback to 3s before the new end and loop there so the shorter cut point can
be reviewed immediately. Growing the play area is unaffected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The x2/x4 toggle always derives the right speed (1/2/4), but mpv's speed could
still drift out of sync during the ab-loop playback (e.g. across loop seeks),
making it feel half-speed after x2 -> x4 -> x2. Reassert the desired speed on
each render tick while playing so mpv always matches the buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When you move the highlight start (click/drag the timeline), leave a single
faint dashed line at where it was, so an accidental move is easy to undo by
eye. Only the most recent prior position is kept, it's suppressed when leaving
an already-exported spot (it has a marker), and it clears on a new file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The clip preview loops via ab-loop; mpv's speed could drift out of sync with
the x2/x4 buttons, so toggling a speed off didn't reliably return to normal.
Centralize the desired speed in MpvWidget and reapply it on every play_loop,
and derive the effective speed from the button state on each click so a
re-click cleanly returns to 1x.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The lower/back side button (Qt BackButton) fits the clip count to the current
play position — same as the A hotkey / autoclip. Forward button left unused.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Restore right-click to the marker/keyframe delete menu (no longer toggles
lock); kept the no-seek guard so it doesn't nudge the cursor.
- Middle-click (no drag) now toggles cursor lock; middle-drag still pans.
- Plain mouse wheel over the timeline adds/removes clips (up +1, down -1,
clamped); Ctrl+wheel still zooms.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mousePressEvent fell through to _seek for right-click, and mouseMoveEvent
scrubbed on any held button — so a middle/right click that nudged the mouse a
pixel moved the cursor. Right-click now returns early in press/release, and the
drag-seek in mouseMoveEvent is restricted to the left button. Middle still
bumps the clip count, right still toggles lock / opens the delete menu, left
still scrubs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Right-click on empty timeline toggles cursor lock (G). Right-clicking a
marker/keyframe still opens the delete menu.
- Middle-click (press+release without dragging) adds one to the clip count
and wraps at the max; middle-drag still pans the zoomed view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A focused QPushButton swallows Space/Enter and a focused spin box swallows
every key (its line edit also makes _KeyFilter suppress the app shortcuts), so
clicking Export or the clip-count spinner left the timeline hotkeys dead.
- Give all main-window buttons (incl. dynamic subprofile/format/unpin buttons)
NoFocus so they never trap keyboard focus.
- Spin boxes clearFocus on editingFinished so hotkeys resume after Enter
(clicking elsewhere already releases focus via _KeyFilter).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
load_for_file no longer runs three DB queries on the UI thread during file
load. A _ScanLoadWorker reads the bundle (hard negatives, scan-export times,
latest scan results) via its own short-lived connection — safe alongside the
main connection now that WAL is on. The table rebuild stays on the UI thread
in _on_scan_bundle_loaded; the timeline scan regions are synced from the new
loaded(filename) signal. Stale results from rapid file switches are ignored,
and the worker is drained on shutdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Group clips by export folder in one scan instead of re-scanning every row for
each folder; also drops the extra get_export_folders() query. Speeds up the
train-dialog stats with many subcategories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Database:
- Enable WAL + synchronous=NORMAL + bigger cache pragmas
- Add (profile, filename) index covering the hot queries
- _refresh_playlist_checks: one get_clip_counts_grouped() scan for the whole
profile instead of one query per file (was O(N) full scans per keystroke/
tab switch/file load)
Timeline (60fps playback):
- set_play_position only repaints when the playhead moves a whole pixel or the
view scrolls (≈30x fewer full repaints in non-zoomed playback)
- Cache all per-paint QColor/QPen objects and the other-folder color table in
__init__ instead of allocating them every frame; drop the per-paint
visible-markers list comprehension
File load / startup:
- PlaylistWidget stats files for the missing-set only when paths change, not on
every filter keystroke
- Cache the vid-folder lookup (DB + os.listdir) per (file, folder) so spinner
ticks don't repeat it; m-counter still recomputed so it stays correct
- Swap the waveform worker without blocking the UI thread (no wait(1000))
- Defer the changelog modal so the window is interactive first
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_on_open_files/dropEvent added to self._playlist (the last-interacted pane,
which could be the tab whose file is loaded in the player). Now they target
_add_target_playlist(): the currently visible tab in tab view, or the active
pane in side-by-side, and make it the active list.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
QTabWidget hides its non-current pages. Pinning a tab that wasn't the active
one reparented a hidden QListWidget into the split panel, where it stayed
hidden — the layout collapsed it, overlapping the header in the middle with
an empty/black list. setVisible(True) after reparenting fixes the panes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Side-by-side layout:
- Reduce pinned lists' min width (200→60) so two fit, widen the main
splitter's left section when split is active (steal from the video pane)
and restore on collapse. Fixed-height headers, list stretch, rebuild on
reparent — fixes the empty/misplaced panes.
Tab→folder per tab:
- Replace the global "Tab→folder" checkbox with a per-tab toggle in the tab
right-click menu ("Export to tab-named folder"). _tab_export_folder() now
reads the active tab's flag; persisted per tab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
self._export_folder is an existing str attribute (stashed during export), so
the new _export_folder() method shadowed it and 'str' object is not callable
crashed on startup at _update_next_label. Renamed to _tab_export_folder().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Side-by-side:
- Right-click a tab → "Show side-by-side" to pin it; 2+ pinned tabs render
in a horizontal splitter (each with a name header + ✕ to unpin), via a
QStackedWidget that swaps between the tab view and split view.
- Tabs are now backed by self._pws (source of truth) so persistence and
layout work regardless of where each list is parented; pinned state saved.
- self._playlist resolves to the last-interacted pane (active pw), so exports
and edits follow the pane you're acting in. Pinned flag persisted per profile.
Tab → export folder (optional):
- New "Tab→folder" checkbox: when on, the active tab's name is appended to the
export folder (mp4 → mp4_BatchA). Default "List N" tabs are ignored.
- _export_folder()/_export_base_name() helpers route exports, markers, next
label, and delete/clear paths so they stay consistent with the tab folder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- _remove_paths re-anchors a separator to the next surviving file (or a
trailing separator) instead of dropping it when its anchor is removed;
used by both Remove and Delete-from-disk. Removal now persists tabs.
- Add "Copy name" / "Copy N names" to the playlist context menu (basenames
to clipboard, newline-joined for multi-select).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The first load of a file decodes the whole audio track in a background
thread; nice'ing it (os.nice(15)) reduces disk/CPU contention with mpv
during the initial open. Result is cached, so subsequent loads are fast.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Missing files are kept in the list instead of being silently dropped on load,
and styled distinctly with a tooltip. add_files gains allow_missing; tab
restore keeps missing entries so they're visible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the per-folder submenu/buttons with one batch action: "Disable all"
moves every enabled subcategory (excluding the main folder and already-disabled
ones) to _disabled in one click; "Enable all" restores them. Available in both
the playlist right-click menu and the Sub button menu.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Folder-wide disable/enable is now reachable right next to the per-video
"Disable in" submenu, listing every subcategory in the profile (not just
ones tied to the loaded video). Backed by profile-wide subcategory counts
pushed to the playlist in _refresh_playlist_checks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously the Sub menu only showed folders from the current video's markers
plus configured subprofiles, so subcategories without clips on the loaded
video (or without a matching subprofile) never appeared. Now it also includes
every subcategory that has clips anywhere in the profile (active or disabled).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sub menu now has per-folder "Disable all" / "Enable all" buttons with live counts
- relocate_video_clips accepts filename=None to move every video's clips in a folder
- get_all_folder_counts returns profile-wide per-folder counts (incl _disabled)
- Disable-all confirms before moving; both refresh markers + playlist counts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap the playlist in a QTabWidget; each tab is its own file list
- "+" corner button adds tabs; double-click a tab to rename inline; tabs are closable (last tab protected) and movable
- self._playlist now resolves to the active tab's PlaylistWidget
- Persist tabs (label + files + separators) per profile as JSON; falls back to legacy session_files/separators on first load
- Filter box and playlist filters apply to the active tab; tab switches reapply filters and refresh marks
- Profile switch/duplicate/delete now save/load/copy/remove per-profile tab state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Context menu offers both "Add/Remove separator above" and "below"
- "Below" anchors to the next visible file, or a trailing line via end sentinel when clicking the last file
- End sentinel preserved across rebuilds and persisted per profile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Train dialog: multi-select positive subcategories via checkbox list, optional model name suffix ({profile}_{model}_{name}.joblib)
- list_trained_models recognizes named model variants
- Disable a video per-subcategory: moves its clips to a sibling {subcat}_disabled folder, rewrites DB output_path, migrates dataset.json, marks the name red
- Disabled clips excluded from training, stats, timeline, and playlist counts
- Playlist per-video count reflects only visible, non-disabled subcategories
- Persist subcategory show/hide visibility per profile across restarts
- Add/remove playlist separator rows (right-click) to mark batches, persisted per profile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add speech detection via faster-whisper with red waveform coloring for speech regions
- Add format variant export buttons (P/S) next to Export and subprofile buttons when portrait/square enabled
- Add force_ratio parameter to _on_export for deterministic format exports
- Add subcategory show/hide with persistent checkbox menu (no longer closes on toggle)
- Show crop overlay lines during video playback, not just when paused
- Delete marker now also removes files from disk and cleans up annotations
- Clear all markers also deletes files and DB entries
- Add playlist text filter, clip spread tick lines on timeline
- Fix LD_PRELOAD for GLIBCXX in conda launcher
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ProcessedDB.update_source_paths() to re-resolve missing or stale
source_path entries by matching filenames against a directory listing
and the current playlist. Exposed as "Update paths" button in the
train dialog next to the video dir field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract the manual export counter (m1, m2, ...) from the output path
so timeline markers match their filenames. Falls back to sequential
numbering for old-format paths without m-prefix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The context menu hit test only searched the current folder's markers.
Now also checks other-folder markers so the delete option appears
for subprofile markers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subprofile/subfolder exports now appear as colored markers (yellow,
green, blue, purple, orange) with their own numbering, separate from
the main folder's red markers. Each folder gets its own color and
independent sequence numbers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subprofile exports (folder_suffix) created markers that interleaved
with main folder markers, shifting their numbering. Now get_markers
and _get_markers_for accept an export_folder parameter and use
SQL LIKE to only return markers whose output_path is in that folder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thin 8px scrollbar appears above the ruler when the timeline is zoomed.
Shows a draggable thumb representing the current view window. Click
outside the thumb to jump, drag the thumb to pan. Ruler and track
shift down to make room. Scrollbar hidden when not zoomed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The marker format was extended to include clip_span but the overlap
check in _on_export still unpacked 3 values, causing a crash on export.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mpv's "absolute" seek lands on the nearest keyframe before the target,
causing playback to start ~3s before the marker. Switch to
"absolute+exact" for both seek() and play_loop() so playback starts
at the precise requested time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Revert span opacity back to 35 (was fine). The actual issue was the
play position line disappearing when scrolled out of the zoomed view.
Now set_play_position auto-pans the view window to keep the playback
marker visible with a 10% margin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- _on_marker_clicked now explicitly sets cursor and seeks mpv to start_time
instead of relying on the timeline's indirect seek chain
- Doubled clip span area opacity (35 → 70) so spans are always visible
- Trigger end-frame preview after config restoration on marker click
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Per-profile playlist persistence (session_files/{profile} in QSettings)
- Training data resolves source videos via playlist paths before fallback dir
- Guard against deleted video files in _load_file
- Fix marker double-click to seek to exact marker time instead of click pixel
- Show manual clip spans as light amber areas on the timeline
- Extend marker tuples with clip_span from DB (clip_duration + overlap)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clip duration spinner (2–30s, default 8s) replacing all hardcoded
8.0 references. Store clip_duration in DB for accurate re-export span
calculations. Add x2/x4 playback speed toggle buttons. On Windows, mpv
renders directly into the widget's native window handle (WId embedding)
instead of slow FBO readback; crop overlays use a transparent child
widget. Fix _poll_render crash when player is None after closeEvent.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-export dialog now offers two modes: keep section length (adjust clip
count) or keep clip count (adjust section length). Files shared with
other profiles are preserved during re-export. Vid folder is resolved
before DB deletions to reuse existing folders. Add delete profile option
with confirmation dialog. Profile duplication now copies all tables
including processed exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-export button (next to Spread spinner) re-exports all manual clips
for the current file into the current folder with the new spread value.
Old files are deleted from their original locations first.
Duplicate profile option in the profile dropdown copies scan_results,
hard_negatives, and hidden_files to a new profile name (exports are not
copied since they reference file paths tied to the source profile).
Also widened get_profiles() to include profiles that only have
scan_results or hard_negatives, not just exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a scan result row is clicked, if the active region falls outside
the current zoomed view the view centers on the region (and widens if
the region is larger than the current span).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ctrl+scroll zooms the timeline view around the mouse. Middle-mouse drag
pans when zoomed. Scrolling all the way out clamps back to full view.
While dragging a scan region edge with Shift, the view auto-pans when
the mouse approaches the widget border so you can extend a region past
the visible range.
All paint and hit-test paths now route through _time_to_x / _pos_to_time
helpers backed by a _view_start / _view_span window, so existing
interactions (seek, marker click, edge resize, keyframe context menu)
all adapt naturally to the zoom level.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add "Merge N rows" context-menu option that combines selected scan rows
into one (min start, max end, max score), with full undo support.
Ctrl+Z is now an application-wide shortcut so it works regardless of
which widget has focus. Negatives undo now respects the exported-green
row color instead of reverting to default.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Scan panel button now reads "Export Selected (N)" while rows are
selected, mirroring the clip-count estimate used for full exports.
Selection changes fire an explicit signal so the label refreshes.
- Export markers remain visible on the timeline in scan/review mode.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Right-click on exported (green) rows shows "Delete export" to wipe
associated clip files, annotations, DB rows and empty vid folders;
scan panel, markers and playlist badge refresh afterwards.
- Exporting with rows selected in the scan panel now runs a partial
export: prior scan exports are preserved, and the area index for new
clip filenames is offset past existing a-suffixes in the vid folder
to avoid collisions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Scan panel rows whose range contains an exported clip's start time
are colored green. Priority: disabled > negative > exported > default.
Exported state refreshes automatically after an auto-export batch
completes on the current file.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Draws a yellow outline around the scan region corresponding to the
selected/clicked row, so overlapping regions can be distinguished.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Time column click still seeks to clip start. End column click seeks
to end - 3s so you can preview the tail of the clip.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Waveform peaks are saved as .npy files keyed by MD5 of the video
path. Subsequent loads of the same video read from cache instead
of re-running ffmpeg extraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the current item is deselected via Ctrl+click, fall back to
the last remaining selected item instead of staying on the
deselected row.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Was using selectedItems()[0] which always returns the first item in
the selection, not the most recently clicked one. Changed to
currentItem() which tracks the last clicked row.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When starting a scan export batch, delete old scan_export entries for
the same file+profile before writing new ones. Logs a warning when
replacing. Prevents stale entry buildup from repeated scan exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs caused vid number collisions (multiple files sharing a vid_NNN):
1. "First gap" assignment (n=1; while vid_n in existing: n++) would
reuse deleted vid numbers. Changed to max(existing) + 1 so numbers
always increase.
2. LIMIT 1 without ORDER BY returned arbitrary rows when a file had
entries in multiple vid folders. Added ORDER BY rowid DESC for
deterministic latest-wins behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Queue scan exports back-to-back: when an export is running, new
batches are queued and drain automatically on completion. Each batch
snapshots its state (file path, jobs, settings) so the user can
switch videos while exports run.
Also updates ScanWorker default and slider initial value to 0.50
to match the core threshold change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set CQ/QP rate control (quality 28) for NVENC, VAAPI, QSV, and AMF
hardware encoders instead of relying on encoder defaults which
produce unnecessarily large files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Manual clips now follow the same pattern as scan exports:
clip_003_m1_0.mp4 (manual) vs clip_003_a1_0.mp4 (auto-scan).
The clip number matches the vid folder number.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
clip_001_a1_0 now matches vid_001 instead of using an independent
counter that created confusing double numbering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9 tasks covering node pack skeleton, all 5 nodes, frontend widget,
API routes, and integration testing. Uses ExecutionBlocker pattern
for the interactive VideoReview node.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
load_for_file and add_scan_results triggered N redundant timeline repaints
via tab_changed → _on_scan_regions_edited for each tab add/remove.
blockSignals(True) during programmatic tab operations eliminates the cascade.
Also adds EAT_LARGE embedding model (1024-dim) and updates design docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Export layout changed from clip_NNN group dirs to vid_NNN per-video folders
- Automatic DB migration rewrites old paths and moves files on startup
- Per-video counter with DB cross-check to prevent overwrites
- Changelog popup on version bump with "don't show again" checkbox
- Scan region resize now requires Shift+drag to prevent accidental edits
- Recalculate vid folder and counter on file load
- Add EAT_LARGE embedding model variant
- Update tests for new flat export path structure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pip install -r requirements.txt can pull CPU-only torchvision via
transitive dependencies (timm, ultralytics). Adding --extra-index-url
with the CUDA wheel index ensures all torch packages stay on the
correct build. Applied to both Linux and Windows setup scripts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>