Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用fluent ffmpeg录制的音频重叠_Javascript_Node.js_Express_Discord.js_Fluent Ffmpeg - Fatal编程技术网

Javascript 使用fluent ffmpeg录制的音频重叠

Javascript 使用fluent ffmpeg录制的音频重叠,javascript,node.js,express,discord.js,fluent-ffmpeg,Javascript,Node.js,Express,Discord.js,Fluent Ffmpeg,因此,我正在开发一个discord机器人,当用户写入时,它会在语音通道中记录用户的音频!录制并在他们写入时停止录制!停止 现在的问题是,如果您录制一次,它就完全正常了,但是当您录制第二次时,randomArr[0]文件夹中的文件也有上一次录制的音频重叠,比如为什么会发生这种情况?如果我重新启动服务器,那么它可以正常工作,直到我记录第二次。将其修复。 mp3Paths正在制造问题, 必须在记录消息事件中清空它。 这就解决了问题 const Discord = require('discord.js

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

将其修复。 mp3Paths正在制造问题, 必须在记录消息事件中清空它。 这就解决了问题

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