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

如何用JavaScript录制网页系统音频?为在线架子鼓添加录制下载功能

为在线架子鼓添加系统音频录制与下载功能

我制作了一个简单的在线架子鼓播放器,现在想为网站添加录制演奏内容并下载的功能。希望代码简单且使用JavaScript,因为刚接触Web开发,仅掌握HTML、CSS和JavaScript等少量技术。曾在网上寻求帮助,但找到的都是使用麦克风录制用户音频的方法,而非录制系统音频,因此前来咨询。

要实现网页音频(架子鼓演奏声音)的录制,我们可以使用Web API中的MediaRecorder结合AudioContext捕获网页音频输出,以下是基于你现有代码的最简实现:


1. 更新HTML,添加录制控制按钮

在架子鼓按钮区域下方添加录制操作按钮:

<div class="set">
  <!-- 原有架子鼓按钮 -->
  <button class="w drum">w</button>
  <button class="a drum">a</button>
  <button class="s drum">s</button>
  <button class="d drum">d</button>
  <button class="j drum">j</button>
  <button class="k drum">k</button>
  <button class="l drum">l</button>
</div>
<!-- 新增录制控制按钮 -->
<div class="controls">
  <button id="startRecord">开始录制</button>
  <button id="stopRecord" disabled>停止并下载</button>
</div>

给控制按钮添加基础样式(写入你的styles.css):

.controls {
  margin: 20px 0;
}
.controls button {
  padding: 10px 20px;
  font-size: 1.2rem;
  margin: 0 10px;
  border: none;
  border-radius: 8px;
  background-color: #DA0463;
  color: white;
  cursor: pointer;
  font-family: 'Arvo', cursive;
}
.controls button:disabled {
  background-color: #888;
  cursor: not-allowed;
}

2. 修改JavaScript,实现录制逻辑

替换原有index.js代码为以下内容,核心是通过AudioContext管理音频播放,并将输出接入MediaRecorder:

// 初始化音频上下文与录制变量
let audioContext;
let mediaRecorder;
let recordingChunks = [];
let isRecording = false;

// 页面加载时初始化音频上下文
window.addEventListener('load', () => {
  audioContext = new (window.AudioContext || window.webkitAudioContext)();
});

// 绑定架子鼓按钮点击与键盘事件
const drumButtons = document.querySelectorAll(".drum");
drumButtons.forEach(button => {
  button.addEventListener("click", function() {
    const key = this.innerHTML;
    makeSound(key);
    buttonAnimation(key);
  });
});

document.addEventListener("keypress", (event) => {
  makeSound(event.key);
  buttonAnimation(event.key);
});

// 绑定录制控制按钮事件
document.getElementById('startRecord').addEventListener('click', startRecording);
document.getElementById('stopRecord').addEventListener('click', stopAndDownloadRecording);

// 开始录制
function startRecording() {
  if (isRecording) return;
  
  // 创建音频流目标,用于捕获输出
  const recordDestination = audioContext.createMediaStreamDestination();
  mediaRecorder = new MediaRecorder(recordDestination.stream);
  
  // 收集录制数据
  mediaRecorder.ondataavailable = (e) => {
    recordingChunks.push(e.data);
  };
  
  // 更新按钮状态
  isRecording = true;
  document.getElementById('startRecord').disabled = true;
  document.getElementById('stopRecord').disabled = false;
  
  mediaRecorder.start();
}

// 停止录制并下载文件
function stopAndDownloadRecording() {
  if (!isRecording) return;
  
  mediaRecorder.stop();
  isRecording = false;
  
  // 更新按钮状态
  document.getElementById('startRecord').disabled = false;
  document.getElementById('stopRecord').disabled = true;
  
  // 录制结束后生成下载链接
  mediaRecorder.onstop = () => {
    const audioBlob = new Blob(recordingChunks, { type: 'audio/webm' });
    const downloadUrl = URL.createObjectURL(audioBlob);
    const downloadLink = document.createElement('a');
    downloadLink.href = downloadUrl;
    downloadLink.download = 'my-drum-recording.webm';
    downloadLink.click();
    
    // 清理资源
    URL.revokeObjectURL(downloadUrl);
    recordingChunks = [];
  };
}

// 播放架子鼓声音(适配录制逻辑)
function makeSound(key) {
  // 激活音频上下文(浏览器要求用户交互后才能播放音频)
  if (audioContext.state === 'suspended') {
    audioContext.resume();
  }

  let audioPath;
  switch (key) {
    case "w": audioPath = "sounds/tom-1.mp3"; break;
    case "a": audioPath = "sounds/tom-2.mp3"; break;
    case "s": audioPath = "sounds/tom-3.mp3"; break;
    case "d": audioPath = "sounds/tom-4.mp3"; break;
    case "j": audioPath = "sounds/snare.mp3"; break;
    case "k": audioPath = "sounds/crash.mp3"; break;
    case "l": audioPath = "sounds/kick-bass.mp3"; break;
    default: console.log(key); return;
  }

  // 加载并播放音频,同时接入录制流
  fetch(audioPath)
    .then(res => res.arrayBuffer())
    .then(buffer => audioContext.decodeAudioData(buffer))
    .then(decodedAudio => {
      const audioSource = audioContext.createBufferSource();
      audioSource.buffer = decodedAudio;
      
      // 如果正在录制,将音频连接到录制目标
      if (isRecording) {
        audioSource.connect(audioContext.createMediaStreamDestination());
      }
      // 始终连接到扬声器
      audioSource.connect(audioContext.destination);
      audioSource.start();
    })
    .catch(err => console.error('音频加载失败:', err));
}

// 按钮动画逻辑(保留原有功能)
function buttonAnimation(currentKey) {
  const activeButton = document.querySelector("." + currentKey);
  activeButton.classList.add("pressed");
  setTimeout(() => {
    activeButton.classList.remove("pressed");
  }, 100);
}

关键注意事项

  • 运行环境: 该功能需要在HTTPS环境或本地localhost下运行(浏览器安全限制)
  • 浏览器兼容性: 支持Chrome、Firefox、Edge等现代浏览器
  • 音频格式: 录制文件为webm格式,是浏览器原生支持的高效音频格式,可直接播放或转换为MP3等格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:29:51