Skip to content

feat: output metadata tagging (--set-title/--set-artist/--set-album/--set-comment)#192

Open
seonghobae wants to merge 1 commit into
mainfrom
feat/metadata-tagging
Open

feat: output metadata tagging (--set-title/--set-artist/--set-album/--set-comment)#192
seonghobae wants to merge 1 commit into
mainfrom
feat/metadata-tagging

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

Adds output metadata tagging: four new CLI options — --set-title, --set-artist, --set-album, --set-comment — inject -metadata key=value pairs into the generated ffmpeg commands, so archived FLAC/Opus outputs carry meaningful tags that are searchable in players and music libraries.

Design

  • _metadata_args(tags) helper produces ["-metadata", "key=value", ...] in sorted key order, so generated commands are deterministic. Values are passed through verbatim as single argv items (plans run without a shell), so spaces, quotes, $(...), and non-ASCII are all safe as given.
  • ffmpeg semantics documented and relied upon: both plans already copy source metadata via -map_metadata 0. The -metadata pairs are injected after it (after -map_chapters 0, before -vn), so each provided key overrides that specific tag copied from the source while every other source tag is preserved.
  • Threaded through the same chain as prefer_flac: parse_args -> _execute_conversions -> convert_file -> _convert_segment -> _execute_segment_conversion -> build_audio_plan / build_opus_plan, including the FLAC-too-large -> Opus fallback path, so segmented and fallback outputs are tagged identically.
  • parse_args collects only the options actually provided into args.tags (empty dict when none passed).
  • Byte-identical default: with no --set-* options, the generated ffmpeg argument lists are unchanged from before this PR (asserted by tests).

Tests

  • parse_args tag collection: all four, partial subset, and default (empty tags, all set_* None).
  • -metadata pair presence, ordering, and placement (after -map_metadata, before -vn) in both the FLAC and Opus plans.
  • No-tags plans byte-identical to baseline plans (tags omitted vs None vs {}).
  • Special characters in values pass through as single argv items.
  • _execute_conversions forwards args.tags to convert_file (and None when empty).

Gates

  • coverage run -m unittest discover -s tests + coverage report --include=media_shrinker.py: 100%
  • interrogate -c pyproject.toml media_shrinker.py: 100% (PASSED)
  • unittest discover -s tests: 125 tests, no new failures — exactly the 5 pre-existing macOS os.listxattr mock errors.

🤖 Generated with Claude Code

…album/--set-comment

Add four CLI options that inject -metadata key=value pairs into the
generated ffmpeg commands so archived outputs carry meaningful, searchable
tags in players and music libraries.

- New _metadata_args() helper emits deterministic (sorted-key) -metadata
  pairs; values are passed through verbatim as single argv items (plans
  run without a shell), so special characters are safe.
- Tags are threaded through the same chain as prefer_flac: parse_args ->
  _execute_conversions -> convert_file -> _convert_segment ->
  _execute_segment_conversion -> build_audio_plan/build_opus_plan,
  including the FLAC-too-large -> Opus fallback path.
- Pairs are injected after -map_metadata 0 / -map_chapters 0 in both the
  FLAC and Opus plans, so each provided key overrides that specific tag
  copied from the source while all other source metadata is preserved
  (standard ffmpeg semantics).
- Default behavior is byte-identical: with no --set-* options the
  generated argument lists are unchanged.
- Tests: parse_args tag collection (all/partial/none), -metadata pair
  placement in both plans, byte-identical no-tags plans, special-character
  pass-through, and tags forwarding in _execute_conversions.
- Docs: README "Metadata tagging" section.

Gates: coverage 100% on media_shrinker.py, interrogate 100%, unittest
baseline unchanged (5 pre-existing macOS os.listxattr errors only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
@seonghobae seonghobae enabled auto-merge (squash) July 6, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant