{"id":84044,"date":"2026-07-26T08:10:06","date_gmt":"2026-07-26T00:10:06","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/84044.html"},"modified":"2026-07-26T08:10:06","modified_gmt":"2026-07-26T00:10:06","slug":"%e6%89%8b%e6%9c%ba%e7%ab%afpython%e8%af%ad%e8%a8%80mid%e8%bd%ac%e6%8d%a2%e6%88%90%e6%95%b0%e5%ad%97%e7%ae%80%e8%b0%b1%e8%bd%af%e4%bb%b6%e4%bb%a3%e7%a0%81qzq-2026-7-25","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/84044.html","title":{"rendered":"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25"},"content":{"rendered":"<p># -*- coding: utf-8 -*-<br \/>\n&#034;&#034;&#034;<br \/>\nMIDI\u8f6c\u7b80\u8c31 &#8211; \u624b\u673a\u9002\u914d\u7248<br \/>\n\u529f\u80fd&#xff1a;\u5bfc\u5165MIDI\u6587\u4ef6&#xff0c;\u8f6c\u6362\u4e3a\u7b80\u8c31\u6587\u672c<br \/>\n\u9002\u914d&#xff1a;\u624b\u673a\u5c4f\u5e55&#xff08;\u5c0f\u5c4f\u4f18\u5316&#xff09;<br \/>\n&#034;&#034;&#034;<\/p>\n<p>import sys<br \/>\nimport os<br \/>\nimport re<br \/>\nimport threading<br \/>\nfrom datetime import datetime<\/p>\n<p># \u5c1d\u8bd5\u5bfc\u5165\u4f9d\u8d56<br \/>\ntry:<br \/>\n    import mido<br \/>\nexcept ImportError:<br \/>\n    print(&#034;\u8bf7\u5148\u5b89\u88c5 mido: pip install mido&#034;)<br \/>\n    sys.exit(1)<\/p>\n<p>try:<br \/>\n    import tkinter as tk<br \/>\n    from tkinter import ttk, filedialog, messagebox, scrolledtext<br \/>\nexcept ImportError:<br \/>\n    print(&#034;\u8bf7\u5148\u5b89\u88c5 tkinter (Python\u81ea\u5e26)&#034;)<br \/>\n    sys.exit(1)<\/p>\n<p>APP_NAME &#061; &#034;MIDI\u8f6c\u7b80\u8c31&#034;<br \/>\nAPP_VERSION &#061; &#034;1.0&#034;<br \/>\nAPP_AUTHOR &#061; &#034;\u53f6\u6d77\u5b81&#034;<br \/>\nAPP_EMAIL &#061; &#034;791687349&#064;qq.com&#034;<\/p>\n<p>class MidiToJianpuMobile:<br \/>\n    def __init__(self, root):<br \/>\n        self.root &#061; root<br \/>\n        self.root.title(f&#034;{APP_NAME} V{APP_VERSION}&#034;)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u624b\u673a\u9002\u914d\u8bbe\u7f6e &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        # \u83b7\u53d6\u5c4f\u5e55\u5c3a\u5bf8<br \/>\n        screen_width &#061; root.winfo_screenwidth()<br \/>\n        screen_height &#061; root.winfo_screenheight()<\/p>\n<p>        # \u8bbe\u7f6e\u7a97\u53e3\u5927\u5c0f&#xff08;\u624b\u673a\u9002\u914d&#xff1a;\u5168\u5c4f\u6216\u63a5\u8fd1\u5168\u5c4f&#xff09;<br \/>\n        if screen_width &lt; 800:  # \u624b\u673a\u5c4f\u5e55<br \/>\n            win_width &#061; screen_width &#8211; 20<br \/>\n            win_height &#061; screen_height &#8211; 40<br \/>\n            self.is_mobile &#061; True<br \/>\n            self.font_size &#061; 8<br \/>\n            self.button_height &#061; 2<br \/>\n            self.padding &#061; 5<br \/>\n        else:  # \u5e73\u677f\u6216\u684c\u9762<br \/>\n            win_width &#061; min(600, screen_width &#8211; 100)<br \/>\n            win_height &#061; min(800, screen_height &#8211; 100)<br \/>\n            self.is_mobile &#061; False<br \/>\n            self.font_size &#061; 8<br \/>\n            self.button_height &#061; 1<br \/>\n            self.padding &#061; 10<\/p>\n<p>        self.root.geometry(f&#034;{win_width}x{win_height}&#034;)<br \/>\n        self.root.minsize(320, 480)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u989c\u8272\u4e3b\u9898&#xff08;\u62a4\u773c\u6a21\u5f0f&#xff09; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        self.bg_color &#061; &#034;#f5f0e8&#034;<br \/>\n        self.fg_color &#061; &#034;#2c3e50&#034;<br \/>\n        self.accent_color &#061; &#034;#4CAF50&#034;<br \/>\n        self.danger_color &#061; &#034;#e74c3c&#034;<br \/>\n        self.primary_color &#061; &#034;#3498db&#034;<\/p>\n<p>        self.root.configure(bg&#061;self.bg_color)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u521b\u5efaUI &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        self.create_widgets()<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u72b6\u6001\u53d8\u91cf &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        self.current_file &#061; None<br \/>\n        self.converted_tracks &#061; []<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u72b6\u6001\u680f &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        self.status_var &#061; tk.StringVar(value&#061;&#034;\u5c31\u7eea | \u8bf7\u5bfc\u5165MIDI\u6587\u4ef6&#034;)<br \/>\n        status_bar &#061; tk.Label(<br \/>\n            root,<br \/>\n            textvariable&#061;self.status_var,<br \/>\n            bd&#061;1,<br \/>\n            relief&#061;tk.SUNKEN,<br \/>\n            anchor&#061;tk.W,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#8211; 2),<br \/>\n            bg&#061;&#034;#ecf0f1&#034;<br \/>\n        )<br \/>\n        status_bar.pack(side&#061;tk.BOTTOM, fill&#061;tk.X)<\/p>\n<p>    def create_widgets(self):<br \/>\n        &#034;&#034;&#034;\u521b\u5efaUI\u7ec4\u4ef6 &#8211; \u624b\u673a\u9002\u914d\u5e03\u5c40&#034;&#034;&#034;<br \/>\n        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u4e3b\u5bb9\u5668 &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        main_frame &#061; tk.Frame(self.root, bg&#061;self.bg_color)<br \/>\n        main_frame.pack(fill&#061;tk.BOTH, expand&#061;True, padx&#061;self.padding, pady&#061;self.padding)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u6807\u9898 &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        title_font &#061; (&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#043; 6, &#034;bold&#034;)<br \/>\n        title &#061; tk.Label(<br \/>\n            main_frame,<br \/>\n            text&#061;f&#034;&#x1f3b5; {APP_NAME}&#034;,<br \/>\n            font&#061;title_font,<br \/>\n            fg&#061;self.primary_color,<br \/>\n            bg&#061;self.bg_color<br \/>\n        )<br \/>\n        title.pack(pady&#061;(10, 5))<\/p>\n<p>        subtitle &#061; tk.Label(<br \/>\n            main_frame,<br \/>\n            text&#061;&#034;\u5bfc\u5165MIDI\u6587\u4ef6 \u2192 \u81ea\u52a8\u8f6c\u6362\u4e3a\u7b80\u8c31&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#8211; 2),<br \/>\n            fg&#061;&#034;#7f8c8d&#034;,<br \/>\n            bg&#061;self.bg_color<br \/>\n        )<br \/>\n        subtitle.pack(pady&#061;(0, 15))<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u6309\u94ae\u533a\u57df&#xff08;\u6a2a\u5411\u5e03\u5c40&#xff09; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        btn_frame &#061; tk.Frame(main_frame, bg&#061;self.bg_color)<br \/>\n        btn_frame.pack(fill&#061;tk.X, pady&#061;5)<\/p>\n<p>        # \u5bfc\u5165\u6309\u94ae<br \/>\n        self.import_btn &#061; tk.Button(<br \/>\n            btn_frame,<br \/>\n            text&#061;&#034;&#x1f4c2; \u5bfc\u5165MIDI&#034;,<br \/>\n            width&#061;10,<br \/>\n            command&#061;self.import_midi_file,<br \/>\n            bg&#061;self.accent_color,<br \/>\n            fg&#061;&#034;white&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size),<\/p>\n<p>            height&#061;self.button_height,<br \/>\n            relief&#061;tk.RAISED<br \/>\n        )<br \/>\n        self.import_btn.pack(side&#061;tk.LEFT, fill&#061;tk.X, expand&#061;True, padx&#061;2)<\/p>\n<p>        # \u590d\u5236\u6309\u94ae<br \/>\n        self.copy_btn &#061; tk.Button(<br \/>\n            btn_frame,<br \/>\n            text&#061;&#034;&#x1f4cb; \u590d\u5236\u7ed3\u679c&#034;,<br \/>\n            width&#061;10,<br \/>\n            command&#061;self.copy_result,<br \/>\n            bg&#061;self.primary_color,<br \/>\n            fg&#061;&#034;white&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size),<\/p>\n<p>            height&#061;self.button_height,<br \/>\n            state&#061;tk.DISABLED,<br \/>\n            relief&#061;tk.RAISED<br \/>\n        )<br \/>\n        self.copy_btn.pack(side&#061;tk.LEFT, fill&#061;tk.X, expand&#061;True, padx&#061;2)<\/p>\n<p>        # \u6e05\u7a7a\u6309\u94ae<br \/>\n        self.clear_btn &#061; tk.Button(<br \/>\n            btn_frame,<br \/>\n            text&#061;&#034;&#x1f5d1;\ufe0f \u6e05\u7a7a&#034;,<br \/>\n            width&#061;10,<br \/>\n            command&#061;self.clear_result,<br \/>\n            bg&#061;self.danger_color,<br \/>\n            fg&#061;&#034;white&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size),<\/p>\n<p>            height&#061;self.button_height,<br \/>\n            relief&#061;tk.RAISED<br \/>\n        )<br \/>\n        self.clear_btn.pack(side&#061;tk.LEFT, fill&#061;tk.X, expand&#061;True, padx&#061;2)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u97f3\u8f68\u9009\u62e9\u533a\u57df &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        track_frame &#061; tk.Frame(main_frame, bg&#061;self.bg_color)<br \/>\n        track_frame.pack(fill&#061;tk.X, pady&#061;5)<\/p>\n<p>        tk.Label(<br \/>\n            track_frame,<br \/>\n            text&#061;&#034;\u9009\u62e9\u97f3\u8f68:&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size),<br \/>\n            bg&#061;self.bg_color<br \/>\n        ).pack(side&#061;tk.LEFT, padx&#061;2)<\/p>\n<p>        self.track_var &#061; tk.StringVar(value&#061;&#034;\u5168\u90e8&#034;)<br \/>\n        self.track_combo &#061; ttk.Combobox(<br \/>\n            track_frame,<br \/>\n            textvariable&#061;self.track_var,<br \/>\n            values&#061;[&#034;\u5168\u90e8&#034;],<br \/>\n            state&#061;&#034;readonly&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size),<br \/>\n            width&#061;15 if self.is_mobile else 20<br \/>\n        )<br \/>\n        self.track_combo.pack(side&#061;tk.LEFT, fill&#061;tk.X, expand&#061;True, padx&#061;2)<br \/>\n        self.track_combo.bind(&#034;&lt;&lt;ComboboxSelected&gt;&gt;&#034;, self.on_track_selected)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u7ed3\u679c\u663e\u793a\u533a\u57df &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        result_frame &#061; tk.Frame(main_frame, bg&#061;self.bg_color)<br \/>\n        result_frame.pack(fill&#061;tk.BOTH, expand&#061;True, pady&#061;5)<\/p>\n<p>        # \u6807\u7b7e<br \/>\n        label_frame &#061; tk.Frame(result_frame, bg&#061;self.bg_color)<br \/>\n        label_frame.pack(fill&#061;tk.X)<\/p>\n<p>        self.info_label &#061; tk.Label(<br \/>\n            label_frame,<br \/>\n            text&#061;&#034;&#x1f4a1; \u8bf7\u5bfc\u5165MIDI\u6587\u4ef6\u67e5\u770b\u8f6c\u6362\u7ed3\u679c&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#8211; 1),<br \/>\n            fg&#061;&#034;#7f8c8d&#034;,<br \/>\n            bg&#061;self.bg_color<br \/>\n        )<br \/>\n        self.info_label.pack(side&#061;tk.LEFT)<\/p>\n<p>        # \u5b57\u7b26\u8ba1\u6570<br \/>\n        self.count_label &#061; tk.Label(<br \/>\n            label_frame,<br \/>\n            text&#061;&#034;&#034;,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#8211; 2),<br \/>\n            fg&#061;&#034;#95a5a6&#034;,<br \/>\n            bg&#061;self.bg_color<br \/>\n        )<br \/>\n        self.count_label.pack(side&#061;tk.RIGHT)<\/p>\n<p>        # \u6587\u672c\u6846&#xff08;\u5e26\u6eda\u52a8\u6761&#xff09;<br \/>\n        self.result_text &#061; scrolledtext.ScrolledText(<br \/>\n            result_frame,<br \/>\n            wrap&#061;tk.WORD,<br \/>\n            font&#061;(&#034;Consolas&#034;, self.font_size),<br \/>\n            bg&#061;&#034;white&#034;,<br \/>\n            fg&#061;self.fg_color,<br \/>\n            relief&#061;tk.FLAT,<br \/>\n            bd&#061;2,<br \/>\n            highlightthickness&#061;1,<br \/>\n            highlightcolor&#061;self.primary_color<br \/>\n        )<br \/>\n        self.result_text.pack(fill&#061;tk.BOTH, expand&#061;True)<\/p>\n<p>        # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u5e95\u90e8\u4fe1\u606f &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n        footer_frame &#061; tk.Frame(main_frame, bg&#061;self.bg_color)<br \/>\n        footer_frame.pack(fill&#061;tk.X, pady&#061;5)<\/p>\n<p>        footer_text &#061; f&#034;{APP_NAME} v{APP_VERSION} | \u652f\u6301\u591a\u97f3\u8f68MIDI | \u81ea\u52a8\u8bc6\u522bBPM&#034;<br \/>\n        tk.Label(<br \/>\n            footer_frame,<br \/>\n            text&#061;footer_text,<br \/>\n            font&#061;(&#034;\u5fae\u8f6f\u96c5\u9ed1&#034;, self.font_size &#8211; 3),<br \/>\n            fg&#061;&#034;#bdc3c7&#034;,<br \/>\n            bg&#061;self.bg_color<br \/>\n        ).pack()<\/p>\n<p>    def update_status(self, message, is_error&#061;False):<br \/>\n        &#034;&#034;&#034;\u66f4\u65b0\u72b6\u6001\u680f&#034;&#034;&#034;<br \/>\n        if is_error:<br \/>\n            self.status_var.set(f&#034;\u274c {message}&#034;)<br \/>\n        else:<br \/>\n            self.status_var.set(f&#034;\u2705 {message}&#034;)<br \/>\n        self.root.update_idletasks()<\/p>\n<p>    def import_midi_file(self):<br \/>\n        &#034;&#034;&#034;\u5bfc\u5165MIDI\u6587\u4ef6&#034;&#034;&#034;<br \/>\n        # \u624b\u673a\u7aef\u4f7f\u7528\u6587\u4ef6\u9009\u62e9\u5668<br \/>\n        midi_file &#061; filedialog.askopenfilename(<br \/>\n            title&#061;&#034;\u9009\u62e9MIDI\u6587\u4ef6&#034;,<br \/>\n            filetypes&#061;[<br \/>\n                (&#034;MIDI\u6587\u4ef6&#034;, &#034;*.mid&#034;),<br \/>\n                (&#034;MIDI\u6587\u4ef6&#034;, &#034;*.midi&#034;),<br \/>\n                (&#034;\u6240\u6709\u6587\u4ef6&#034;, &#034;*.*&#034;)<br \/>\n            ]<br \/>\n        )<\/p>\n<p>        if not midi_file:<br \/>\n            return<\/p>\n<p>        self.current_file &#061; midi_file<br \/>\n        self.update_status(f&#034;\u6b63\u5728\u89e3\u6790: {os.path.basename(midi_file)}&#034;)<\/p>\n<p>        # \u5728\u65b0\u7ebf\u7a0b\u4e2d\u5904\u7406&#xff0c;\u907f\u514d\u754c\u9762\u5361\u987f<br \/>\n        threading.Thread(target&#061;self._process_midi, args&#061;(midi_file,), daemon&#061;True).start()<\/p>\n<p>    def _process_midi(self, midi_file):<br \/>\n        &#034;&#034;&#034;\u5904\u7406MIDI\u6587\u4ef6&#xff08;\u5728\u540e\u53f0\u7ebf\u7a0b\u8fd0\u884c&#xff09;&#034;&#034;&#034;<br \/>\n        try:<br \/>\n            tracks &#061; self.midi_to_jianpu_multi_track(midi_file)<\/p>\n<p>            if not tracks:<br \/>\n                self.root.after(0, lambda: self._show_error(&#034;MIDI\u6587\u4ef6\u4e2d\u672a\u627e\u5230\u97f3\u7b26&#034;))<br \/>\n                return<\/p>\n<p>            self.converted_tracks &#061; tracks<\/p>\n<p>            # \u66f4\u65b0\u97f3\u8f68\u9009\u62e9\u4e0b\u62c9\u6846<br \/>\n            track_names &#061; [&#034;\u5168\u90e8&#034;] &#043; [f&#034;\u97f3\u8f68{i &#043; 1}: {t[&#039;name&#039;]}&#034; for i, t in enumerate(tracks)]<br \/>\n            self.root.after(0, lambda: self._update_track_combo(track_names))<\/p>\n<p>            # \u663e\u793a\u5168\u90e8\u97f3\u8f68\u7ed3\u679c<br \/>\n            self.root.after(0, lambda: self._display_all_tracks())<\/p>\n<p>            # \u542f\u7528\u590d\u5236\u6309\u94ae<br \/>\n            self.root.after(0, lambda: self.copy_btn.config(state&#061;tk.NORMAL))<\/p>\n<p>            self.root.after(0, lambda: self.update_status(<br \/>\n                f&#034;\u5b8c\u6210! \u5171 {len(tracks)} \u4e2a\u97f3\u8f68 | {os.path.basename(midi_file)}&#034;<br \/>\n            ))<\/p>\n<p>        except Exception as e:<br \/>\n            self.root.after(0, lambda: self._show_error(f&#034;\u8f6c\u6362\u5931\u8d25: {str(e)}&#034;))<\/p>\n<p>    def _show_error(self, message):<br \/>\n        &#034;&#034;&#034;\u663e\u793a\u9519\u8bef\u4fe1\u606f&#034;&#034;&#034;<br \/>\n        self.update_status(message, is_error&#061;True)<br \/>\n        messagebox.showerror(&#034;\u9519\u8bef&#034;, message)<\/p>\n<p>    def _update_track_combo(self, track_names):<br \/>\n        &#034;&#034;&#034;\u66f4\u65b0\u97f3\u8f68\u4e0b\u62c9\u6846&#034;&#034;&#034;<br \/>\n        self.track_combo[&#039;values&#039;] &#061; track_names<br \/>\n        self.track_var.set(&#034;\u5168\u90e8&#034;)<\/p>\n<p>    def _display_all_tracks(self):<br \/>\n        &#034;&#034;&#034;\u663e\u793a\u6240\u6709\u97f3\u8f68\u7684\u7b80\u8c31&#034;&#034;&#034;<br \/>\n        if not self.converted_tracks:<br \/>\n            return<\/p>\n<p>        result_parts &#061; []<br \/>\n        total_notes &#061; 0<\/p>\n<p>        for i, track in enumerate(self.converted_tracks):<br \/>\n            bpm &#061; track.get(&#039;bpm&#039;, 120)<br \/>\n            jianpu &#061; track[&#039;jianpu&#039;]<br \/>\n            total_notes &#043;&#061; len(jianpu)<\/p>\n<p>            # result_parts.append(f&#034;\u3010\u97f3\u8f68 {i &#043; 1}: {track[&#039;name&#039;]}\u3011&#034;)<br \/>\n            # result_parts.append(f&#034;\u901f\u5ea6: {bpm} BPM&#034;)<br \/>\n            result_parts.append(&#034;[0,320,G\u5927\u8c03]&#034;)<br \/>\n            # result_parts.append(&#034;&#034;)<\/p>\n<p>            # \u683c\u5f0f\u5316\u7b80\u8c31&#xff08;\u6bcf80\u5b57\u7b26\u6362\u884c&#xff09;<br \/>\n            for j in range(0, len(jianpu), 80):<br \/>\n                result_parts.append(jianpu[j:j &#043; 80])<br \/>\n            result_parts.append(&#034;&#034;)<br \/>\n            # result_parts.append(&#034;-&#034; * 50)<br \/>\n            result_parts.append(&#034;&#034;)<\/p>\n<p>        full_text &#061; &#034;\\\\n&#034;.join(result_parts)<br \/>\n        self.result_text.delete(&#034;1.0&#034;, tk.END)<br \/>\n        self.result_text.insert(&#034;1.0&#034;, full_text)<\/p>\n<p>        # \u66f4\u65b0\u4fe1\u606f<br \/>\n        self.info_label.config(text&#061;f&#034;&#x1f3b5; \u5171 {len(self.converted_tracks)} \u4e2a\u97f3\u8f68&#034;)<br \/>\n        self.count_label.config(text&#061;f&#034;\u97f3\u7b26\u6570: {total_notes}&#034;)<\/p>\n<p>    def on_track_selected(self, event):<br \/>\n        &#034;&#034;&#034;\u9009\u62e9\u97f3\u8f68\u65f6\u89e6\u53d1&#034;&#034;&#034;<br \/>\n        selection &#061; self.track_var.get()<\/p>\n<p>        if not self.converted_tracks:<br \/>\n            return<\/p>\n<p>        if selection &#061;&#061; &#034;\u5168\u90e8&#034;:<br \/>\n            self._display_all_tracks()<br \/>\n            return<\/p>\n<p>        # \u89e3\u6790\u97f3\u8f68\u7d22\u5f15<br \/>\n        try:<br \/>\n            # \u683c\u5f0f: &#034;\u97f3\u8f68X: \u540d\u79f0&#034;<br \/>\n            import re<br \/>\n            match &#061; re.search(r&#039;\u97f3\u8f68(\\\\d&#043;)&#039;, selection)<br \/>\n            if match:<br \/>\n                idx &#061; int(match.group(1)) &#8211; 1<br \/>\n                if 0 &lt;&#061; idx &lt; len(self.converted_tracks):<br \/>\n                    self._display_single_track(idx)<br \/>\n        except:<br \/>\n            pass<\/p>\n<p>    def _display_single_track(self, idx):<br \/>\n        &#034;&#034;&#034;\u663e\u793a\u5355\u4e2a\u97f3\u8f68&#034;&#034;&#034;<br \/>\n        track &#061; self.converted_tracks[idx]<br \/>\n        bpm &#061; track.get(&#039;bpm&#039;, 120)<br \/>\n        jianpu &#061; track[&#039;jianpu&#039;]<\/p>\n<p>        result_parts &#061; []<br \/>\n        # result_parts.append(f&#034;\u3010\u97f3\u8f68 {idx &#043; 1}: {track[&#039;name&#039;]}\u3011&#034;)<br \/>\n        # result_parts.append(f&#034;\u901f\u5ea6: {bpm} BPM&#034;)<br \/>\n        result_parts.append(&#034;[0,320,G\u5927\u8c03]&#034;)<br \/>\n        # result_parts.append(&#034;&#034;)<\/p>\n<p>        for j in range(0, len(jianpu), 80):<br \/>\n            result_parts.append(jianpu[j:j &#043; 80])<\/p>\n<p>        full_text &#061; &#034;\\\\n&#034;.join(result_parts)<br \/>\n        self.result_text.delete(&#034;1.0&#034;, tk.END)<br \/>\n        self.result_text.insert(&#034;1.0&#034;, full_text)<\/p>\n<p>        self.info_label.config(text&#061;f&#034;&#x1f3b5; \u5f53\u524d: {track[&#039;name&#039;]}&#034;)<br \/>\n        self.count_label.config(text&#061;f&#034;\u97f3\u7b26\u6570: {len(jianpu)}&#034;)<\/p>\n<p>    def copy_result(self):<br \/>\n        &#034;&#034;&#034;\u590d\u5236\u7ed3\u679c\u5230\u526a\u8d34\u677f&#034;&#034;&#034;<br \/>\n        content &#061; self.result_text.get(&#034;1.0&#034;, tk.END).strip()<br \/>\n        if content:<br \/>\n            self.root.clipboard_clear()<br \/>\n            self.root.clipboard_append(content)<br \/>\n            self.update_status(&#034;\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f&#034;)<br \/>\n            # \u624b\u673a\u7aef\u663e\u793a\u63d0\u793a<br \/>\n            messagebox.showinfo(&#034;\u6210\u529f&#034;, &#034;\u7b80\u8c31\u5185\u5bb9\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f&#034;)<\/p>\n<p>    def clear_result(self):<br \/>\n        &#034;&#034;&#034;\u6e05\u7a7a\u7ed3\u679c&#034;&#034;&#034;<br \/>\n        self.result_text.delete(&#034;1.0&#034;, tk.END)<br \/>\n        self.converted_tracks &#061; []<br \/>\n        self.track_combo[&#039;values&#039;] &#061; [&#034;\u5168\u90e8&#034;]<br \/>\n        self.track_var.set(&#034;\u5168\u90e8&#034;)<br \/>\n        self.copy_btn.config(state&#061;tk.DISABLED)<br \/>\n        self.info_label.config(text&#061;&#034;&#x1f4a1; \u8bf7\u5bfc\u5165MIDI\u6587\u4ef6\u67e5\u770b\u8f6c\u6362\u7ed3\u679c&#034;)<br \/>\n        self.count_label.config(text&#061;&#034;&#034;)<br \/>\n        self.update_status(&#034;\u5df2\u6e05\u7a7a&#034;)<\/p>\n<p>    # &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; MIDI\u8f6c\u6362\u6838\u5fc3\u4ee3\u7801 &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/p>\n<p>    def midi_to_jianpu_multi_track(self, midi_file_path):<br \/>\n        &#034;&#034;&#034;<br \/>\n        \u5c06MIDI\u6587\u4ef6\u8f6c\u6362\u4e3a\u591a\u6761\u7b80\u8c31&#xff08;\u6bcf\u4e2a\u8f68\u9053\u72ec\u7acb&#xff09;<br \/>\n        \u652f\u6301\u5347\u53f7 # \u97f3\u7b26<br \/>\n        &#034;&#034;&#034;<br \/>\n        # \u5b8c\u6574\u97f3\u7b26\u6620\u5c04&#xff08;\u5305\u542b\u5347\u53f7 #&#xff09;<br \/>\n        note_map &#061; {<br \/>\n            # \u4e2d\u97f3\u533a (C4-B4)<br \/>\n            60: &#039;1&#039;, 61: &#039;1#&#039;, 62: &#039;2&#039;, 63: &#039;2#&#039;, 64: &#039;3&#039;,<br \/>\n            65: &#039;4&#039;, 66: &#039;4#&#039;, 67: &#039;5&#039;, 68: &#039;5#&#039;, 69: &#039;6&#039;,<br \/>\n            70: &#039;6#&#039;, 71: &#039;7&#039;,<br \/>\n            # \u9ad8\u516b\u5ea6 (C5-B5)<br \/>\n            72: &#034;1&#039;&#034;, 73: &#034;1#&#039;&#034;, 74: &#034;2&#039;&#034;, 75: &#034;2#&#039;&#034;, 76: &#034;3&#039;&#034;,<br \/>\n            77: &#034;4&#039;&#034;, 78: &#034;4#&#039;&#034;, 79: &#034;5&#039;&#034;, 80: &#034;5#&#039;&#034;, 81: &#034;6&#039;&#034;,<br \/>\n            82: &#034;6#&#039;&#034;, 83: &#034;7&#039;&#034;,<br \/>\n            # \u9ad8\u4e24\u4e2a\u516b\u5ea6 (C6-B6)<br \/>\n            84: &#034;1&#039;&#039;&#034;, 85: &#034;1#&#039;&#039;&#034;, 86: &#034;2&#039;&#039;&#034;, 87: &#034;2#&#039;&#039;&#034;, 88: &#034;3&#039;&#039;&#034;,<br \/>\n            89: &#034;4&#039;&#039;&#034;, 90: &#034;4#&#039;&#039;&#034;, 91: &#034;5&#039;&#039;&#034;, 92: &#034;5#&#039;&#039;&#034;, 93: &#034;6&#039;&#039;&#034;,<br \/>\n            94: &#034;6#&#039;&#039;&#034;, 95: &#034;7&#039;&#039;&#034;,<br \/>\n            # \u9ad8\u4e09\u4e2a\u516b\u5ea6 (C7-B7)<br \/>\n            96: &#034;1&#039;&#039;&#039;&#034;, 97: &#034;1#&#039;&#039;&#039;&#034;, 98: &#034;2&#039;&#039;&#039;&#034;, 99: &#034;2#&#039;&#039;&#039;&#034;, 100: &#034;3&#039;&#039;&#039;&#034;,<br \/>\n            101: &#034;4&#039;&#039;&#039;&#034;, 102: &#034;4#&#039;&#039;&#039;&#034;, 103: &#034;5&#039;&#039;&#039;&#034;, 104: &#034;5#&#039;&#039;&#039;&#034;, 105: &#034;6&#039;&#039;&#039;&#034;,<br \/>\n            106: &#034;6#&#039;&#039;&#039;&#034;, 107: &#034;7&#039;&#039;&#039;&#034;,<br \/>\n            # \u4f4e\u516b\u5ea6 (C3-B3)<br \/>\n            48: &#039;1.&#039;, 49: &#039;1#.&#039;, 50: &#039;2.&#039;, 51: &#039;2#.&#039;, 52: &#039;3.&#039;,<br \/>\n            53: &#039;4.&#039;, 54: &#039;4#.&#039;, 55: &#039;5.&#039;, 56: &#039;5#.&#039;, 57: &#039;6.&#039;,<br \/>\n            58: &#039;6#.&#039;, 59: &#039;7.&#039;,<br \/>\n            # \u4f4e\u4e24\u4e2a\u516b\u5ea6 (C2-B2)<br \/>\n            36: &#039;1..&#039;, 37: &#039;1#..&#039;, 38: &#039;2..&#039;, 39: &#039;2#..&#039;, 40: &#039;3..&#039;,<br \/>\n            41: &#039;4..&#039;, 42: &#039;4#..&#039;, 43: &#039;5..&#039;, 44: &#039;5#..&#039;, 45: &#039;6..&#039;,<br \/>\n            46: &#039;6#..&#039;, 47: &#039;7..&#039;,<br \/>\n            # \u4f4e\u4e09\u4e2a\u516b\u5ea6 (C1-B1)<br \/>\n            24: &#039;1&#8230;&#039;, 25: &#039;1#&#8230;&#039;, 26: &#039;2&#8230;&#039;, 27: &#039;2#&#8230;&#039;, 28: &#039;3&#8230;&#039;,<br \/>\n            29: &#039;4&#8230;&#039;, 30: &#039;4#&#8230;&#039;, 31: &#039;5&#8230;&#039;, 32: &#039;5#&#8230;&#039;, 33: &#039;6&#8230;&#039;,<br \/>\n            34: &#039;6#&#8230;&#039;, 35: &#039;7&#8230;&#039;,<br \/>\n        }<\/p>\n<p>        try:<br \/>\n            mid &#061; mido.MidiFile(midi_file_path)<br \/>\n            ticks_per_beat &#061; mid.ticks_per_beat<br \/>\n            tracks_result &#061; []<br \/>\n            global_tempo &#061; 500000<\/p>\n<p>            for track_idx, track in enumerate(mid.tracks):<br \/>\n                active_notes &#061; {}<br \/>\n                note_events &#061; []<br \/>\n                current_tempo &#061; global_tempo<br \/>\n                track_name &#061; f&#034;\u97f3\u8f68{track_idx &#043; 1}&#034;<\/p>\n<p>                abs_time &#061; 0<br \/>\n                for msg in track:<br \/>\n                    abs_time &#043;&#061; msg.time<\/p>\n<p>                    if msg.is_meta:<br \/>\n                        if msg.type &#061;&#061; &#039;set_tempo&#039;:<br \/>\n                            current_tempo &#061; msg.tempo<br \/>\n                            global_tempo &#061; current_tempo<br \/>\n                        elif msg.type &#061;&#061; &#039;track_name&#039;:<br \/>\n                            track_name &#061; msg.name<br \/>\n                        continue<\/p>\n<p>                    if msg.type &#061;&#061; &#039;note_on&#039; and msg.velocity &gt; 0:<br \/>\n                        active_notes[msg.note] &#061; abs_time<br \/>\n                    elif msg.type &#061;&#061; &#039;note_off&#039; or (msg.type &#061;&#061; &#039;note_on&#039; and msg.velocity &#061;&#061; 0):<br \/>\n                        if msg.note in active_notes:<br \/>\n                            duration &#061; abs_time &#8211; active_notes[msg.note]<br \/>\n                            note_events.append((active_notes[msg.note], duration, msg.note))<br \/>\n                            del active_notes[msg.note]<\/p>\n<p>                if not note_events:<br \/>\n                    continue<\/p>\n<p>                note_events.sort(key&#061;lambda x: x[0])<br \/>\n                quarter_ticks &#061; ticks_per_beat<br \/>\n                score_parts &#061; []<\/p>\n<p>                for start_time, duration, note in note_events:<br \/>\n                    note_str &#061; note_map.get(note, &#039;&#039;)<br \/>\n                    if not note_str:<br \/>\n                        continue<\/p>\n<p>                    beat_ratio &#061; duration \/ quarter_ticks<br \/>\n                    duration_symbol &#061; self._get_duration_symbol(beat_ratio)<\/p>\n<p>                    score_parts.append(note_str)<br \/>\n                    if duration_symbol:<br \/>\n                        score_parts.append(duration_symbol)<\/p>\n<p>                bpm &#061; int(mido.tempo2bpm(current_tempo))<br \/>\n                jianpu_text &#061; &#039;&#039;.join(score_parts)<\/p>\n<p>                # \u9650\u5236\u957f\u5ea6<br \/>\n                if len(jianpu_text) &gt; 5000:<br \/>\n                    jianpu_text &#061; jianpu_text[:5000]<\/p>\n<p>                tracks_result.append({<br \/>\n                    &#039;name&#039;: track_name,<br \/>\n                    &#039;bpm&#039;: bpm,<br \/>\n                    &#039;jianpu&#039;: jianpu_text,<br \/>\n                    &#039;track_index&#039;: track_idx<br \/>\n                })<\/p>\n<p>            return tracks_result if tracks_result else None<\/p>\n<p>        except Exception as e:<br \/>\n            print(f&#034;MIDI\u5bfc\u5165\u9519\u8bef: {e}&#034;)<br \/>\n            return None<\/p>\n<p>    def _get_duration_symbol(self, beat_ratio):<br \/>\n        &#034;&#034;&#034;\u6839\u636e\u62cd\u6570\u6bd4\u4f8b\u8fd4\u56de\u65f6\u503c\u7b26\u53f7&#034;&#034;&#034;<br \/>\n        beats &#061; round(beat_ratio * 4) \/ 4<\/p>\n<p>        if beats &gt;&#061; 4.0:<br \/>\n            return &#039;&#8212;-&#039;<br \/>\n        elif beats &gt;&#061; 3.5:<br \/>\n            return &#039;&#8212;&#039;<br \/>\n        elif beats &gt;&#061; 3.0:<br \/>\n            return &#039;&#8212;&#039;<br \/>\n        elif beats &gt;&#061; 2.5:<br \/>\n            return &#039;&#8211;&#039;<br \/>\n        elif beats &gt;&#061; 2.0:<br \/>\n            return &#039;&#8211;&#039;<br \/>\n        elif beats &gt;&#061; 1.75:<br \/>\n            return &#039;-&#039;<br \/>\n        elif beats &gt;&#061; 1.5:<br \/>\n            return &#039;-&#039;<br \/>\n        elif beats &gt;&#061; 1.25:<br \/>\n            return &#039;-&#039;<br \/>\n        elif beats &gt;&#061; 1.0:<br \/>\n            return &#039;&#039;<br \/>\n        else:<br \/>\n            return &#039;&#039;<\/p>\n<p>def main():<br \/>\n    root &#061; tk.Tk()<\/p>\n<p>    # \u8bbe\u7f6e\u5e94\u7528\u56fe\u6807&#xff08;\u5982\u679c\u6709\u7684\u8bdd&#xff09;<br \/>\n    try:<br \/>\n        root.iconbitmap(&#039;icon.ico&#039;)<br \/>\n    except:<br \/>\n        pass<\/p>\n<p>    app &#061; MidiToJianpuMobile(root)<br \/>\n    root.mainloop()<\/p>\n<p>if __name__ &#061;&#061; &#034;__main__&#034;:<br \/>\n    main()<\/p>\n","protected":false},"excerpt":{"rendered":"<p># -*- coding: utf-8 -*-<br \/>\n\\&#8221;\\&#8221;\\&#8221;<br \/>\nMIDI\u8f6c\u7b80\u8c31 &#8211; \u624b\u673a\u9002\u914d\u7248<br \/>\n\u529f\u80fd&#xff1a;\u5bfc\u5165MIDI\u6587\u4ef6&#xff0c;\u8f6c\u6362\u4e3a\u7b80\u8c31\u6587\u672c<br \/>\n\u9002\u914d&#xff1a;\u624b\u673a\u5c4f\u5e55&#xff08;\u5c0f\u5c4f\u4f18\u5316&#xff09;<br \/>\n\\&#8221;\\&#8221;\\&#8221;import sys<br \/>\nimport os<br \/>\nimport re<br \/>\nimport threading<br \/>\nfrom datetime import datetime# \u5c1d\u8bd5\u5bfc\u5165\u4f9d\u8d56<br \/>\ntry:import mido<br \/>\nexcept ImportError:pri<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[81,427],"topic":[],"class_list":["post-84044","post","type-post","status-publish","format-standard","hentry","category-server","tag-python","tag-427"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/84044.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"# -*- coding: utf-8 -*- &quot;&quot;&quot; MIDI\u8f6c\u7b80\u8c31 - \u624b\u673a\u9002\u914d\u7248 \u529f\u80fd&#xff1a;\u5bfc\u5165MIDI\u6587\u4ef6&#xff0c;\u8f6c\u6362\u4e3a\u7b80\u8c31\u6587\u672c \u9002\u914d&#xff1a;\u624b\u673a\u5c4f\u5e55&#xff08;\u5c0f\u5c4f\u4f18\u5316&#xff09; &quot;&quot;&quot;import sys import os import re import threading from datetime import datetime# \u5c1d\u8bd5\u5bfc\u5165\u4f9d\u8d56 try:import mido except ImportError:pri\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/84044.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-26T00:10:06+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/84044.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/84044.html\",\"name\":\"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-07-26T00:10:06+00:00\",\"dateModified\":\"2026-07-26T00:10:06+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/84044.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/84044.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/84044.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/84044.html","og_locale":"zh_CN","og_type":"article","og_title":"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"# -*- coding: utf-8 -*- \"\"\" MIDI\u8f6c\u7b80\u8c31 - \u624b\u673a\u9002\u914d\u7248 \u529f\u80fd&#xff1a;\u5bfc\u5165MIDI\u6587\u4ef6&#xff0c;\u8f6c\u6362\u4e3a\u7b80\u8c31\u6587\u672c \u9002\u914d&#xff1a;\u624b\u673a\u5c4f\u5e55&#xff08;\u5c0f\u5c4f\u4f18\u5316&#xff09; \"\"\"import sys import os import re import threading from datetime import datetime# \u5c1d\u8bd5\u5bfc\u5165\u4f9d\u8d56 try:import mido except ImportError:pri","og_url":"https:\/\/www.wsisp.com\/helps\/84044.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-07-26T00:10:06+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"8 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/84044.html","url":"https:\/\/www.wsisp.com\/helps\/84044.html","name":"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-07-26T00:10:06+00:00","dateModified":"2026-07-26T00:10:06+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/84044.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/84044.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/84044.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"\u624b\u673a\u7aefpython\u8bed\u8a00mid\u8f6c\u6362\u6210\u6570\u5b57\u7b80\u8c31\u8f6f\u4ef6\u4ee3\u7801QZQ-2026-7-25"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/84044","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=84044"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/84044\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=84044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=84044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=84044"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=84044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}