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

使用mido拆分Lakh MIDI数据集时遇OSError: undefined status byte 0xf9错误

使用mido拆分Lakh/Clean MIDI子集时遇到OSError: undefined status byte 0xf9错误

错误信息

OSError: undefined status byte 0xf9

删除疑似有问题的MIDI文件后错误仍出现,无法确定是MIDI文件本身还是Python脚本导致问题。以下是运行的完整脚本:

from mido import Message, MidiFile, MidiTrack
import os

root_dir = r"C:\Users\admin\Desktop\clean_midi"
mid = MidiFile(r"C:\Users\admin\Desktop\clean_midi\.38 Special\Caught Up In You.mid")

musicain_dirs = os.listdir(root_dir)
for dir in musicain_dirs:
    musicain_dir = os.path.join(root_dir, dir)
    if not os.path.exists(dir):
        os.makedirs(dir)
    musics = os.listdir(musicain_dir)
    for music in musics:
        src_mid = MidiFile(os.path.join(musicain_dir, music))
        tar_dir = os.path.join(dir, music)
        if not os.path.exists(tar_dir):
            os.makedirs(tar_dir)
        for track in src_mid.tracks:
            if len(track) > 5:
                tar_mid = MidiFile()
                tar_mid.tracks.append(track)
                tar_name = os.path.join(tar_dir, track.name.replace("/"," ") + "_" + music)
                if not os.path.exists(tar_name):
                    tar_mid.save(tar_name)
    print(music)

对SPEC_BY_STATUS和specs.py完全不了解,找不到相关信息。


解决方案

1. 让mido忽略未知MIDI消息

错误中的0xf9是MIDI定时时钟消息,mido默认不处理这类消息。加载MIDI文件时添加ignore_unknown=True参数,即可跳过无法识别的状态字节:

src_mid = MidiFile(os.path.join(musicain_dir, music), ignore_unknown=True)

2. 修复脚本路径问题

原脚本创建目标目录时使用相对路径,会导致文件夹位置混乱,改为绝对路径:

  • 替换原代码中创建艺术家目录的逻辑:
    # 原代码
    # if not os.path.exists(dir):
    #     os.makedirs(dir)
    # 修改为
    artist_target_dir = os.path.join(root_dir, f"{dir}_split")
    if not os.path.exists(artist_target_dir):
        os.makedirs(artist_target_dir)
    
  • 替换目标轨道目录的逻辑:
    # 原代码
    # tar_dir = os.path.join(dir, music)
    # 修改为
    tar_dir = os.path.join(artist_target_dir, music.replace('.mid', ''))
    

3. 优化轨道过滤逻辑

除了按长度过滤,还可以过滤掉仅包含无效消息的轨道:

for track in src_mid.tracks:
    # 过滤掉短轨道和无有效消息的轨道
    valid_messages = [msg for msg in track if hasattr(msg, 'type')]
    if len(valid_messages) > 5:
        tar_mid = MidiFile()
        tar_mid.tracks.append(track)
        tar_name = os.path.join(tar_dir, track.name.replace("/"," ") + "_" + music)
        tar_mid.save(tar_name)

修改后的完整脚本

from mido import Message, MidiFile, MidiTrack
import os

root_dir = r"C:\Users\admin\Desktop\clean_midi"

musicain_dirs = os.listdir(root_dir)
for dir in musicain_dirs:
    musicain_dir = os.path.join(root_dir, dir)
    # 创建艺术家拆分后的目录
    artist_target_dir = os.path.join(root_dir, f"{dir}_split")
    if not os.path.exists(artist_target_dir):
        os.makedirs(artist_target_dir)
    
    if not os.path.isdir(musicain_dir):
        continue  # 跳过非目录文件
    
    musics = os.listdir(musicain_dir)
    for music in musics:
        music_path = os.path.join(musicain_dir, music)
        if not music.endswith('.mid'):
            continue  # 跳过非MIDI文件
        
        # 加载MIDI时忽略未知消息
        src_mid = MidiFile(music_path, ignore_unknown=True)
        
        # 创建单首歌的轨道目录
        tar_dir = os.path.join(artist_target_dir, music.replace('.mid', ''))
        if not os.path.exists(tar_dir):
            os.makedirs(tar_dir)
        
        for track in src_mid.tracks:
            # 过滤有效轨道
            valid_messages = [msg for msg in track if hasattr(msg, 'type')]
            if len(valid_messages) > 5:
                tar_mid = MidiFile()
                tar_mid.tracks.append(track)
                # 处理轨道名中的非法字符
                safe_track_name = track.name.replace("/"," ").replace("\\"," ").replace(":"," ").replace("*"," ").replace("?"," ").replace('"'," ").replace("<"," ").replace(">"," ").replace("|"," ")
                tar_name = os.path.join(tar_dir, f"{safe_track_name}_{music}")
                tar_mid.save(tar_name)
    print(f"{dir} 处理完成")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:44:58