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

Python Flask应用如何在后台运行函数以实现midi键盘输入监听?

解决方案

以下是可直接运行的修改后代码,已经解决后台线程启动、线程安全、数据重置等核心问题:

from flask import Flask, json
import mido
import threading

app = Flask(__name__)

# 存储按下的按键
notes_pressed = []
# 线程锁,保证共享变量读写安全,避免数据异常
note_lock = threading.Lock()
# 请根据你的midi键盘实际最低音调整数值,88键标准钢琴最低音对应midi值为21(A0)
lowest_key = 21

@app.route('/get_notes', methods=['GET'])
def return_pressed_notes():
    global notes_pressed
    with note_lock:
        # 先复制当前列表作为返回结果,再清空列表,保证每次返回的是两次请求间隔内的按键数据
        res = notes_pressed.copy()
        notes_pressed.clear()
    return json.dumps(res)

# 转换midi键号到音名
def translate_key(key_num):
    # 可根据自己的需求调整转换逻辑
    note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    octave = key_num // 12
    note = note_names[key_num % 12]
    return f"{note}{octave}"

# 后台监听midi输入的函数
def get_notes():
    global notes_pressed
    with mido.open_input() as inport:
        for msg in inport:
            # 过滤有效按键事件
            if msg.type=='note_on' and msg.velocity!=0 and msg.channel==0:
                with note_lock:
                    notes_pressed.append(translate_key(msg.note - lowest_key))

if __name__ == '__main__':
    # 先启动后台midi监听线程,daemon设为True保证主进程退出时后台线程同步关闭
    midi_thread = threading.Thread(target=get_notes, daemon=True)
    midi_thread.start()
    # 关闭debug模式,避免Flask重载导致后台线程重复启动、端口占用等问题
    app.run(debug=False)

额外注意事项

  • 如果你的设备存在多个midi输入端口,可先通过mido.get_input_names()打印所有可用端口名,再在mido.open_input()中传入指定端口名即可
  • 不需要每次请求清空历史按键的话,删掉return_pressed_notes函数里的notes_pressed.clear()行即可
  • 生产环境部署建议用Gunicorn等WSGI服务器,单worker启动即可避免多进程下出现多个重复midi监听线程的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 08:15:03