7.1 KiB
Project Context & System Architecture Blueprint
Repository: qbittorrent-performer-sorter
Gitea Remote: http://truenas.local:30008/david/qbittorrent-performer-sorter.git
Working Workspace: /home/david & /home/david/github/qbittorrent-performer-sorter
Primary App Port: 8000 (http://localhost:8000)
Stash GraphQL Endpoint: http://servervm.local:9999/graphql (Internal /data maps to /mnt/isolation/videos)
1. Executive Summary & Purpose
This application is a unified web-based media organizer, AI intelligence engine, video stream previewer, and Stash media server control center. It bridges qBittorrent, local/SMB filesystem storage (TrueNAS), and Stash GraphQL API to provide automated performer sorting, duplicate scene analysis, Stash database tag/performer normalization, and transcode optimization.
2. Key Architecture & File Structure
qbittorrent-performer-sorter/
├── server.py # Python 3 standard-library HTTP & API server
├── qbittorrent_performer_sorter.html # Single-Page Application (HTML5, Vanilla JS, CSS3)
├── mount_isolation.sh # Auto-mount helper script for TrueNAS SMB shares
├── performer_sorter.db # SQLite persistent caching & audit log database
├── README.md # Quick start and feature overview
└── CONTEXT.md # LLM Session Save Point & Deep Architecture Spec
Zero-Dependency Python Architecture
server.py relies exclusively on Python standard library modules (http.server, socketserver, sqlite3, urllib.request, urllib.parse, json, re, os, shutil, threading, time, mimetypes). No external pip dependencies are required.
3. UI Tab Layout & Feature Modules
-
Tab 1: 📡 qBittorrent Sorter
- Direct integration with qBittorrent WebUI (
/qb-proxy/api/v2/...). - Analyzes torrent files, multi-file torrent hierarchies, and moves seeding torrents using
torrents/setLocationwithout breaking active seeding. - AI performer parsing with multi-candidate pill selectors.
- Direct integration with qBittorrent WebUI (
-
Tab 2: 📂 SMB Video Sorter
- Direct filesystem scanner for TrueNAS video shares (
/mnt/isolation/videos/videodownloader&/mnt/isolation/videos/unsorted). - Categorizes, cleans filenames, and relocates files to performer destination folders (
/mnt/isolation/videos/<performer>/). - Automatic SMB auto-mount detection and auto-recovery.
- Direct filesystem scanner for TrueNAS video shares (
-
Tab 3: 🖼️ Stash Image Review
- Performer avatar manager, gallery browser, and quick-tagging studio.
- Hover cards and image zoom preview modals.
-
Tab 4: 📜 Relocation History & Analytics
- Persistent SQLite audit log tracking moves, size changes, timestamps, and performer classifications.
- One-click rollback and undo support.
-
Tab 5: ⚡ Stash Tasks & Tool Control
- Section A: 👥 Performer Merge & Deduplication Studio: Scans fuzzy and punctuation duplicate performer profiles (
cory.chasevsCory Chase) and merges them via Stash GraphQLperformerMerge. Includes 1-Click Batch Merge All. - Section B: 📡 Missing Metadata Radar: Scans scenes lacking studios, performers, or tags with quick autotag triggers.
- Section C: 🏷️ Tag Normalizer & Deduplication: Identifies tag casing/alias duplicates and merges them via
tagsMerge. Includes 1-Click Batch Merge All. - Section D: 🔀 Stash Transcode Correlator & Storage Saver:
- Scans generated transcodes in
/mnt/isolation/stashapp/generated/transcodes/. - Matches OSHash filenames against Stash library database paths.
- Side-by-side 🎬 Orig vs ⚡ Transcode in-browser video streaming comparisons.
- True physical storage savings metrics (
\text{Freed} = \text{Original File Size}). - Atomic replacement: Staging copy
\tosize validation\toos.replace\tocache deletion\tobackground directory metadata rescan. - Embedded Real-Time Live Execution Terminal Console (
#transcode-terminal-wrapper) with auto-scroll and status monitoring.
- Scans generated transcodes in
- Section E: 🔍 Duplicate Scene Comparator & Plugin Hub:
- Visual side-by-side comparison of duplicate scenes with resolution/codec/bitrate badges and stream previews.
- Direct triggers for Stash plugins (
DupFileManager,phashDuplicateTagger).
- Section F: ⚡ Task Manager:
- Live polling of active/queued background Stash jobs (
findJobStatus). - Library Scan, Identify/Auto-tag, Clean, and Generate task starters with instant job cancellation (
stopJob/stopAllJobs).
- Live polling of active/queued background Stash jobs (
- Section A: 👥 Performer Merge & Deduplication Studio: Scans fuzzy and punctuation duplicate performer profiles (
4. Path Mapping & Filesystem Translation Rules
| Context | Stash Container Path | Local TrueNAS Mount Path |
|---|---|---|
| Main Videos Share | /data/... |
/mnt/isolation/videos/... |
| Generated Transcodes | /generated/transcodes/... or /media/stashapp/generated/... |
/mnt/isolation/stashapp/generated/transcodes/... |
| Download Incomplete | /downloads/... |
/mnt/isolation/incomplete/... or /mnt/isolation/videos/unsorted/... |
Streaming Path Translation (resolve_stream_video_path in server.py)
- Accepts any Stash GraphQL path (e.g.
/data/performer/scene.mp4) or local path and resolves to the actual local mount path on disk before serving HTTP 206 partial content chunks.
5. GraphQL Mutation Conventions (Stash v0.31+ Compliance)
Stash v0.31+ strict GraphQL schema rejects variable declarations in mutations with HTTP 422: GRAPHQL_PARSE_FAILED.
Standard: All mutations must be constructed using build_stash_mutation(mutation_name, input_obj, fields):
- Keys are unquoted in GraphQL literals.
- String filters like
performers,studios,tagsinmetadataAutoTagrequire string array filters (e.g.["*"]).
6. Database Schema (performer_sorter.db)
ai_cache Table
item_key(TEXT PRIMARY KEY) - Torrent hash or SMB file path.item_name(TEXT)performer_result(TEXT) - Primary chosen performer slug.candidates_json(TEXT) - JSON list of multi-performer candidate names.source_type(TEXT) -'qb'or'smb'.move_status(TEXT) -'unmoved'or'moved'.target_path(TEXT)updated_at(TIMESTAMP)
relocation_history Table
id(INTEGER PRIMARY KEY AUTOINCREMENT)source_type(TEXT) -'qb','smb', or'stash_transcode'.item_key(TEXT)item_name(TEXT)source_path(TEXT)target_path(TEXT)performer(TEXT)file_size(INTEGER)timestamp(TIMESTAMP)
7. Operational Guidelines for Future AI Sessions
- Syncing Changes: Always ensure modifications to
server.pyandqbittorrent_performer_sorter.htmlin/home/davidare mirrored to/home/david/github/qbittorrent-performer-sorter, committed with semantic messages, and pushed tohttp://truenas.local:30008/david/qbittorrent-performer-sorter.git. - Standard Library Integrity: Keep
server.pyfree of external pip packages. - HTTP Range 206 Streaming: Maintain HTTP Range handling in
handle_stream_videofor smooth seeking in the web player. - Safety Verification in File Ops: Always maintain atomic staging (
.tmp\toverify size\toos.replace) when modifying or replacing media files.