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

如何使用JS录制在线钢琴的用户弹奏音频并实现下载?

Hey there! 针对你在线钢琴项目里的录制和下载需求,完全不用纠结复杂的Base64操作,这里有两个简单直接的方案,根据你的需求选就行:

方案1:用浏览器原生的MediaRecorder录制真实音频

这是最省心的方式,利用Web Audio API和MediaRecorder API就能搞定,不需要自己处理任何编码逻辑:

核心思路

  1. 把你钢琴的音频输出接入到MediaStreamDestination节点(Web Audio API的一部分)
  2. 用MediaRecorder监听这个流,收集录制的音频数据
  3. 录制结束后直接生成音频Blob,创建下载链接

代码示例

// 假设你已经有了创建好的AudioContext实例,命名为audioCtx
const mediaStreamDest = audioCtx.createMediaStreamDestination();
// 把你钢琴的发声节点(比如增益节点、振荡器输出)连接到这个 destination
// 替换成你实际的音频输出节点,比如 yourPianoGainNode
yourPianoAudioOutput.connect(mediaStreamDest);

// 初始化MediaRecorder
const recorder = new MediaRecorder(mediaStreamDest.stream);
const audioChunks = [];

// 收集录制的音频片段
recorder.ondataavailable = (event) => {
  if (event.data.size > 0) {
    audioChunks.push(event.data);
  }
};

// 录制结束时生成下载链接
recorder.onstop = () => {
  // 把片段合并成Blob,格式选webm(兼容性好)
  const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
  const downloadUrl = URL.createObjectURL(audioBlob);
  
  // 创建临时a标签触发下载
  const downloadLink = document.createElement('a');
  downloadLink.href = downloadUrl;
  downloadLink.download = 'my-piano-recording.webm';
  downloadLink.click();
  
  // 释放URL资源,避免内存泄漏
  URL.revokeObjectURL(downloadUrl);
};

// 封装开始/停止录制的函数,绑定到你的按钮上就行
function startRecording() {
  audioChunks.length = 0; // 清空之前的录制数据
  recorder.start();
}

function stopRecording() {
  recorder.stop();
}

优点

  • 原生API支持,不用引入第三方库
  • 全程不用碰Base64,浏览器帮你搞定编码
  • 现代浏览器(Chrome、Firefox、Edge等)都支持

方案2:记录按键事件(适合只需要重放逻辑的场景)

如果你的需求不是录制真实音频,而是记录用户的按键顺序、时长,之后可以重放弹奏,那这个方案更轻量:

核心思路

  1. 用户按下/松开琴键时,记录事件详情(键名、时间戳、操作类型)
  2. 下载时把记录的数组转成JSON格式的Blob
  3. 重放时读取JSON,按时间顺序触发对应的琴键发声

代码示例

const recordingEvents = [];
let sessionStartTime;

// 替换成你实际的琴键按下事件处理函数
function handleKeyDown(noteName) {
  if (!sessionStartTime) {
    sessionStartTime = Date.now();
  }
  recordingEvents.push({
    type: 'press',
    note: noteName,
    timestamp: Date.now() - sessionStartTime // 记录相对时间
  });
}

// 替换成你实际的琴键松开事件处理函数
function handleKeyUp(noteName) {
  recordingEvents.push({
    type: 'release',
    note: noteName,
    timestamp: Date.now() - sessionStartTime
  });
}

// 下载录制的事件数据
function downloadRecording() {
  const jsonString = JSON.stringify(recordingEvents, null, 2);
  const jsonBlob = new Blob([jsonString], { type: 'application/json' });
  const downloadUrl = URL.createObjectURL(jsonBlob);
  
  const downloadLink = document.createElement('a');
  downloadLink.href = downloadUrl;
  downloadLink.download = 'piano-recording.json';
  downloadLink.click();
  
  URL.revokeObjectURL(downloadUrl);
}

// 重放录制的内容(需要你有对应的playNote/stopNote函数)
function replayRecording(recordingData) {
  const replayStartTime = Date.now();
  recordingData.forEach(event => {
    setTimeout(() => {
      if (event.type === 'press') {
        playNote(event.note); // 调用你原来的播放琴键函数
      } else {
        stopNote(event.note); // 调用你原来的停止琴键函数
      }
    }, event.timestamp);
  });
}

优点

  • 完全不用处理音频编码,代码更简单
  • 录制的数据量极小,下载速度快
  • 可以轻松编辑录制的内容(比如修改按键顺序)

根据你的实际需求选就行:如果要保存真实的弹奏音频,选方案1;如果只需要记录弹奏逻辑用于重放,方案2更合适。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:48:25