mirror of
https://github.com/YuzuZensai/NekoMelody.git
synced 2026-01-31 14:57:58 +00:00
🐛 fix: Skip error
This commit is contained in:
@@ -21,12 +21,10 @@ const main = async () => {
|
|||||||
player.startCurrentStream();
|
player.startCurrentStream();
|
||||||
});
|
});
|
||||||
|
|
||||||
const info = await player.enqueue(
|
await player.enqueue(`https://www.youtube.com/watch?v=${videoId}`);
|
||||||
`https://www.youtube.com/watch?v=${videoId}`,
|
|
||||||
);
|
|
||||||
console.log(info);
|
|
||||||
|
|
||||||
await player.enqueue(`https://www.youtube.com/watch?v=${videoId2}`);
|
await player.enqueue(`https://www.youtube.com/watch?v=${videoId2}`);
|
||||||
|
|
||||||
|
console.log(player.getQueue());
|
||||||
};
|
};
|
||||||
|
|
||||||
let lastFFmpeg: ffmpeg.FfmpegCommand | null = null;
|
let lastFFmpeg: ffmpeg.FfmpegCommand | null = null;
|
||||||
@@ -68,6 +66,7 @@ const playSpeaker = async (player: Player) => {
|
|||||||
// .on("end", async () => {
|
// .on("end", async () => {
|
||||||
// await closeSpeaker();
|
// await closeSpeaker();
|
||||||
// })
|
// })
|
||||||
|
// @ts-expect-error - ffmpeg typings are incorrect
|
||||||
.on("error", (err) => {
|
.on("error", (err) => {
|
||||||
console.error("[FFmpeg] > Error:", err.message);
|
console.error("[FFmpeg] > Error:", err.message);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export class Player {
|
|||||||
private currentAudioInformation: AudioInformation | null = null;
|
private currentAudioInformation: AudioInformation | null = null;
|
||||||
|
|
||||||
public _stream: SeekableStream | null = null;
|
public _stream: SeekableStream | null = null;
|
||||||
|
private _skipFlag: boolean = false;
|
||||||
|
|
||||||
constructor(providers: Provider[]) {
|
constructor(providers: Provider[]) {
|
||||||
this.providers = providers;
|
this.providers = providers;
|
||||||
@@ -25,26 +26,17 @@ export class Player {
|
|||||||
information: AudioInformation,
|
information: AudioInformation,
|
||||||
url: string,
|
url: string,
|
||||||
seekTime: number,
|
seekTime: number,
|
||||||
|
noDestroy: boolean = false,
|
||||||
) {
|
) {
|
||||||
// If already playing, destroy the current stream
|
// If already playing, destroy the current stream
|
||||||
if (this._stream) {
|
if (this._stream && !noDestroy) {
|
||||||
this._stream.destroy();
|
this._stream.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._stream = new SeekableStream(information, url, seekTime);
|
this._stream = new SeekableStream(information, url, seekTime);
|
||||||
this.currentAudioInformation = information;
|
this.currentAudioInformation = information;
|
||||||
this._stream.on("destroy", () => {
|
this._stream.on("destroy", () => {
|
||||||
console.log("Stream destroyed, total song", this.queue.length);
|
console.debug("Stream destroyed");
|
||||||
if (this.queue.length > 0) {
|
|
||||||
const next = this.queue.shift();
|
|
||||||
console.log("Playing next in queue");
|
|
||||||
if (next) {
|
|
||||||
this._createStream(next, next.url, 0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._stream = null;
|
|
||||||
this.currentAudioInformation = null;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.playerEvent.emit("play", information);
|
this.playerEvent.emit("play", information);
|
||||||
@@ -56,10 +48,30 @@ export class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public endCurrentStream() {
|
public endCurrentStream(skip: boolean = false) {
|
||||||
|
if (this._skipFlag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
this._skipFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._stream) {
|
if (this._stream) {
|
||||||
this._stream.destroy();
|
this._stream.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.queue.length > 0) {
|
||||||
|
const next = this.queue.shift();
|
||||||
|
if (next) {
|
||||||
|
this._createStream(next, next.url, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._stream = null;
|
||||||
|
this.currentAudioInformation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._skipFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public on(event: string, listener: (...args: any[]) => void) {
|
public on(event: string, listener: (...args: any[]) => void) {
|
||||||
@@ -79,12 +91,17 @@ export class Player {
|
|||||||
this.currentProvider = providers[0];
|
this.currentProvider = providers[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.debug(
|
||||||
|
"Using provider",
|
||||||
|
this.currentProvider.constructor.name,
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
|
||||||
return await this.currentProvider.getInformation(url);
|
return await this.currentProvider.getInformation(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async play(url: string, seekTime: number = 0) {
|
public async play(url: string, seekTime: number = 0) {
|
||||||
const information = await this.getInformation(url);
|
const information = await this.getInformation(url);
|
||||||
//console.log(information);
|
|
||||||
|
|
||||||
if (information.livestream)
|
if (information.livestream)
|
||||||
// TODO: Implement livestreams
|
// TODO: Implement livestreams
|
||||||
@@ -124,14 +141,8 @@ export class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async skip() {
|
public async skip() {
|
||||||
if (this.queue.length === 0) {
|
this.endCurrentStream(true);
|
||||||
throw new Error("No song in queue");
|
console.debug("Skipping");
|
||||||
}
|
|
||||||
|
|
||||||
const next = this.queue.shift();
|
|
||||||
if (next) {
|
|
||||||
this._createStream(next, next.url, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCurrentSampleRate() {
|
public getCurrentSampleRate() {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export async function getYouTubeFormats(id: string) {
|
|||||||
waitUntil: "networkidle2",
|
waitUntil: "networkidle2",
|
||||||
});
|
});
|
||||||
const body = await page.evaluate(() => document.body.innerHTML);
|
const body = await page.evaluate(() => document.body.innerHTML);
|
||||||
await page.close();
|
page.close();
|
||||||
|
|
||||||
const match = body.match(
|
const match = body.match(
|
||||||
/var ytInitialPlayerResponse = (.*?)(?=;\s*<\/script>)/,
|
/var ytInitialPlayerResponse = (.*?)(?=;\s*<\/script>)/,
|
||||||
@@ -91,6 +91,7 @@ export async function getYouTubeFormats(id: string) {
|
|||||||
|
|
||||||
return formats;
|
return formats;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
throw new Error("Failed to parse YouTube formats");
|
throw new Error("Failed to parse YouTube formats");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,6 +366,10 @@ export class SeekableStream {
|
|||||||
this.event.on(event, listener);
|
this.event.on(event, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeAllListeners(event: string) {
|
||||||
|
this.event.removeAllListeners(event);
|
||||||
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
if (this.destroyed) return;
|
if (this.destroyed) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user