MIDI 转 MP3 / WAV
使用 SoundFont 音色库渲染 MIDI 为音频 · 钢琴谱转音频 / 翻唱伴奏制作
翻唱伴奏/钢琴谱→音频互转
使用 SoundFont 音色库渲染 MIDI 为音频 · 钢琴谱转音频 / 翻唱伴奏制作
MIDI(Musical Instrument Digital Interface)是音乐数字接口标准,文件存储的不是音频波形而是"乐谱"(音符 / 时值 / 力度 / 乐器)。需要 SoundFont(音色库)才能渲染为真实音频。
MuseScore(免费 / Win/Mac/Linux):开源乐谱软件,支持 MIDI 导入 + 多种 SoundFont + 导出 MP3 / WAV / OGG / FLAC。是非专业用户最易上手的工具。
Synthesia(付费 / Win/Mac):钢琴学习软件,MIDI 文件可视化 + 自动跟弹。
MidiEditor(免费 / Win/Mac/Linux):MIDI 编辑器,支持音色库切换 + 导出音频。
conversion-tool.com:MIDI → MP3 在线转换,免费且无需注册。
solmire.com:MIDI 在线播放 + 转 MP3。
⚠ 上传隐私:MIDI 文件如果是您原创作品(未发表),建议本地处理。商业服务可能存留文件。
音频转 MIDI 是难得多的问题,需要 AI 音高检测 + 节奏检测。准确度在多乐器混音上很差。
Spotify Basic Pitch(开源):
Magenta Onsets-and-Frames:Google 开源,钢琴单乐器专门优化。
商业:AnthemScore(付费 GUI)/ Melodyne / Klangio API。
了解工具定位 · 使用场景 · 对比优势
翻唱爱好者手头只有原版 MP3,想消人声做伴奏但效果不佳。本工具将 MP3 转为 MIDI 后,可在钢琴卷帘中手动删除人声音符、调整和弦节奏,再转回 WAV 输出干净伴奏,比常规消音算法保留更多低频细节。
作曲新手在打谱软件里写完一段 MIDI 钢琴谱,不确定实际听感是否像想象中那样。本工具把 MIDI 直接转成 MP3,无需加载 DAW 或虚拟乐器,30 秒内听到带力度和踏板的真实钢琴音色,快速判断音符密度和声部平衡是否合理。
乐队排练时即兴了一段吉他 riff,手机录的 WAV 音质嘈杂。本工具将 WAV 转为 MIDI 后,自动提取主音高和节奏网格,成员可直接在谱面上标注和弦级数、修改错音,省去逐帧听写的时间,排练效率提升一倍。
视频创作者找到一首喜欢的流行歌想做 BGM,但原曲有人声或版权受限。本工具将 MP3 转为 MIDI 后,可自由移调、变速、替换音色(钢琴→电子琴→管弦乐),再导出 WAV 作为无版权风险的纯器乐版背景音乐。
音乐老师需要批量生成不同调性、节奏型的听音练习曲。本工具将 MIDI 谱转成 MP3 音频,支持指定速度(60-200 BPM)和音色(钢琴/小提琴/单簧管),学生听完音频后默写旋律,系统自动比对 MIDI 原谱给出正确率。
| 维度 | 本工具 | 竞品 A (Audacity) | 传统方法 |
|---|---|---|---|
| 数据隐私 | 纯浏览器端处理,音频文件不上传服务器 | 本地软件处理,文件不离开电脑 | 需将文件发送给第三方制作人或混音师 |
| 处理速度 | 秒级完成,取决于文件大小 | 分钟级,需手动导入、设置参数并导出 | 数小时到数天,需预约、沟通、等待交付 |
| 操作门槛 | 上传文件即转,无需学习 | 需学习软件界面、音频轨道、导出设置等 | 需具备乐理知识或联系专业人员 |
| 输出格式 | 直接输出 MP3/WAV 音频文件 | 可输出多种格式,但需手动配置编码器参数 | 通常交付 WAV 或 MP3,格式固定 |
| 设备依赖 | 有现代浏览器即可,跨平台 | 需安装特定操作系统版本的软件 | 依赖线下设备(合成器/音源)或人工 |
| 适用场景 | 快速试听、翻唱伴奏制作、教学演示 | 专业音频编辑、多轨混音、效果处理 | 高质量唱片级制作、复杂编曲需求 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| C D E F G A B C D E F G A B C | 生成一个 16 音符的 C 大调音阶 WAV 文件,每个音符持续 0.5 秒 | 典型场景:将简单的单音旋律转为音频试听 |
| 伴奏.wav | 生成一个 MIDI 文件,包含原 WAV 中识别出的主要旋律和和弦轨道 | 典型场景:将人声清唱或乐器录音转为 MIDI 谱 |
| 钢琴谱.mid | 生成一个 128kbps MP3 文件,使用标准钢琴音色播放全部音符 | 典型场景:将 MIDI 钢琴谱转为可分享的 MP3 音频 |
| empty.mid | 错误提示:MIDI 文件为空,无任何音符数据 | 边界 case:空文件或损坏文件会直接报错 |
| 采样率_192kHz.wav | 生成一个 MIDI 文件,但高频泛音可能丢失(FFmpeg 默认降采样至 44.1kHz) | 边界 case:极高采样率 WAV 转 MIDI 时精度受限 |
| 和弦密集.mid | 生成一个 WAV 文件,但同时发声音符超过 16 个时部分音符被静音 | 边界 case:MIDI 标准限制同时发音数(通常 16 通道) |
| 无声音频.wav | 生成一个空 MIDI 文件(无音符事件) | 易错 case:用户误以为静音段会被忽略,实际会生成空文件 |
| 中文歌名.mid | 生成一个 WAV 文件,但文件名中的中文字符在部分浏览器中显示为乱码 | 易错 case:非 ASCII 文件名可能导致下载后无法识别 |
上传一个 .wav 或 .mp3 文件到「MIDI → MP3/WAV」转换入口确认文件后缀是 .mid 或 .midi;MIDI 是乐谱指令集,不是波形文件MIDI 只记录音符、时长、力度等控制信息,不包含实际声音波形。工具内部用 FFmpeg 合成音色,输入必须为 MIDI 格式。
用 MIDI→MP3 转换一首歌曲的伴奏,期望输出包含原唱人声MIDI→MP3 只生成乐器音色,不含任何录音人声;如需提取人声请用人声分离工具MIDI 是纯乐谱数据,不包含录音采样。转换后听到的是 FFmpeg 用内置音色库(如 FluidSynth)实时合成的电子音,不是原曲录音。
上传一段 64kbps 的 MP3 或带有大量混响/背景噪音的录音上传 320kbps 或无损 WAV,且音频尽量干净(无混响、无背景噪)音频转 MIDI 依赖音高检测算法(如 FFT 峰值提取)。低码率或混响会模糊音高边界,导致识别出大量错音或缺失音符。
上传一首完整歌曲(人声+吉他+鼓+贝斯)到 WAV→MIDI,期望输出分轨 MIDI先分离出单乐器音轨(如纯钢琴独奏),再转 MIDIFFmpeg 的音频→MIDI 转换基于单声道/单音色音高检测。多乐器混音中多个音高重叠,算法无法区分,输出会变成混乱的单一音轨。
转换后播放,发现音量比正常音频文件小很多,认为工具输出有问题在 MIDI 编辑软件中检查各轨道的 velocity(力度)值,或使用音频编辑软件(如 Audacity)对输出做归一化处理MIDI 的力度值(0-127)直接映射到合成音量的振幅。很多 MIDI 文件默认力度偏低(如 64),FFmpeg 合成时不会自动增益。
上传一个 Type 0 格式(单轨)的 MIDI 文件,期望输出多个独立音轨确认 MIDI 文件类型:Type 0 是单轨,Type 1 是多轨。转换前用 MIDI 查看器检查轨道数FFmpeg 会按 MIDI 文件的实际轨道结构合成。Type 0 所有乐器挤在一轨,输出就是单声道混合,无法分离。
上传一段包含密集和弦(如钢琴柱式和弦、吉他扫弦)的音频,期望输出 MIDI 准确记录每个音符优先上传单音旋律或简单双音(如人声哼唱、单音口哨),和弦部分手动转录FFmpeg 的音高检测算法对同时发声的多个频率(和弦)识别准确率很低,常会漏音或产生错误泛音。单音识别最可靠。
不检查输出采样率(默认 44100Hz),直接转换用于专业编曲根据用途选择采样率:CD 音质 44100Hz,专业录音 48000Hz,电影 96000HzFFmpeg 合成时默认输出 44100Hz。若用于视频或专业音频项目,采样率不匹配会导致播放时音高/时长偏移。
公式推导 · 流程图解 · 依据出处
f(t) = A(t) \cdot \sin(2\pi \cdot \text{pitch}(t) \cdot t + \phi(t))
f(t) — 时刻 t 的音频采样值A(t) — 时刻 t 的音量包络(振幅)pitch(t) — 时刻 t 的音高(频率,Hz)t — 时间(秒)ϕ(t) — 时刻 t 的相位偏移MIDI 音符 C4(pitch=261.63Hz)持续 1 秒,音量恒定 A=0.8,相位 ϕ=0。采样率 44100Hz,t 从 0 到 1 秒。第 0.5 秒处:f(0.5) = 0.8 × sin(2π × 261.63 × 0.5 + 0) = 0.8 × sin(821.86) ≈ 0.8 × 0.309 ≈ 0.247。所有采样点合成后得到该音符的 WAV 波形。
适用于 MIDI 音符到 PCM 音频的合成,基于加法合成原理。不适用于包含复杂音色(如人声、真实乐器采样)的音频,此时需使用波表合成或物理建模。来源:MIDI 标准(MMA/AMEI)及数字音频基础理论。
3 种主流语言 · 复制即用
import subprocess
import os
# MIDI → WAV 转换(使用 FluidSynth,需安装 fluidsynth 和 SoundFont)
midi_file = "input.mid"
wav_file = "output.wav"
soundfont = "/usr/share/sounds/sf2/FluidR3_GM.sf2" # 常见 SoundFont 路径
# 调用 fluidsynth 渲染 MIDI 为音频
result = subprocess.run([
"fluidsynth",
"-ni", soundfont,
midi_file,
"-F", wav_file,
"-r", "44100" # 采样率
], capture_output=True, text=True)
if result.returncode != 0:
print(f"转换失败: {result.stderr}")
else:
print(f"已生成 {wav_file}")
# WAV → MP3 编码(使用 FFmpeg)
mp3_file = "output.mp3"
subprocess.run([
"ffmpeg", "-i", wav_file,
"-codec:a", "libmp3lame",
"-b:a", "192k",
mp3_file
], check=True)
print(f"已生成 {mp3_file}")
package main
import (
"fmt"
"os/exec"
)
func main() {
// MIDI → WAV(依赖 fluidsynth 命令行工具)
midiFile := "input.mid"
wavFile := "output.wav"
soundfont := "/usr/share/sounds/sf2/FluidR3_GM.sf2"
cmd := exec.Command("fluidsynth",
"-ni", soundfont,
midiFile,
"-F", wavFile,
"-r", "44100",
)
if err := cmd.Run(); err != nil {
fmt.Printf("MIDI→WAV 失败: %v\n", err)
return
}
fmt.Println("WAV 生成成功:", wavFile)
// WAV → MP3(依赖 ffmpeg)
mp3File := "output.mp3"
cmd = exec.Command("ffmpeg",
"-i", wavFile,
"-codec:a", "libmp3lame",
"-b:a", "192k",
mp3File,
)
if err := cmd.Run(); err != nil {
fmt.Printf("WAV→MP3 失败: %v\n", err)
return
}
fmt.Println("MP3 生成成功:", mp3File)
}
// 浏览器端 MIDI → 音频(使用 Web Audio API + MIDI 解析)
// 需要先加载 midi-parser-js 和 soundfont-player
async function midiToAudio(midiArrayBuffer) {
// 解析 MIDI 文件
const MidiParser = require('midi-parser-js');
const midi = MidiParser.parse(new Uint8Array(midiArrayBuffer));
// 创建音频上下文
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// 加载 SoundFont(使用 tonejs 的通用音色库)
const Soundfont = require('soundfont-player');
const instrument = await Soundfont.instrument(audioCtx, 'acoustic_grand_piano');
// 按 MIDI 事件播放(简化示例:仅播放第一个轨道的前几个音符)
const track = midi.track[0];
const noteEvents = track.event.filter(e => e.type === 9); // Note On 事件
noteEvents.slice(0, 5).forEach(event => {
const note = event.data[1]; // MIDI 音符编号
const velocity = event.data[2] / 127; // 力度
const startTime = event.deltaTime / 1000; // 秒
instrument.play(note.toString(), audioCtx.currentTime + startTime, {
duration: 0.5,
gain: velocity
});
});
// 渲染为 WAV(需要 AudioBuffer → WAV Blob 转换)
// 此处省略具体编码实现,通常使用 offlineAudioContext 渲染
console.log('MIDI 已解析,音频播放中...');
}
// 使用示例:从文件输入获取 ArrayBuffer
// const fileInput = document.getElementById('midiFile');
// fileInput.addEventListener('change', async (e) => {
// const buffer = await e.target.files[0].arrayBuffer();
// midiToAudio(buffer);
// });
8 个高频疑问
「制作工具」下的其他工具