5.9 KiB
5.9 KiB
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:
ffprobefor media introspection.ffmpegfor 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/cli.py, exposed as theffxcommand and viapython -m ffx. - A Textual terminal UI rooted in
src/ffx/ffx_app.pywith screens for shows, patterns, file inspection, tracks, tags, and shifted seasons.
- A Click-based CLI in
- 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.
MediaDescriptorChangeSetcomputes 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, andcpulimit, with explicit disabled states for niceness and CPU limiting and a combinedcpulimit -- nice -n ... <command>execution shape when both limits are configured. - HTTP adapter for TMDB via
requests.
- Process execution wrapper for
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.TrackandTrackTag: persisted target stream records, codec, dispositions, audio layout, and stream-level tags. Detailed source-to-target mapping rules live inrequirements/subtrack_mapping.md.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_KEYfor TMDB access. - Config keys
databasePath,logDirectory, andoutputFilenameTemplate, 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.
- 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.ClickExceptionor warnings. - Ambiguous default and forced stream states trigger prompts unless
--no-promptis 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.
- User-facing operational failures are raised as
Deployment And Operations
- Runtime environment:
- Local Python environment with the package installed and
ffmpeg,ffprobe,nice, andcpulimitavailable onPATH.
- Local Python environment with the package installed and
- 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.
- TMDB secret is read from
- 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~/.localremain 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.