Files
163-music-dl/CLAUDE.md
T

4.4 KiB
Executable File
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

A modular CommonJS Node.js CLI for downloading music from NetEase Cloud Music (网易云音乐), with lyrics, cover art, and ID3 tag embedding. 163_music_downloader.js owns CLI argument handling and the interactive menu; reusable logic lives under lib/. There is no package.json — the script runs on Node built-ins only (https, http, fs, path, readline, child_process). The UI, comments, and console output are entirely in Chinese.

Running

# Interactive menu (TTY required for pause hotkey)
node 163_music_downloader.js

# Command-line batch mode (bypasses the menu entirely)
node 163_music_downloader.js <songId> <songId> ...
node 163_music_downloader.js --playlist=<playlistId>

# Flags (batch mode only)
--level=lossless    # override quality; see QUALITY_LEVELS
--retries=5         # download retry count (default 3)
--no-lyric          # skip .lrc download
--no-cover          # skip cover/tag embedding

There are no tests, linter, or build step. Verify changes by running the script.

External dependencies (all optional / runtime-detected)

  • api.chksz.top — third-party API (API object at top of file) for song URLs, search, lyrics, and playlists. This is the core download source.
  • music.163.com — queried directly (fetchNeteaseSongDetail, fetchNeteaseAlbumDetail) for rich metadata (album, publish date, popularity). Requires Cookie: os=pc header.
  • node-id3 (npm) — preferred for MP3 tag/lyric/cover embedding. required lazily via hasNodeID3(); absent by default.
  • ffmpeg (system) — fallback embedder for non-MP3 (FLAC etc.) and when node-id3 is missing. Detected via hasFFmpeg().
  • Audio players (mpv, ffplay, play, cvlc, aplay) — for the preview/play features, detected via which. Note: which is Unix-only, so preview won't find players on Windows even if installed.

If a dependency is missing the relevant feature degrades gracefully (skips embedding, prints the URL, etc.).

Architecture

163_music_downloader.js drives batch mode or the interactive menu loop, while lib/ contains feature modules:

  • lib/network.jsfetchJSON, downloadFile (streams with a live progress bar, follows redirects), and downloadBuffer.
  • lib/downloader.js — the core retry/download pipeline: resolves the URL, handles existing files, writes audio and lyrics, embeds cover/tags, then records history.
  • lib/lyrics.js — lyric fetching, translation merging, credit parsing, and standalone .lrc saving.
  • lib/metadata.js — NetEase song/album metadata, album directory naming, and cover.jpg saving.
  • lib/tagging.js — node-id3/ffmpeg detection and audio tag embedding.
  • lib/config.js, history.js, pause.js, quality.js, catalog.js, utils.js — configuration, persistence, batch state, quality selection, search, and shared helpers.
  • Persistence (all JSON in the script's __dirname, not the download dir):
    • download_history.json — capped at 500 entries, newest-first (addHistory).
    • downloader_config.json — key/value config, currently only the level quality setting (getConfig/setConfig).
  • Output layout — audio + .lrc files go to downloads/. Deletes move files to .trash/ (not permanent). ZIP packaging uses .tmp_zip/. The c menu option cleans these up.

Conventions & gotchas

  • Quality levelsQUALITY_LEVELS array is the source of truth; DEFAULT_LEVEL = 'jymaster'. The chksz API may return a lower actualLevel than requested.
  • Filenames — always sanitize(${artist} - ${name}) (strips /\:*?"<>|). Lyric/rename logic depends on this exact "artist - name" shape when parsing filenames back out.
  • Menu dispatch — adding a feature means adding a case in the main() switch AND a line in both printMenu() and the h help text. Note the switch currently has a duplicated case 'p'/'P' block (the second is unreachable) and the keypress listener is registered twice — mirror the existing style rather than assuming it's clean.
  • Pauselib/pause.js owns pause state; waitIfPaused() gates batch loops and the p hotkey toggles it in interactive TTY mode.
  • Batch loops sleep ~300500ms between songs to avoid hammering the API — preserve this when editing download loops.