1. 项目概述:当终端遇上流媒体音乐

如果你和我一样,是个重度命令行用户,同时又对音乐流媒体服务有深度依赖,那你肯定经历过这种割裂感:想快速搜首歌、建个播放列表,或者只是看看某个乐队的全部专辑,都不得不离开你心爱的终端,打开浏览器,登录Tidal的网页版,在一堆图形界面里点来点去。这种上下文切换不仅打断工作流,效率也低得让人抓狂。更别提当你想要自动化一些操作,比如根据心情自动生成播放列表,或者把喜欢的音乐库备份出来时,那种无处下手的无力感。

tidal-cli 的出现,就是为了弥合这个鸿沟。它本质上是一个用 TypeScript 编写的命令行工具,将 Tidal 官方的 V2 API 完整地封装了起来。这意味着,Tidal 网页版和移动端 App 里你能做的几乎所有事情——搜索、浏览艺人、管理播放列表、收藏音乐,甚至播放控制——现在都可以通过一行行简洁的命令来完成。它的目标用户非常明确:开发者、系统管理员、自动化爱好者,以及任何喜欢用键盘而非鼠标来高效操控数字生活的“极客”。

但它的野心不止于此。通过原生支持 --json 参数输出结构化数据,以及无缝集成到 MCP(Model Context Protocol)和 OpenClaw 这样的 AI 智能体平台, tidal-cli 正在从一个单纯的命令行工具,演变为连接人类音乐需求与 AI 自动化能力的“管道”。你可以让 Claude 这样的 AI 助手直接帮你操作 Tidal,实现“用自然语言管理音乐库”的愿景。接下来,我们就深入拆解这个工具,看看它如何工作,以及如何最大化地利用它来提升你的音乐体验和工作效率。

2. 核心设计与架构解析

2.1 为什么选择命令行接口(CLI)?

在图形用户界面(GUI)大行其道的今天,为什么还要回归命令行?答案在于 精确、可重复、可编程 。GUI 适合探索和偶然发现,但当你明确知道自己要做什么时,CLI 的效率是碾压级的。比如,你想把所有收藏的 Radiohead 歌曲添加到一个名为“深夜沉思”的播放列表。在 GUI 里,你需要:1) 找到 Radiohead 艺人页,2) 进入歌曲列表,3) 可能还需要分页加载,4) 勾选所有歌曲(或者一首首点),5) 找到“添加到播放列表”按钮,6) 选择或创建播放列表。而在 tidal-cli 中,这可能就是两三条命令的组合,甚至可以写成一个脚本,一键完成。

更深层次地,CLI 是自动化的基石。任何能通过命令执行的操作,都可以被脚本(Shell, Python, Node.js)调度,可以被定时任务(cron, systemd timer)触发,也可以被外部系统(如 Home Assistant 智能家居)调用。 tidal-cli 的设计哲学正是抓住了这一点,它不仅仅是一个替代点击的工具,而是一个将音乐服务 API 转化为可编程接口的“适配器”。

2.2 技术栈与依赖考量

项目采用 Node.js(>=20)和 TypeScript 构建,这是一个非常务实且现代化的选择。

  • Node.js 生态 :npm 包管理器使得全球分发和安装( npm install -g )变得极其简单。丰富的第三方库(如 axios 用于 HTTP 请求、 commander 用于构建 CLI、 inquirer 用于交互式问答)能快速实现核心功能,开发者可以把精力集中在业务逻辑而非底层轮子上。
  • TypeScript 的优势 :对于与复杂 API(如 Tidal API)打交道的项目,TypeScript 的静态类型检查是“救命稻草”。它能确保 API 请求参数和返回数据的结构正确性,极大减少运行时错误。这对于需要稳定运行的 CLI 工具和后续的 AI 智能体集成至关重要。
  • 版本要求 Node.js >=20 :这个要求不算低,但它确保了可以使用最新的 ES 模块特性、稳定的 Fetch API(替代传统的 request 库)以及更好的性能。对于目标用户(开发者)而言,他们的环境通常能较容易地满足或升级到此版本。

注意 :如果你在服务器或资源受限的环境(如树莓派)中使用,需要确认 Node.js 版本。对于生产环境的自动化脚本,建议使用 nvm fnm 这类 Node 版本管理工具来锁定运行环境,避免因版本差异导致脚本失败。

2.3 认证机制:OAuth 2.0 的优雅处理

音乐服务 API 的核心门槛是用户认证。 tidal-cli 采用了标准的 OAuth 2.0 授权码流程,并且处理得非常用户友好。

当你首次运行 tidal-cli auth 时,会发生以下几步:

  1. 工具会在你的默认浏览器中打开 Tidal 的官方授权页面。
  2. 你需要登录你的 Tidal 账户并授权该应用。
  3. 授权成功后,页面会跳转到一个本地服务器(通常由 CLI 工具临时启动),并携带一个授权码。
  4. CLI 工具用这个授权码向 Tidal 交换得到 访问令牌(Access Token) 刷新令牌(Refresh Token)
  5. 这些令牌会被安全地存储在本地(通常是用户主目录下的一个配置文件,如 ~/.config/tidal-cli/config.json )。

关键在于刷新令牌 :访问令牌通常有效期较短(如1小时)。如果没有刷新机制,用户每隔一小时就要重新授权一次,体验极差。 tidal-cli 在后台自动管理令牌刷新。当它检测到访问令牌过期时,会使用刷新令牌自动获取一组新的令牌,并更新本地存储。这个过程对用户完全透明,实现了“一次认证,长期使用”,这对于需要 7x24 小时运行的自动化任务(如 AI 智能体)是基础保障。

3. 功能深度剖析与实战指南

3.1 搜索功能:从模糊到精确

搜索是音乐探索的起点。 tidal-cli 的搜索命令设计得既全面又灵活。

# 基本搜索:按类型过滤
tidal-cli search track "Bohemian Rhapsody"
tidal-cli search album "The Dark Side of the Moon"
tidal-cli search artist "Daft Punk"

但实战中,你往往需要更多信息。原始命令只返回 ID 和名称列表,这对于脚本处理可能不够。结合 --json 输出和 jq 工具,你可以进行强大的数据提取和筛选:

# 搜索专辑,并以JSON格式输出,然后用jq提取第一张专辑的ID、艺术家和发行年份
tidal-cli --json search album "Kid A" | jq -r '.[0] | {id, title, artist: .artists[0].name, releaseDate}'

# 搜索建议(自动完成),非常适合构建交互式脚本
tidal-cli --json search suggest "radio" | jq -r '.[] | .value'

实操心得 :Tidal 的搜索 API 有时返回的结果顺序可能与网页版略有不同,因为它可能更侧重于算法推荐而非纯文本匹配。对于自动化脚本,一个稳健的做法是:1) 执行搜索,2) 从 JSON 结果中提取前 N 个条目,3) 根据你的逻辑(如精确匹配标题、过滤特定艺术家)进行二次筛选,而不是盲目取第一个结果。

3.2 播放列表管理:自动化编排的核心

播放列表管理是 tidal-cli 最亮眼的功能之一,它实现了完整的 CRUD(创建、读取、更新、删除)操作。

创建与批量添加

# 创建一个新的播放列表
tidal-cli playlist create --name "2024年跑步歌单" --description "节奏感强,适合配速5‘30“"

# 添加单曲
tidal-cli playlist add-track --playlist-id $PLAYLIST_ID --track-id $TRACK_ID

# 添加整张专辑!这个功能在网页版上都不那么直观,但CLI一行命令搞定。
tidal-cli playlist add-album --playlist-id $PLAYLIST_ID --album-id $ALBUM_ID

高级操作:重排序 : 这是 GUI 很难高效完成的任务。假设你想把某首歌移动到播放列表的顶部。

# 首先,列出播放列表内容,找到目标歌曲的 `itemId` 和它前面一首歌的 `itemId`
tidal-cli --json playlist list-tracks $PLAYLIST_ID > playlist.json
# 假设你想把 itemId 为 “track:123456:789012” 的歌移到开头
# 在Tidal API中,`move-track` 操作需要指定一个 `before` 参数,即移动到哪个 itemId 之前。
# 要移到开头,可以获取当前第一首歌的 itemId。
FIRST_ITEM_ID=$(jq -r '.[0].itemId' playlist.json)
tidal-cli playlist move-track --playlist-id $PLAYLIST_ID --track-id 123456 --before $FIRST_ITEM_ID

重要提示 playlist add-track playlist move-track 中的 --track-id 参数,指的是 Tidal 系统中歌曲的全局 ID。而 move-track 中的 --before 参数,指的是播放列表内特定条目(item)的唯一 itemId ,格式通常像 track:123456:789012 。这两个 ID 含义不同,切勿混淆。获取 itemId 的唯一可靠方式是通过 playlist list-tracks 命令。

3.3 音乐发现与库管理

tidal-cli 将 Tidal 的个性化推荐和用户历史数据也带到了命令行。

  • 个性化推荐 tidal-cli recommend 命令会返回你的“我的混音”、“发现”等个性化推荐列表。这对于打造“每日自动更新歌单”脚本是绝佳的数据源。
  • 收听历史 tidal-cli history tracks 可以获取你最近添加或播放的歌曲。结合脚本,你可以定期将最近喜欢的歌曲自动归档到一个名为“近期最爱”的播放列表中,实现音乐库的自动整理。
  • 库管理 :收藏(Favorite)操作是同步的,即在任何设备上通过 tidal-cli library add --track-id <id> 收藏一首歌,它都会立刻出现在你手机 App 的“我的音乐”中。这为统一管理音乐品味提供了可能。

3.4 播放与音频流处理

播放功能 ( playback ) 稍微特殊一些。它不直接在你的终端里播放音频(那需要复杂的音频解码和输出),而是提供了两种方式:

  1. 获取流媒体URL tidal-cli playback url <track-id> --quality LOSSLESS 会返回一个可以直接用于播放的临时 URL。你可以将这个 URL 传递给本地的媒体播放器,如 mpv vlc ffplay
    # 在macOS上,用QuickTime Player播放
    tidal-cli playback url 123456 --quality HIGH | xargs open -a "QuickTime Player"
    # 在Linux上,用mpv播放
    tidal-cli playback url 123456 --quality HIGH | xargs mpv
    
  2. 直接播放命令 tidal-cli playback play <id> 这个命令更像是一个“远程控制”,它通知 Tidal 的服务端:“在用户的默认播放设备上开始播放这首歌曲”。这需要你已经在某个设备(如手机、电脑的 Tidal App)上登录了同一账户并处于活动状态。对于完全无头的服务器环境,第一种方式(获取 URL 后用本地播放器)更可靠。

音质选择策略 :Tidal 提供从 LOW HI_RES 的多档音质。在自动化脚本中,选择 HIGH (320kbps AAC)通常是最平衡的选择,兼顾了音质和流量的稳定性。 LOSSLESS HI_RES 需要订阅更高级别的套餐,且文件体积巨大,仅推荐在本地网络环境极佳且存储/带宽不敏感的场景下使用。

4. 与AI智能体集成:从工具到智能管道

这才是 tidal-cli 项目最具前瞻性的部分。它通过两种主要方式拥抱 AI 智能体生态:MCP Server 和 OpenClaw Skill。

4.1 作为MCP服务器集成到Claude Desktop

MCP(Model Context Protocol)是 Anthropic 推出的一种协议,旨在让外部工具和能力安全、结构化地提供给 Claude 这类大模型。 tidal-cli 将自己包装成一个远程 MCP 服务器。

配置步骤详解

  1. 在 Claude Desktop 应用中,进入设置(Settings)。
  2. 找到“Connectors”(连接器)或“Developer”(开发者)选项。
  3. 选择“Add custom connector”(添加自定义连接器)。
  4. 在服务器 URL 处填入: https://tidal-cli.lucaperret.ch/api/mcp
  5. 点击“Connect”(连接)。

此时,Claude 会引导你完成一次 OAuth 登录流程(与 tidal-cli auth 类似)。成功后,Claude 就获得了通过这个 MCP 服务器调用 Tidal API 的能力。你会发现,在和 Claude 对话时,你可以直接说:

  • “帮我创建一个叫做‘周末电子乐’的播放列表。”
  • “找找和 Four Tet 风格相似的艺术家,并把他们的热门歌曲列出来。”
  • “把我最近收藏的5张专辑都加到‘待听列表’里。”

Claude 会在后台将你的自然语言指令,转化为对 tidal-cli MCP 服务器的一系列标准化工具调用。这彻底改变了人机交互方式,你不再需要记忆命令语法,只需描述你的意图。

4.2 作为OpenClaw Skill实现自动化工作流

OpenClaw 是另一个 AI 智能体框架。 tidal-cli 作为其上的一个 Skill(技能)发布。安装方式更为简单:

clawhub install tidal-cli

安装并完成 tidal-cli auth 认证后,你的 OpenClaw 智能体就具备了所有 Tidal 操作能力。

与MCP模式的区别 :MCP 更像是一个“实时辅助工具”,你在聊天窗口中驱动 Claude 完成任务。而 OpenClaw Skill 更适合部署 长期的、自动化的智能体 。例如,你可以创建一个智能体,它的任务是:

  • 每周一早上 ,检查 Tidal 的“新发行”推荐,将符合你口味的电子音乐专辑自动添加到一个“本周新碟”播放列表。
  • 监听你的播放历史 ,如果发现你连续三天都播放了某个冷门艺人的歌,自动将这个艺人的全部专辑收藏到音乐库。
  • 根据外部数据源 (如你关注的音乐博客 RSS)提及的专辑,自动在 Tidal 上搜索并为你收藏。

这些场景下,智能体是自主运行的, tidal-cli 提供了它所需的全部原子操作。

4.3 脚本模式:连接其他工具的粘合剂

即使你不使用 AI 智能体, tidal-cli --json 输出模式也让它成为 Shell 脚本或 Python/Node.js 脚本中的强大组件。

场景示例:备份所有播放列表

#!/bin/bash
# backup_playlists.sh

BACKUP_DIR="./tidal_backup_$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

# 获取所有播放列表ID和名称
tidal-cli --json playlist list | jq -c '.[]' | while read playlist; do
    PLAYLIST_ID=$(echo $playlist | jq -r '.uuid')
    PLAYLIST_TITLE=$(echo $playlist | jq -r '.title' | sed 's/[\/]/_/g') # 处理文件名中的斜杠

    echo "Backing up: $PLAYLIST_TITLE"
    # 获取播放列表详情和所有曲目,保存为JSON
    tidal-cli --json playlist info $PLAYLIST_ID > "$BACKUP_DIR/${PLAYLIST_TITLE}_info.json"
    tidal-cli --json playlist list-tracks $PLAYLIST_ID > "$BACKUP_DIR/${PLAYLIST_TITLE}_tracks.json"
done

echo "Backup completed to $BACKUP_DIR"

这个脚本将你的所有播放列表元数据和曲目列表以 JSON 格式备份到本地,万一线上列表误删,你可以依据这些数据轻松重建。

场景示例:同步两个播放列表 : 假设你想把“歌单A”中的歌曲,全部复制到“歌单B”,但排除某些艺人。

#!/bin/bash
SOURCE_PLAYLIST_ID="your_source_playlist_id_here"
TARGET_PLAYLIST_ID="your_target_playlist_id_here"
EXCLUDED_ARTIST="Some Artist Name"

# 获取源播放列表所有曲目ID,并过滤掉排除艺人的歌曲
tidal-cli --json playlist list-tracks $SOURCE_PLAYLIST_ID | \
  jq -r --arg exclude "$EXCLUDED_ARTIST" \
  '.[] | select(.artist.name != $exclude) | .id' | \
  while read track_id; do
    echo "Adding track $track_id"
    tidal-cli playlist add-track --playlist-id $TARGET_PLAYLIST_ID --track-id "$track_id"
    sleep 0.5 # 避免请求过快被API限制
  done

5. 开发、测试与问题排查

5.1 本地开发环境搭建

如果你想贡献代码或自定义功能,搭建开发环境很简单:

git clone https://github.com/lucaperret/tidal-cli.git
cd tidal-cli
npm install          # 安装所有依赖
npm run build        # 编译TypeScript到JavaScript
npm link             # 将本地构建的版本链接到全局,方便测试 `tidal-cli` 命令

项目结构清晰,核心逻辑在 src/ 目录下,命令定义通常在 src/commands/ 中。API 客户端封装在 src/api/ 里。修改代码后,需要重新运行 npm run build 才能生效。

5.2 测试策略与运行

项目包含了超过 110 个测试,这是一个非常健康的信号,表明其稳定性和可维护性有保障。

npm test           # 运行完整的测试套件
npm run test:watch # 开发模式下,监听文件变化并自动运行测试

测试覆盖了搜索、播放列表、艺人、曲库、认证等主要模块。对于开发者而言,在添加新功能或修改现有代码时,应尽量为相关功能编写或补充测试用例,这能极大避免回归错误。

5.3 常见问题与排查技巧

  1. 认证失败 / Error: Invalid grant

    • 原因 :访问令牌和刷新令牌都已过期或失效。通常发生在长时间未使用,或者你在 Tidal 账户设置中撤销了 tidal-cli 的授权。
    • 解决 :直接删除本地存储的令牌文件(位置因系统而异,通常在 ~/.config/tidal-cli/config.json 或类似路径),然后重新运行 tidal-cli auth 进行认证。
  2. 命令执行返回 [Object object] 或乱码

    • 原因 :你很可能在管道(pipe)中使用了 --json 输出,但后续处理工具(如 jq )期望的是纯 JSON,而 CLI 可能默认输出了一些状态信息。
    • 解决 :确保命令格式为 tidal-cli --json <subcommand> ... --json 标志必须紧跟在 tidal-cli 之后,子命令之前。这是 Commander.js 库参数解析的常见模式。
  3. API 速率限制

    • 现象 :请求频繁失败,返回 429 错误。
    • 解决 :Tidal API 有调用频率限制。在编写自动化脚本时,务必在连续请求之间加入延迟(例如 sleep 1 )。对于批量操作(如添加100首歌到播放列表),建议每处理10-20个请求后暂停几秒。 tidal-cli 本身可能没有内置重试或限流机制,这需要你在脚本层面实现。
  4. 播放命令 playback play 无反应

    • 原因 :该命令是“远程控制”命令,需要至少一个已登录且活跃的 Tidal 客户端(如手机 App、桌面 App 并处于播放状态)。
    • 排查 :先确保你的手机 Tidal App 正在运行或电脑客户端已打开。可以尝试先用 playback url 获取链接,用本地播放器测试,以确认网络和账户权限正常。
  5. 在无图形界面的服务器上如何完成初次 auth

    • 挑战 tidal-cli auth 依赖打开浏览器进行 OAuth 授权,这在无 GUI 的服务器上无法直接进行。
    • 解决方案
      • 方案A(推荐) :在本地电脑(有浏览器)上完成 tidal-cli auth 。认证成功后,配置文件(含令牌)会生成在本地。将这个配置文件( config.json )安全地复制到服务器上的对应路径( ~/.config/tidal-cli/ )。令牌是可移植的。
      • 方案B :在服务器上运行 tidal-cli auth 时,它会打印出一个授权 URL。你需要手动在另一台有浏览器的设备上访问这个 URL,完成登录授权。授权后,页面通常会显示一个代码(authorization code),你需要将这个代码手动输入回服务器的命令行提示中。这个过程比较繁琐,但可行。

我个人在实际使用中的体会是 tidal-cli 最强大的地方在于它把“音乐”这个感性的东西,变成了“数据”和“操作”这种理性的、可编程的对象。它可能不会让你更爱音乐,但它绝对能让你管理音乐的方式变得前所未有的高效和智能。从简单的命令行搜索,到复杂的智能体自动化,它搭建了一座坚实的桥梁。最后一个小技巧:善用 Shell 的函数功能,将你常用的复杂操作封装成简洁的自定义命令,比如 alias tidal-mix='tidal-cli recommend | jq ...' ,这能让你的音乐命令行体验再上一个台阶。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐