如何通过Python或命令行将MIDI Type 1文件转换为MIDI Type 0?
Great question! Converting MIDI Type 1 files to Type 0 is totally feasible with Python, and I’ll walk you through two solid approaches: using a dedicated library with a reusable function, and a command-line ready script you can run directly. Let’s dive in:
mido Python Library mido is a lightweight, well-documented library for working with MIDI files across all major platforms. It handles the heavy lifting of parsing and writing MIDI data, making conversion straightforward.
First, install the library:
pip install mido
Here’s a robust conversion function that properly handles parallel tracks in Type 1 files (critical for accurate timing):
import mido def convert_type1_to_type0(input_path, output_path): # Load the input MIDI file mid = mido.MidiFile(input_path) # Check if the file is already Type 0 if mid.type != 1: print(f"Warning: Input file is already Type {mid.type} — no conversion needed.") return # Collect all messages with their absolute time from the start of the file all_messages = [] for track in mid.tracks: current_absolute_time = 0 for msg in track: current_absolute_time += msg.time # Skip end-of-track messages until the final track if not isinstance(msg, mido.MetaMessage) or msg.type != 'end_of_track': # Store absolute time and a copy of the message (resetting its relative time) all_messages.append((current_absolute_time, msg.copy(time=0))) # Sort messages by their absolute time to maintain proper playback order all_messages.sort(key=lambda x: x[0]) # Create a new Type 0 MIDI file (single track) new_mid = mido.MidiFile(type=0) new_track = mido.MidiTrack() new_mid.tracks.append(new_track) # Convert absolute times back to relative times for the single track previous_time = 0 for abs_time, msg in all_messages: msg.time = abs_time - previous_time new_track.append(msg) previous_time = abs_time # Add the final end-of-track marker new_track.append(mido.MetaMessage('end_of_track')) # Save the converted file new_mid.save(output_path) print(f"Success! Converted {input_path} to Type 0 MIDI at {output_path}") # Example usage convert_type1_to_type0("your_input_file.mid", "your_output_file.mid")
This script ensures all parallel tracks from the Type 1 file are merged into a single track with correct timing, which is essential for proper playback of the Type 0 file.
If you want to run conversions directly from the terminal without modifying code, use this version with command-line argument support:
import mido import argparse def convert_type1_to_type0(input_path, output_path): mid = mido.MidiFile(input_path) if mid.type != 1: print(f"Warning: Input file is already Type {mid.type} — no conversion needed.") return all_messages = [] for track in mid.tracks: current_absolute_time = 0 for msg in track: current_absolute_time += msg.time if not isinstance(msg, mido.MetaMessage) or msg.type != 'end_of_track': all_messages.append((current_absolute_time, msg.copy(time=0))) all_messages.sort(key=lambda x: x[0]) new_mid = mido.MidiFile(type=0) new_track = mido.MidiTrack() new_mid.tracks.append(new_track) previous_time = 0 for abs_time, msg in all_messages: msg.time = abs_time - previous_time new_track.append(msg) previous_time = abs_time new_track.append(mido.MetaMessage('end_of_track')) new_mid.save(output_path) print(f"Conversion complete: {input_path} → {output_path}") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Convert MIDI Type 1 files to Type 0.') parser.add_argument('input', help='Path to your input Type 1 MIDI file') parser.add_argument('output', help='Path to save the converted Type 0 MIDI file') args = parser.parse_args() convert_type1_to_type0(args.input, args.output)
Save this as midi_type_converter.py, then run it like this:
python midi_type_converter.py path/to/input.mid path/to/output.mid
内容的提问来源于stack exchange,提问作者user11253780




