树莓派GPIO控制:按键按下/释放播放不同MP3的问题求助
树莓派按键切换MP3播放问题解决
需求
无焊面包板按键未按下时播放一段MP3,按住时播放另一段(类似《Deal or No Deal》电话预录音效),使用Raspberry Pi 3B通过GPIO引脚连接按键。
原代码
主脚本
from gpiozero import Button from signal import pause button = Button(2) while True: if button.is_pressed == True: import playLeft #run the playLeft script when button is pressed else: import playRight #run the playRight script when not pressed
playLeft脚本
#import the Pygame sound module import pygame #designate where the files are located declared in variables path = "/home/pi/" sound_files = "phoneLEFT.mp3" #initialise Pygame pygame.mixer.init() speaker_volume = 1.0 #100% speaker volume pygame.mixer.music.set_volume(speaker_volume) #sets the mixer volume to the speaker_volume variable for sound_file in sound_files: #iterating loop playing the files in the sound_files variable pygame.mixer.music.load("/home/john/phoneLEFT.mp3") #using the pygame module loads the sound file... pygame.mixer.music.play() #plays the sound file
playRight脚本
#import the Pygame sound module import pygame #designate where the files are located declared in variables path = "/home/pi/" sound_files = "handsetright.mp3" #initialise Pygame pygame.mixer.init() speaker_volume = 1.0 #100% speaker volume pygame.mixer.music.set_volume(speaker_volume) #sets the mixer volume to the speaker_volume variable for sound_file in sound_files: #iterating loop playing the files in the sound_files variable pygame.mixer.music.load("/home/john/handsetright.mp3") #using the pygame module loads the sound file... pygame.mixer.music.play() #plays the sound file
当前问题
启动后播放playRight音频,按住按键可切换到playLeft,但释放按键无法切回playRight。
问题根源
- import机制限制:Python里模块一旦被导入,后续再import不会重新执行代码,只会引用已加载的模块。第一次按按键导入playLeft后,释放时再import playRight根本不会触发播放逻辑。
- 播放逻辑错误:playLeft/playRight里的
for sound_file in sound_files是错误的——sound_files是字符串,循环会逐个字符遍历,导致重复加载播放;而且每次导入都初始化pygame.mixer,既冗余又可能引发冲突。 - 轮询效率低:while True循环持续占用CPU,不如用gpiozero的事件回调更合理。
优化后的完整代码
from gpiozero import Button import pygame import time # 初始化pygame mixer,只做一次 pygame.mixer.init() pygame.mixer.music.set_volume(1.0) # 替换成你实际的音频文件路径 RIGHT_SOUND = "/home/john/handsetright.mp3" LEFT_SOUND = "/home/john/phoneLEFT.mp3" # 记录当前播放的音频类型 current_playing = "right" button = Button(2) def play_sound(sound_path, sound_type): global current_playing # 已经在播放目标音频,直接返回 if current_playing == sound_type: return # 停止当前播放的音频 pygame.mixer.music.stop() # 加载新音频并设置无限循环播放 pygame.mixer.music.load(sound_path) pygame.mixer.music.play(-1) # -1表示无限循环 current_playing = sound_type # 按键按下时触发 def on_button_press(): play_sound(LEFT_SOUND, "left") # 按键释放时触发 def on_button_release(): play_sound(RIGHT_SOUND, "right") # 绑定按键事件 button.when_pressed = on_button_press button.when_released = on_button_release # 程序启动时默认播放right音频 play_sound(RIGHT_SOUND, "right") # 保持程序运行 while True: time.sleep(0.1)
优化说明
- 复用初始化:只在主脚本初始化一次pygame.mixer,避免重复初始化的资源冲突。
- 事件回调替代轮询:用gpiozero的
when_pressed/when_released事件,CPU占用更低,逻辑更清晰。 - 避免重复播放:通过
current_playing变量跟踪状态,只有状态变化时才切换音频,减少无效操作。 - 循环播放设置:
play(-1)让音频无限循环,符合“未按下/按住时持续播放”的需求。 - 整合逻辑:把原来拆分的两个脚本合并到主脚本,更简洁易维护。
- 修复路径问题:原代码里path变量和实际加载路径不一致,现在统一成正确路径(记得根据你的实际情况调整)。
内容的提问来源于stack exchange,提问作者jHouse82
相关产品推荐
相关产品推荐

