使用小爱音箱播放音乐

使用小爱音箱播放音乐很简单,但随着小爱音箱和QQ音乐深度合作,很多vip歌曲都只能试听了。

为了让家里的小爱音箱再次随时接受语音指令,播放自己喜爱的音乐,我又开始了折腾。

xiaomusic

xiaomusic 是一个免费的开源服务,使用yt-dlp下载音乐并让小爱音箱播放

安装

只需要配置docker compose 就可以开箱即用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3"
services:
xiaomusic:
container_name: xiaomusic
image: hanxi/xiaomusic
ports:
- 0.0.0.0:5678:5678
restart: always
volumes:
- /data/docker/xiaomusic/music:/app/music
- /data/docker/xiaomusic/conf:/app/conf
- /data/docker/xiaomusic/plugins:/app/plugins
- /etc/localtime:/etc/localtime:ro
environment:
XIAOMUSIC_PORT: 5678

启动后,通过8090端口即可访问控制面板,在主机/xiaomusic/conf 目录下会生成配置文件

在配置小米音响的过程中也踩过不少坑,也查阅了github上的一些文档,这里记录一下,避免遗忘

注意事项

无法登录

在配置完小米账号和密码后,发现日志中有可能提示登录错误。大概率原因是部署的docker的服务器从来没有登录过这个小米账号。解决方案也很简单,只需要通过主机的公网IP地址在小米官网登录一次即可。如果主机是家里的NAS,那只需要使用同局域网的其他设备访问小米官网登录账号一次即可。如果像我一样是部署在云服务器上的话,那就比较麻烦了,可以采用代理http的方式,让电脑浏览器通过云服务器的代理访问小米官网并登录一次。

公网部署和反向代理

首先如果公网部署又有反向代理,那么xiaomusic的服务端口就不再重要,可以随意修改。但是,别忘记修改/xiaomusic/conf/setting.json文件中端口

setting.json配置

1
2
"port": 8090,
"public_port": 80,

其中public_port需要修改,填写云服务器web服务端口,由于目前不支持https协议,所以通常是80端口

docker compose 配置

1
2
ports:
- 8090:8090

安全

最重要的一点是注意安全,由于服务存放了小米账号和密码,所以控制面板的服务建议采用密码和HTTPS保护。

是不是刚刚public_port设置80端口,并且不支持https矛盾了?

其实可以这样配置,配置2个二级域名:A域名和B域名。

A域名用来访问控制面板,增加密码配置和HTTPS保护

B域名用来提供给小米音响下载音乐文件,只开放/music 路径,配置HTTPS

最后记得修改docker映射和setting.json配置

docker映射:

1
2
3
ports:
- 127.0.0.1:8090:8090

setting.json配置:

1
"hostname": "B域名",

总结

配置完成之后就可以正常的采用语音命令小爱音箱,xiaomusic会先去搜索歌曲下载到服务器,然后由小爱音箱下载服务器上的音乐文件进行播放。

但经常会碰到播放的歌曲不是我想要的,毕竟同名不同版本的歌曲太多了。这个时候就需要对接自己的歌单了。

对接明月浩空音乐歌单

明月浩空音乐播放器研发于2014年,并持续更新至今,已兼容地球上所有语言程序的任何网站
是基于网易音乐、QQ音乐、酷狗音乐、咪咕音乐等歌曲ID全自动解析的Html5音乐播放器

这个平台上也有API对接,于是就可以用xiaomusic从明月浩空上获取歌单,并在小爱同学上播放了

主要分为3步,配置用户秘钥和歌单id,通过命令获取歌单和所有歌曲url,下载音乐文件到服务器上

配置用户秘钥和歌单id

在docker配置中使用MYHKW_KEY和MYHKW_SONG_LIST_ID 这2个环境变量设置用于秘钥和歌单id

秘钥获取方法

获取歌单id

同步歌曲到服务器上

需要在plugins目录中创建一个myhkw.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import requests
import json
import urllib.request
import os

async def myhkw():
global log, xiaomusic
log.info("刷新歌单")
did = xiaomusic._cur_did
data = {'key': os.getenv("MYHKW_KEY",""),'type':'my','id':os.getenv("MYHKW_SONG_LIST_ID","")}
response = requests.post("https://myhkw.cn/open/music/list",data=data, timeout=5)
response.raise_for_status() # 如果响应不是200,引发HTTPError异常
result = response.json()
if result['code'] != 1:
# 获取歌单失败
log.info("获取歌单失败")
await xiaomusic.do_tts(did, "获取歌单失败")
return
else:
songIdArray = result['data']['songId']
songTypeArray = result['data']['type']
songNameArray = result['data']['songName']
for i in range(len(songIdArray)):
songId = songIdArray[i]
songType = songTypeArray[i]
songName = songNameArray[i]
songName = songName.replace('/',' ')
log.info(f"导入歌曲:{songName}")
data = {'key': os.getenv("MYHKW_KEY",""),'type':songType,'id':songId}
response = requests.post("https://myhkw.cn/open/music/url",data=data, timeout=5)
response.raise_for_status() # 如果响应不是200,引发HTTPError异常
result = response.json()
if result['code'] != 1:
url = ""
else:
url = result['data']
if url != "" :
urllib.request.urlretrieve(url, xiaomusic.config.music_path+"/我的歌单/"+songName+".mp3")
log.info(f"导入歌曲:{songName} 完成")
log.info("刷新列表")
await xiaomusic.gen_music_list()
log.info("保存歌单完成")
await xiaomusic.do_tts(did, "保存歌单完成")
# await xiaomusic.do_tts(did, "你好,我是自定义的测试口令")

这个插件的作用就是将明月浩空上的歌单歌曲文件下载到服务器的 “我的歌单”目录中,最后调用刷新列表命令让xiaomusic重新加载歌单。

接着需要配置自定义命令,这里以“刷新歌单”为例

修改setting.json

  1. 需要在active_cmd 激活命令配置中,加上exec#myhkw()
1
"active_cmd": "play,set_random_play,playlocal,play_music_list,stop,exec#myhkw()"
  1. 需要增加自定义命令
1
2
3
"user_key_word_dict": {
"刷新歌单": "exec#myhkw()"
}
  1. 增加字典
1
2
"key_word_dict": {
"刷新歌单": "exec#myhkw()",

配置完成之后,重启容器即可

使用

对小爱音箱说 “刷新歌单”就能看到同步结果了,如果报错,检查一下是否存在“我的歌单”这个目录,如果没有需要手动添加(其实也可以修改python代码自动创建,懒得改了)

接着可以对小爱音箱说 “播放列表我的歌单”,小爱同学就会开始方法音乐了