Files
ffx/requirements/architecture.md
2026-04-12 17:12:32 +02:00

6.3 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:
    • 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/cli.py, exposed as the ffx command and via python -m ffx, including lightweight maintenance wrappers for bundle setup, workstation preparation, and upgrade tasks.
    • A Textual terminal UI rooted in 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.
    • File inspection caches combined ffprobe data and crop-detection results per source and sampling window within one process to avoid repeated subprocess work.
  • 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, with explicit disabled states for niceness and CPU limiting, support for both absolute cpulimit values and machine-wide percent input, and a combined cpulimit -- nice -n ... <command> execution shape when both limits are configured.
    • 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 records, codec, dispositions, audio layout, and stream-level tags. Detailed source-to-target mapping rules live in requirements/subtrack_mapping.md.
    • MediaTag: persisted container-level metadata for a pattern.
    • ShiftedSeason: mapping from source numbering ranges to adjusted season and episode numbers, owned either by a show as fallback or by a pattern as override.
    • 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.
    • Shifted-season ranges are intended not to overlap within the same owner scope and season, and runtime resolution prefers pattern-owned matches over show-owned matches.
    • 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.