diff --git a/documentation/TABLEOFCONTENTS.md b/documentation/TABLEOFCONTENTS.md index bb677cb..0d87a7c 100644 --- a/documentation/TABLEOFCONTENTS.md +++ b/documentation/TABLEOFCONTENTS.md @@ -48,7 +48,7 @@ - **qBittorrent integration (torrents)** → [phase3/qbittorrent.md](phase3/qbittorrent.md) - **SABnzbd integration (Usenet/NZB)** → [phase3/sabnzbd.md](phase3/sabnzbd.md) - **File organization, seeding** → [phase3/file-organization.md](phase3/file-organization.md) -- **Chapter merging (PRD, not implemented)** → [features/chapter-merging.md](features/chapter-merging.md) +- **Chapter merging (auto-merge to M4B)** → [features/chapter-merging.md](features/chapter-merging.md) ## Background Jobs - **Bull queue, processors, retry logic** → [backend/services/jobs.md](backend/services/jobs.md) @@ -93,7 +93,7 @@ **"How do I use the unified container?"** → [deployment/unified.md](deployment/unified.md) **"OAuth redirects to localhost / PUBLIC_URL not working"** → [backend/services/environment.md](backend/services/environment.md) **"What environment variables do I need?"** → [backend/services/environment.md](backend/services/environment.md) -**"How does chapter merging work?"** → [features/chapter-merging.md](features/chapter-merging.md) (PRD only, not implemented) +**"How does chapter merging work?"** → [features/chapter-merging.md](features/chapter-merging.md) **"How does Audiobookshelf integration work?"** → [features/audiobookshelf-integration.md](features/audiobookshelf-integration.md) (PRD only, not implemented) **"How do I use OIDC/Authentik/Keycloak?"** → [features/audiobookshelf-integration.md](features/audiobookshelf-integration.md) (PRD only, not implemented) **"How does manual user registration work?"** → [features/audiobookshelf-integration.md](features/audiobookshelf-integration.md) (PRD only, not implemented) diff --git a/documentation/features/chapter-merging.md b/documentation/features/chapter-merging.md index b083419..c344575 100644 --- a/documentation/features/chapter-merging.md +++ b/documentation/features/chapter-merging.md @@ -1,6 +1,6 @@ # Chapter Merging Feature -**Status:** ❌ Not Started | Product Requirements Document +**Status:** ✅ Implemented | Auto-merge multi-file chapters to M4B ## Overview diff --git a/documentation/phase3/ranking-algorithm.md b/documentation/phase3/ranking-algorithm.md index 5d3edc5..565bed2 100644 --- a/documentation/phase3/ranking-algorithm.md +++ b/documentation/phase3/ranking-algorithm.md @@ -6,7 +6,7 @@ Evaluates and scores torrents to automatically select best audiobook download. ## Scoring Criteria (100 points max) -**1. Title/Author Match (50 pts max) - MOST IMPORTANT** +**1. Title/Author Match (60 pts max) - MOST IMPORTANT** **Multi-Stage Matching:** @@ -24,7 +24,7 @@ Evaluates and scores torrents to automatically select best audiobook download. - "Dennis E. Taylor - Bobiverse - 01 - We Are Legion" → 3/3 = 100% → **PASSES** - Prevents wrong series books from matching while handling common subtitle patterns -**Stage 2: Title Matching (0-35 pts)** +**Stage 2: Title Matching (0-45 pts)** - Only scored if Stage 1 passes - **Tries full title first, then required title (without parentheses)** if no match - Example: "We Are Legion (We Are Bob)" tries both full title and "We Are Legion" @@ -35,7 +35,7 @@ Evaluates and scores torrents to automatically select best audiobook download. - Title preceded by metadata separator (` - `, `: `, `—`) — handles "Author - Series - 01 - Title" - Author name appears in prefix — handles "Author Name - Title" - **Acceptable suffix**: Followed by metadata markers: " by", " [", " -", " (", " {", " :", "," or end of string -- Complete match → 35 pts +- Complete match → 45 pts - Unstructured prefix (words without separators) → fuzzy similarity (partial credit) - Prevents: "This Inevitable Ruin Dungeon Crawler Carl" matching "Dungeon Crawler Carl" - Suffix continues with non-metadata → fuzzy similarity (partial credit) @@ -61,12 +61,7 @@ Evaluates and scores torrents to automatically select best audiobook download. **3. Seeder Count (15 pts max)** - Formula: `Math.min(15, Math.log10(seeders + 1) * 6)` - 1 seeder: 0pts, 10 seeders: 6pts, 100 seeders: 12pts, 1000+: 15pts - -**4. Size Reasonableness (10 pts max)** -- Expected: 1-2 MB/min (64-128 kbps) -- Perfect match: 10 pts -- Deviation → penalty -- Unknown duration: 5 pts (neutral) +- Note: Usenet/NZB results without seeders get full 15 pts (centralized availability) ## Bonus Points System @@ -148,7 +143,6 @@ interface RankedTorrent extends TorrentResult { breakdown: { formatScore: number; seederScore: number; - sizeScore: number; matchScore: number; totalScore: number; // Same as score notes: string[]; diff --git a/prisma/migrations/20260108120000_add_chapter_merging_config/migration.sql b/prisma/migrations/20260108120000_add_chapter_merging_config/migration.sql new file mode 100644 index 0000000..be20ab9 --- /dev/null +++ b/prisma/migrations/20260108120000_add_chapter_merging_config/migration.sql @@ -0,0 +1,16 @@ +-- Add chapter merging configuration +-- This allows admin to enable/disable automatic merging of multi-file chapter downloads into single M4B + +-- Insert default configuration for chapter merging (disabled by default) +INSERT INTO configuration (id, key, value, encrypted, category, description, created_at, updated_at) +VALUES ( + gen_random_uuid(), + 'chapter_merging_enabled', + 'false', + false, + 'automation', + 'Automatically merge multi-file chapter downloads into a single M4B audiobook with chapter markers. Improves playback experience and library organization.', + NOW(), + NOW() +) +ON CONFLICT (key) DO NOTHING; diff --git a/src/app/admin/settings/page.tsx b/src/app/admin/settings/page.tsx index 0dd85dc..e938a87 100644 --- a/src/app/admin/settings/page.tsx +++ b/src/app/admin/settings/page.tsx @@ -81,6 +81,7 @@ interface Settings { downloadDir: string; mediaDir: string; metadataTaggingEnabled: boolean; + chapterMergingEnabled: boolean; }; ebook: { enabled: boolean; @@ -1974,6 +1975,37 @@ export default function AdminSettings() { + {/* Chapter Merging Toggle */} +
+
+ { + setSettings({ + ...settings, + paths: { ...settings.paths, chapterMergingEnabled: e.target.checked }, + }); + setValidated({ ...validated, paths: false }); + }} + className="mt-1 h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500" + /> +
+ +

+ Automatically merge multi-file chapter downloads into a single M4B audiobook with chapter + markers. Improves playback experience and library organization. +

+
+
+
+
+ {/* Chapter Merging Toggle */} +
+
+ onUpdate('chapterMergingEnabled', e.target.checked)} + className="mt-1 h-5 w-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500" + /> +
+ +

+ Automatically merge multi-file chapter downloads into a single M4B audiobook with chapter + markers. Improves playback experience and library organization. +

+
+
+
+