MovieMapper/docs/FEATURES.md
Jarian Cottingham 2ce7ab14c9 chore: reorganize repo layout, remove dead files
- 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/)
2026-08-20 20:11:57 +00:00

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 .audit files

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