Batch Import SOP: Agent SOP for batch importing new music # Batch Import > Agent SOP for preparing newly acquired music for Rekordbox import. Process newly acquired music (downloaded albums, loose tracks, zips) into an organized structure ready for Rekordbox import. **Goal:** After this SOP, any processed track can be imported into Rekordbox with Artist, Title, Album, Year, Track Number, and Label displaying correctly. Genre is handled separately via the genre classification SOP. ### Agent prompt [Section titled “Agent prompt”](#agent-prompt) Paste into your agent to start: ```plaintext Process the new music in [/path/to/folder] for Rekordbox import. ``` ## Constraints * **Tags are source of truth.** Write tags before renaming — filenames are derived from tags. * **Never set genre.** Leave genre tags empty; handled via genre classification SOP. * **Stop on ambiguity.** Never guess artist names, album years, or label names — ask the user. * **Process album by album.** Complete one fully before starting the next. * **WAV dual-tag rule.** WAV files need both ID3v2 and RIFF INFO in sync. `write_file_tags` handles this automatically. * **Verify before moving.** Confirm tags and filenames before moving to final location. ## Prerequisites | Tool | Purpose | | ---------------- | ------------------------------------------------------------------ | | `reklawdbox` MCP | Tag reading/writing, Discogs/Beatport lookups, cover art embedding | `lookup_discogs`, `lookup_beatport`, `lookup_bandcamp`, `lookup_musicbrainz`, `read_file_tags`, `write_file_tags`, `embed_cover_art`, and `extract_cover_art` are MCP tool calls. *** ## Phase 1: Assessment ### Step 1: Discover library structure Before importing, understand how the destination library is organized. Use `read_library` to find the content root, then scan 2 levels deep: ```sh find "/path/to/content-root" -maxdepth 2 -type d | head -80 ``` Identify: * **Album directory** — which top-level directory contains `Artist/Album (Year)/` subdirectories? * **Loose track directory** — which top-level directory contains batch folders with flat audio files? Present your findings to the user and confirm before proceeding: ```plaintext Your library structure appears to be: - Albums: {albums-dir}/{Artist}/{Album (Year)}/ - Loose tracks: {loose-dir}/{batch-name}/ Is this correct? What should this batch's loose tracks folder be named? ``` Use the confirmed paths for all move operations in Phase 2 Step 9 and Phase 3 Step 4. If the library is empty or the structure is unclear, ask the user to define their preferred convention. ### Step 2: List the batch directory ```sh ls -la "/path/to/batch/" ``` Categorize: directories (albums/EPs), audio files at root (loose tracks), zip files (need extraction). ### Step 3: Handle zip files Extract all root-level zips. Already-extracted zips (matching directory exists with files) are archived without re-extraction. Failed extractions go to `_failed_zips/`. ```sh cd "/path/to/batch" mkdir -p "_processed_zips" "_failed_zips" find . -maxdepth 1 -type f -name "*.zip" -print0 | while IFS= read -r -d '' zip; do zip="${zip#./}" dir="${zip%.zip}" if [ -d "$dir" ] && find "$dir" -type f -print -quit | grep -q .; then mv "$zip" "_processed_zips/$zip" echo "Archived already-extracted: $zip" continue fi tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/batch-import-unzip.XXXXXX")" if unzip -o "$zip" -d "$tmp_dir"; then mkdir -p "$dir" find "$tmp_dir" -mindepth 1 -maxdepth 1 -exec mv -n {} "$dir"/ \; if find "$dir" -type f -print -quit | grep -q .; then mv "$zip" "_processed_zips/$zip" echo "Extracted: $zip" else mv "$zip" "_failed_zips/$zip" echo "No files extracted: $zip" fi else mv "$zip" "_failed_zips/$zip" echo "Extraction failed: $zip" fi rm -rf "$tmp_dir" done ``` ### Step 4: Report to user Summarize what was found: album directories, loose tracks, zip results. *** ## Phase 2: Process Albums For each album subdirectory, follow these steps in order. ### Step 1: Survey current state ```sh ls -la "/path/to/batch/Album Directory/" ``` Read tags for all files: ```plaintext read_file_tags(directory="/path/to/batch/Album Directory/") ``` Note: current filename pattern, which tags are present, whether cover art exists. ### Step 2: Parse directory name Common incoming patterns: * `Artist Name - Album Name` * `Artist Name - Album Name (Year)` * `Artist Name - Album Name [FLAC 24-96]` Extract: artist, album name, year (if present). ### Step 3: Determine album type * **Same artist on all tracks** → Single Artist * **Different artists per track** → VA Compilation * **“Various Artists” in dir name** → VA Compilation For VA: label name is **required**. Check Publisher tag, directory name, or look up. ### Step 4: Look up metadata ```plaintext lookup_discogs(artist="Artist Name", title="First Track Title", album="Album Name") ``` If no Discogs result, try Beatport: ```plaintext lookup_beatport(artist="Artist Name", title="First Track Title") ``` If still missing data (common with self-released and digital-only music), try Bandcamp: ```plaintext lookup_bandcamp(artist="Artist Name", title="First Track Title") ``` Bandcamp is the authoritative source for Bandcamp-sourced downloads and is often the **only** source for self-released music. The tool handles search and metadata extraction with caching automatically. If still missing year or label, try MusicBrainz as a final fallback: ```plaintext lookup_musicbrainz(artist="Artist Name", title="First Track Title") ``` Use results for: release year, label name, artist/album spelling verification. **Stop and ask** on: multiple matches with different years, no results and year/label unknown, ambiguous artist. Never use lookup results for genre. ### Step 5: Write tags Use `write_file_tags` for all tag writes. It handles WAV dual-tagging automatically. **Album-wide + per-track tags:** ```plaintext write_file_tags(writes=[ {path: "/path/to/album/01 original.flac", tags: { artist: "Track Artist", title: "Track Title", track: "1", album: "Album Name", year: "YEAR", publisher: "Label Name", album_artist: "Artist Name" }}, ... ]) ``` **Per-track tags** — parse from filenames. Common incoming patterns: | Pattern | Parse as | | ------------------------------- | ------------------------------- | | `Artist - Album - NN Title.wav` | Track N: Artist - Title | | `NN Artist - Title.wav` | Track N: Artist - Title | | `NN Title.wav` | Track N: \[AlbumArtist] - Title | | `NN. Title.wav` | Track N: \[AlbumArtist] - Title | ### Step 6: Verify tags ```plaintext read_file_tags(directory="/path/to/album/") ``` Confirm every file has: Artist, Title, Track, Album, Year. ### Step 7: Rename files from tags Construct target filenames from tags: `NN Artist - Title.ext` Use `mv -n` (no-clobber) for each file. Validate the target filename is non-empty before renaming. ```sh mv -n "/path/to/album/old filename.flac" "/path/to/album/01 Artist Name - Track Title.flac" ``` If rename produces unexpected results, stop and check tags — rename depends entirely on tag correctness. ### Step 8: Embed cover art Check for existing cover art in the directory: ```sh find "/path/to/album/" -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -print ``` **Single obvious cover** (`cover.jpg`, `front.jpg`, `folder.jpg`): ```plaintext embed_cover_art(image_path="/path/to/album/cover.jpg", targets=["/path/to/album/01 Artist - Track.flac", ...]) ``` **Multiple images:** Ask user which is the cover. **No images:** Try `lookup_bandcamp(artist="...", title="...")` first — if the result includes a `cover_image` URL, download it: ```sh curl -sL -o "/path/to/album/cover.jpg" "BANDCAMP_COVER_URL" ``` If no Bandcamp result, try `lookup_discogs(...)` — if result includes `cover_image`, download and embed: ```sh curl -sL -o "/path/to/album/cover.jpg" "DISCOGS_COVER_IMAGE_URL" ``` ```plaintext embed_cover_art(image_path="/path/to/album/cover.jpg", targets=["/path/to/album/01 Artist - Track.flac", ...]) ``` If no cover from `lookup_bandcamp` or `lookup_discogs`, note for user to source manually. ### Step 9: Create target directory and move files Use the album directory convention established in Phase 1 Step 1. Determine clean directory name (strip tech specs, add year, clean special chars). ```sh # Single Artist — use the confirmed album directory mkdir -p "/path/to/albums-dir/Artist Name/Album Name (Year)" # Or VA mkdir -p "/path/to/albums-dir/Various Artists/Label Name/Album Name (Year)" # Move audio + cover art find "/path/to/batch/Old Dir" -maxdepth 1 -type f \ \( -iname "*.wav" -o -iname "*.flac" -o -iname "*.mp3" \) \ -exec mv -n {} "/path/to/dest/Artist Name/Album Name (Year)/" \; find "/path/to/batch/Old Dir" -maxdepth 1 -type f -iname "cover.*" \ -exec mv -n {} "/path/to/dest/Artist Name/Album Name (Year)/" \; # Remove old empty directory rmdir "/path/to/batch/Old Dir" ``` ### Step 10: Verify final state ```sh ls -la "/path/to/dest/Artist Name/Album Name (Year)/" ``` ```plaintext read_file_tags(directory="/path/to/dest/Artist Name/Album Name (Year)/") ``` Confirm: files in correct location, `NN Artist - Title.ext` format, all tags present, VA has label subdirectory, cover art embedded. *** ## Phase 3: Process Loose Tracks For audio files at the root of the batch directory. ### Step 1: Clean filenames Strip store-generated `(Original)`, `(Original Mix)`, and `(Original Version)` suffixes. Keep other parenthetical info (`(Remix)`, `(Edit)`, `(Original Club Mix)`, etc.): ```sh cd "/path/to/batch" find . -maxdepth 1 -type f \( -name "* (Original Mix).*" -o -name "* (Original Version).*" -o -name "* (Original).*" \) -print0 | while IFS= read -r -d '' f; do new_name="$(echo "$f" | sed -E 's/ \(Original( (Mix|Version))?\)//')" mv -n "$f" "$new_name" done ``` Expected format: `Artist Name - Track Title.ext`. If unparseable, ask user. ### Step 2: Read/write tags For each loose track, read existing tags: ```plaintext read_file_tags(paths=["/path/to/batch/Artist - Title.wav"]) ``` If tags are missing, look up with `lookup_discogs(...)` / `lookup_beatport(...)` / `lookup_bandcamp(...)` / `lookup_musicbrainz(...)`. Bandcamp is often the only source for self-released and digital-only music. Write tags (include album — almost always available from the source release): ```plaintext write_file_tags(writes=[{ path: "/path/to/batch/Artist - Title.wav", tags: {artist: "Artist Name", title: "Track Title", album: "Release Name", publisher: "Label Name", year: "YEAR"} }]) ``` ### Step 3: Embed cover art Check for `cover_Artist Name - Track Title.jpg` files. If found: ```plaintext embed_cover_art(image_path="/path/to/cover.jpg", targets=["/path/to/track.flac"]) ``` If no local cover file exists, try `lookup_bandcamp(artist="...", title="...")` — if the result includes a `cover_image` URL, download it: ```sh curl -sL -o "/path/to/cover_Artist - Title.jpg" "BANDCAMP_COVER_URL" ``` ```plaintext embed_cover_art(image_path="/path/to/cover_Artist - Title.jpg", targets=["/path/to/Artist - Title.wav"]) ``` **WAV files:** Keep the cover image file alongside the audio — Rekordbox cannot import cover art from WAV tags, so the user needs the image colocated for manual import. For other formats (FLAC, MP3, AIFF), clean up the downloaded image after embedding. If no Bandcamp result, try `lookup_discogs(...)` for `cover_image`. Note any tracks without cover art in the report. ### Step 4: Move loose tracks Use the loose track destination established in Phase 1 Step 1. ```sh mkdir -p "/path/to/loose-dir/batch-name" mv -n "/path/to/batch/Artist - Title.wav" "/path/to/loose-dir/batch-name/" ``` *** ## Phase 4: Multi-Disc Albums If an album has disc subdirectories (`CD1/`, `CD2/`, `Disc 1/`, etc.): * Track numbers restart at 01 per disc * Cover art at album root (not in disc folders) * Set Disc Number tag on each track via `write_file_tags` * Album-wide tags (album, year, publisher) go on all tracks across all discs *** ## Phase 5: Final Verification Summarize: albums processed (single artist vs VA), loose tracks processed, any unresolved items, WAV tracks needing manual cover art in Rekordbox, and next steps (import, collection audit SOP, genre classification SOP). *** ## Decision Reference ### Proceed automatically when * Artist clearly identified in tags, filename, or directory name * Year present in tags, directory name, or single clear Discogs match * Label present in tags or Discogs (for VA) * Single artist with consistent tags across album ### Stop and ask when * Multiple matches with different years * No results and year/label unknown * VA album but label unknown * Ambiguous: collaboration vs VA vs single artist * Multiple images — which is album cover? * Conflicting metadata between tags and filenames * Unparseable filenames *** ## Common Incoming Filename Patterns ### Album tracks | Pattern | Parse as | | ----------------------------------- | ------------------------------- | | `Artist - Album - NN Title.wav` | Track N: Artist - Title | | `Artist - Album - NN. Title.wav` | Track N: Artist - Title | | `NN Artist - Title.wav` | Track N: Artist - Title | | `NN. Artist - Title.wav` | Track N: Artist - Title | | `NN Title.wav` | Track N: \[AlbumArtist] - Title | | `NN. Title.wav` | Track N: \[AlbumArtist] - Title | | `Artist - Album - NN AX. Title.wav` | Track N: Artist - Title (vinyl) | ### Loose tracks | Pattern | Status | | ----------------------------------- | -------------------------------------------------------------------- | | `Artist - Title.wav` | Correct | | `Artist - Title (Remix Info).wav` | Correct | | `Artist, Artist B - Title.wav` | Correct | | `Artist - Title (Original Mix).wav` | Remove `(Original)` / `(Original Mix)` / `(Original Version)` suffix | | `Title.wav` | Missing artist — ask user |