Files
163-music-dl/CLAUDE.md
T

60 lines
4.4 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```bash
# 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. `require`d 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.js`** — `fetchJSON`, `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 levels** — `QUALITY_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.
- **Pause** — `lib/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.