10 KiB
10 KiB
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 throughFilePropertiesandMediaDescriptor- descriptor-level metadata and disposition mutation through
MediaDescriptorandTrackDescriptor - diff and ffmpeg token generation through
MediaDescriptorChangeSet - stream-copy remux execution through
FfxControllerwithVideoEncoder.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
defaultandforced - 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 diskdraft descriptor: mutable in-memory representation of the desired output stateedit mode: the database-free TUI mode used byffx editplanned changes: user-visible summary of the differences between baseline and draft plus any configured cleanup actionstemporary output file: the write target used before replacing the original file path
Rules
METADATA_EDITOR-0001: The system shall provide a commandffx edit <file>that requires exactly one existing media file path and opens an interactive Textual editor for that file.METADATA_EDITOR-0002:ffx editshall not initialize SQLite, shall not open the configured database file, shall not prompt for database migration, and shall not instantiate any controller that depends oncontext['database'].METADATA_EDITOR-0003:ffx editmay 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 currentMediaDetailsScreenbehavior 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 usingMediaDescriptorChangeSetor an equivalent descriptor-diff mechanism. It shall no longer meanfile -> 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 clearingdefaultandforceddispositions in the draft descriptor, while enforcing that there is at most onedefaultand at most oneforcedstream 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 throughffx 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 offfx edit.METADATA_EDITOR-0014: Because ffmpeg cannot rewrite the source file in place,ffx editshall 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-runbehavior shall apply toffx 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.mkvopens 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
defaultorforcedon 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 aVideoEncoder.COPYpath that can remux streams and apply metadata and disposition tokens.MediaDescriptorChangeSetalready computes container-tag, stream-tag, and disposition differences and can generate ffmpeg metadata tokens.TagDetailsScreenandTrackDetailsScreenalready provide reusable edit dialogs for draft state.PatternDetailsScreenalready demonstrates add, edit, and delete flows for tags and tracks in a draft-first UI.
- Refactor required:
ffxCLI initialization currently creates a database context for all non-lightweight commands, soeditneeds its own DB-free bootstrap path.FilePropertiescurrently instantiatesPatternControllereagerly, so probing must be split from pattern matching or made lazy.MediaDetailsScreencurrently assumescommand == 'inspect'and mixes file state with database-backed target-pattern state.MediaDetailsScreencurrently mutates the probed source descriptor directly. Edit mode needs an immutable baseline descriptor and a separate mutable draft descriptor.TrackDetailsScreencurrently 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.