🎉 一个简约的第三方酷狗概念版音乐播放器
See the code
EchoMusic —— 一个专为桌面端打造的简约、精致、功能强大的第三方音乐播放器。


bindgen 生成绑定需要)安装 Xcode Command Line Tools 和 LLVM(以下依赖安装命令使用 Homebrew):
xcode-select --install
brew install llvm pkg-config
export LIBCLANG_PATH="$(brew --prefix llvm)/lib"
已安装 Command Line Tools 时跳过第一条命令。在设置了 LIBCLANG_PATH 的同一终端中执行后续构建。
安装 Visual Studio Build Tools 的“使用 C++ 的桌面开发”工作负载及 Windows SDK,使用 MSVC Rust 工具链;编译 ARM64 时还需安装对应的 ARM64 C++ 工具。LLVM/libclang 可通过以下 PowerShell 命令安装、配置:
winget install LLVM.LLVM
$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"
LIBCLANG_PATH 必须指向包含 libclang.dll 的目录。以上设置立即作用于当前终端;如需持久化,可再执行 setx LIBCLANG_PATH "C:\Program Files\LLVM\bin",新终端才会读取该持久化设置。也可使用 Visual Studio 自带 LLVM 的相应目录。
以 Debian / Ubuntu 为例,安装编译工具、libclang 和音频后端开发库;后半部分为运行 Electron 所需的桌面依赖:
sudo apt-get update
sudo apt-get install -y build-essential pkg-config clang libclang-dev \
libasound2-dev libpulse-dev libpipewire-0.3-dev \
libgtk-3-dev libnotify-dev libnss3 libxss1 libxtst6 xdg-utils
其他发行版安装对应软件包。播放引擎的 Linux 后端同时启用 ALSA、PulseAudio 和 PipeWire,不能只安装其中一个后端的开发库。
克隆仓库
git clone https://github.com/hoowhoami/EchoMusic.git
cd EchoMusic
git submodule update --init --recursive
安装依赖
pnpm install
server子模块已作为 pnpm workspace 成员管理,上述命令会自动一并安装其运行依赖,无需再单独进入server目录执行npm install。
在Linux下,可能会出现如下报错:
Error: ENOENT: no such file or directory, open '/home/xxx/Projects/Work/EchoMusic/node_modules/electron/path.txt'
需手动下载并解压Electron到对应目录:
cd node_modules/.pnpm/[email protected]/node_modules/electron/
mkdir -p dist
curl -L -o /tmp/electron.zip "https://npmmirror.com/mirrors/electron/v43.7.2/electron-v43.7.2-linux-x64.zip"
unzip -o /tmp/electron.zip -d dist/
printf '%s' './electron' > path.txt
编译全部 Native 模块
*.node 产物不随源码提交。首次开发、修改 Rust 代码或切换系统/CPU 架构后,都需要构建对应模块。根目录的 pnpm install 只覆盖根项目和 server workspace,pnpm dev / pnpm build 不会自动编译这些 Native 模块。
| 模块目录 | 用途 | 构建平台 |
|---|---|---|
native/echo-audio-player | 播放、解码及音效处理 | macOS / Windows / Linux |
native/echo-audio-capture | 系统音频和麦克风采集 | macOS / Windows / Linux |
native/echo-media-controls | 系统媒体控制 | macOS / Windows / Linux |
native/echo-sqlite-store | SQLite 持久化存储 | macOS / Windows / Linux |
native/echo-opencc | 歌词简繁转换 | macOS / Windows / Linux |
native/echo-upnp | DLNA / UPnP 设备控制 | macOS / Windows / Linux |
native/echo-airplay | AirPlay 设备发现与音频发送 | macOS / Windows / Linux |
native/echo-platform-adaptor | 系统窗口、任务栏等平台适配 | macOS / Windows;Linux 无需构建 |
以下命令均从仓库根目录执行,逐个安装模块的构建依赖并运行其 build 脚本(napi build --release --no-const-enum),遇到错误即停止。
macOS / Linux(Bash):
bash <<'BASH'
set -e
addons=(echo-audio-player echo-audio-capture echo-media-controls echo-sqlite-store echo-opencc echo-upnp echo-airplay)
if [[ "$(uname -s)" == "Darwin" ]]; then
addons+=(echo-platform-adaptor)
fi
for addon in "${addons[@]}"; do
(
cd "native/$addon"
npm install
npm run build
)
done
BASH
Windows(PowerShell):
$addons = @("echo-audio-player", "echo-audio-capture", "echo-media-controls", "echo-sqlite-store", "echo-opencc", "echo-upnp", "echo-airplay", "echo-platform-adaptor")
foreach ($addon in $addons) {
Push-Location "native/$addon"
try {
npm install
if ($LASTEXITCODE -ne 0) { throw "安装 $addon 构建依赖失败" }
npm run build
if ($LASTEXITCODE -ne 0) { throw "构建 $addon 失败" }
} finally {
Pop-Location
}
}
每个模块会在自身目录生成同名 .node,例如 native/echo-audio-capture/echo-audio-capture.node。新模块不使用 index.node 作为产物名。仅执行 cargo build --release 不会将产物转换并放到应用期望的这个路径,应使用上述 napi-rs 脚本。
检查产物(在仓库根目录执行,适用于三平台):
node -e 'const fs = require("node:fs"); const addons = ["echo-audio-player", "echo-audio-capture", "echo-media-controls", "echo-sqlite-store", "echo-opencc", "echo-upnp", "echo-airplay"]; if (process.platform === "darwin" || process.platform === "win32") addons.push("echo-platform-adaptor"); for (const name of addons) { const file = "native/" + name + "/" + name + ".node"; if (!fs.existsSync(file)) throw new Error("缺少产物: " + file); console.log(file); } console.log("当前 Node 平台/架构:", process.platform, process.arch);'
此检查只确认文件存在。所有 .node 的平台和架构还必须与运行的 Electron 或打包目标一致:x64 与 arm64 产物不能混用。通常在目标平台、目标架构的环境中构建;交叉编译时,需先准备目标工具链、SDK 和 rustup target add <target>,再在每个模块目录运行 npx napi build --release --no-const-enum --target <target>,打包时选择相同架构。可参考 CI 构建矩阵。
常见问题:
Cannot find module .../echo-*.node:检查对应模块是否构建成功、产物是否位于上述路径。Unable to find libclang:检查 LLVM/libclang 安装与 LIBCLANG_PATH;它应指向库所在目录,而不是可执行文件。pkg-config 错误:补齐上面的开发库,并确认 pkg-config 能找到目标架构的库。Falling back to attempting to link the system's FFmpeg:检查 native/echo-audio-player/vendor/ffmpeg-audio/crates/ffmpeg_audio_sys/vendor/ 中的 ffmpeg_slim.zip 和 configs.zip 是否完整。默认构建不需要设置 FFMPEG_MODE=system;使用系统 FFmpeg 会引入额外的开发库及运行时动态库依赖。启动本地开发服务器
pnpm dev
开发模式下会由 Electron 主进程自动拉起本地服务端。
需要观察 Electron 主进程、Renderer、GPU 等进程的内存变化时,可以开启启动阶段内存诊断日志:
ECHOMUSIC_MEMORY_DIAGNOSTICS=1 pnpm dev
日志会写入 Electron 日志文件,例如 macOS 下为:
~/Library/Logs/EchoMusic/echo-music-YYYY-MM-DD.log
EchoMusic 无需导入外部引擎即可使用内置音效能力。兼容的 DSP Provider 可以在“设置 → 音效管理”中导入、启用和切换,为播放器增加独立预设、参数设置及组合音效支持。播放器根据 Provider 声明的能力生成界面和应用音效,不依赖某个特定引擎的实现。
EchoMusic 支持在线插件源和本地插件,可以扩展页面、音源、歌词、播放器交互、后台任务、独立浮窗与本地服务。插件运行在受信任的本地扩展环境中,并非浏览器扩展沙盒;请只安装来源可信的插件。
项目使用 GitHub Actions 进行自动化构建。每当推送 v* 格式的 Tag 时,会自动触发多平台构建并将二进制包上传至 Releases。
手动编译:
先完成“快速开始”中的依赖安装及全部 Native 模块构建,确认 .node 与打包架构一致,再在根目录执行:
pnpm build
pnpm build 执行类型检查、Vite 构建和 electron-builder 打包;npmRebuild 已关闭,打包过程只复制现有 Native 产物,不会替你补编译。Windows / macOS 需包含全部 8 个模块,Linux 需包含除 echo-platform-adaptor 外的 7 个模块。
除了推送 v* Tag 时运行的完整桌面发布流程,Actions 还提供独立的 Build Native Addons 手动 workflow。进入 GitHub Actions 后点击 Run workflow,可以分别勾选 macOS arm64/x64、Linux arm64/x64、Windows arm64/x64;默认全部勾选。选中的目标会在独立矩阵任务中并行编译,未选中的目标不会启动。
该流程只上传 GitHub Actions 的 CI artifact,不创建或发布 GitHub Release,也不是完整桌面安装包。每个目标生成一个独立 artifact,例如:
EchoMusic-native-macos-arm64EchoMusic-native-macos-x64EchoMusic-native-linux-arm64EchoMusic-native-linux-x64EchoMusic-native-windows-arm64EchoMusic-native-windows-x64artifact 内的目录根为 native,模块路径为 native/<模块文件夹>/<模块名>.node,例如 native/echo-audio-player/echo-audio-player.node。GitHub Actions 会自动将 artifact 打包;下载后解压到仓库根目录即可恢复本地 pnpm build 或 electron-builder 所需的目录布局。Linux 包含七个通用模块;macOS 和 Windows 额外包含 echo-platform-adaptor。x64 与 arm64 的 .node 产物不能混用。
该 workflow 与主桌面发布流程复用 pnpm 依赖缓存和 Rust 缓存,但每个平台在独立 runner 中编译并打包,避免不同架构覆盖同名 .node 文件。
dmg、zipexe (nsis,x64/arm64)deb、rpm、AppImage、tar.gz当前发行版使用 ad-hoc 签名,不支持 Squirrel.Mac 自动安装更新。应用内检查更新后,请下载对应架构的 DMG(Apple Silicon 选择 arm64,Intel 选择 x64),退出 EchoMusic,再将新版本拖入「应用程序」替换旧版本。
xattr -cr /Applications/EchoMusic.app && codesign --force --deep --sign - /Applications/EchoMusic.app
感谢以下开源项目及其贡献者提供的支持:
本项目的设计与交互受到以下开源项目的启发:
本项目是基于公开 API 接口开发的第三方音乐客户端,仅供个人学习和技术研究使用。
本项目不接受任何商业合作、广告或捐赠。
基于 GNU General Public License v3.0 协议发布,完整协议文本见 LICENSE。
第三方依赖与授权说明见 THIRD_PARTY_NOTICES.md。
🎉 一个简约的第三方酷狗概念版音乐播放器
See the code
EchoMusic —— 一个专为桌面端打造的简约、精致、功能强大的第三方音乐播放器。


bindgen 生成绑定需要)安装 Xcode Command Line Tools 和 LLVM(以下依赖安装命令使用 Homebrew):
xcode-select --install
brew install llvm pkg-config
export LIBCLANG_PATH="$(brew --prefix llvm)/lib"
已安装 Command Line Tools 时跳过第一条命令。在设置了 LIBCLANG_PATH 的同一终端中执行后续构建。
安装 Visual Studio Build Tools 的“使用 C++ 的桌面开发”工作负载及 Windows SDK,使用 MSVC Rust 工具链;编译 ARM64 时还需安装对应的 ARM64 C++ 工具。LLVM/libclang 可通过以下 PowerShell 命令安装、配置:
winget install LLVM.LLVM
$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"
LIBCLANG_PATH 必须指向包含 libclang.dll 的目录。以上设置立即作用于当前终端;如需持久化,可再执行 setx LIBCLANG_PATH "C:\Program Files\LLVM\bin",新终端才会读取该持久化设置。也可使用 Visual Studio 自带 LLVM 的相应目录。
以 Debian / Ubuntu 为例,安装编译工具、libclang 和音频后端开发库;后半部分为运行 Electron 所需的桌面依赖:
sudo apt-get update
sudo apt-get install -y build-essential pkg-config clang libclang-dev \
libasound2-dev libpulse-dev libpipewire-0.3-dev \
libgtk-3-dev libnotify-dev libnss3 libxss1 libxtst6 xdg-utils
其他发行版安装对应软件包。播放引擎的 Linux 后端同时启用 ALSA、PulseAudio 和 PipeWire,不能只安装其中一个后端的开发库。
克隆仓库
git clone https://github.com/hoowhoami/EchoMusic.git
cd EchoMusic
git submodule update --init --recursive
安装依赖
pnpm install
server子模块已作为 pnpm workspace 成员管理,上述命令会自动一并安装其运行依赖,无需再单独进入server目录执行npm install。
在Linux下,可能会出现如下报错:
Error: ENOENT: no such file or directory, open '/home/xxx/Projects/Work/EchoMusic/node_modules/electron/path.txt'
需手动下载并解压Electron到对应目录:
cd node_modules/.pnpm/[email protected]/node_modules/electron/
mkdir -p dist
curl -L -o /tmp/electron.zip "https://npmmirror.com/mirrors/electron/v43.7.2/electron-v43.7.2-linux-x64.zip"
unzip -o /tmp/electron.zip -d dist/
printf '%s' './electron' > path.txt
编译全部 Native 模块
*.node 产物不随源码提交。首次开发、修改 Rust 代码或切换系统/CPU 架构后,都需要构建对应模块。根目录的 pnpm install 只覆盖根项目和 server workspace,pnpm dev / pnpm build 不会自动编译这些 Native 模块。
| 模块目录 | 用途 | 构建平台 |
|---|---|---|
native/echo-audio-player | 播放、解码及音效处理 | macOS / Windows / Linux |
native/echo-audio-capture | 系统音频和麦克风采集 | macOS / Windows / Linux |
native/echo-media-controls | 系统媒体控制 | macOS / Windows / Linux |
native/echo-sqlite-store | SQLite 持久化存储 | macOS / Windows / Linux |
native/echo-opencc | 歌词简繁转换 | macOS / Windows / Linux |
native/echo-upnp | DLNA / UPnP 设备控制 | macOS / Windows / Linux |
native/echo-airplay | AirPlay 设备发现与音频发送 | macOS / Windows / Linux |
native/echo-platform-adaptor | 系统窗口、任务栏等平台适配 | macOS / Windows;Linux 无需构建 |
以下命令均从仓库根目录执行,逐个安装模块的构建依赖并运行其 build 脚本(napi build --release --no-const-enum),遇到错误即停止。
macOS / Linux(Bash):
bash <<'BASH'
set -e
addons=(echo-audio-player echo-audio-capture echo-media-controls echo-sqlite-store echo-opencc echo-upnp echo-airplay)
if [[ "$(uname -s)" == "Darwin" ]]; then
addons+=(echo-platform-adaptor)
fi
for addon in "${addons[@]}"; do
(
cd "native/$addon"
npm install
npm run build
)
done
BASH
Windows(PowerShell):
$addons = @("echo-audio-player", "echo-audio-capture", "echo-media-controls", "echo-sqlite-store", "echo-opencc", "echo-upnp", "echo-airplay", "echo-platform-adaptor")
foreach ($addon in $addons) {
Push-Location "native/$addon"
try {
npm install
if ($LASTEXITCODE -ne 0) { throw "安装 $addon 构建依赖失败" }
npm run build
if ($LASTEXITCODE -ne 0) { throw "构建 $addon 失败" }
} finally {
Pop-Location
}
}
每个模块会在自身目录生成同名 .node,例如 native/echo-audio-capture/echo-audio-capture.node。新模块不使用 index.node 作为产物名。仅执行 cargo build --release 不会将产物转换并放到应用期望的这个路径,应使用上述 napi-rs 脚本。
检查产物(在仓库根目录执行,适用于三平台):
node -e 'const fs = require("node:fs"); const addons = ["echo-audio-player", "echo-audio-capture", "echo-media-controls", "echo-sqlite-store", "echo-opencc", "echo-upnp", "echo-airplay"]; if (process.platform === "darwin" || process.platform === "win32") addons.push("echo-platform-adaptor"); for (const name of addons) { const file = "native/" + name + "/" + name + ".node"; if (!fs.existsSync(file)) throw new Error("缺少产物: " + file); console.log(file); } console.log("当前 Node 平台/架构:", process.platform, process.arch);'
此检查只确认文件存在。所有 .node 的平台和架构还必须与运行的 Electron 或打包目标一致:x64 与 arm64 产物不能混用。通常在目标平台、目标架构的环境中构建;交叉编译时,需先准备目标工具链、SDK 和 rustup target add <target>,再在每个模块目录运行 npx napi build --release --no-const-enum --target <target>,打包时选择相同架构。可参考 CI 构建矩阵。
常见问题:
Cannot find module .../echo-*.node:检查对应模块是否构建成功、产物是否位于上述路径。Unable to find libclang:检查 LLVM/libclang 安装与 LIBCLANG_PATH;它应指向库所在目录,而不是可执行文件。pkg-config 错误:补齐上面的开发库,并确认 pkg-config 能找到目标架构的库。Falling back to attempting to link the system's FFmpeg:检查 native/echo-audio-player/vendor/ffmpeg-audio/crates/ffmpeg_audio_sys/vendor/ 中的 ffmpeg_slim.zip 和 configs.zip 是否完整。默认构建不需要设置 FFMPEG_MODE=system;使用系统 FFmpeg 会引入额外的开发库及运行时动态库依赖。启动本地开发服务器
pnpm dev
开发模式下会由 Electron 主进程自动拉起本地服务端。
需要观察 Electron 主进程、Renderer、GPU 等进程的内存变化时,可以开启启动阶段内存诊断日志:
ECHOMUSIC_MEMORY_DIAGNOSTICS=1 pnpm dev
日志会写入 Electron 日志文件,例如 macOS 下为:
~/Library/Logs/EchoMusic/echo-music-YYYY-MM-DD.log
EchoMusic 无需导入外部引擎即可使用内置音效能力。兼容的 DSP Provider 可以在“设置 → 音效管理”中导入、启用和切换,为播放器增加独立预设、参数设置及组合音效支持。播放器根据 Provider 声明的能力生成界面和应用音效,不依赖某个特定引擎的实现。
EchoMusic 支持在线插件源和本地插件,可以扩展页面、音源、歌词、播放器交互、后台任务、独立浮窗与本地服务。插件运行在受信任的本地扩展环境中,并非浏览器扩展沙盒;请只安装来源可信的插件。
项目使用 GitHub Actions 进行自动化构建。每当推送 v* 格式的 Tag 时,会自动触发多平台构建并将二进制包上传至 Releases。
手动编译:
先完成“快速开始”中的依赖安装及全部 Native 模块构建,确认 .node 与打包架构一致,再在根目录执行:
pnpm build
pnpm build 执行类型检查、Vite 构建和 electron-builder 打包;npmRebuild 已关闭,打包过程只复制现有 Native 产物,不会替你补编译。Windows / macOS 需包含全部 8 个模块,Linux 需包含除 echo-platform-adaptor 外的 7 个模块。
除了推送 v* Tag 时运行的完整桌面发布流程,Actions 还提供独立的 Build Native Addons 手动 workflow。进入 GitHub Actions 后点击 Run workflow,可以分别勾选 macOS arm64/x64、Linux arm64/x64、Windows arm64/x64;默认全部勾选。选中的目标会在独立矩阵任务中并行编译,未选中的目标不会启动。
该流程只上传 GitHub Actions 的 CI artifact,不创建或发布 GitHub Release,也不是完整桌面安装包。每个目标生成一个独立 artifact,例如:
EchoMusic-native-macos-arm64EchoMusic-native-macos-x64EchoMusic-native-linux-arm64EchoMusic-native-linux-x64EchoMusic-native-windows-arm64EchoMusic-native-windows-x64artifact 内的目录根为 native,模块路径为 native/<模块文件夹>/<模块名>.node,例如 native/echo-audio-player/echo-audio-player.node。GitHub Actions 会自动将 artifact 打包;下载后解压到仓库根目录即可恢复本地 pnpm build 或 electron-builder 所需的目录布局。Linux 包含七个通用模块;macOS 和 Windows 额外包含 echo-platform-adaptor。x64 与 arm64 的 .node 产物不能混用。
该 workflow 与主桌面发布流程复用 pnpm 依赖缓存和 Rust 缓存,但每个平台在独立 runner 中编译并打包,避免不同架构覆盖同名 .node 文件。
dmg、zipexe (nsis,x64/arm64)deb、rpm、AppImage、tar.gz当前发行版使用 ad-hoc 签名,不支持 Squirrel.Mac 自动安装更新。应用内检查更新后,请下载对应架构的 DMG(Apple Silicon 选择 arm64,Intel 选择 x64),退出 EchoMusic,再将新版本拖入「应用程序」替换旧版本。
xattr -cr /Applications/EchoMusic.app && codesign --force --deep --sign - /Applications/EchoMusic.app
感谢以下开源项目及其贡献者提供的支持:
本项目的设计与交互受到以下开源项目的启发:
本项目是基于公开 API 接口开发的第三方音乐客户端,仅供个人学习和技术研究使用。
本项目不接受任何商业合作、广告或捐赠。
基于 GNU General Public License v3.0 协议发布,完整协议文本见 LICENSE。
第三方依赖与授权说明见 THIRD_PARTY_NOTICES.md。