简体   繁体   中英

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? 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. that fixed it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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