如何在 Node JS 中为 Discord 机器人将原始 PCM 流转换为 opus 或 wav 流?

问题描述

​​背景:

我正在为 Discord 创建个人音乐机器人,主要使用 discord.js,我想添加功能之一是让机器人直接从 Voicemeeter 播放音频。这个解决方案是最佳的,因为机器人能够以比 discord 用户更好的质量进行流式传输,并且他们能够播放立体声而不是单声道,我可以选择使用 Voicemeeter 流式传输的源。

Voicemeeter 带有一项称为 VBAN 的功能,它允许您使用 VBAN protocol 通过网络将音频数据发送到另一台运行 VBAN 接收器的计算机。

Jacob Bower 在 Node JS 中制作了一个 VBAN receiver script,它获取原始 PCM 音频数据并使用 node-speaker 通过您的扬声器播放。

问题:

使用 Jacob 的脚本,如果您尝试将 PCM 音频直接通过管道传输到 discord 机器人,则会出现错误错误 [VOICE_PLAY_INTERFACE_BAD_TYPE]:未知流类型”。我相信这是因为从脚本接收的 PCM 音频包含在一个缓冲区中,discord bot 无法本地播放。我需要找到一种方法以可读格式获取 PCM 音频,以便 discord 机器人播放。 (我认为可读格式包括 opus 和 wav,(可能还有其他非 PCM 的流媒体格式)

我尝试过的:

  • 如上所述,我直接将 PCM 音频缓冲区通过管道传输到机器人中,但它给出了错误
  • 我尝试将缓冲区放入 Passthrough 流,并将该流通过管道传输到机器人中。 这在控制台中没有错误,机器人像它应该的那样加入语音通道,并且不发出声音。我认为这是因为 discord.js 不支持播放我事后了解到的原始 PCM 音频。
  • The Discord.js guide 提到 PCM 需要使用 opus 进行编码才能在不和谐状态下播放。所以我尝试使用 opus encoder built into discord.js。首先,我尝试对每个 PCM 缓冲区进行编码并将其写入 Passthrough 流。
const { OpusEncoder } = require('@discordjs/opus');
const { Passthrough } = require('stream');
const EncodedStream = new Passthrough();
const encoder = new OpusEncoder(48000,2); //48000 hz,2 channels

. . .

if (data.header.sp == 0) { //This code executes each time there is a new frame sent from VBAN
     EncodedStream.write(encoder.encode(data.audio));
}

. . .

connection.play(EncodedStream); //Connection is just the Bot being inside a voice channel.

遇到错误 "Cannot create a Buffer larger than 0xffffffff bytes." 我不知道为什么会出现这个错误,因为在每个缓冲区上运行 Buffer.byteLength 会产生 1024。

  • 然后我继续尝试使用 prism-media 对流进行编码,发现更多错误并且更多机器人保持沉
  • 我安装了一些 npm 模块,声称它们可以将流转换为 AudioBuffers,另一个模块可以将 PCM AudioBuffer 转换为可用的 wav 格式,但我也发现了更多错误

我现在正竭尽全力解决这个问题,如果能帮助我指明正确的方向,我们将不胜感激。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)