最近买了小爱音箱pro,老婆让我扔了,吃灰多年的旧音箱。当然舍不得,比小爱还贵,刚好还有一台红米手机,能插音箱,为了让音箱更加灵活,买了个2元的蓝牙接收模块Type-c供电3.5接口。这就是本次尝试起因和硬件组成。
前文介绍了小爱音箱结合xiaomusic实现尘封的NAS音乐不自由
那个文章实现小爱同学声控xiaomusic 这就是本次尝试的软件基础。
本文最终目的是,小爱声控xiaomusic通过红米(其他TV,机顶盒等)播放歌曲输出到旧音箱(3.5借口或者蓝牙接收器)
本文的附加目标是阻止要改小爱电路板的冲动,本人也曾想用折腾电路板去取代软件工程的活。那样一不小心万劫不复,就算成功还有电磁干扰,就算无干扰线路是硬连接,还需要硬切换,跟未来感的声控对比太复古,就好比太空方碑上雕刻了一个火柴人。
说了这么多上使用说明:
如图,将本工程的网页在红米打开,点一次播放。因为启动阶段必须手点,接下来放在一边。小爱语音控制,切歌听歌。
后台框架:
采用flask做原型开发,后期转到rust。需要socketio-flask网页处于监听长联接状态。xiaomusic,在听到红米语音时,所有操作,转入3thplay。通过requests请求flask-url,传递指令内容,socketio,分发给web浏览器,进行播放控制。
02.13夜晚构思软件架构
02.14借助ima在deepseek实现前端界面,测试手机浏览器播放效果。
后端和集成可能需要一周时间,调试一周。有活干了,开工。
万万没想到这些只是尝试的开始吧。
2.16成果问题和解决 :
成果:
先上结论3thplay网页播放,播放列表可持续, 除了语音控制.其他任意终端可以web网页,操控小爱的时候同步歌曲消息,切换歌曲
问题和解决:
- xiaomusic docker 安装 pip python-socketio 以后无法import socketio,于是放弃了本容器集成.新建了容器运行正常.
sio = socketio.AsyncServer(
async_mode='asgi',
cors_allowed_origins='*' # 允许所有跨域请求,生产环境应限制
)
#创建FastAPI应用
app = FastAPI()
#将Socket.IO挂载到FastAPI应用
socketio_app = socketio.ASGIApp(
socketio_server=sio,
other_asgi_app=app,
socketio_path='/socket.io'
)
@app.post("/items/")
async def create_item(item: Item):
result = {**item.dict()}
if item.action=="play":
await sio.emit('response',{"action":item.action,"args":item.args,"status":item.args},)
else:
await sio.emit('response',{"action":item.action,"status":item.args})
return result
wocketio地址 ws://192.168.1.10:58091
2. 在新容器其托管3thplay.html网页时候, 歌曲jurl处于跨域访问,被阻止,在容器 解决方式,在xiaomusic容器的/app/xiaomusic/static/, 放上3thplay.html.可以接收推送消息. 播放端设备打开http://192.168.1.10:58090/static/3thplay.html
3. 更改/app/xiaomusic/xiaomusic.py 中 async def _playmusic(self, name).在播放初始,触发消息发送
async def thdplay(self,url):
#若没有requests 安装和引用
data={"action":"play","args":url}
url="HTTP://192.168.1.10:58091/items/"
t=requests.post(url, json=data).text
print(t)
async def _playmusic(self, name):
#取消组内所有的下一首歌曲的定时器
self.cancel_group_next_timer()
self._playing = True
self.device.cur_music = name
self.log.info(f"cur_music {self.get_cur_music()}")
sec, url = await self.xiaomusic.get_music_sec_url(name)
await self.thdplay(url)
- 播放页面的核心js
<script> // 连接到服务端
const socket = io("http://192.168.1.10:58091/", { transports: ["websocket"] });
// 接收广播消息
socket.on("response", (data) => { const div = document.createElement("div");
div.textContent = `${data.action}: ${data.status}`;
if( data.action=='play')
{
playlist[0].src=data.args;
console.log(data.args)
playSong(0) ;
}
})
剩余问题, **小爱音箱的同时播放问题 **
自定义语音指令和现有代码逻辑有点冲突. 需要一个重构,加入本扩展为一个独立声音输出设备, 这样就能不影响小爱音箱的功能.,目前只是关掉小爱音量.
阶段性完成
接龙2.16
分离小爱音箱和3thplay的播放,
小爱音箱xiaomusic传声