iteration1
This commit is contained in:
198
requirements/metadata_editor.md
Normal file
198
requirements/metadata_editor.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Metadata Editor
|
||||
|
||||
This file defines the requirements for a database-free interactive metadata
|
||||
editor command derived from the current file-inspection UI.
|
||||
|
||||
Feasibility from the current codebase: yes, with a moderate refactor.
|
||||
|
||||
The strongest reusable pieces already exist:
|
||||
|
||||
- `ffprobe`-backed media probing through `FileProperties` and `MediaDescriptor`
|
||||
- descriptor-level metadata and disposition mutation through `MediaDescriptor`
|
||||
and `TrackDescriptor`
|
||||
- diff and ffmpeg token generation through `MediaDescriptorChangeSet`
|
||||
- stream-copy remux execution through `FfxController` with `VideoEncoder.COPY`
|
||||
- reusable tag and track edit dialogs in the Textual UI
|
||||
|
||||
The main missing pieces are:
|
||||
|
||||
- a CLI bootstrap path that does not initialize SQLite
|
||||
- a probe-only path that does not instantiate database-backed controllers
|
||||
- a clean separation between original file state and editable draft state
|
||||
- a safe temporary-output and replace workflow for writing changes back to the
|
||||
same file path
|
||||
|
||||
## Scope
|
||||
|
||||
- One new command: `ffx edit <file>`
|
||||
- One-file interactive editing through a Textual screen derived from
|
||||
`MediaDetailsScreen`
|
||||
- Editing container-level metadata and per-stream metadata already visible in
|
||||
the application
|
||||
- Editing stream dispositions that are represented as metadata-like output
|
||||
state, especially `default` and `forced`
|
||||
- Writing the result back to the original file path through a temporary output
|
||||
file and replace step
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- SQLite reads, writes, migrations, or pattern matching
|
||||
- TMDB lookups, show selection, pattern selection, or shifted-season logic
|
||||
- Batch editing multiple files in one command invocation
|
||||
- Video or audio transcoding
|
||||
- Container changes, filename changes, or rename workflows
|
||||
- Stream add, stream delete, stream reorder, or stream substitution from
|
||||
external files in the first release
|
||||
- Editing technical stream identity such as codec, stream type, source index,
|
||||
or audio layout in the first release
|
||||
- Chapter editing
|
||||
|
||||
## Terms
|
||||
|
||||
- `baseline descriptor`: immutable in-memory representation of the file as last
|
||||
probed from disk
|
||||
- `draft descriptor`: mutable in-memory representation of the desired output
|
||||
state
|
||||
- `edit mode`: the database-free TUI mode used by `ffx edit`
|
||||
- `planned changes`: user-visible summary of the differences between baseline
|
||||
and draft plus any configured cleanup actions
|
||||
- `temporary output file`: the write target used before replacing the original
|
||||
file path
|
||||
|
||||
## Rules
|
||||
|
||||
- `METADATA_EDITOR-0001`: The system shall provide a command `ffx edit <file>`
|
||||
that requires exactly one existing media file path and opens an interactive
|
||||
Textual editor for that file.
|
||||
- `METADATA_EDITOR-0002`: `ffx edit` shall not initialize SQLite, shall not
|
||||
open the configured database file, shall not prompt for database migration,
|
||||
and shall not instantiate any controller that depends on `context['database']`.
|
||||
- `METADATA_EDITOR-0003`: `ffx edit` may still read configuration and logging
|
||||
settings from `~/.local/etc/ffx.json`, but any global database option shall
|
||||
have no effect on this command's behavior.
|
||||
- `METADATA_EDITOR-0004`: Edit mode shall be derived from the current
|
||||
`MediaDetailsScreen` behavior and layout where practical, but all DB-only UI
|
||||
elements and actions such as show selection, pattern input, and pattern CRUD
|
||||
actions shall be hidden, disabled, or replaced.
|
||||
- `METADATA_EDITOR-0005`: Edit mode shall keep the baseline descriptor and the
|
||||
draft descriptor as separate objects. Editing actions shall mutate only the
|
||||
draft descriptor until the operator explicitly applies changes.
|
||||
- `METADATA_EDITOR-0006`: The application shall keep raw metadata values
|
||||
separate from rendered labels. Rich or Textual markup may be used for
|
||||
presentation, but it shall never be stored in descriptor state, reused as
|
||||
source data, or written into the media file.
|
||||
- `METADATA_EDITOR-0007`: The planned-changes view shall compare the baseline
|
||||
descriptor with the draft descriptor using `MediaDescriptorChangeSet` or an
|
||||
equivalent descriptor-diff mechanism. It shall no longer mean `file -> db`.
|
||||
- `METADATA_EDITOR-0008`: The editor shall support container-tag add, edit, and
|
||||
delete operations on the draft descriptor.
|
||||
- `METADATA_EDITOR-0009`: The editor shall support per-stream metadata edit
|
||||
operations on the draft descriptor, including at least language, title, and
|
||||
arbitrary stream tag key-value pairs.
|
||||
- `METADATA_EDITOR-0010`: The editor shall support setting and clearing
|
||||
`default` and `forced` dispositions in the draft descriptor, while enforcing
|
||||
that there is at most one `default` and at most one `forced` stream per track
|
||||
type.
|
||||
- `METADATA_EDITOR-0011`: The first released editor scope shall treat technical
|
||||
stream structure as immutable. A user shall not be able to change stream
|
||||
count, output order, codec, track type, audio layout, or source-index
|
||||
mapping through `ffx edit`.
|
||||
- `METADATA_EDITOR-0012`: The track-edit UI used in edit mode shall therefore
|
||||
expose only metadata fields and supported disposition fields. Structural
|
||||
fields that are editable in pattern-authoring workflows shall be read-only or
|
||||
absent in edit mode.
|
||||
- `METADATA_EDITOR-0013`: The command shall write changes through an ffmpeg
|
||||
stream-copy remux workflow only. No transcoding shall be performed as part of
|
||||
`ffx edit`.
|
||||
- `METADATA_EDITOR-0014`: Because ffmpeg cannot rewrite the source file in
|
||||
place, `ffx edit` shall write to a temporary output file on the same
|
||||
filesystem as the source file and shall replace the original path only after
|
||||
ffmpeg reports success.
|
||||
- `METADATA_EDITOR-0015`: The temporary output path shall preserve the original
|
||||
container type and file extension. The feature shall not silently change the
|
||||
container or extension during a metadata-only edit.
|
||||
- `METADATA_EDITOR-0016`: If the rewrite step fails, the original file shall
|
||||
remain untouched. The system shall not leave the user with a partially
|
||||
replaced source file.
|
||||
- `METADATA_EDITOR-0017`: After a successful replace, the application shall
|
||||
reprobe the rewritten file, refresh the baseline descriptor from disk, reset
|
||||
the draft state to that fresh baseline, and clear the dirty state.
|
||||
- `METADATA_EDITOR-0018`: Edit mode shall track whether unsaved draft changes
|
||||
exist and shall require confirmation before dismissing the screen or quitting
|
||||
the app when such changes would be lost.
|
||||
- `METADATA_EDITOR-0019`: Edit mode shall not inject conversion-only encoding
|
||||
metadata such as encoder quality or preset markers.
|
||||
- `METADATA_EDITOR-0020`: Signature-tag behavior shall be explicit for
|
||||
metadata-only editing. The default behavior shall not add a misleading
|
||||
recoding-style signature to a file that was only remuxed for metadata
|
||||
updates.
|
||||
- `METADATA_EDITOR-0021`: Configured metadata-removal rules from the local
|
||||
configuration shall be surfaced clearly in the UI and in the planned-changes
|
||||
view. If those rules are applied during save, the operator shall be able to
|
||||
tell that the file will be cleaned in addition to any manual edits.
|
||||
- `METADATA_EDITOR-0022`: The command shall provide an invocation-level way to
|
||||
disable config-driven cleanup when the operator wants a pure manual metadata
|
||||
edit without automatic tag removal.
|
||||
- `METADATA_EDITOR-0023`: The existing global `--dry-run` behavior shall apply
|
||||
to `ffx edit`. In dry-run mode the command shall not replace the original
|
||||
file and shall expose the planned write operation clearly enough for the user
|
||||
to understand what would happen.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- `ffx edit /path/to/file.mkv` opens successfully on a workstation where the
|
||||
configured database is missing, empty, incompatible, or intentionally
|
||||
inaccessible.
|
||||
- Opening a file in edit mode does not trigger database bootstrap or migration
|
||||
prompts.
|
||||
- A user can change a container tag, save, and see the rewritten file at the
|
||||
same path with the updated metadata.
|
||||
- A user can change a stream title or language, save, and see the rewritten
|
||||
file at the same path with the updated stream metadata.
|
||||
- A user can change `default` or `forced` on a track, save, and see the
|
||||
rewritten file at the same path with the updated dispositions.
|
||||
- The planned-changes view reflects manual edits relative to the original file
|
||||
and, when enabled, any configured cleanup removals.
|
||||
- No rendered Rich or Textual color markup appears in the saved file metadata.
|
||||
- If ffmpeg fails while saving, the original file remains present and readable
|
||||
at the original path.
|
||||
- In dry-run mode, the original file remains untouched.
|
||||
|
||||
## Current Code Fit
|
||||
|
||||
- Good fit:
|
||||
- `FfxController.runJob(...)` already has a `VideoEncoder.COPY` path that
|
||||
can remux streams and apply metadata and disposition tokens.
|
||||
- `MediaDescriptorChangeSet` already computes container-tag, stream-tag, and
|
||||
disposition differences and can generate ffmpeg metadata tokens.
|
||||
- `TagDetailsScreen` and `TrackDetailsScreen` already provide reusable edit
|
||||
dialogs for draft state.
|
||||
- `PatternDetailsScreen` already demonstrates add, edit, and delete flows for
|
||||
tags and tracks in a draft-first UI.
|
||||
- Refactor required:
|
||||
- `ffx` CLI initialization currently creates a database context for all
|
||||
non-lightweight commands, so `edit` needs its own DB-free bootstrap path.
|
||||
- `FileProperties` currently instantiates `PatternController` eagerly, so
|
||||
probing must be split from pattern matching or made lazy.
|
||||
- `MediaDetailsScreen` currently assumes `command == 'inspect'` and mixes
|
||||
file state with database-backed target-pattern state.
|
||||
- `MediaDetailsScreen` currently mutates the probed source descriptor
|
||||
directly. Edit mode needs an immutable baseline descriptor and a separate
|
||||
mutable draft descriptor.
|
||||
- `TrackDetailsScreen` currently exposes structural fields that are valid for
|
||||
pattern authoring but too dangerous for metadata-only file editing.
|
||||
|
||||
## Risks
|
||||
|
||||
- Container-level metadata support differs across formats, so some requested tag
|
||||
changes may not round-trip identically through ffmpeg for every supported
|
||||
container.
|
||||
- The existing metadata-removal implementation is conversion-oriented and may
|
||||
remove tags more aggressively than a user expects from a manual editor unless
|
||||
cleanup policy is made explicit.
|
||||
- The current codebase lacks a dedicated descriptor clone API, so draft-state
|
||||
separation should be implemented deliberately instead of via accidental shared
|
||||
references.
|
||||
- Replacing a file path with a temporary output changes inode identity, so any
|
||||
future requirement around preserving timestamps, hard links, or extended
|
||||
attributes would need additional explicit handling.
|
||||
Reference in New Issue
Block a user