跳转到内容
⌂ 回到首页

Linux 构建指南

这份文档是 ECHO Next 的 Linux x64 打包、验收和故障定位指南。目标不是“能跑一下命令”,而是把 Linux 包从环境准备、FFmpeg、ALSA、native host、electron-builder 到发布前验收都讲清楚。

当前 Linux 支持属于稳健首阶段:产出 x64 AppImagedeb,应用能启动、能扫描本地曲库、能播放本地 WAV / FLAC / MP3,并且在 Linux shared native output 下提供明确的 ALSA 后端。

[!IMPORTANT] Linux 包必须在 Linux x64 环境中构建。不要在 Windows 上直接交叉打 Linux 包。这个项目的 Linux 包需要 Linux 版 echo-audio-host、Linux 版 FFmpeg、Linux 原生开发库和 Linux 打包工具;跨平台硬凑很容易产出“看起来有包、实际上不能播放”的假产物。

  • Linux x64 桌面包。
  • AppImage
  • deb
  • Electron 主程序、Renderer、Preload、主进程服务。
  • 本地曲库扫描和本地播放主流程。
  • Linux 版 echo-audio-host
  • Linux shared native output。
  • shared backend Auto
  • shared backend ALSA
  • PipeWire 通过 ALSA compatibility layer 暴露出来的设备路径。
  • 独立 Linux 工具目录 electron-app/tools-linux/
  • Linux arm64 / aarch64。
  • rpm / snap / Flatpak 正式产物。
  • JACK 原生后端。
  • PipeWire 原生后端。
  • Linux 独占 / bit-perfect 级别 HiFi 后端。
  • 从 Windows 直接交叉构建 Linux 包。
  • 发行版全矩阵兼容承诺。
  • WASAPI Exclusive。
  • ASIO。
  • DirectSound compatibility mode。
  • SMTC。
  • Windows taskbar thumbnail controls。
  • Windows audio service restart。

这些边界要保持清楚。Linux 适配不能影响 Windows 端已有播放链路,也不能把尚未验收的 Linux 能力包装成已完成能力。

优先级从高到低:

  1. 原生 Linux x64。
  2. Linux x64 VM。
  3. Linux CI runner。
  4. WSL2 Ubuntu x64。

WSL2 可以用于构建和基础命令验证,但不建议把 WSL2 当成完整桌面验收环境。音频设备、桌面 session、AppImage 启动行为、FUSE 和 sandbox 细节都可能与真实用户环境不同。

推荐版本:

项目建议
Node.js20 LTS
npm9 或更高
CPUx64
C++支持 C++17
CMake3.24 或更高更稳妥
Electron使用仓库 package-lock.json 固定版本
FFmpegLinux x64 可执行文件,至少包含 aresample

确认平台:

Terminal window
uname -a
node -p "process.platform + '/' + process.arch"

期望 Node 输出:

linux/x64

基础构建和打包工具:

Terminal window
sudo apt update
sudo apt install cmake g++ pkg-config fakeroot dpkg rpm binutils

JUCE / audio host 相关依赖:

Terminal window
sudo apt install \
libasound2-dev libjack-jackd2-dev \
libfreetype-dev libfontconfig1-dev \
libx11-dev libxcomposite-dev libxcursor-dev libxext-dev \
libxinerama-dev libxrandr-dev libxrender-dev

桌面运行和 AppImage 验收可能需要:

Terminal window
sudo apt install libgtk-3-0 libnss3 libxss1 libxtst6 libdrm2 libgbm1

如果 AppImage 报 FUSE 相关错误,按发行版安装对应 FUSE 运行时。例如 Ubuntu 新版本可能需要:

Terminal window
sudo apt install libfuse2

不同发行版包名可能不同,但核心依赖类别不变:

  • C++ 编译链。
  • CMake。
  • pkg-config。
  • ALSA 开发库。
  • X11 开发库。
  • fontconfig / freetype。
  • electron-builder 打包需要的 dpkg / fakeroot / rpm / binutils。

新环境从零开始:

Terminal window
git clone https://github.com/moekotori/echo.git
cd echo
npm ci

开发机已有仓库时:

Terminal window
git pull
npm ci

不要把 Windows 下的 node_modules 拷到 Linux。这个项目包含 native dependency,Linux 构建需要在当前 Linux 环境里重新安装或重建。

build:linux 会自动执行:

Terminal window
npm run rebuild:native

它会让 better-sqlite3 等 native dependency 匹配当前 Electron ABI。

Linux 包使用独立工具目录:

electron-app/tools-linux/
README.md
ffmpeg
ffmpeg-manifest.json
yt-dlp

打包后会复制到:

dist/linux-unpacked/resources/tools/

要求:

文件是否必须作用
ffmpeg必须解码、探测和音频处理工具链的一部分
ffmpeg-manifest.json必须记录 FFmpeg 版本、hash、必需 filter 和许可证信息
yt-dlp可选下载和部分 streaming helper
README.md已在仓库说明目录用途

yt-dlp 缺失不应该阻断本地曲库扫描、本地播放和 Linux 包构建。它只会让下载/部分流媒体提取能力不可用。

示例:

Terminal window
mkdir -p electron-app/tools-linux
cp /path/to/linux/ffmpeg electron-app/tools-linux/ffmpeg
chmod +x electron-app/tools-linux/ffmpeg

确认它不是 Windows 二进制:

Terminal window
file electron-app/tools-linux/ffmpeg
electron-app/tools-linux/ffmpeg -hide_banner -version

file 输出应该能看出 ELF / Linux x86-64。不要放 .exe

Terminal window
cp /path/to/yt-dlp electron-app/tools-linux/yt-dlp
chmod +x electron-app/tools-linux/yt-dlp

如果没有 yt-dlp,可以跳过。

当前模板在:

electron-app/tools-linux/ffmpeg-manifest.json

字段含义:

字段说明
name工具名,通常是 ffmpeg
versionffmpeg -hide_banner -version 输出里能匹配到的片段
source本地或 CI 准备方式说明
sourceUrl精确来源 URL,能填就填
downloadPage下载页
artifact仓库内 artifact 路径,应为 electron-app/tools-linux/ffmpeg
sha256当前 FFmpeg 文件的 SHA256
requiresSoxr是否要求 --enable-libsoxr
requiredFilters必须存在的 FFmpeg filters,目前至少 aresample
licenseFamily许可证族,当前模板为 GPLv3

计算 hash:

Terminal window
sha256sum electron-app/tools-linux/ffmpeg

检查 filters:

Terminal window
electron-app/tools-linux/ffmpeg -hide_banner -filters | grep aresample

检查 soxr:

Terminal window
electron-app/tools-linux/ffmpeg -hide_banner -version | grep enable-libsoxr

当前仓库模板里 requiresSoxrtrue。如果你准备的 FFmpeg 没有 --enable-libsoxrnpm run verify:ffmpeg 会失败。此时有两个选择:

  • 换一个带 --enable-libsoxr 的 FFmpeg。
  • 如果当前发布目标不要求 soxr,把 manifest 里的 requiresSoxr 改成 false,但要明确这是发布策略变化。
Terminal window
npm run verify:ffmpeg

在 Linux 上,这条命令默认检查:

electron-app/tools-linux/ffmpeg-manifest.json

如果要显式指定:

Terminal window
ECHO_FFMPEG_MANIFEST=electron-app/tools-linux/ffmpeg-manifest.json npm run verify:ffmpeg

通过时会看到类似:

[verify:ffmpeg] OK ... sha256=...

Linux shared native output 由 echo-audio-host 提供。构建入口:

Terminal window
npm run build:audio-host

相关源码和配置:

native/audio-host/CMakeLists.txt
native/audio-host/src/main.cpp
native/audio-host/tests/audio_engine_tests.cpp
scripts/build-audio-host.mjs

Linux 平台构建特点:

  • ECHO_ENABLE_ASIO 默认 OFF
  • 非 Windows 平台启用 JUCE_ALSA=1
  • 非 Windows 平台禁用 JUCE_JACK=0
  • CMake 会 find_package(ALSA REQUIRED)
  • 生成文件是 electron-app/build/echo-audio-host,没有 .exe
  • 构建完成后脚本会给 Linux host 设置可执行权限。

手动确认:

Terminal window
npm run build:audio-host
file electron-app/build/echo-audio-host
test -x electron-app/build/echo-audio-host

应用层的 shared backend 有两种 Linux 重点路径:

  • Auto:让 native host 根据当前设备枚举选择可用 shared backend。
  • ALSA:只选择 ALSA 类型设备,用于明确验证 ALSA 链路。

PipeWire 系统通常通过 ALSA compatibility layer 暴露设备,所以很多现代发行版也可以走 ALSA 路径。但文档和发布说明里仍应写“ALSA 路径”,不要把 PipeWire 原生支持写成已完成。

从干净 Linux x64 环境开始:

Terminal window
npm ci
npm run verify:ffmpeg
npm run test:audio-engine
npm run build:linux

如果只是重复打包,并且依赖和工具链没有变化:

Terminal window
npm run verify:ffmpeg
npm run build:linux

如果正在排查 audio host:

Terminal window
npm run build:audio-host
npm run test:audio-engine

如果只想先确认前端/主进程能编译:

Terminal window
npm run build

package.json 中:

npm run build:linux

实际执行:

node scripts/build-linux.mjs

脚本会按顺序做这些事:

  1. 检查 process.platform === "linux"
  2. 检查 process.arch === "x64"
  3. 检查 electron-app/tools-linux/ffmpeg 存在且可执行。
  4. 执行 npm run rebuild:native
  5. 执行 npm run verify:ffmpeg
  6. 执行 npm run build:audio-host
  7. 检查 electron-app/build/echo-audio-host 存在且可执行。
  8. 执行 npm run build
  9. 执行 electron-builder --linux
  10. 检查打包后的 resources/echo-audio-host
  11. 检查打包后的 resources/tools/ffmpeg
  12. 如果源码目录有 yt-dlp,检查打包后的 resources/tools/yt-dlp
  13. 检查 dist/ 下是否有 .AppImage
  14. 检查 dist/ 下是否有 .deb

只要其中任一步失败,脚本会停止。不要跳过失败继续发布。

Linux 配置在 package.jsonbuild.linux

build.linux.icon = software.png
build.linux.target = AppImage x64 + deb x64
build.linux.category = AudioVideo

Linux extra resources:

electron-app/build/echo-audio-host -> resources/echo-audio-host
electron-app/tools-linux -> resources/tools

也就是说,Linux 包里的 audio host 和 FFmpeg 都不是从 Windows 资源目录拿的。

预期产物:

dist/linux-unpacked/resources/echo-audio-host
dist/linux-unpacked/resources/tools/ffmpeg
dist/*.AppImage
dist/*.deb

如果存在 yt-dlp

dist/linux-unpacked/resources/tools/yt-dlp

产包后检查权限:

Terminal window
test -x dist/linux-unpacked/resources/echo-audio-host
test -x dist/linux-unpacked/resources/tools/ffmpeg
test ! -f dist/linux-unpacked/resources/tools/yt-dlp || test -x dist/linux-unpacked/resources/tools/yt-dlp
Terminal window
chmod +x dist/*.AppImage
./dist/*.AppImage
Terminal window
sudo apt install ./dist/*.deb

安装后从桌面启动器或命令行启动。

用小曲库验收,不要一上来导入超大库:

  1. 启动应用。
  2. 首次启动能进入主界面。
  3. 导入一个小型本地音乐文件夹。
  4. Songs 页面能显示歌曲。
  5. Albums 页面能显示基本专辑信息。
  6. 播放 WAV。
  7. 播放 FLAC。
  8. 播放 MP3。
  9. 暂停、继续、上一首、下一首正常。
  10. 切换曲目不会提前结束。
  11. 进度不会异常跳动。

按顺序验收:

  1. System 输出播放一首歌。
  2. Shared + Auto 播放一首歌。
  3. Shared + ALSA 播放一首歌。
  4. ALSA 下切换曲目。
  5. ALSA 下暂停 / 继续。
  6. ALSA 下拖动进度。
  7. 打开播放诊断或专业状态面板,确认 output mode / backend 与选择一致。

确认 Linux 上不要出现错误可用的 Windows-only 能力:

  • WASAPI Exclusive 不应作为 Linux 可用输出能力出现。
  • ASIO 不应作为 Linux 可用输出能力出现。
  • DirectSound 不应作为 Linux 可用 shared backend 出现。
  • SMTC 相关能力不应被当作 Linux 桌面集成能力。

如果 UI 上能看到某些灰掉或说明性质的 Windows-only 文案,要确认它不会被误认为 Linux 可用路径。

发布前至少覆盖:

维度最小要求
包格式AppImage、deb
音频格式WAV、FLAC、MP3
输出模式System、Shared + Auto、Shared + ALSA
曲库小曲库导入和基础浏览
播放控制播放、暂停、继续、切歌、拖动进度
平台隔离Windows-only 输出不在 Linux 上误暴露

有条件时增加:

维度建议
发行版Ubuntu LTS、Debian stable、Fedora 或 Arch 派生环境
音频服务PulseAudio、PipeWire with ALSA compatibility
设备内置声卡、USB DAC、蓝牙输出
时间连续播放 30 分钟以上
曲库中型曲库扫描后播放

不要把所有压力混在一轮里。先确认播放,再确认扫描,再确认长时间稳定性。这样出现问题时更好定位。

现象:

[build:linux] Linux packages must be built on Linux x64.

处理:

  • 切到 Linux x64。
  • 使用 WSL2 / VM / CI runner。
  • 不要绕过脚本的平台检查。

现象:

[build:linux] Linux packaging currently supports x64 only.

处理:

  • 换 x64 runner。
  • arm64 支持要另做构建链、依赖、产物和验收,不要直接复用 x64 文档。

现象:

[build:linux] Missing Linux ffmpeg

处理:

Terminal window
ls -l electron-app/tools-linux/ffmpeg
file electron-app/tools-linux/ffmpeg
chmod +x electron-app/tools-linux/ffmpeg

确认它是 Linux ELF x86-64 文件。

现象:

[build:linux] Linux ffmpeg is not executable

处理:

Terminal window
chmod +x electron-app/tools-linux/ffmpeg

如果是在 CI artifact 解压后丢失权限,也要在 CI 里显式 chmod +x

现象:

[verify:ffmpeg] SHA256 mismatch

处理:

Terminal window
sha256sum electron-app/tools-linux/ffmpeg

把 manifest 的 sha256 更新为当前文件 hash。注意:如果 FFmpeg 来源不可信,先换可信二进制,不要为了过校验直接改 hash。

现象:

[verify:ffmpeg] Version output does not contain "..."

处理:

Terminal window
electron-app/tools-linux/ffmpeg -hide_banner -version

把 manifest 的 version 改成输出中真实存在的稳定片段。

现象:

[verify:ffmpeg] Required FFmpeg filter is missing: aresample

处理:

  • 换带 aresample 的 FFmpeg。
  • 不建议移除 requiredFilters 来绕过,因为音频链路依赖重采样能力。

现象:

[verify:ffmpeg] FFmpeg build configuration does not include --enable-libsoxr

处理:

  • 使用带 --enable-libsoxr 的 FFmpeg。
  • 或在确认发布策略允许后,把 requiresSoxr 改成 false

处理:

  • 确认 Node.js 是 20 LTS。
  • 删除当前 Linux 环境的 node_modules 后重新 npm ci
  • 不要复用 Windows node_modules
  • 如果是网络问题,先处理 npm registry / proxy,不要改业务代码。

可能表现为 better-sqlite3 加载失败或 Electron ABI 不匹配。

处理:

Terminal window
npm run rebuild:native

然后重新:

Terminal window
npm run build:linux

现象:

[build:audio-host] Failed to build JUCE audio host.

优先检查:

Terminal window
cmake --version
g++ --version
pkg-config --modversion alsa

再确认依赖:

Terminal window
sudo apt install cmake g++ pkg-config libasound2-dev libfreetype-dev libfontconfig1-dev

如果日志里是 JUCE 拉取失败,先处理网络或 CMake FetchContent 缓存,不要先改 audio host 代码。

13.12 electron-builder 没产出 AppImage / deb

Section titled “13.12 electron-builder 没产出 AppImage / deb”

检查:

Terminal window
ls -la dist

确认 package.json 里的 Linux target 仍包含:

AppImage x64
deb x64

如果只缺某一种包,优先看 electron-builder 输出,不要直接改构建脚本绕过检查。

先执行:

Terminal window
chmod +x dist/*.AppImage
./dist/*.AppImage

FUSE 相关问题按发行版安装 FUSE runtime。临时分析可用:

Terminal window
./dist/*.AppImage --appimage-extract

但发布验收仍要回到标准 AppImage 启动路径。

执行:

Terminal window
sudo apt install ./dist/*.deb

保留 apt 输出。常见方向:

  • 目标系统依赖缺失。
  • deb metadata 不适配目标发行版。
  • 本机已有旧安装残留。

不要用强制安装掩盖依赖问题作为发布验收结论。

先分层确认:

  1. 系统播放器是否有声音。
  2. ECHO System 输出是否有声音。
  3. ECHO Shared + Auto 是否有声音。
  4. ECHO Shared + ALSA 是否有声音。
  5. 只有某个文件无声,还是所有格式无声。
  6. 只有某个设备无声,还是所有设备无声。

可用系统命令辅助:

Terminal window
aplay -l
pactl info

如果 System 正常但 ALSA 不正常,优先看 ALSA 设备枚举和 audio host 日志。如果所有输出都不正常,先看系统音频服务和应用启动日志。

CI runner 要是 Linux x64。最小流程:

Terminal window
npm ci
chmod +x electron-app/tools-linux/ffmpeg
test ! -f electron-app/tools-linux/yt-dlp || chmod +x electron-app/tools-linux/yt-dlp
npm run verify:ffmpeg
npm run test:audio-engine
npm run build:linux

CI 可以缓存:

  • npm cache。
  • Electron 下载缓存。
  • FFmpeg artifact。
  • CMake 下载缓存。

不要跨平台缓存:

  • Windows node_modules
  • Windows native module build output。
  • Windows electron-app/build/echo-audio-host.exe
  • Windows electron-app/tools/

CI 构建通过只说明包能产出,不说明真实桌面音频已经验收。发布前仍要做 Linux 桌面手动验收。

产物:

  • dist/*.AppImage 存在。
  • dist/*.deb 存在。
  • dist/linux-unpacked/resources/echo-audio-host 存在。
  • dist/linux-unpacked/resources/echo-audio-host 可执行。
  • dist/linux-unpacked/resources/tools/ffmpeg 存在。
  • dist/linux-unpacked/resources/tools/ffmpeg 可执行。
  • 如果带 yt-dlp,打包后也存在且可执行。

基础应用:

  • AppImage 能启动。
  • deb 安装后能启动。
  • 首次启动能进入主界面。
  • 小曲库能导入。
  • Songs / Albums 基础显示正常。

播放:

  • WAV 可播放。
  • FLAC 可播放。
  • MP3 可播放。
  • 暂停 / 继续正常。
  • 切歌正常。
  • 拖动进度正常。
  • 没有明显提前结束。
  • 没有明显异常跳进度。

输出:

  • System 可播放。
  • Shared + Auto 可播放。
  • Shared + ALSA 可播放。
  • 诊断状态显示和实际输出选择一致。

平台边界:

  • WASAPI Exclusive 没有作为 Linux 可用能力出现。
  • ASIO 没有作为 Linux 可用能力出现。
  • DirectSound 没有作为 Linux 可用 shared backend 出现。
  • Windows SMTC 相关能力没有被当作 Linux 能力。

发布说明:

  • 标明 Linux 当前是 x64。
  • 标明包格式是 AppImage / deb。
  • 标明 ALSA 是当前明确支持的 shared native backend。
  • 不承诺 JACK / PipeWire native / Linux exclusive HiFi,除非后续已经真实实现并验收。

Linux 构建和 ALSA 支持后续继续按低风险方式推进:

  • 构建链问题先定位环境和脚本,不要先动播放核心。
  • FFmpeg 问题先看 manifest、hash、filter、权限和二进制来源。
  • ALSA 问题先看设备枚举、backend 选择和 audio host 日志。
  • 新增 Linux backend 要保持 Windows 行为隔离。
  • 发布前优先做小曲库和播放链路验收,再做大曲库压力。
  • 任何可能影响播放稳定性的改动,都要有针对性验证,不能只凭构建通过判断。