Pouvez-vous m’aider à convertir le format audio Twilio mu-law 8Hz en un format lisible en temps réel dans Discord.js? J’essaie de créer un bot Discord qui peut diffuser l’audio reçu d’un appel Twilio, mais j’ai des problèmes avec la conversion de format. Avez-vous des suggestions sur la façon dont je peux y parvenir?
Je sais qu’ici il y a des cracks.
Voilà ce que j’ai essayé. Je reçois un payload mulaw, 8khz, 1 canal encodé en base64, que je décode, puis tente de convertir en PCM pour qu’il soit lu par discord.js, mais ça ne marche pas. J’ai également essayé de le convertir en opus avec la librairie @discord.js/opus, mais la conversion de marche pas je tombe sur message d’erreur (Error: Cannot create a Buffer larger than 0x100000000 bytes, cf https://github.com/discordjs/opus/issues/51).
console.log("Receiving audio...");
// ici, je voudrais essayer de convertir le payload dans un format qui puisse être lu par discord.js
// J'essaye de le convertir en PCM, mais sans succès.
const payload = msg.media.payload;
const wav = new WaveFile();
wav.fromScratch(1, 8000, "8m", Buffer.from(payload, "base64"));
wav.fromMuLaw();
// You can resample.
wav.toSampleRate(16000);
// You can write this straight to a file (will have the headers)
const results = wav.toBuffer();
// Or you can access the samples without the WAV header
const samples = wav.data.samples;
fs.writeFileSync('./stream.wav', results);
try {
const resource = createAudioResource('./stream.wav');
player.play(resource);
} catch (ex) {
console.log(ex);
}
Code complet:
const { WebSocketServer } = require("ws");
const base64 = require("base64-js");
const Discord = require("discord.js");
const client = new Discord.Client();
const { VoiceConnectionStatus, Events } = require("@discordjs/voice");
const {
getVoiceConnection,
createAudioResource,
createAudioPlayer,
NoSubscriberBehavior,
joinVoiceChannel,
StreamType,
createDefaultAudioReceiveStreamOptions,
} = require("@discordjs/voice");
const RADIO_VOICE_CHANNEL = "1000397725231235205";
const RADIO_TEXT_CHANNEL = "1000397055442817096";
const { createReadStream } = require("node:fs");
const { Readable } = require("stream");
const WaveFile = require("wavefile").WaveFile;
const fs = require("fs");
const { OpusEncoder } = require("@discordjs/opus");
const pcmUtil = require("pcm-util");
const wav = require("wav");
const convert = require("pcm-convert");
client.login(`TOKEN`);
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
const channel = client.channels.cache.get(RADIO_VOICE_CHANNEL);
if (!channel) {
return console.error("The channel does not exist!");
}
connection = joinVoiceChannel({
channelId: channel.id,
guildId: channel.guild.id,
adapterCreator: channel.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false,
});
connection.on(VoiceConnectionStatus.Ready, () => {
console.log("Connection ready");
});
});
let resource = null;
let player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Pause,
},
});
const wss = new WebSocketServer({ port: 5000 });
wss.on("connection", (ws) => {
console.log("Connection accepted");
connection.subscribe(player);
ws.on("message", async (message) => {
const msg = JSON.parse(message);
switch (msg.event) {
case "connected":
console.log("A new call has connected");
break;
case "start":
console.log(`Starting media stream...`, msg);
break;
case "media":
console.log("Receiving audio...");
// ici, je voudrais essayer de convertir le payload dans un format qui puisse être lu par discord.js
// J'essaye de le convertir en PCM, mais sans succès.
const payload = msg.media.payload;
const wav = new WaveFile();
wav.fromScratch(1, 8000, "8m", Buffer.from(payload, "base64"));
wav.fromMuLaw();
// You can resample.
wav.toSampleRate(16000);
// You can write this straight to a file (will have the headers)
const results = wav.toBuffer();
// Or you can access the samples without the WAV header
const samples = wav.data.samples;
fs.writeFileSync('./stream.wav', results);
try {
const resource = createAudioResource('./stream.wav');
player.play(resource);
} catch (ex) {
console.log(ex);
}
break;
case "stop":
console.log("Call has ended");
break;
default:
break;
}
});
ws.on("close", () => {
console.log(`Connection closed.`);
});
});