简体   繁体   English

使用 fluent-ffmpeg 与之前录制的音频重叠

[英]Audio overlapping from previous recording with fluent-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(/\r\n|\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 + '\n\n');

        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 + '\n\n');
      }
  }
});

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()

So I am developing a discord bot that records audio of the users in the voice channel when the write.record and stops recording when they write,stop, now, the thing is if you record once it is completely fine, but when you record the second time, the file in the randomArr[0] folder had audio from the previous recording overlapping it too, like why does that happen?所以我正在开发一个 discord 机器人,它在 write.record 时在语音通道中记录用户的音频,并在他们写时停止录制,停止,现在,如果你录制一次它完全没问题,但是当你录制第二次, randomArr[0]文件夹中的文件也与之前的录音重叠,为什么会这样? If i restart the server then it works fine until i record the second time..如果我重新启动服务器,那么它工作正常,直到我记录第二次..

got it fixed.把它修好了。 mp3Paths was making the issue, had to empty it in the the record message event. mp3Paths 出现问题,必须在记录消息事件中清空它。 that fixed it.解决了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM