diff --git a/example/test.ts b/example/discord.ts similarity index 65% rename from example/test.ts rename to example/discord.ts index 99b3897..b23127e 100644 --- a/example/test.ts +++ b/example/discord.ts @@ -1,7 +1,5 @@ import NekoMelody, { Player } from "../src"; -import Speaker from "speaker"; -import ffmpeg from "fluent-ffmpeg"; import { NoSubscriberBehavior, VoiceConnectionStatus, @@ -76,6 +74,7 @@ const main = async () => { //inlineVolume: true, }); discordPlayer.play(resource); + player.startCurrentStream(); discordPlayer.on("stateChange", (oldState, newState) => { console.log("State change", oldState.status, newState.status); @@ -89,50 +88,4 @@ const main = async () => { await player.enqueue(`https://www.youtube.com/watch?v=${videoId2}`); }; -// TODO: player end event to automate changing the stream -let lastFFmpeg: ffmpeg.FfmpegCommand | null = null; -let lastSpeaker: Speaker | null = null; -const playSpeaker = async (player: Player) => { - if (!player.stream) { - console.error("No input stream"); - return; - } - - // A function that resolves when the speaker is closed and the ffmpeg process is killed - const closeSpeaker = () => { - return new Promise((resolve) => { - if (lastSpeaker) { - lastSpeaker.on("close", () => { - resolve(); - }); - if (lastFFmpeg) lastFFmpeg.kill("SIGKILL"); - lastSpeaker.close(true); - } else { - resolve(); - } - }); - }; - - await closeSpeaker(); - - // Create the Speaker instance - const speaker = new Speaker(); - lastSpeaker = speaker; - - // PCM data from stdin gets piped into the speaker - const ffmpegProcess = ffmpeg() - .input(player.stream) - .format("s16le") // Output format (PCM 16-bit little-endian) - .audioChannels(2) - .audioFrequency(44100) - .on("error", (err) => { - console.error("[FFmpeg] > Error:", err.message); - }); - - // Pipe the ffmpeg output to the speaker - ffmpegProcess.pipe(speaker, { end: true }); - - lastFFmpeg = ffmpegProcess; -}; - main(); diff --git a/example/speaker.ts b/example/speaker.ts new file mode 100644 index 0000000..c110053 --- /dev/null +++ b/example/speaker.ts @@ -0,0 +1,82 @@ +import NekoMelody, { Player } from "../src"; + +import Speaker from "speaker"; +import ffmpeg from "fluent-ffmpeg"; +import { YtDlpProvider } from "../src/providers"; +import { AudioInformation } from "../src/providers/base"; + +import dotenv from "dotenv"; +dotenv.config(); + +const main = async () => { + const videoId = "2gigEGxnsmo"; + const videoId2 = "oM-JneFEdBk"; + + // Providers + const providers = [new YtDlpProvider()]; + const player = NekoMelody.createPlayer(providers); + + player.on("play", async (information: AudioInformation) => { + await playSpeaker(player); + player.startCurrentStream(); + }); + + await player.enqueue(`https://www.youtube.com/watch?v=${videoId}`); + await player.enqueue(`https://www.youtube.com/watch?v=${videoId2}`); +}; + +let lastFFmpeg: ffmpeg.FfmpegCommand | null = null; +let lastSpeaker: Speaker | null = null; + +const playSpeaker = async (player: Player) => { + if (!player.stream) { + console.error("No input stream"); + return; + } + + // A function that resolves when the speaker is closed and the ffmpeg process is killed + const closeSpeaker = () => { + return new Promise((resolve) => { + if (lastSpeaker) { + lastSpeaker.on("close", () => { + resolve(); + }); + if (lastFFmpeg) lastFFmpeg.kill("SIGKILL"); + lastSpeaker.close(true); + } else { + resolve(); + } + }); + }; + + await closeSpeaker(); + + // Create the Speaker instance + const speaker = new Speaker(); + lastSpeaker = speaker; + + // PCM data from stdin gets piped into the speaker + const ffmpegProcess = ffmpeg() + .input(player.stream) + .format("s16le") // Output format (PCM 16-bit little-endian) + .audioChannels(2) + .audioFrequency(44100) + // .on("end", async () => { + // await closeSpeaker(); + // }) + .on("error", (err) => { + console.error("[FFmpeg] > Error:", err.message); + }); + + speaker.on("unpipe", () => { + console.log("Speaker ended"); + player.endCurrentStream(); + }); + + // Pipe the ffmpeg output to the speaker + ffmpegProcess.pipe(speaker, { end: true }); + + lastFFmpeg = ffmpegProcess; +}; + +main();