Skip to content

🦀 原生模块 (Rust NAPI)

EchoMusic 使用 Rust 编写原生扩展,通过 napi-rs 框架编译为 Node.js 可调用的原生模块。原生模块运行在 Electron 主进程中,提供高性能的底层能力。

为什么用 Rust?

优势说明
零延迟调用进程内直接函数调用,无 IPC 开销
高性能Rust 编译为原生机器码,执行效率接近 C/C++
内存安全Rust 的所有权系统保证内存安全,无 GC 停顿
丰富生态通过 FFI 可调用 C 库(如 libmpv)

模块概览

echo-mpv-player — 播放引擎

封装 libmpv 播放器,提供完整音频播放能力。

核心功能

功能说明
播放控制播放/暂停/停止/跳转
音量控制音量调节、静音
倍速播放0.5x - 2.0x 倍速
淡入淡出平滑的切歌过渡
EQ 均衡器10 段图形化 EQ
音量均衡基于 LUFS 的响度标准化
事件回调播放进度、状态变化等回调

依赖

toml
[dependencies]
napi = "2"
napi-derive = "2"
# libmpv 通过 FFI 绑定调用

调用方式

typescript
import { MpvPlayer } from 'echo-mpv-player'

const player = new MpvPlayer()
player.load('https://example.com/song.mp3')
player.play()
player.setVolume(80)
player.setEq([0, 2, -1, 3, 0, 1, 2, 0, -2, 1])

echo-media-controls — 系统媒体控制

集成各操作系统的原生媒体控制 API。

核心功能

平台API说明
macOSMPNowPlayingInfoCenter控制中心媒体信息展示
macOSMPRemoteCommandCenter响应系统媒体键
WindowsSMTC系统媒体传输控制
LinuxMPRISD-Bus 媒体播放器接口

调用方式

typescript
import { MediaControls } from 'echo-media-controls'

const controls = new MediaControls()
controls.setMetadata({
  title: '歌曲名',
  artist: '歌手',
  album: '专辑',
  duration: 240,  // 秒
})
controls.setPlaybackState('playing')
controls.on('play', () => { /* 播放 */ })
controls.on('pause', () => { /* 暂停 */ })
controls.on('next', () => { /* 下一首 */ })
controls.on('previous', () => { /* 上一首 */ })

echo-storage — 本地存储

基于 SQLite 的轻量级本地持久化存储。

核心功能

功能说明
键值存储通用 K-V 存储,支持序列化
播放队列持久化播放队列与状态
播放历史记录播放历史
收藏管理歌曲/歌单收藏列表
设置存储应用偏好设置

调用方式

typescript
import { Storage } from 'echo-storage'

const db = new Storage()
await db.open('echo-music.db')

// 设置存储
await db.set('settings', { theme: 'dark', volume: 80 })

// 读取设置
const settings = await db.get('settings')

// 播放历史
await db.addHistory({ songId: 'xxx', playedAt: Date.now() })
const history = await db.getHistory({ limit: 50 })

开发原生模块

添加新的原生模块

  1. native/ 下创建新 crate:
bash
cd native
npx @napi-rs/cli new my-new-addon
  1. 在 Cargo.toml 中配置依赖
  2. 在 lib.rs 中使用 #[napi] 宏导出函数
  3. 在 Electron 主进程中加载 .node 文件

编译

bash
# Debug 编译
cd native/<module>
cargo build

# Release 编译(优化后)
cargo build --release

跨平台编译注意事项

  • macOS.dylib → 重命名为 .node
  • Linux.so → 重命名为 .node
  • Windows.dll → 重命名为 .node

.node 文件在 .gitignore 中被排除,每次克隆后需重新编译。

调试技巧

  • 使用 println!() 宏输出调试信息(会输出到 Electron 主进程控制台)
  • 在 Rust 代码中使用 napi::bindgen_prelude::console_log!() 输出到 Node.js 控制台
  • 推荐使用 VS Code + rust-analyzer 进行开发

参考资源