- Move phase/plan docs into docs/ - Move legacy node:test files into tests/legacy/ with README - Remove .backup file, test audit artifacts, and unused AI prompt/skill files - Remove broken iOS GitHub workflows (reference missing MovieMapper-iOS/)
8.3 KiB
MovieMapper Feature Specification
Project Overview
A desktop application for organizing and managing movie and TV show collections with intelligent file mapping using TheTVDB API.
Current State
- Electron-based application (v40.4.1)
- TheTVDB v4 API integration with bearer token authentication
- FFmpeg-based media file metadata extraction
- Basic file renaming and directory navigation
- Audit logging to
.auditfiles
Target Architecture
- Main Process: Rust backend with Node.js Electron bridge
- Renderer Process: Electron web UI (unchanged)
- Performance: Native Rust for CPU-intensive operations
Core Features
1. Directory Scanning (Rust Implementation)
Priority: High Status: Current - Node.js, Target - Rust
Requirements:
- Non-recursive directory scanning
- Media file detection (mp4, mkv, avi, mov, flv, webm)
- FFmpeg metadata extraction (duration, quality, FPS)
- Progress callback support for UI updates
- Permission error handling
API:
pub struct FileMetadata {
pub path: String,
pub name: String,
pub size: u64,
pub modified: SystemTime,
pub duration: String,
pub quality: String,
pub fps: String,
pub is_folder: bool,
}
pub fn scan_directory(
directory_path: &str,
progress_callback: Option<Box<dyn Fn(u32, u32, &str) + Send>>
) -> Result<Vec<FileMetadata>, ScanError>;
2. FFmpeg Integration (Rust Implementation)
Priority: High Status: Current - fluent-ffmpeg, Target - ffmpeg-kit or rust-ffmpeg
Requirements:
- ffprobe for metadata extraction
- Duration calculation (mm:ss format)
- Video quality detection (4K, 1440p, 1080p, 720p, 480p)
- Frame rate extraction
- Graceful error handling for corrupted files
API:
pub struct VideoStreamInfo {
pub width: u32,
pub height: u32,
pub codec: String,
pub frame_rate: f64,
}
pub struct AudioStreamInfo {
pub codec: String,
pub channels: u32,
pub sample_rate: u32,
}
pub struct MediaInfo {
pub duration: f64, // seconds
pub format: String,
pub video_streams: Vec<VideoStreamInfo>,
pub audio_streams: Vec<AudioStreamInfo>,
}
pub fn probe_file(path: &str) -> Result<MediaInfo, ProbeError>;
3. TheTVDB API Integration (Rust Implementation)
Priority: High Status: Current - axios, Target - reqwest with async/await
Requirements:
- TVDB v4 API authentication (apikey → token)
- Show search with query
- Show details with seasons
- Episode listing per season
- Token caching (30-day validity)
- Rate limiting handling
API:
pub struct Show {
pub id: u64,
pub name: String,
pub status: Option<String>,
pub first_aired: Option<String>,
pub overview: Option<String>,
pub image: Option<String>,
pub slug: Option<String>,
}
pub struct Season {
pub id: u64,
pub number: u32,
pub episode_count: u32,
}
pub struct Episode {
pub id: u64,
pub name: String,
pub number: u32,
pub season_number: u32,
pub aired: Option<String>,
pub overview: Option<String>,
}
pub struct TVDBClient {
token: Option<String>,
api_key: String,
}
impl TVDBClient {
pub fn new(api_key: String) -> Self;
pub async fn search(&self, query: &str) -> Result<Vec<Show>, TVDBError>;
pub async fn get_show_details(&self, show_id: u64) -> Result<Show, TVDBError>;
pub async fn get_seasons(&self, show_id: u64) -> Result<Vec<Season>, TVDBError>;
pub async fn get_episodes(&self, show_id: u64, season_number: u32) -> Result<Vec<Episode>, TVDBError>;
}
4. File Operations (Rust Implementation)
Priority: High Status: Current - Node.js fs, Target - std::fs + tokio
Requirements:
- File renaming with atomic operations
- Directory creation (recursive)
- File movement to folder (extras, commentary, etc.)
- Audit log writing
- Conflict detection (duplicate files)
API:
pub struct AuditLogEntry {
pub timestamp: String,
pub action: AuditAction,
pub details: HashMap<String, String>,
}
pub enum AuditAction {
RenameFile { old_path: String, new_path: String },
MoveFile { original_path: String, new_path: String, folder: String },
}
pub struct FileManager {
base_path: String,
}
impl FileManager {
pub fn new(base_path: &str) -> Self;
pub async fn rename_file(&self, old_path: &str, new_name: &str) -> Result<(), FileError>;
pub async fn move_to_folder(&self, file_path: &str, folder_name: &str) -> Result<String, FileError>;
pub async fn write_audit_log(&self, action: AuditAction) -> Result<(), FileError>;
}
5. File Mapping/Batch Rename (Rust Implementation)
Priority: High Status: Current - Node.js, Target - Rust
Requirements:
- Parse show name from folder
- Extract season number (multiple formats: "Season 01", "S01", etc.)
- Map files to episodes using TVDB data
- Handle single episodes and episode ranges (1-3)
- Quality suffix support
- Folder naming with TVDB ID
API:
pub struct EpisodeMapping {
pub show_name: String,
pub season_number: u32,
pub episodes: Vec<EpisodeRange>,
pub quality: Option<String>,
}
pub struct EpisodeRange {
pub start: u32,
pub end: u32,
}
pub struct MappingResult {
pub success_count: u32,
pub error_count: u32,
pub renamed_files: Vec<String>,
}
pub async fn begin_mapping(
directory: &str,
files: Vec<MediaFile>,
tvdb_id: u64,
client: &TVDBClient
) -> Result<MappingResult, MappingError>;
6. IPC Bridge (Rust Implementation)
Priority: Medium Status: Current - Direct ipcMain/handle, Target - Node.js addon or IPC socket
Requirements:
- Node.js native addon or IPC interface
- Async message handling
- Progress event streaming
- Error propagation
API:
#[repr(C)]
pub struct IpcMessage {
pub channel: *const c_char,
pub data: *const c_char,
}
pub type IpcCallback = extern "C" fn(channel: *const c_char, data: *const c_char);
#[no_mangle]
pub extern "C" fn init_ipc(callback: IpcCallback);
#[no_mangle]
pub extern "C" fn handle_request(channel: *const c_char, data: *const c_char) -> *const c_char;
Implementation Phases
Phase 1: Core Foundation (Weeks 1-2)
- Set up Rust project structure
- Implement FileMetadata and scan_directory
- Integrate FFmpeg for metadata extraction
- Create basic error types
- Write unit tests for core utilities
Phase 2: API Integration (Weeks 2-3)
- Implement TVDBClient with authentication
- Add show search functionality
- Implement show details and episode fetching
- Add token caching mechanism
- Write integration tests
Phase 3: File Operations (Weeks 3-4)
- Implement FileManager with async operations
- Add audit logging
- Implement file movement and renaming
- Add conflict detection
- Write integration tests
Phase 4: File Mapping (Weeks 4-5)
- Implement begin_mapping logic
- Add episode range handling
- Implement quality suffix logic
- Add folder naming with TVDB ID
- Write integration tests
Phase 5: IPC Bridge (Weeks 5-6)
- Create Node.js native addon
- Implement message handling
- Add progress streaming
- Handle async callbacks
- Write integration tests
Phase 6: Testing & Documentation (Weeks 6-7)
- Comprehensive integration tests
- Performance benchmarks
- Documentation
- Migration guide
Technical Decisions
FFmpeg Integration
Option A: ffmpeg-kit (prebuilt binaries)
- Pros: Easy setup, cross-platform
- Cons: Larger binary size
Option B: rust-ffmpeg (FFmpeg C bindings)
- Pros: Full control, smaller binary
- Cons: Build complexity, dependency management
Decision: ffmpeg-kit for rapid development and reliability
Async Runtime
- tokio for async operations
- Standard library for sync operations
- Cross-platform async file I/O
Error Handling
- Custom error types with meaningful messages
- Consistent error propagation
- Detailed logging for debugging
Testing Strategy
- Unit tests for pure functions
- Integration tests for file operations
- Mock TVDB API for API tests
- Benchmark tests for performance-critical paths
Success Criteria
- All features work identically to Node.js version
- Performance improvement for large directories
- Memory usage below Node.js baseline
- No crashes or memory leaks
- All tests passing
- Documentation complete