- 后端
【免费下载链接】discord.js
A powerful JavaScript library for interacting with the Discord API
@discordjs/voice是 discord.js 官方对 Discord Voice API 的 TypeScript 实现,承载了机器人加入语音频道、播放与接收音频的核心能力。本文以 packages/voice/CHANGELOG.md 为骨架,结合仓库源码逐版梳理 0.8.0 → 0.19.2 之间影响最大的一批变更——包括加密后端迁移、DAVE 端到端加密落地、Voice Gateway v8 升级与 Node.js 版本门槛变化——帮助你在升级依赖时准确评估破坏性变更,并理解底层实现原理。
版本演进总览
该包当前版本为0.19.2(见 package.json),CHANGELOG 记录的主要里程碑如下:
| 版本 | 发布时间 | 核心主题 |
|---|---|---|
| 0.19.2 | 2026-03-13 | 剥离 RTP 包填充字节并增加守卫 |
| 0.19.1 | 2026-03-09 | DAVE 成为必需、修复负超时与多转换并发、移除 builders/formatters 再导出 |
| 0.19.0 | 2025-08-17 | 实现 DAVE 端到端加密、升级 Voice Gateway v8、Node.js 门槛提升 |
| 0.18.0 | 2024-11-17 | 移除 tweetnacl,迁移到新一代加密库(破坏性变更) |
| 0.17.0 | 2024-05-04 | TransformerGraph 修复、FFmpeg 优化检测改为懒加载 |
| 0.15.0 | 2023-03-12 | 心跳保活不再等待响应 |
| 0.11.0 | 2022-07-17 | VoiceReceiver 数据包解析修复、恢复类型化事件 |
下文按「加密体系」「连接与网络」「音频处理」「工程化」四条主线展开说明。
加密体系的两次大变革
语音包加密是 voice 包演进的主线,先后经历了两次方向性调整:0.18.0淘汰 tweetnacl,0.19.0引入 DAVE 协议。
0.18.0:告别 tweetnacl,迁移到新加密库
0.18.0是一次带有BREAKING CHANGE的版本:由于 Discord 官方废弃了 tweetnacl 所支持的旧加密算法(xsalsa20-poly1305系列),该库不再支持以tweetnacl作为加密后端。受影响用户需迁移到以下任一方案:
sodium-nativesodium@stablelib/xchacha20poly1305@noble/cipherslibsodium-wrappers
如果系统本身支持aes-256-gcm,则无需安装任何加密库。可以通过如下命令验证:
require('node:crypto').getCiphers().includes('aes-256-gcm');这一设计在源码中有完整印证:packages/voice/src/util/Secretbox.ts 定义了统一的Methods接口(crypto_aead_xchacha20poly1305_ietf_encrypt/decrypt),并为五个候选库逐一提供适配器;加载时通过动态import依次尝试,只要有一个库能成功导入就立即使用。若全部缺失,则会抛出提示安装加密库的明确错误:
Cannot play audio as no valid encryption package is installed. - Install one of: - sodium - libsodium-wrappers - @stablelib/xchacha20poly1305 - @noble/ciphers. - Use the generateDependencyReport() function for more information.注意libsodium-wrappers需要先等待其ready标记再使用(源码中if (libName === 'libsodium-wrappers' && lib.ready) await lib.ready;),这是它异步初始化 WASM 导致的。
从 packages/voice/src/networking/Networking.ts 可以看到加密模式的实际选择逻辑:SUPPORTED_ENCRYPTION_MODES默认只含AeadXChaCha20Poly1305RtpSize,只有当crypto.getCiphers()包含aes-256-gcm时,才把AeadAes256GcmRtpSize置于列表首位优先协商。
0.19.0:DAVE 端到端加密落地
0.19.0实现了DAVE(Discord Audio & Video End-to-End Encryption)协议(PR #10921),语音数据在传输前即完成加密,服务端不再能看到明文音频。配套变更还包括:
- Voice Gateway 升级到 v8(PR #10918),承载 DAVE 握手相关的新消息类型;
- 原生
aes-256-gcm支持检测(PR #10764),运行时打印系统是否支持该密码套件; - 首个贡献者 @Snazzah 正是 DAVE 实现的主要作者。
0.19.1进一步将 DAVE 升级为必需依赖(PR #11385):@snazzah/davey是当前唯一受支持的 DAVE 协议库,且随包预装,无需用户手动安装。这一点在 package.json 的 dependencies 中可以看到"@snazzah/davey": "^0.1.11"。
底层实现位于 packages/voice/src/networking/DAVESession.ts,它包装了 davey 的会话对象,负责:
- 协议版本协商:
protocolVersion为 0 表示未启用 DAVE;getMaxProtocolVersion()直接取自Davey.DAVE_PROTOCOL_VERSION; - 过渡(Transition)管理:
prepareTransition/executeTransition配合pendingTransitionsMap 处理升级与降级。降级到 v0 时先进入 passthrough 模式,TRANSITION_EXPIRY_PENDING_DOWNGRADE(24 秒)为连接延迟留出缓冲;0.19.1修复的"同时处理多个转换"(PR #11100)正对应这套并发逻辑; - 解密容错自愈:连续解密失败次数超过
decryptionFailureTolerance(默认DEFAULT_DECRYPTION_FAILURE_TOLERANCE = 36)后,recoverFromInvalidTransition会重新初始化会话; - 对静音帧放行:
encrypt/decrypt对SILENCE_FRAME直接透传,避免无谓的加解密开销。
0.19.1的另一处修复是负超时处理(PR #11362),防止在abortAfter等场景传入负数导致行为异常;同版本还移除了对 builders 与 formatters 的再导出(PR #11361),依赖这些符号的外部代码需要改为直接从对应包导入。
0.19.2:剥离 RTP 填充并增加守卫
0.19.2修复了接收端 RTP 数据包中携带填充字节(padding)时解析不正确的问题:现在会先剥离填充并增加边界守卫(PR #11449),提升与其他客户端互操作时的健壮性。RTP 载荷类型常量RTP_OPUS_PAYLOAD_TYPE = 0x78定义在 packages/voice/src/util/constants.ts。
连接层:Gateway v8 与心跳保活
- Voice Gateway v8(0.19.0):网络层状态机
NetworkingStatusCode(OpeningWs → Identifying → UdpHandshaking → SelectingProtocol → Ready → Resuming → Closed)定义在 packages/voice/src/networking/Networking.ts,消息类型使用discord-api-types/voice/v8,NetworkingReadyState中新增了可选的dave会话字段。 - 心跳不再等待响应(0.15.0):PR #9202 让 keep-alive 发送后不阻塞等待应答,降低了网络抖动对连接状态机的干扰。
Buffer#slice()→Buffer#subarray()(0.19.1):全局替换避免了slice复制内存的开销,subarray共享底层内存,在高频语音包处理场景下减少 GC 压力。
音频处理与接收端的稳定性修复
- TransformerGraph(0.17.0 / 0.16.1):修复了可读输入场景下输入参数未显式传入的问题(PR #9793),确保 FFmpeg/Opus 转换图在各类输入源下参数传递一致。
- FFmpeg 优化检测懒加载(0.17.0):
getNode/canEnableFFmpegOptimizations被移入懒加载调用(PR #9918),避免在模块加载阶段就执行昂贵的环境探测。 - VoiceReceiver(0.11.0):修复
parsePacket对 RTP 头的解析(PR #8277);SpeakingMap修正事件名以兼容 docgen(PR #8236);0.11.0 还恢复了类型化事件(PR #8109)。 - 本地/预览检测(0.17.0):新增 local 与 preview 环境的探测能力,便于在非生产网关环境下调试。
Node.js 版本门槛的持续提升
CHANGELOG 中记录了两次 Build 级别的BREAKING CHANGE:
| 版本 | 最低 Node.js | 说明 |
|---|---|---|
| 0.19.0 | 22.12.0(PR #10726) | 配合 DAVE 与新版工具链 |
| 0.19.0 内 | 20(PR #10616) | 先升到 20,再进一步升到 22.12 |
| 当前 | 24.17.0 | 见 package.jsonengines字段 |
升级时务必先确认运行环境的 Node.js 满足要求,否则engines检查会直接失败。
如何快速验证依赖环境
CHANGELOG 多次提到依赖安装问题,实际排查时可使用包内自带的依赖报告工具 packages/voice/src/util/generateDependencyReport.ts:generateDependencyReport()会汇总 Core(@discordjs/voice、prism-media)、Opus(@discordjs/opus、opusscript)、Encryption(aes-256-gcm支持情况及五个候选库)、DAVE(@snazzah/davey)与 FFmpeg(版本及--enable-libopus)的安装情况,是定位"无法播放音频"类问题最快的手段。
小结与升级建议
纵观0.8.0至0.19.2,@discordjs/voice的演进主线十分清晰:从兼容多加密后端(Secretbox 适配器体系),到跟随 Discord 官方废弃旧算法,再到主动实现 DAVE 端到端加密并强制要求 davey,同时持续收紧 Node.js 版本门槛、优化包处理性能。升级路径上的关键动作有三:
- 确认 Node.js ≥ 24.17.0;
- 若系统不支持
aes-256-gcm,从五个候选加密库中任选其一安装; - 若用到 builders/formatters 的再导出,改为从
@discordjs/builders、@discordjs/formatters直接导入。
如需深入验证上述行为,可直接阅读 DAVESession.ts、Secretbox.ts 与 Networking.ts 的对应实现,以及tests目录下覆盖这些逻辑的单元测试。
- 后端
【免费下载链接】discord.js
A powerful JavaScript library for interacting with the Discord API
相关推荐
SQLCipher数据库迁移:从普通SQLite到加密版本
SQLCipher数据库迁移:从普通SQLite到加密版本 引言:为什么需要数据库加密? 在当今数字化时代,数据安全已成为重中之重。SQLite作为一款轻量级嵌
数据库关系型数据库嵌入式数据库密码学Dify.AI数据加密:端到端加密
Dify.AI数据加密:端到端加密 概述 在人工智能应用开发领域,数据安全是至关重要的考量因素。Dify.AI作为一个开源的大型语言模型应用开发平台,采用了先进
人工智能大模型LLMOpsAI 应用RAGAI Agent低代码Joplin 端到端加密同步快照深度解析:从 JED 密文格式到 Sync Version 3 迁移测试
Joplin 端到端加密同步快照深度解析:从 JED 密文格式到 Sync Version 3 迁移测试 Joplin 以"隐私优先的笔记同步"为核心能力,其端
知识管理跨平台插件系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考