# Architecture ## Architecture Goals - Keep the tool small, local, and easy to reason about. - Separate media inspection, stored normalization rules, and conversion execution clearly enough that users can inspect and adjust behavior. - Favor explicit local state and deterministic rule application over opaque automation. - Make external runtime dependencies and platform assumptions visible. ## System Context - Primary actors: - Local operator running the CLI. - Local operator using the Textual TUI to inspect files and maintain rules. - External systems: - `ffprobe` for media introspection. - `ffmpeg` for conversion and extraction. - TMDB API for optional show and episode metadata. - Local filesystem for source media, generated outputs, subtitles, logs, config, and database files. - Data entering the system: - Media container and stream metadata from source files. - Regex patterns and per-show normalization rules entered in the TUI. - Optional config values from `~/.local/etc/ffx.json`. - Optional TMDB identifiers and CLI overrides. - Optional external subtitle files. - Data leaving the system: - Normalized output media files. - Extracted stream files from unmux operations. - SQLite rows representing shows, patterns, tracks, tags, shifted seasons, and properties. - Local log output and console messages. ## High-Level Building Blocks - Frontend, CLI, API, or worker: - A Click-based CLI in [`src/ffx/ffx.py`](/home/osgw/.local/src/codex/ffx/src/ffx/ffx.py). - A Textual terminal UI rooted in [`src/ffx/ffx_app.py`](/home/osgw/.local/src/codex/ffx/src/ffx/ffx_app.py) with screens for shows, patterns, file inspection, tracks, tags, and shifted seasons. - Core business logic: - Descriptor objects model media files, shows, and tracks. - Controllers encapsulate CRUD operations and workflow orchestration for shows, patterns, tags, tracks, season shifts, configuration, and conversion. - `MediaDescriptorChangeSet` computes differences between a file and its stored target schema to drive metadata and disposition updates. - Storage: - SQLite via SQLAlchemy ORM, with schema rooted in shows, patterns, tracks, media tags, track tags, shifted seasons, and generic properties. - A configuration JSON file supplies optional path, metadata-filtering, and filename-template settings. - Integration adapters: - Process execution wrapper for `ffmpeg`, `ffprobe`, `nice`, and `cpulimit`. - HTTP adapter for TMDB via `requests`. ## Data And Interface Notes - Key entities or records: - `Show`: canonical TV show metadata plus digit-formatting rules for generated filenames. - `Pattern`: regex rule tying filenames to one show and one target media schema. - `Track` and `TrackTag`: persisted target stream layout, codec, dispositions, audio layout, and stream-level tags. - `MediaTag`: persisted container-level metadata for a pattern. - `ShiftedSeason`: mapping from source numbering ranges to adjusted season and episode numbers. - `Property`: internal key-value storage currently used for database versioning. - External interfaces: - CLI commands for conversion, inspection, extraction, and crop detection. - TUI workflows for rule authoring and rule maintenance. - Environment variable `TMDB_API_KEY` for TMDB access. - Config keys `databasePath`, `logDirectory`, and `outputFilenameTemplate`, plus optional metadata-filter rules. - Validation rules: - Only supported media-file extensions are accepted for conversion. - Stored database version must match the runtime-required version. - A normalized descriptor may have at most one default and one forced stream per relevant track type. - Stored target tracks must refer to valid source tracks of matching types. - Shifted-season ranges are intended not to overlap for the same show and season. - TMDB lookups require a show ID and season and episode numbers. - Error-handling approach: - User-facing operational failures are raised as `click.ClickException` or warnings. - Ambiguous default and forced stream states trigger prompts unless `--no-prompt` is set, in which case the command fails fast. - External-process failures and invalid media are surfaced through logs and command errors rather than retries, except for TMDB rate-limit retries. ## Deployment And Operations - Runtime environment: - Local Python environment with the package installed and `ffmpeg`, `ffprobe`, `nice`, and `cpulimit` available on `PATH`. - Deployment shape: - Single-process command execution on demand; no daemon, queue, or network service of its own. - Secrets and configuration handling: - TMDB secret is read from `TMDB_API_KEY`. - User config is read from `~/.local/etc/ffx.json`. - Database path may also be overridden per command via `--database-file`. - Logging and monitoring approach: - File and console logging configured per invocation. - Default log file path is `~/.local/var/log/ffx.log`. - No dedicated monitoring integration is present. ## Open Technical Questions - Question: Should Linux-specific assumptions such as `/dev/null`, `nice`, `cpulimit`, and `~/.local` remain part of the supported-platform contract? - Risk: Portability and operational behavior are underspecified for non-Linux environments. - Next decision needed: Either document Linux-like systems as the official support boundary or refactor the process and path handling for broader portability. - Question: Should placeholder TUI surfaces such as settings and help become part of the required product surface or stay explicitly out of scope? - Risk: The UI appears broader than the actually finished feature set. - Next decision needed: Either remove or complete placeholder screens and update requirements accordingly.