Files
8-cut/docs/plans/2026-04-06-playlist-db-design.md
T

81 lines
3.9 KiB
Markdown

# Playlist & Processed-Files Database Design
## Overview
Two new features added to the existing 8-cut tool:
1. **Playlist** — a queue of source video files; auto-advances to the next file after each export.
2. **Processed-files database** — SQLite store of exported source filenames; warns when a newly loaded file is fuzzy-similar to one already processed.
## Stack additions
- `sqlite3` (Python built-in) — persistent DB at `~/.8cut.db`
- `difflib.SequenceMatcher` (Python built-in) — fuzzy filename similarity, threshold 0.75
## Layout
```
┌──────────────────────────────────────────────────────┐
│ [Drop video files here] │
├─────────────────┬────────────────────────────────────┤
│ QUEUE │ │
│ ▶ clip_a.mp4 │ mpv video preview │
│ clip_b.mp4 │ │
│ clip_c.mp4 ├────────────────────────────────────┤
│ │ Timeline ──────|cursor────── │
│ ├────────────────────────────────────┤
│ │ [▶ Play 8s] [⏸] cursor / dur │
├─────────────────┴────────────────────────────────────┤
│ Name: [clip] Folder: [~] → clip_001.mp4 [Export] │
└──────────────────────────────────────────────────────┘
```
- Drop one or multiple files → all added to the queue
- Clicking a queue item loads it immediately
- `▶` marks the current file
- Auto-advances to next item after a successful export
## Components
### `ProcessedDB`
Wraps `sqlite3`. DB file: `~/.8cut.db`, created on first run.
Table:
```sql
CREATE TABLE IF NOT EXISTS processed (
filename TEXT NOT NULL,
processed_at TEXT NOT NULL
)
```
Methods:
- `add(filename: str)` — inserts row with `filename` and current UTC ISO timestamp
- `find_similar(filename: str) -> str | None` — loads all filenames, iterates with `SequenceMatcher(None, a, b).ratio() >= 0.75`, returns the best-matching stored filename or `None`
### `PlaylistWidget(QListWidget)`
- Accepts file drops (via `dragEnterEvent` / `dropEvent`)
- Emits `file_selected = pyqtSignal(str)` when an item is activated (click or auto-advance)
- `add_files(paths: list[str])` — appends paths, skips duplicates already in the list
- `advance()` — selects the next item; if at end, does nothing (queue exhausted)
- Current item shown with a `▶ ` prefix in the display text; others show bare filename
### `MainWindow` changes
- Drop zone (`dragEnterEvent`/`dropEvent`) now calls `playlist.add_files(paths)` instead of loading directly
- `playlist.file_selected` connected to `_load_file`
- `_after_load`: calls `db.find_similar(os.path.basename(path))` — if match found, shows `"⚠ Similar to already processed: {match}"` in status bar
- `_on_export_done`: calls `db.add(os.path.basename(self._file_path))`, then `self._playlist.advance()`
## Warning behavior
- Warning is informational only — does not block export
- Shown in the existing status bar with a `⚠` prefix
- Shown each time a file is loaded (queue advance or manual click)
## Error handling
- DB connection errors on startup: logged to stderr, app continues without DB (warning feature silently disabled)
- Queue exhaustion (advance past last item): silently does nothing; user can add more files