使用流畅的ffmpeg与以前录制的音频重叠


const Discord = require('discord.js');
const client = new Discord.Client();
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(ffmpegInstaller.path);
const fs = require('fs-extra')
const mergeStream = require('merge-stream');
const config = require('./config.json');
const cp = require('child_process');
const path1 = require('path');

class Readable extends require('stream').Readable { _read() {} }
let recording = false;
let currently_recording = {};
let mp3Paths = [];
const silence_buffer = new Uint8Array(3840);
const express = require('express')
const app = express()
const port = 3000
const publicIP = require('public-ip')
const { program } = require('commander');
const { path } = require('@ffmpeg-installer/ffmpeg');
const version = '0.0.1'
program.version(version);
let debug = false
let runProd = false
let fqdn = "";
require("dotenv").config()

function bufferToStream(buffer) {
let stream = new Readable();
stream.push(buffer);
return stream;
}



client.on('ready', async () => {
console.log(`Logged in as ${client.user.tag}`);
let host = "localhost"

let ip = await publicIP.v4();
let protocol = "http";
if (!runProd) {
host = "localhost"
} else {
host = ip;
}
fqdn = `${protocol}://${host}:${port}`
app.listen(port, host, () => {
console.log(`Listening on port ${port} for ${host} at fqdn ${fqdn}`)
})
});
let randomArr = []
let randomArr2 = []
let finalArrWithIds = []
let variable = 0
client.on('message', async message => {

if(message.content === `$record`){
finalArrWithIds = []
let membersToScrape = Array.from(message.member.voice.channel.members.values());
membersToScrape.forEach((member) => {
if(member.id === `740372581118640149`) {
console.log(`botid`);
}
else {
finalArrWithIds.push(member.id)
}

})
const randomNumber = Math.floor(Math.random() * 100)
randomArr = []
randomArr.push(randomNumber)
const randomNumber2 = Math.floor(Math.random() * 100)
randomArr2 = []
randomArr.push(randomNumber2)
}
console.log(finalArrWithIds)
console.log(`HERE IT IS !!!!!!!!!!!! ${randomArr[0]}`)

const generateSilentData = async (silentStream, memberID) => {
while(recording) {
if (!currently_recording[memberID]) {
silentStream.push(silence_buffer);
}
await new Promise(r => setTimeout(r, 20));
}
return "done";
}

function generateOutputFile(channelID, memberID) {
const dir = `./recordings/${channelID}/${memberID}`;
fs.ensureDirSync(dir);
const fileName = `${dir}/${randomArr[0]}.mp3`;
return fs.createWriteStream(fileName);
}

if (!fs.existsSync("public")) {
fs.mkdirSync("public");
}
app.use("/public", express.static("./public"));
if (!message.guild) return;
if (message.content === config.prefix + config.record_command) {
if (recording) {
message.reply("bot is already recording");
return
}
if (message.member.voice.channel) {
recording = true;
const connection = await message.member.voice.channel.join();
const dispatcher = connection.play('./audio.mp3');
connection.on('speaking', (user, speaking) => {
if (speaking.has('SPEAKING')) {
currently_recording[user.id] = true;
} else {
currently_recording[user.id] = false;
}
})

let members = Array.from(message.member.voice.channel.members.values());
members.forEach((member) => {
if (member.id != client.user.id) {
let memberStream = connection.receiver.createStream(member, {mode : 'pcm', end : 'manual'})
let outputFile = generateOutputFile(message.member.voice.channel.id, member.id);
console.log(outputFile);
mp3Paths.push(outputFile.path);
silence_stream = bufferToStream(new Uint8Array(0));
generateSilentData(silence_stream, member.id).then(data => console.log(data));
let combinedStream = mergeStream(silence_stream, memberStream);
ffmpeg(combinedStream)
.inputFormat('s32le')
.audioFrequency(48000)
.audioChannels(2)
.on('error', (error) => {console.log(error)})
.audioCodec('libmp3lame')
.format('mp3')
// .audioFilters('silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-90dB')
.pipe(outputFile)
}
})
} else {
message.reply('You need to join a voice channel first!');
}
}
if (message.content === config.prefix + config.stop_command) {
let currentVoiceChannel = message.member.voice.channel;
if (currentVoiceChannel) {
recording = false;
await currentVoiceChannel.leave();
let mergedOutputFolder = './recordings/' + message.member.voice.channel.id + `/${randomArr[0]}/`;
fs.ensureDirSync(mergedOutputFolder);
let file_name = `${randomArr[0]}` + '.mp3';
let mergedOutputFile = mergedOutputFolder + file_name;

let download_path = message.member.voice.channel.id + `/${randomArr[0]}/` + file_name;
let mixedOutput = new ffmpeg();
mp3Paths.forEach((mp3Path) => {
mixedOutput.addInput(mp3Path);
})
//mixedOutput.complexFilter('amix=inputs=2:duration=longest');
mixedOutput.complexFilter('amix=inputs=' + mp3Paths.length + ':duration=longest');
function saveMp3(mixedData, outputMixed) {
return new Promise((resolve, reject) => {
mixedData.on('error', reject).on('progress',
(progress) => {
console.log('Processing: ' + progress.targetSize + ' KB converted');
}).on('end', () => {
console.log('Processing finished !');
resolve()
}).saveToFile(outputMixed);
})
}
// mixedOutput.saveToFile(mergedOutputFile);
await saveMp3(mixedOutput, mergedOutputFile);
// We saved the recording, now copy the recording
if (!fs.existsSync(`./public`)) {
fs.mkdirSync(`./public`);
}
let sourceFile = `${__dirname}/recordings/${download_path}`
console.log(`DOWNLOAD PATH HERE ${download_path}`)
const guildName = message.guild.id;
const serveExist = `/public/${guildName}`
if (!fs.existsSync(`.${serveExist}`)) {
fs.mkdirSync(`.${serveExist}`)
}
let destionationFile = `${__dirname}${serveExist}/${member}-${file_name}`
let errorThrown = false
try {
fs.copySync(sourceFile, destionationFile);
} catch (err) {
errorThrown = true
await message.channel.send(`Error: ${err.message}`)
}
if (!errorThrown) {
message.channel.send(`Link to full recording located at: ${fqdn}/public/${guildName}/${member}-${file_name}`);
}


} else {
message.reply('You need to join a voice channel first!');
}
} else {
if (message.content.split(/rn|r|n/).length > config.line_length_limit && config.channel_name_log.includes(message.channel.name)) {
file = `./recordings/${'text_logs'}/${message.member.id}/logs.txt`;
fs.ensureFileSync(file);
fs.appendFileSync(file, 'Channel: ' + message.channel.name + 'n' + message.createdAt + 'n' + message.content + 'nn');
let date = [`a`,`b`,`c`,`d`]
let tmp_file_name = date[0] + date[1] + date[2];
let daily_file = `./recordings/${'text_logs'}/${tmp_file_name}.txt`;
fs.ensureFileSync(daily_file);
fs.appendFileSync(daily_file, 'Channel: ' + message.channel.name + 'n' + message.createdAt + 'n' + message.content + 'nn');
}
}
});
async function main() {
program.option('-debug')
program.option('-prod')
program.parse(process.argv)
console.log(program.opts())
if (program.Debug != undefined) {
debug = !debug
}
if (program.Prod != undefined) {
runProd = !runProd
}
if (runProd) {
client.login(process.env.DISCORD_TOKEN_PROD).catch(e => {
console.log("ERROR")
console.log(e)
})
} else {
client.login(process.env.DISCORD_TOKEN_TEST).catch(e => {
console.log("ERROR")
console.log(e)
})
}
}
main()

所以我正在开发一个discord机器人,当用户写的时候,它会在语音通道中记录用户的音频!记录并在他们写入时停止记录!停止现在,问题是,如果你录制一次,那就完全可以了,但当你录制第二次时,randomArr[0]文件夹中的文件也有上一次录制的音频重叠,比如为什么会发生这种情况?如果我重新启动服务器,那么它可以正常工作,直到我记录第二次。。

修复了它。mp3Paths制造了这个问题,必须在记录消息事件中清空它。修复了它。

最新更新