Skip to content

Latest commit

 

History

History
241 lines (166 loc) · 11.2 KB

File metadata and controls

241 lines (166 loc) · 11.2 KB

kuwo-cli

Go Version Release

English | 简体中文

A command-line Kuwo Music downloader written in Go, with zero third-party dependencies (standard library only).

The API calling logic is referenced from MusicBot-Go/plugins/kuwo.

This project is developed with Trae.

Features

Downloading

  • Keyword search with interactive batch selection & download; download directly by rid is also supported
  • Multiple qualities: 128k / 320k (mp3), FLAC lossless, Hi-Res
  • VIP tracks via the official car-player endpoint (no third-party service needed; mp3 direct)
  • Auto-decrypt mgg/mflac encrypted formats: encrypted audio (with ekey) from the car-player source is decrypted locally to ogg/flac
  • Auto-detect the actual audio format (mp3 / flac / wma / m4a / ogg, etc.) and name the extension correctly

Batching & Performance

  • Concurrent downloads (-c, default 5) using a dedicated connection pool with TCP reuse for faster batch downloads
  • Auto deduplication: same rid downloaded only once; local files with the same song name (any format) are skipped
  • A single failure in batch mode won't abort the rest; a success/skip/fail summary is printed at the end
  • Search results default to 50, expandable up to 500 via -n (auto-paginated)

Encryption Decryption

  • Auto-decrypt Kuwo mgg/mflac (QMC2 / KwmV2) encrypted formats, no third-party service required
  • Decryption chain: DES-ECB extracts raw key → TEA derives QMC key → stream cipher decrypts audio
  • Algorithm ported from nonebot-plugin-kuwo (src/qmc.rs) and unlock-music/cli

UX

  • Real-time progress bar (per-file for single / overall bar pinned at the bottom for batch, showing active concurrency and speed)
  • Preview clips auto-rejected
  • Download URL log: successful song - url entries are appended to <output-dir>/download.log
  • Pure Go standard library, cross-platform, single-file binary

Quick Start

Install

Option 1: download the prebuilt binary from Releases.

Option 2: build from source (requires Go 1.21+):

go build -o kuwo-cli.exe .   # Windows
go build -o kuwo-cli .       # Linux / macOS

Minimal Usage

# Search "Jay Chou Sunny", pick interactively, then batch download
kuwo-cli.exe Jay Chou Sunny

Usage

kuwo-cli [options] <search keywords>

Options

Option Default Description
-q 320 Quality: 128 / 320 (mp3) / flac / hires
-o mp3 Output directory
-n 50 Number of search results (1-500, auto-paginated)
-i Specify a song rid directly, skip search
-a false Download all search results (non-interactive)
-y false Auto-pick the first search result (non-interactive)
-c 5 Concurrency
-s true Skip locally existing files (cross-format dedup by song name; -s=false to disable)
-l false List search results only, no download
-t 30s Per-request timeout
-v false Verbose debug output

Examples

# Search then interactively batch download into the mp3 directory
kuwo-cli.exe Jay Chou Sunny

# Download all results concurrently (5 workers)
kuwo-cli.exe -a -c 5 Jay Chou

# 200 results, FLAC lossless
kuwo-cli.exe -q flac -n 200 Fish Leong

# Download directly by rid
kuwo-cli.exe -i 228908

# Auto-pick the first, 128k, with debug logs
kuwo-cli.exe -y -q 128 -v Jay Chou Sunny

# Force overwrite existing files (disable dedup skip)
kuwo-cli.exe -s=false -a Jay Chou

# List search results only, no download
kuwo-cli.exe -l Jay Chou

Interactive Flow

After searching, a numbered list is printed (default 50, up to 500 with -n, auto-paginated):

No.   Song                            Artist                  Length    rid
------------------------------------------------------------------------------------------
1     Sunny                           Jay Chou                04:29     228908
2     ...

Then a batch-selection prompt supports multiple formats:

Enter indices to batch download (e.g. 1,3,5-8 or all, q to quit):
Input Meaning
1 Download #1
1,3,5 Download #1, #3, #5
1-5 Download #1 through #5
1,3,5-8 Mixed: #1, #3, #5, #6, #7, #8
all or * Download all results
q Quit

A single failure in batch mode won't abort the rest; a success/skip/fail summary is printed at the end.

Concurrency & Deduplication

  • Concurrency: -c controls simultaneous downloads (default 5). Tracks are resolved and downloaded concurrently for a significant speedup. A dedicated HTTP connection pool reuses TCP connections with a 64KB buffer. Single-track downloads show a per-file progress bar; batch downloads keep an overall progress bar pinned at the bottom (done/total, active concurrency, percentage, bytes, live speed), with per-track completion/skip/fail messages scrolling above it.
  • rid dedup: songs with the same rid in a batch are downloaded only once.
  • Local dedup (-s, on by default): before downloading, files of any extension matching the song name (Artist - Song) in the output directory cause a skip. For example, if Jay Chou - Sunny.mp3 already exists, even a FLAC request will skip. -s=false disables this to force overwrite.

Download Log

After each successful download, a song - url line is appended to download.log in the output directory (default mp3/download.log). Skipped or failed tracks are not recorded; multiple runs accumulate. Example:

Jay Chou - Blue and White Porcelain - https://kw-er.kuwo.cn/.../M500002qU5aY3Qu24y.mp3
Jay Chou - Red Dust Inn - https://kw-lv.kuwo.cn/.../M500000Y1WC02Sb2n7.mp3
Jay Chou - Sunny - https://kw-er.kuwo.cn/.../M500000bYDlc2XxKLs.mp3

Note: The third-party resolver (kw-api.cenguigui.cn) may return transient errors under high concurrency; the tool retries automatically. If a large batch has many failures, lower -c and rerun (already-downloaded files are auto-skipped).

How It Works

Three-Tier Candidate Fallback

Download URL resolution uses a three-tier candidate fallback, returning on the first hit:

  1. Mobile car-player endpoint mobi.kuwo.cn/mobi.s (type=convert_url_with_sign)

    • Spoofs a car player (source=kwplayercar_ar_6.0.0.9) + official APK user, no signature/cookie needed; fetches full VIP audio directly (mp3).
    • Encrypted formats (mgg/mflac) with an ekey are decrypted locally (DES-ECB to extract raw key → TEA to derive QMC key → stream cipher to decrypt audio); files too small (previews) are rejected.
  2. Third-party direct-link resolver kw-api.cenguigui.cn (level=standard/exhigh/lossless/hires)

    • Serves as a high-bitrate fallback for flac/Hi-Res, with retries for transient network errors.
    • Only adopted when ekey is empty (unencrypted).
  3. Web playUrl www.kuwo.cn/api/v1/www/music/playUrl (signed)

    • Final fallback.

The search and Web playUrl endpoints require a signed GET: fetch an anonymous session cookie from the Kuwo homepage, derive the Secret header via an LCG algorithm, and append a reqId param.

Quality & Candidate Order

Requested quality Candidate resolution order
128 mobile 128k → 3rd-party standard → web
320 mobile 320k → mobile 128k → 3rd-party exhigh → web
flac mobile flac → 3rd-party lossless → mobile 320k → 3rd-party exhigh → web
hires mobile hires → mobile flac → 3rd-party hires → 3rd-party lossless → mobile 320k → web

For VIP tracks requested at flac/hires, the mobile car-player source returns encrypted formats (mgg/mflac) + ekey; the tool downloads and decrypts them locally to ogg/flac. If unencrypted flac is preferred, the 3rd-party resolver is used; if it's unavailable, the tool falls back to mobile 320k mp3 to guarantee playable output.

mgg/mflac Decryption Flow

Encrypted audio from the car-player source (extensions like mgg/mflac) comes with an ekey. It is decrypted locally as follows:

  1. kuwo_base64_decrypt: base64 decode → custom DES-ECB decrypt (key ylzsxkwm) → trim trailing zero bytes
  2. extract_qmc_raw_key: extract a 704/364-byte base64-decodable substring from the tail as the QMC raw key
  3. derive_key: base64 decode → V2 prefix check → double TEA-CBC decrypt + V1 derivation → 512-byte QMC key
  4. Stream cipher decryption: pick RC4 / Map / Static cipher by key length and decrypt the audio data

The actual audio format (flac / ogg / mp3) is auto-detected after decryption and used for the file extension.

Preview Rejection

After resolving a URL, a HEAD request gets Content-Length; an estimate based on a conservative 64kbps lower bound is used to reject files that are too small (preview clips) and continue to the next candidate.

Project Structure

kuwo-cli/
├── go.mod         # module definition
├── kuwo.go        # API client (session/signature/search/resolution/validation)
├── main.go        # CLI entry (args/interactive selection/concurrent download/progress/log)
├── qmc.go         # mgg/mflac decryption (DES-ECB + TEA + stream cipher)
├── qmc_test.go    # decryption chain unit tests
├── testdata/      # test fixtures (ekey and expected outputs)
├── .gitignore
└── README.md

FAQ

Many downloads fail. What should I do?

  • The third-party resolver (kw-api.cenguigui.cn) may be rate-limited under high concurrency. Lower -c and rerun (already-downloaded files are auto-skipped).
  • Some tracks may only have preview versions due to copyright restrictions, in which case all candidates will fail.

Why is my FLAC download an .ogg file?

Encrypted mgg/mflac from the car-player source may actually be an ogg container (Vorbis codec) after decryption. The tool names it by the actual format; playback is unaffected.

Can decrypted files be played?

Yes. The output is standard flac / ogg / mp3 audio playable in any player.

Notes

  • For personal study and research only. Please respect copyright and delete downloaded files within 24 hours.
  • The third-party resolver (kw-api.cenguigui.cn) is an external service; its availability and speed are out of this tool's control.
  • Kuwo's APIs may change at any time; if something breaks, update the signature/param logic against the upstream repo.

Acknowledgements