fix(media): Umstieg auf yt-dlp -> ffmpeg Transcoding (s16le/48kHz) statt ytdl-core; stabil gegen 410

This commit is contained in:
vibe-bot 2025-08-08 16:42:27 +02:00
parent 598ebaeda6
commit e401124001

View file

@ -14,6 +14,7 @@ import {
getVoiceConnection, getVoiceConnection,
type VoiceConnection, type VoiceConnection,
type AudioResource, type AudioResource,
StreamType,
generateDependencyReport, generateDependencyReport,
entersState, entersState,
VoiceConnectionStatus VoiceConnectionStatus
@ -623,26 +624,13 @@ app.post('/api/play-url', async (req: Request, res: Response) => {
const useVolume = typeof volume === 'number' ? Math.max(0, Math.min(1, volume)) : state.currentVolume ?? 1; const useVolume = typeof volume === 'number' ? Math.max(0, Math.min(1, volume)) : state.currentVolume ?? 1;
// Audio-Stream besorgen // Audio-Stream besorgen
let stream: any; // Einheitlicher Weg: yt-dlp + ffmpeg Transcoding (stabiler als ytdl-core)
if (ytdl.validateURL(url)) { const yt = child_process.spawn('yt-dlp', ['-f', 'bestaudio', '--no-playlist', '--quiet', '--no-warnings', '-o', '-', url]);
// Nutze ytdl-core, fallback auf yt-dlp bei HTTP Fehlern (410/403 etc.) yt.on('error', (err) => console.error('yt-dlp spawn error:', err));
try { const ff = child_process.spawn('ffmpeg', ['-i', 'pipe:0', '-f', 's16le', '-ar', '48000', '-ac', '2', 'pipe:1']);
stream = ytdl(url, { filter: 'audioonly', quality: 'highestaudio', highWaterMark: 1 << 25 }); yt.stdout.pipe(ff.stdin);
stream.on('error', (e: any) => { throw e; });
} catch (e) {
console.warn('ytdl-core fehlgeschlagen, versuche yt-dlp:', e);
const yt = child_process.spawn('yt-dlp', ['-f', 'bestaudio', '-o', '-', url]);
yt.on('error', (err) => console.error('yt-dlp spawn error:', err));
stream = yt.stdout;
}
} else {
// Fallback via yt-dlp, benötigt binary im Image/Host
// wir nutzen stdout mit ffmpeg pipe
const yt = child_process.spawn('yt-dlp', ['-f', 'bestaudio', '-o', '-', url]);
stream = yt.stdout;
}
const resource = createAudioResource(stream as any, { inlineVolume: true }); const resource = createAudioResource(ff.stdout as any, { inlineVolume: true, inputType: StreamType.Raw });
if (resource.volume) resource.volume.setVolume(useVolume); if (resource.volume) resource.volume.setVolume(useVolume);
state.player.stop(); state.player.stop();
state.player.play(resource); state.player.play(resource);