mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 04:40:09 +00:00
ef98dcf438
Previously, files were always being copied to /media/audiobooks regardless of the configured media directory in settings. This was caused by: 1. FileOrganizer singleton reading from MEDIA_DIR env var (never set) instead of database config 'media_dir' 2. Hardcoded /media/audiobooks fallback being used when env var not found 3. Three locations passing hardcoded paths to addOrganizeJob (unused) Changes: - Modified getFileOrganizer() to read media_dir from database config - Made targetPath parameter optional in addOrganizeJob (not used by processor) - Removed hardcoded /media/audiobooks paths from all addOrganizeJob calls - Updated organize-files processor to await getFileOrganizer() - Updated documentation to reflect configuration behavior Files now correctly copy to the directory configured in setup wizard or settings page, with /media/audiobooks only as fallback if not configured. Fixes: User-reported issue where configured media directory was ignored
137 lines
4.5 KiB
Markdown
137 lines
4.5 KiB
Markdown
# File Organization System
|
|
|
|
**Status:** ✅ Implemented
|
|
|
|
Copies completed downloads to standardized directory structure for Plex. Automatically tags audio files with correct metadata. Originals kept for seeding, cleaned up by scheduled job after requirements met.
|
|
|
|
## Target Structure
|
|
|
|
Target directory read from database config `media_dir` (configurable in setup wizard and settings).
|
|
|
|
```
|
|
[media_dir]/
|
|
└── Author Name/
|
|
└── Book Title (Year)/
|
|
├── Book Title.m4b
|
|
└── cover.jpg
|
|
```
|
|
|
|
Default: `/media/audiobooks/` (if not configured)
|
|
|
|
## Process
|
|
|
|
1. Download completes in `/downloads/[torrent-name]/` or `/downloads/[filename]` (single file)
|
|
2. Identify audiobook files (.m4b, .m4a, .mp3) - supports both directories and single files
|
|
3. Read media directory from database config `media_dir`
|
|
4. Create `[media_dir]/[Author]/[Title]/`
|
|
5. **Copy** files (not move - originals stay for seeding)
|
|
6. **Tag metadata** (if enabled) - writes correct title, author, narrator to audio files
|
|
7. Copy cover art if found, else download from Audible
|
|
8. Originals remain until seeding requirements met
|
|
|
|
## Metadata Tagging
|
|
|
|
**Status:** ✅ Implemented
|
|
|
|
**Purpose:** Automatically writes correct metadata to audio files during file organization to improve Plex matching accuracy.
|
|
|
|
**Supported Formats:**
|
|
- m4b, m4a, mp4 (AAC audiobooks)
|
|
- mp3 (ID3v2 tags)
|
|
|
|
**Metadata Written:**
|
|
- `title` - Book title
|
|
- `album` - Book title (PRIMARY field for Plex matching)
|
|
- `album_artist` - Author (PRIMARY field for Plex matching)
|
|
- `artist` - Author (fallback)
|
|
- `composer` - Narrator (standard audiobook field)
|
|
- `date` - Year
|
|
|
|
**Configuration:**
|
|
- Key: `metadata_tagging_enabled` (Configuration table)
|
|
- Default: `true`
|
|
- Configurable in: Setup wizard (Paths step), Admin settings (Paths tab)
|
|
|
|
**Implementation:**
|
|
- Uses ffmpeg with `-codec copy` (no re-encoding, metadata only)
|
|
- Fast (no audio transcoding)
|
|
- Lossless (original audio preserved)
|
|
- Runs after file copy, before cover art download
|
|
- Non-blocking (errors don't fail file organization)
|
|
- Logs success/failure per file
|
|
|
|
**Benefits:**
|
|
- Fixes torrents with missing/incorrect metadata
|
|
- Ensures Plex can match audiobooks correctly
|
|
- Writes metadata from Audible/Audnexus (known accurate)
|
|
- Prevents "[Various Albums]" and other metadata issues
|
|
|
|
**Tech Stack:**
|
|
- ffmpeg (system dependency - included in Docker image)
|
|
- `src/lib/utils/metadata-tagger.ts` - Tagging utility
|
|
- Integrated into `src/lib/utils/file-organizer.ts`
|
|
|
|
**Requirements:**
|
|
- ffmpeg must be installed in the container
|
|
- **Multi-container setup** (`Dockerfile`): Added at line 56 via `apk add ffmpeg`
|
|
- **Unified setup** (`dockerfile.unified`): Added at line 16 via `apt-get install ffmpeg`
|
|
- **Verify installation:**
|
|
- Multi-container: `docker exec readmeabook ffmpeg -version`
|
|
- Unified: `docker exec readmeabook-unified ffmpeg -version`
|
|
|
|
## Seeding Support
|
|
|
|
**Config:** `seeding_time_minutes` (0 = unlimited, never cleanup)
|
|
|
|
**Cleanup Job:** `cleanup_seeded_torrents` (every 30 mins)
|
|
1. Check 'available' and 'downloaded' status requests with download history
|
|
2. Query qBittorrent for actual `seeding_time` field
|
|
3. Delete torrent + files only after requirement met
|
|
4. Respects config (0 = never cleanup)
|
|
|
|
## Interface
|
|
|
|
```typescript
|
|
interface OrganizationResult {
|
|
success: boolean;
|
|
targetPath: string;
|
|
filesMovedCount: number;
|
|
errors: string[];
|
|
audioFiles: string[];
|
|
coverArtFile?: string;
|
|
}
|
|
|
|
async function organize(
|
|
downloadPath: string,
|
|
audiobook: {title: string, author: string, year?: number, coverArtUrl?: string}
|
|
): Promise<OrganizationResult>;
|
|
```
|
|
|
|
## Path Sanitization
|
|
|
|
- Remove invalid chars: `<>:"/\|?*`
|
|
- Trim dots/spaces
|
|
- Collapse multiple spaces
|
|
- Limit to 200 chars
|
|
- Example: `Author: The <Best>! Book?` → `Author The Best! Book`
|
|
|
|
## Configuration
|
|
|
|
- **Media directory:** Read from database config key `media_dir` (set in setup wizard or settings)
|
|
- **Fallback:** `/media/audiobooks` if not configured
|
|
- **Temp directory:** `/tmp/readmeabook` (or `TEMP_DIR` env var)
|
|
|
|
## Fixed Issues ✅
|
|
|
|
**1. EPERM errors** - Fixed with `fs.readFile/writeFile` instead of `copyFile`
|
|
**2. Immediate deletion** - Changed to copy-only, scheduled cleanup after seeding
|
|
**3. Files moved not copied** - Now copies to support seeding
|
|
**4. Single file downloads** - Now supports files directly in downloads folder (not just directories)
|
|
**5. Hardcoded media path** - Now reads `media_dir` from database config instead of hardcoded `/media/audiobooks`
|
|
|
|
## Tech Stack
|
|
|
|
- Node.js `fs/promises`
|
|
- `path` module
|
|
- axios (cover art download)
|