You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Discord.js检测语音通话分贝并实现音量触发音频播放的机器人?

基于Discord.js实现根据语音分贝播放对应音频的机器人

可行性说明

完全可行。Discord.js结合官方的@discordjs/voice库,能够获取语音通话中的用户音频流,通过分析PCM音频数据计算分贝值,再根据预设的分贝区间触发对应音频的播放,整个流程的技术链路是完整的。

实现步骤与代码示例

1. 安装依赖

首先安装核心依赖包:

npm install discord.js @discordjs/voice prism-media ffmpeg-static
  • discord.js:处理Discord API交互
  • @discordjs/voice:管理语音连接与音频播放
  • prism-media:解码Opus音频流为PCM数据
  • ffmpeg-static:处理本地音频文件的编码

2. 基础框架与语音连接

先实现机器人登录、响应命令加入语音频道的逻辑:

const { Client, GatewayIntentBits } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource, VoiceReceiver } = require('@discordjs/voice');
const prism = require('prism-media');

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates
  ]
});

client.on('ready', () => {
  console.log(`已登录:${client.user.tag}`);
});

// 响应/join命令,加入用户所在语音频道
client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'join') return;

  const voiceChannel = interaction.member.voice.channel;
  if (!voiceChannel) return interaction.reply('请先加入一个语音频道!');

  const connection = joinVoiceChannel({
    channelId: voiceChannel.id,
    guildId: voiceChannel.guild.id,
    adapterCreator: voiceChannel.guild.voiceAdapterCreator,
  });

  // 监听用户开始说话的事件
  const receiver = connection.receiver;
  receiver.speaking.on('start', (userId) => {
    analyzeUserAudio(receiver, userId, connection);
  });

  await interaction.reply('已加入语音频道,开始监听音量!');
});

// 替换为你的机器人Token
client.login('YOUR_BOT_TOKEN');

3. 音频分贝分析

通过解码用户的音频流,计算PCM数据的均方根(RMS)并转换为分贝值:

function analyzeUserAudio(receiver, userId, connection) {
  const audioStream = receiver.subscribe(userId, {
    end: {
      behavior: VoiceReceiver.EndBehavior.AfterSilence,
      duration: 100, // 静音100ms后停止监听
    },
  });

  // 将Opus流解码为16位PCM数据
  const pcmStream = audioStream.pipe(new prism.opus.Decoder({ rate: 48000, channels: 2, frameSize: 960 }));

  let sampleBuffer = [];
  pcmStream.on('data', (chunk) => {
    // 将Buffer转换为Int16数组(16位PCM)
    const samples = new Int16Array(chunk.buffer);
    sampleBuffer.push(...samples);

    // 每积累0.1秒的数据计算一次分贝
    if (sampleBuffer.length >= 48000 * 2 * 0.1) {
      const rms = calculateRMS(sampleBuffer);
      // 转换为分贝(16位PCM最大值为32767)
      const decibels = 20 * Math.log10(rms / 32767);
      console.log(`用户${userId}当前分贝:${decibels.toFixed(2)}dB`);

      // 根据分贝播放对应音频
      playTargetAudio(decibels, connection);
      sampleBuffer = [];
    }
  });

  pcmStream.on('end', () => {
    console.log(`用户${userId}停止说话`);
  });
}

// 计算均方根(RMS),用于转换分贝
function calculateRMS(samples) {
  let sum = 0;
  for (const sample of samples) {
    sum += sample ** 2;
  }
  return Math.sqrt(sum / samples.length);
}

4. 根据分贝播放对应音频

定义分贝区间与音频文件的映射,触发播放逻辑:

const audioPlayer = createAudioPlayer();

function playTargetAudio(decibels, connection) {
  let audioFilePath;
  // 根据实际场景调整分贝阈值
  if (decibels < -45) {
    audioFilePath = './audio/quiet.mp3';
  } else if (decibels >= -45 && decibels < -25) {
    audioFilePath = './audio/normal.mp3';
  } else {
    audioFilePath = './audio/loud.mp3';
  }

  const audioResource = createAudioResource(audioFilePath);
  audioPlayer.play(audioResource);
  connection.subscribe(audioPlayer);
}

注意事项

  • 分贝阈值需要根据实际环境校准:不同麦克风、背景噪音会影响数值,建议先测试获取基准值后再调整区间。
  • 处理音频播放冲突:可以通过判断audioPlayer.state.status避免同时播放多个音频。
  • 权限配置:确保机器人拥有CONNECT、SPEAK以及读取语音状态的权限。
  • 音频格式:优先使用MP3或Opus格式,避免出现播放失败的情况。

内容的提问来源于stack exchange,提问作者Falow1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:53:10