我正在使用simple-peer将带有AudioTrack的MediaStream从浏览器窗口发送到本地托管的服务器(通过电子BrowserView与通过Puppeteer插入到主进程的代码隔离)
通过查看源代码并阅读文档,我能够成功地在两者之间建立连接并接收MediaStream。我发现,当您将node-webrtc (wrtc on NPM)用作webrtc实现时,ontrack事件还会为您提供该库的MediaTrack实现。然后,您可以使用非标准的RTCAudioSink获取RTCAudioData对象(记录在here中)。
这是我代码的相关部分:
/* ... */
// Requiring node-webrtc and simple-peer
const { RTCAudioSink } = require("wrtc").nonstandard;
const SimplePeer = require("simple-peer");
/* ... */
// A self-executing async function to wrap my code
(async () => {
/* Variable initialization */
const peer = new Peer({ wrtc: wrtc });
/* ... */
// This function is called when the BrowserView is created, but the events are fired later on
function setPeerDataToMainPeerFunction() {
// Page is a reference to a Puppeteer Page
page.exposeFunction("sendDataToPeer", (data) => {
peer.signal(data);
});
// Establishing the connection
peer.on('signal', data => {
page.evaluate((data) => {
//@ts-ignore
window.simplePeerPeer.signal(data)
}, data);
});
// The important event handler where I try to play the newly added MediaTrack
// There is always only one AudioTrack present in the MediaStream at one time.
peer.on('track', (track, stream) => {
/**
* @type {MediaStreamTrack}
*/
const audioTrack = stream.getAudioTracks()[0];
const sink = new RTCAudioSink(audioTrack);
sink.ondata = (rtcAudioData) => {
console.log(rtcAudioData);
// Here, I want to play the rtcAudioData.
// Obviously, simply calling the play function on a VoiceConnection (Discord.js) with rtcAudioData won't work.
}
let streamtest = fs.createReadStream(buffer);
bot.functions.playAudioStream(streamtest);
// Stopping the sink, when the MediaStreamTrack ends
audioTrack.addEventListener("ended", () => { sink.stop() });
});
}
/* ... */
})();
运行脚本时,ondata事件处理程序的控制台输出将如下所示:
(请忽略,下面显示的AudioTrack的部分几乎没有声音。这不是我的问题。)
{
samples: Int16Array [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 0, 0, 0,
... 380 more items
],
bitsPerSample: 16,
sampleRate: 48000,
channelCount: 1,
numberOfFrames: 480,
type: 'data'
}
{
samples: Int16Array [
-1, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -2,
-2, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
0, -1, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0,
-1, -1, -1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
1, 0, 0, 0,
... 380 more items
],
bitsPerSample: 16,
sampleRate: 48000,
channelCount: 1,
numberOfFrames: 480,
type: 'data'
}
{
samples: Int16Array [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 380 more items
],
bitsPerSample: 16,
sampleRate: 48000,
channelCount: 1,
numberOfFrames: 480,
type: 'data'
}
{
samples: Int16Array [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0,
0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1,
-1, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 380 more items
],
bitsPerSample: 16,
sampleRate: 48000,
channelCount: 1,
numberOfFrames: 480,
type: 'data'
}
{
samples: Int16Array [
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,
1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1,
... 380 more items
],
bitsPerSample: 16,
sampleRate: 48000,
channelCount: 1,
numberOfFrames: 480,
type: 'data'
}
我想知道是否可以播放Discord.js中来自MediaStream的音频数据。