Ffmpeg fixx
This commit is contained in:
parent
b1bc4306eb
commit
f15a527de1
|
@ -5,6 +5,37 @@ const { EmbedBuilder } = require('discord.js');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { exec, spawn, execSync } = require('child_process');
|
const { exec, spawn, execSync } = require('child_process');
|
||||||
|
|
||||||
|
const MAX_RETRIES = 3;
|
||||||
|
const RETRY_DELAY = 1000;
|
||||||
|
|
||||||
|
function spawnFFmpegProcess(args, callback, retries = 0) {
|
||||||
|
const ffmpegProcess = spawn('ffmpeg', args);
|
||||||
|
|
||||||
|
ffmpegProcess.on('close', (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
callback(null);
|
||||||
|
} else if (retries < MAX_RETRIES) {
|
||||||
|
console.warn(`FFmpeg process failed, retrying (${retries + 1}/${MAX_RETRIES})...`);
|
||||||
|
setTimeout(() => {
|
||||||
|
spawnFFmpegProcess(args, callback, retries + 1);
|
||||||
|
}, RETRY_DELAY);
|
||||||
|
} else {
|
||||||
|
callback(new Error(`FFmpeg process failed after ${MAX_RETRIES} retries.`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ffmpegProcess.on('error', (err) => {
|
||||||
|
if (retries < MAX_RETRIES) {
|
||||||
|
console.warn(`FFmpeg process error, retrying (${retries + 1}/${MAX_RETRIES})...`, err);
|
||||||
|
setTimeout(() => {
|
||||||
|
spawnFFmpegProcess(args, callback, retries + 1);
|
||||||
|
}, RETRY_DELAY);
|
||||||
|
} else {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'play',
|
name: 'play',
|
||||||
description: 'Play a song from YouTube, a URL, or an uploaded media file',
|
description: 'Play a song from YouTube, a URL, or an uploaded media file',
|
||||||
|
@ -84,15 +115,13 @@ module.exports = {
|
||||||
const tempVideoPath = path.join(__dirname, '../utils/tmp', attachment.name);
|
const tempVideoPath = path.join(__dirname, '../utils/tmp', attachment.name);
|
||||||
fs.writeFileSync(tempVideoPath, buffer);
|
fs.writeFileSync(tempVideoPath, buffer);
|
||||||
|
|
||||||
const ffmpegProcess = spawn('ffmpeg', [
|
spawnFFmpegProcess(['-i', tempVideoPath, '-f', 'mp3', '-ab', '192000', '-vn', tempFilePath], (err) => {
|
||||||
'-i', tempVideoPath,
|
if (err) {
|
||||||
'-f', 'mp3',
|
console.error('Error converting file:', err);
|
||||||
'-ab', '192000',
|
message.reply('Failed to convert the video file.');
|
||||||
'-vn',
|
return;
|
||||||
tempFilePath
|
}
|
||||||
]);
|
|
||||||
|
|
||||||
ffmpegProcess.on('close', () => {
|
|
||||||
console.log(`Converted and saved: ${tempFilePath}`);
|
console.log(`Converted and saved: ${tempFilePath}`);
|
||||||
fs.unlinkSync(tempVideoPath);
|
fs.unlinkSync(tempVideoPath);
|
||||||
|
|
||||||
|
@ -112,11 +141,6 @@ module.exports = {
|
||||||
playNextInQueue(message.guild.id);
|
playNextInQueue(message.guild.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
ffmpegProcess.on('error', (err) => {
|
|
||||||
console.error('Error converting file:', err);
|
|
||||||
message.reply('Failed to convert the video file.');
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
console.error('Attachment is not a supported media file.');
|
console.error('Attachment is not a supported media file.');
|
||||||
|
@ -172,15 +196,13 @@ module.exports = {
|
||||||
const tempVideoPath = path.join(__dirname, '../utils/tmp', path.basename(searchQuery.split('?')[0]));
|
const tempVideoPath = path.join(__dirname, '../utils/tmp', path.basename(searchQuery.split('?')[0]));
|
||||||
fs.writeFileSync(tempVideoPath, buffer);
|
fs.writeFileSync(tempVideoPath, buffer);
|
||||||
|
|
||||||
const ffmpegProcess = spawn('ffmpeg', [
|
spawnFFmpegProcess(['-i', tempVideoPath, '-f', 'mp3', '-ab', '192000', '-vn', tempFilePath], (err) => {
|
||||||
'-i', tempVideoPath,
|
if (err) {
|
||||||
'-f', 'mp3',
|
console.error('Error converting file:', err);
|
||||||
'-ab', '192000',
|
message.reply('Failed to convert the video file.');
|
||||||
'-vn',
|
return;
|
||||||
tempFilePath
|
}
|
||||||
]);
|
|
||||||
|
|
||||||
ffmpegProcess.on('close', () => {
|
|
||||||
console.log(`Converted and saved: ${tempFilePath}`);
|
console.log(`Converted and saved: ${tempFilePath}`);
|
||||||
fs.unlinkSync(tempVideoPath);
|
fs.unlinkSync(tempVideoPath);
|
||||||
|
|
||||||
|
@ -200,11 +222,6 @@ module.exports = {
|
||||||
playNextInQueue(message.guild.id);
|
playNextInQueue(message.guild.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
ffmpegProcess.on('error', (err) => {
|
|
||||||
console.error('Error converting file:', err);
|
|
||||||
message.reply('Failed to convert the video file.');
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fs.writeFileSync(tempFilePath, buffer);
|
fs.writeFileSync(tempFilePath, buffer);
|
||||||
console.log(`Downloaded and saved: ${tempFilePath}`);
|
console.log(`Downloaded and saved: ${tempFilePath}`);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const { createAudioPlayer, createAudioResource, AudioPlayerStatus, joinVoiceChannel } = require('@discordjs/voice');
|
const { createAudioPlayer, createAudioResource, AudioPlayerStatus, joinVoiceChannel } = require('@discordjs/voice');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const { spawn } = require('child_process')
|
||||||
|
|
||||||
const queueMap = new Map();
|
const queueMap = new Map();
|
||||||
const playerMap = new Map();
|
const playerMap = new Map();
|
||||||
|
@ -94,45 +95,70 @@ function playTrack(guildId, voiceChannel, track) {
|
||||||
adapterCreator: voiceChannel.guild.voiceAdapterCreator,
|
adapterCreator: voiceChannel.guild.voiceAdapterCreator,
|
||||||
});
|
});
|
||||||
|
|
||||||
const audioPlayer = playerMap.get(guildId) || createAudioPlayer();
|
let audioPlayer = playerMap.get(guildId);
|
||||||
playerMap.set(guildId, audioPlayer);
|
|
||||||
|
if (!audioPlayer) {
|
||||||
|
audioPlayer = createAudioPlayer();
|
||||||
|
playerMap.set(guildId, audioPlayer);
|
||||||
|
|
||||||
|
audioPlayer.on(AudioPlayerStatus.Idle, () => {
|
||||||
|
if (!repeatMap.get(guildId)) {
|
||||||
|
currentTrackMap.delete(guildId);
|
||||||
|
fs.unlink(track.filePath, (err) => {
|
||||||
|
if (err) console.error('Error deleting file:', track.filePath, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue = getQueue(guildId);
|
||||||
|
if (queue.length > 0 || repeatMap.get(guildId)) {
|
||||||
|
playNextInQueue(guildId);
|
||||||
|
} else {
|
||||||
|
if (connection && connection.state.status !== 'destroyed') {
|
||||||
|
connection.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.on('error', (err) => {
|
||||||
|
console.error('AudioPlayer error:', err);
|
||||||
|
currentTrackMap.delete(guildId);
|
||||||
|
if (connection && connection.state.status !== 'destroyed') {
|
||||||
|
connection.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track.ffmpegProcess) {
|
||||||
|
try {
|
||||||
|
track.ffmpegProcess.kill();
|
||||||
|
console.log('Killed existing ffmpeg process.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error killing existing ffmpeg process:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(track.filePath)) {
|
if (!fs.existsSync(track.filePath)) {
|
||||||
console.error('Audio file not found:', track.filePath);
|
console.error('Audio file not found:', track.filePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resource = createAudioResource(track.filePath);
|
track.ffmpegProcess = spawn('ffmpeg', [
|
||||||
|
'-i', track.filePath,
|
||||||
|
'-analyzeduration', '0',
|
||||||
|
'-loglevel', '0',
|
||||||
|
'-acodec', 'libopus',
|
||||||
|
'-f', 'opus',
|
||||||
|
'-ar', '48000',
|
||||||
|
'-ac', '2',
|
||||||
|
'pipe:1'
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resource = createAudioResource(track.ffmpegProcess.stdout);
|
||||||
|
|
||||||
audioPlayer.play(resource);
|
audioPlayer.play(resource);
|
||||||
connection.subscribe(audioPlayer);
|
connection.subscribe(audioPlayer);
|
||||||
|
|
||||||
currentTrackMap.set(guildId, { ...track, resource });
|
currentTrackMap.set(guildId, { ...track, resource });
|
||||||
|
|
||||||
audioPlayer.on(AudioPlayerStatus.Idle, () => {
|
|
||||||
if (!repeatMap.get(guildId)) {
|
|
||||||
currentTrackMap.delete(guildId);
|
|
||||||
fs.unlink(track.filePath, (err) => {
|
|
||||||
if (err) console.error('Error deleting file:', track.filePath, err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const queue = getQueue(guildId);
|
|
||||||
if (queue.length > 0 || repeatMap.get(guildId)) {
|
|
||||||
playNextInQueue(guildId);
|
|
||||||
} else {
|
|
||||||
if (connection && connection.state.status !== 'destroyed') {
|
|
||||||
connection.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
audioPlayer.on('error', (err) => {
|
|
||||||
console.error('AudioPlayer error:', err);
|
|
||||||
currentTrackMap.delete(guildId);
|
|
||||||
if (connection && connection.state.status !== 'destroyed') {
|
|
||||||
connection.destroy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipTrack(guildId) {
|
function skipTrack(guildId) {
|
||||||
|
|
Loading…
Reference in New Issue