feat: implement Opus demuxing for browser streams, cache headers for playback, and enable microphone input in recorder
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
# Discord Bot Token (dari Discord Developer Portal)
|
||||
DISCORD_TOKEN=""
|
||||
|
||||
# ID Channel Voice yang ingin di-join bot saat startup
|
||||
VOICE_CHANNEL_ID=
|
||||
GUILD_ID=
|
||||
# Folder penyimpanan rekaman (opsional, default: ./recordings)
|
||||
RECORDINGS_DIR=./recordings
|
||||
+8
-5
@@ -8,6 +8,8 @@ import {
|
||||
} from "@discordjs/voice";
|
||||
import { Readable } from "stream";
|
||||
|
||||
import prism from "prism-media";
|
||||
|
||||
export class DiscordPlayer {
|
||||
private player: AudioPlayer;
|
||||
private connection: VoiceConnection | null = null;
|
||||
@@ -30,12 +32,13 @@ export class DiscordPlayer {
|
||||
}
|
||||
|
||||
public playStream(stream: Readable) {
|
||||
// We assume the stream is Opus or PCM.
|
||||
// For MediaRecorder (webm/opus), we might need to parse it.
|
||||
// But let's start with a simple resource.
|
||||
const resource = createAudioResource(stream, {
|
||||
inputType: StreamType.WebmOpus,
|
||||
// Use WebmDemuxer to extract Opus packets from browser stream
|
||||
const demuxer = new prism.opus.WebmDemuxer();
|
||||
|
||||
const resource = createAudioResource(stream.pipe(demuxer), {
|
||||
inputType: StreamType.Opus,
|
||||
});
|
||||
|
||||
this.player.play(resource);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ export async function startRecording(client: Client, channel: VoiceChannel): Pro
|
||||
guildId: channel.guild.id,
|
||||
adapterCreator: channel.guild.voiceAdapterCreator as any,
|
||||
selfDeaf: false,
|
||||
selfMute: true,
|
||||
selfMute: false,
|
||||
debug: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -11,12 +11,17 @@ export function startWebserver(port: number = 3000) {
|
||||
const wss = new WebSocketServer({ server });
|
||||
|
||||
const listeners = new Set<express.Response>();
|
||||
let headerChunks: Buffer[] = [];
|
||||
|
||||
app.use(express.static(path.join(__dirname, "../public")));
|
||||
|
||||
// Endpoint for receiving (listening) audio from Discord
|
||||
app.get("/listen", (req, res) => {
|
||||
res.setHeader("Content-Type", "audio/ogg");
|
||||
|
||||
// Send cached headers so the browser can decode the stream
|
||||
headerChunks.forEach(chunk => res.write(chunk));
|
||||
|
||||
listeners.add(res);
|
||||
console.log(`[webserver] New listener connected. Total: ${listeners.size}`);
|
||||
|
||||
@@ -28,6 +33,10 @@ export function startWebserver(port: number = 3000) {
|
||||
|
||||
// Function to broadcast audio chunks to all listeners
|
||||
(global as any).broadcastToWeb = (chunk: Buffer) => {
|
||||
// Store the first two chunks as headers (OpusHead and OpusTags)
|
||||
if (headerChunks.length < 2) {
|
||||
headerChunks.push(chunk);
|
||||
}
|
||||
listeners.forEach(res => res.write(chunk));
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user