feat: Metadata fields (artist, album, comment) with ID3 tag export

Backend:
- Added artist, album, comment columns to clips DB (migration in init_db)
- New update_metadata() function in database.py
- New PATCH /api/clips/{id}/metadata endpoint
- Updated download endpoint to write ID3 tags using mutagen:
  * TIT2 (Title) — from clip title
  * TPE1 (Artist) — from clip artist
  * TALB (Album) — from clip album
  * COMM (Comment) — from clip comment
  * TBPM (BPM) — from detected BPM
  * TKEY (Key) — from detected key
  * TIT1 (Content Group) — prompt for reference
- Added mutagen==1.47.0 to requirements.txt
- Creates temporary copy with tags, original file untouched

Frontend:
- Clip interface updated with artist, album, comment fields
- New MetadataField component in DetailPanel:
  * Inline editing with click-to-edit
  * Input field with lyria-accent border
  * Enter to save, Escape to cancel, blur to save
  * Pencil icon on hover
  * Shows placeholder when empty
- App.tsx: handleUpdateMetadata() function, passed to DetailPanel
- Updates state across clips, currentClip, selectedClip

Architecture KB and Tasks KB updated.
This commit is contained in:
rin.kagamine committed 2026-05-29 22:55:01 -04:00
1 parent e687f7d457
commit a713488fb7
6 files changed
+238 -10

No files matched your search

+8 -1
View File
@@ -81,14 +81,21 @@ class Clip(BaseModel):
prompt_structure: Optional[dict] = None
bpm: Optional[float] = None
key: Optional[str] = None
artist: Optional[str] = None
album: Optional[str] = None
comment: Optional[str] = None
class RenameRequest(BaseModel):
title: str
class MetadataRequest(BaseModel):
artist: Optional[str] = None
album: Optional[str] = None
comment: Optional[str] = None
class GenerateArtworkRequest(BaseModel):
prompt: str
class ClipList(BaseModel):
clips: list[Clip]
total: int
total: int