如何用脚本批量修改MIDI速度?

wen 实用脚本 1

本文目录导读:

如何用脚本批量修改MIDI速度?

  1. 方案一:使用 Python 脚本(推荐,跨平台)
  2. 方案二:使用 Bash 脚本(仅限 Linux/macOS,需安装 midicsv
  3. 方案三:使用 Python + 外部工具(更简单,适合一次性修改)
  4. 常见问题与注意点
  5. 推荐选择

批量修改MIDI文件的速度(BPM),通常有以下几种方法,取决于你使用的操作系统和脚本语言,最推荐的方法是使用 Pythonmido 库,因为它跨平台且能精确控制 MIDI 消息。

以下是几种常见的脚本方案:

使用 Python 脚本(推荐,跨平台)

这是最灵活、最强大的方法,可以按照比率(如加速1.2倍)或绝对值(统一设为120 BPM)修改。

安装依赖库

需要安装 mido 库,打开终端(命令行)运行:

pip install mido

Python 脚本代码

创建一个文件,change_midi_bpm.py,复制以下代码:

import mido
from mido import MidiFile, MidiTrack, MetaMessage
import os
def change_tempo(midi_path, output_path, factor=1.0, new_bpm=None):
    """
    修改 MIDI 文件速度。
    :param midi_path: 输入文件路径
    :param output_path: 输出文件路径
    :param factor: 速度倍数 (2.0 表示加速一倍,0.5 表示减速一半)
    :param new_bpm: (可选)直接设置新的BPM值,若提供则忽略 factor
    """
    mid = MidiFile(midi_path)
    for track in mid.tracks:
        for msg in track:
            # 找到 Set Tempo 消息 (元事件)
            if msg.type == 'set_tempo':
                if new_bpm:
                    # 使用 mido 的 bpm2tempo 函数转换
                    msg.tempo = mido.bpm2tempo(new_bpm)
                else:
                    # 按比例调整 tempo 值 (microseconds per beat)
                    msg.tempo = int(msg.tempo / factor)
    # 保存修改后的文件
    mid.save(output_path)
    print(f"已完成: {os.path.basename(midi_path)} -> BPM 已调整")
def batch_process(input_folder, output_folder, factor=1.0, new_bpm=None, file_extension='.mid'):
    """
    批量处理文件夹中的 MIDI 文件
    """
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    for filename in os.listdir(input_folder):
        if filename.lower().endswith(file_extension):
            in_path = os.path.join(input_folder, filename)
            out_path = os.path.join(output_folder, filename)
            change_tempo(in_path, out_path, factor, new_bpm)
if __name__ == "__main__":
    # ===== 配置参数 =====
    input_dir = "./input_midi"    # 输入文件夹(放原始MIDI)
    output_dir = "./output_midi"  # 输出文件夹
    # 方法1:按比例调整(加速到1.2倍)
    # batch_process(input_dir, output_dir, factor=1.2)
    # 方法2:统一设置固定BPM(全部设为 140 BPM)
    batch_process(input_dir, output_dir, new_bpm=140)
    # 方法3:减速到 0.8 倍
    # batch_process(input_dir, output_dir, factor=0.8)

使用方法

  • 在脚本同目录下创建 input_midi 文件夹,放入你的 .mid 文件。
  • 运行脚本:python change_midi_bpm.py
  • 修改后的文件会出现在 output_midi 文件夹。

使用 Bash 脚本(仅限 Linux/macOS,需安装 midicsv

如果你比较习惯命令行,可以使用 midicsvcsvmidi 工具链。

安装工具

# macOS
brew install midicsv
# Ubuntu/Debian
sudo apt install midicsv

Bash 脚本

创建一个 change_bpm.sh 文件,内容如下:

#!/bin/bash
INPUT_DIR="./input"
OUTPUT_DIR="./output"
NEW_BPM=140  # 设定新BPM值
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mid; do
    # 将 MIDI 转为 CSV 文本格式
    csvname=$(basename "$file" .mid).csv
    midicsv "$file" "/tmp/$csvname"
    # 使用 sed 找到 Tempo 行并替换(Tempo 在 CSV 中格式为: 0, 0, Meta, Tempo, <value>)
    # 注意:MIDI内部存的是 microseconds per quarter note,需要转换:
    # tempo_value = 60000000 / BPM
    NEW_TEMPO_VALUE=$((60000000 / NEW_BPM))
    sed -i '' "s/^0, 0, Meta, Tempo, [0-9]*$/0, 0, Meta, Tempo, $NEW_TEMPO_VALUE/" "/tmp/$csvname"
    # 转回 MIDI
    csvmidi "/tmp/$csvname" "$OUTPUT_DIR/$(basename "$file")"
done
echo "批量转换完成!"
  • 优点:小脚本,无需安装Python库。
  • 缺点:无法处理嵌套文件夹;macOS 上 sed -i 需要加空格和引号。

使用 Python + 外部工具(更简单,适合一次性修改)

如果你不想处理MIDI底层消息,也可以使用 TiMidity++FluidSynth 渲染后重新设置BPM,但这样会丢失MIDI的控制信息,上面两种方案更精确。


常见问题与注意点

  1. BPM 与 tempo 的区别
    MIDI文件内部存储的是“每四分音符的微秒数”(tempo)。
    换算公式:tempo = 60,000,000 / BPM
    mido 库的 bpm2tempo() 函数已经帮你做这件事。

  2. 某些 MIDI 文件可能没有 Set Tempo 事件
    如果文件没有明确的节拍事件,系统会默认使用 120 BPM,对这种情况,可以考虑在第一个音轨开头插入一个 set_tempo 消息。

  3. 变速后音符长度变化?
    放心,MIDI 文件只记录音符的“开始时间”和“时长”(以 tick 为单位),修改 tempo 后,播放器会根据新 tempo 重新计算实际时间长度,因此音符节奏会自动等比缩放

  4. 文件编码
    建议只处理标准的 .mid.midi 文件。


推荐选择

  • 如果你希望简单、跨平台、可编程:用上面的 Python 方案一
  • 如果你是 Linux/macOS 用户且熟悉命令行:用 Bash 方案二
  • 只需要修改一两个文件:也可以直接用 DAW(如FL Studio、Logic、Cubase) 直接导入后改BPM再导出。

如果你能提供更具体的需求(比如要固定为120 BPM,还是按某个百分比加速),我可以帮你直接生成完整可用的脚本文件。

抱歉,评论功能暂时关闭!