7.21
【写在前面】
想搞一个小智AI通过MCP播放M10上的本地音乐,搞来搞去没有成,先做了一个M10版的音乐播放器,用来听听音乐。

材料清单
- M10行空板 X1
- M10电池扩展板组合 X1
- 蓝牙小音箱 X
步骤1 把蓝牙小音箱连接行空板M10
步骤2 代码准备
从B站网友的开源项目中拿到了一段代码,想改写成小智MCP控制M10本地播放mp3的播放器,没有成功。
先是改写成了通过终端输入命令来控制M10播放音乐的功能。


代码如下,贴在这里存档。
注:本代码需在mind+中运行,命令从终端输入。
代码
# local_player.py
import os
import pygame
import threading
import time
import random
class MusicPlayer:
def __init__(self):
self.current_play_list = []
self.current_play_mode = "single"
self.current_song_index = -1
self.is_playing = False
self.is_paused = False
pygame.mixer.init()
print("音频系统初始化完成")
# 启动播放线程
self.playback_thread = threading.Thread(target=self._playback_thread, daemon=True)
self.playback_thread.start()
def _playback_thread(self):
while True:
if self.is_playing and not self.is_paused:
if not pygame.mixer.music.get_busy():
self._play_next()
time.sleep(0.1)
else:
time.sleep(0.5)
def _play_next(self):
if not self.current_play_list:
return
if self.current_play_mode == "single":
# 单曲循环,重新播放当前歌曲
pass
elif self.current_play_mode == "list":
self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
elif self.current_play_mode == "random":
self.current_song_index = random.randint(0, len(self.current_play_list) - 1)
self._play_current()
def _play_current(self):
if not self.current_play_list or self.current_song_index < 0:
return
song_file = self.current_play_list[self.current_song_index]
song_path = os.path.join("music_file", song_file)
if os.path.exists(song_path):
try:
pygame.mixer.music.load(song_path)
pygame.mixer.music.play()
print(f"正在播放: {song_file}")
except:
print(f"播放失败: {song_file}")
def play(self, song_name="", play_mode="single"):
# 获取音乐文件列表
music_files = [f for f in os.listdir("music_file") if f.endswith(".mp3")]
if not music_files:
print("没有可播放的音乐文件")
return
# 筛选歌曲
if song_name:
self.current_play_list = [f for f in music_files if song_name.lower() in f.lower()]
else:
self.current_play_list = music_files
if not self.current_play_list:
print(f"未找到匹配 '{song_name}' 的歌曲")
return
self.current_play_mode = play_mode
self.current_song_index = 0 if play_mode != "random" else random.randint(0, len(self.current_play_list) - 1)
self.is_playing = True
self.is_paused = False
self._play_current()
def pause(self):
if self.is_playing and not self.is_paused:
pygame.mixer.music.pause()
self.is_paused = True
print("音乐已暂停")
def unpause(self):
if self.is_playing and self.is_paused:
pygame.mixer.music.unpause()
self.is_paused = False
print("音乐已恢复")
def stop(self):
pygame.mixer.music.stop()
self.is_playing = False
self.is_paused = False
print("音乐已停止")
def next(self):
if not self.current_play_list:
print("播放列表为空")
return
self.current_play_mode = "list" # 切换到列表模式
self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
self._play_current()
def previous(self):
if not self.current_play_list:
print("播放列表为空")
return
self.current_play_mode = "list" # 切换到列表模式
self.current_song_index = (self.current_song_index - 1) % len(self.current_play_list)
self._play_current()
if __name__ == "__main__":
player = MusicPlayer()
# 示例用法
player.play(play_mode="list")
# 保持主线程运行
try:
while True:
command = input("输入命令 (play/pause/stop/next/prev/exit): ").strip().lower()
if command == "exit":
break
elif command == "play":
player.play(play_mode="list")
elif command == "pause":
player.pause()
elif command == "stop":
player.stop()
elif command == "next":
player.next()
elif command == "prev":
player.previous()
except KeyboardInterrupt:
print("\n程序退出")
步骤3 改写代码成屏幕触摸按钮控制方式
用终端命令控制,太不友好了,继续改写成按钮控制播放,并且增加音量控制按钮。

代码如下:
代码
# local_player.py
import os
import pygame
import threading
import time
import random
import sys
from unihiker import GUI
# 添加扩展库路径
sys.path.append("/root/mindplus/.lib/thirdExtension/nick-unihiker_sound-thirdex")
from unihiker_sound import SoundManager
# 创建播放器实例
player = None
status_label = None
volume_label = None
unihiker_sound = None
current_volume = 60 # 默认音量
# 事件回调函数
def button_click1():
player.play(play_mode="list")
update_status("播放中")
def button_click2():
player.pause()
update_status("已暂停")
def button_click3():
player.unpause()
update_status("播放中")
def button_click4():
player.stop()
update_status("已停止")
def button_click5():
player.next()
update_status("下一首")
def button_click6():
player.previous()
update_status("上一首")
def button_click_vol_up():
global current_volume
current_volume = min(100, current_volume + 10)
unihiker_sound.set_volume(current_volume)
update_volume_display()
update_status(f"音量 + → {current_volume}")
def button_click_vol_down():
global current_volume
current_volume = max(0, current_volume - 10)
unihiker_sound.set_volume(current_volume)
update_volume_display()
update_status(f"音量 - → {current_volume}")
def update_status(text):
"""更新状态显示"""
global status_label
if status_label:
status_label.config(text=f"状态: {text}")
else:
print(f"状态: {text}")
def update_volume_display():
"""更新音量显示"""
global volume_label
if volume_label:
volume_label.config(text=f"音量: {current_volume}%")
else:
print(f"音量: {current_volume}%")
# 初始化GUI
u_gui = GUI()
u_gui.draw_image(image="back.png", x=0, y=0)
u_gui.draw_text(text="M10音乐播放器", x=10, y=0, font_size=20, color="#FFFFFF")
# 添加状态显示标签
status_label = u_gui.draw_text(text="状态: 就绪", x=150, y=20, font_size=12, color="#FFFFFF")
# 添加音量显示标签
volume_label = u_gui.draw_text(text=f"音量: {current_volume}%", x=150, y=40, font_size=12, color="#FFFFFF")
# 创建播放控制按钮
play_btn = u_gui.add_button(text="播放", x=30, y=40, w=60, h=30, onclick=button_click1)
pause_btn = u_gui.add_button(text="暂停", x=30, y=80, w=60, h=30, onclick=button_click2)
resume_btn = u_gui.add_button(text="继续", x=30, y=120, w=60, h=30, onclick=button_click3)
stop_btn = u_gui.add_button(text="停止", x=30, y=160, w=60, h=30, onclick=button_click4)
next_btn = u_gui.add_button(text="下一首", x=30, y=200, w=60, h=30, onclick=button_click5)
prev_btn = u_gui.add_button(text="上一首", x=30, y=240, w=60, h=30, onclick=button_click6)
# 创建音量控制按钮
vol_up_btn = u_gui.add_button(text="音量+", x=100, y=40, w=60, h=30, onclick=button_click_vol_up)
vol_down_btn = u_gui.add_button(text="音量-", x=100, y=80, w=60, h=30, onclick=button_click_vol_down)
class MusicPlayer:
def __init__(self):
self.current_play_list = []
self.current_play_mode = "single"
self.current_song_index = -1
self.is_playing = False
self.is_paused = False
pygame.mixer.init()
print("音频系统初始化完成")
# 启动播放线程
self.playback_thread = threading.Thread(target=self._playback_thread, daemon=True)
self.playback_thread.start()
def _playback_thread(self):
while True:
if self.is_playing and not self.is_paused:
if not pygame.mixer.music.get_busy():
self._play_next()
time.sleep(0.1)
else:
time.sleep(0.5)
def _play_next(self):
if not self.current_play_list:
return
if self.current_play_mode == "single":
# 单曲循环,重新播放当前歌曲
pass
elif self.current_play_mode == "list":
self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
elif self.current_play_mode == "random":
self.current_song_index = random.randint(0, len(self.current_play_list) - 1)
self._play_current()
def _play_current(self):
if not self.current_play_list or self.current_song_index < 0:
return
song_file = self.current_play_list[self.current_song_index]
song_path = os.path.join("music_file", song_file)
if os.path.exists(song_path):
try:
pygame.mixer.music.load(song_path)
pygame.mixer.music.play()
print(f"正在播放: {song_file}")
update_status(f"播放中: {song_file}")
except Exception as e:
print(f"播放失败: {song_file}, 错误: {str(e)}")
update_status(f"播放失败: {song_file}")
def play(self, song_name="", play_mode="single"):
# 如果已经在播放,先停止
if self.is_playing:
self.stop()
# 获取音乐文件列表
music_files = [f for f in os.listdir("music_file") if f.endswith(".mp3")]
if not music_files:
print("没有可播放的音乐文件")
update_status("无音乐文件")
return
# 筛选歌曲
if song_name:
self.current_play_list = [f for f in music_files if song_name.lower() in f.lower()]
else:
self.current_play_list = music_files
if not self.current_play_list:
print(f"未找到匹配 '{song_name}' 的歌曲")
update_status("未找到歌曲")
return
self.current_play_mode = play_mode
self.current_song_index = 0 if play_mode != "random" else random.randint(0, len(self.current_play_list) - 1)
self.is_playing = True
self.is_paused = False
self._play_current()
def pause(self):
if self.is_playing and not self.is_paused:
pygame.mixer.music.pause()
self.is_paused = True
print("音乐已暂停")
update_status("已暂停")
def unpause(self):
if self.is_playing and self.is_paused:
pygame.mixer.music.unpause()
self.is_paused = False
print("音乐已恢复")
update_status("播放中")
def stop(self):
if self.is_playing:
pygame.mixer.music.stop()
self.is_playing = False
self.is_paused = False
print("音乐已停止")
update_status("已停止")
def next(self):
if not self.current_play_list:
print("播放列表为空")
return
# 如果未在播放,先开始播放
if not self.is_playing:
self.play(play_mode="list")
return
self.current_play_mode = "list" # 切换到列表模式
self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
self._play_current()
update_status("下一首")
def previous(self):
if not self.current_play_list:
print("播放列表为空")
return
# 如果未在播放,先开始播放
if not self.is_playing:
self.play(play_mode="list")
return
self.current_play_mode = "list" # 切换到列表模式
self.current_song_index = (self.current_song_index - 1) % len(self.current_play_list)
self._play_current()
update_status("上一首")
if __name__ == "__main__":
# 初始化声音管理器
unihiker_sound = SoundManager()
unihiker_sound.set_volume(current_volume)
player = MusicPlayer()
update_status("就绪")
update_volume_display()
# 保持程序运行
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\n程序退出")
运行代码,可以用屏幕触摸按钮控制各种功能。

注:这个代码上传后可以从M10启动运行。
使用说明:
确保音乐文件放在music_file目录中(MP3格式)
背景图片back.png需要存在(或修改为其他图片路径)
按钮功能:
播放:开始播放音乐(随机选择模式)
暂停:暂停当前播放
继续:从暂停处继续播放
停止:完全停止播放
下一首:切换到下一首歌曲
上一首:切换到上一首歌曲
音量+:增加10%音量(最大100%)
音量-:减少10%音量(最小0%)
当前音量百分比会实时显示在界面上
这个实现完全通过按钮控制音乐播放,无需终端输入命令,界面更加友好。
状态显示让用户随时了解当前播放状态。
本项目代码由DeepSeek协助完成,致谢。
评论