Fix: Loudnorm-Cache korrekt als Stream lesen + Tee-Caching
Zwei Fehler behoben: 1. Gecachte PCM-Datei wurde als Pfad-String an createAudioResource übergeben → discord.js versuchte die headerlose PCM als Container zu proben → Rauschen/Stille Fix: fs.createReadStream() + StreamType.Raw 2. Erster Play wartete auf komplette ffmpeg-Verarbeitung bevor Wiedergabe startete Fix: Tee-Stream — ffmpeg-Output wird gleichzeitig an Player UND Cache-Datei geschrieben → Sofortige Wiedergabe auch beim ersten Mal, Cache wird nebenbei gefüllt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4b4a61b2bd
commit
83b8f1acac
1 changed files with 29 additions and 21 deletions
|
|
@ -24,6 +24,7 @@ import sodium from 'libsodium-wrappers';
|
|||
import nacl from 'tweetnacl';
|
||||
// Streaming externer Plattformen entfernt – nur MP3-URLs werden noch unterstützt
|
||||
import child_process from 'node:child_process';
|
||||
import { PassThrough } from 'node:stream';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
|
@ -311,29 +312,36 @@ async function playFilePath(guildId: string, channelId: string, filePath: string
|
|||
: (state.currentVolume ?? 1);
|
||||
let resource: AudioResource;
|
||||
if (NORMALIZE_ENABLE) {
|
||||
// Cache-basierte Normalisierung: ffmpeg läuft nur beim 1. Mal
|
||||
let cachedPath = getNormCachePath(filePath);
|
||||
if (!cachedPath) {
|
||||
try {
|
||||
cachedPath = await normalizeToCache(filePath);
|
||||
const cachedPath = getNormCachePath(filePath);
|
||||
if (cachedPath) {
|
||||
// Cache-Hit: gecachte PCM-Datei als Stream lesen (kein ffmpeg, instant)
|
||||
const pcmStream = fs.createReadStream(cachedPath);
|
||||
resource = createAudioResource(pcmStream, { inlineVolume: true, inputType: StreamType.Raw });
|
||||
} else {
|
||||
// Cache-Miss: ffmpeg streamen (sofortige Wiedergabe) UND gleichzeitig in Cache schreiben
|
||||
const cacheFile = path.join(NORM_CACHE_DIR, normCacheKey(filePath));
|
||||
const ffArgs = ['-hide_banner', '-loglevel', 'error', '-i', filePath,
|
||||
'-af', `loudnorm=I=${NORMALIZE_I}:LRA=${NORMALIZE_LRA}:TP=${NORMALIZE_TP}`,
|
||||
'-f', 's16le', '-ar', '48000', '-ac', '2', 'pipe:1'];
|
||||
const ff = child_process.spawn('ffmpeg', ffArgs);
|
||||
// Tee: Daten gleichzeitig an Player und Cache-Datei
|
||||
const playerStream = new PassThrough();
|
||||
const cacheWrite = fs.createWriteStream(cacheFile);
|
||||
ff.stdout.on('data', (chunk: Buffer) => {
|
||||
playerStream.write(chunk);
|
||||
cacheWrite.write(chunk);
|
||||
});
|
||||
ff.stdout.on('end', () => {
|
||||
playerStream.end();
|
||||
cacheWrite.end();
|
||||
console.log(`${new Date().toISOString()} | Loudnorm cached: ${path.basename(filePath)}`);
|
||||
} catch (e) {
|
||||
console.warn(`${new Date().toISOString()} | Loudnorm cache failed, fallback direct:`, e);
|
||||
// Fallback: direkt ohne Normalisierung abspielen
|
||||
resource = createAudioResource(filePath, { inlineVolume: true });
|
||||
if (resource.volume) resource.volume.setVolume(useVolume);
|
||||
state.player.stop();
|
||||
state.player.play(resource);
|
||||
state.currentResource = resource;
|
||||
state.currentVolume = useVolume;
|
||||
const soundLabel = relativeKey ? path.parse(relativeKey).name : path.parse(filePath).name;
|
||||
nowPlaying.set(guildId, soundLabel);
|
||||
sseBroadcast({ type: 'nowplaying', guildId, name: soundLabel });
|
||||
if (relativeKey) incrementPlaysFor(relativeKey);
|
||||
return;
|
||||
});
|
||||
ff.on('error', () => { try { fs.unlinkSync(cacheFile); } catch {} });
|
||||
ff.on('close', (code) => {
|
||||
if (code !== 0) { try { fs.unlinkSync(cacheFile); } catch {} }
|
||||
});
|
||||
resource = createAudioResource(playerStream, { inlineVolume: true, inputType: StreamType.Raw });
|
||||
}
|
||||
}
|
||||
resource = createAudioResource(cachedPath, { inlineVolume: true, inputType: StreamType.Raw });
|
||||
} else {
|
||||
resource = createAudioResource(filePath, { inlineVolume: true });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue