xiaomusic/docs/issues/269.md
Issues Docs [BOT] 37a82e8c98 Auto-Generate docs 🤖
2024-12-13 10:23:54 +00:00

533 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 如何添加 网易云音乐playlist
---
# 如何添加 网易云音乐playlist
利用 NeteaseCloudMusicApi 获取歌单和播放地址
我在你基础上改了一下,但是我的逻辑不合理
https://github.com/dissipator/xiaomusic
## 评论
### 评论 1 - hanxi
建议通过插件实现或者新增一个页面工具把歌单导出 json 。
歌单的 json 格式见 /issues/78.html
---
### 评论 2 - qiujie8092916
> 利用 NeteaseCloudMusicApi 获取歌单和播放地址 我在你基础上改了一下,但是我的逻辑不合理 [dissipator/xiaomusic](https://github.com/dissipator/xiaomusic)
老哥在实现插件了吗?我也急需播放歌单
我诉求是:我用网易云音乐单独新建了一个歌单,我往里面扔歌曲,以更新歌单。希望创建一个自定义的语音命令,让小爱同学随机播放这个歌单里的音乐。然后我通过在米家里执行,比如触发了「我回来了」的智能场景时,就让小爱音箱执行这个自定义的语音命令,就会自动播放我新建的这个歌单里的音乐了。
现在的小爱音箱虽然能勉强实现,但是很垃圾。随机播放的随机性有问题,并且只能选择歌单里的 30 首歌。
(老哥如果没实现的话,我可以尝试搞搞)
---
### 评论 3 - dissipator
我都能直接利用这个直接播放NeteaseCloudMusicApi这上的歌了。在配合unblk,无敌。我就是没设备,还在路上
通过插件实现,非常好,就是不知道怎么开发,有文档我可以尝试一下。
---
### 评论 4 - dissipator
> 建议通过插件实现或者新增一个页面工具把歌单导出 json 。 歌单的 json 格式见 #78
配置处直接填了api的接口
http://127.0.0.1:3000/playlist/detail?id=12758992226
我是直接再你歌单保存上强改的。
```python
async def downloadjson(data: UrlInfo, Verifcation=Depends(verification)):
log.info(data)
url = data.url
content = "[{"
host = f"{url.split('/')[0]}//{url.split('/')[2]}"
try:
ret = "OK"
jsons = await downloadfile(url,"json")
# print(jsons)
list_name = jsons['playlist']['name']
content += '"name":"'+list_name+'","musics":['
for song in jsons['playlist']['tracks']:
content += f"{{\"name\":\"{song['name']}\",\"url\": \"{host}/song/url?br=999000&proxy=http:%2F%2F127.0.0.1:8080&realIP=211.161.244.70&id={song['id']}\"}}"
except Exception as e:
log.exception(f"Execption {e}")
ret = "Download JSON file failed."
content = content[:-1] + "]}]"
```
照着你的说明。而且能成功播发
```python
@app.get("/musicinfo")
async def musicinfo(
name: str, musictag: bool = False, Verifcation=Depends(verification)
):
url = xiaomusic.get_music_url(name)
if("song/url" in url):
jsons = await downloadfile(url,"json")
url = jsons['data'][0]['url']
```
播放处加了一个判断
---
### 评论 5 - hanxi
> > 建议通过插件实现或者新增一个页面工具把歌单导出 json 。 歌单的 json 格式见 #78
你的修改我看了不太通用。生成json再用现有的接口提交json更通用。
---
### 评论 6 - dissipator
是的,不通用。最好是用插件实现。
1. 就是不知道你插件的逻辑。
2. 如果用插件就考虑直接读取网易账号下所有歌单。然后选择一个导入,或者全部导入。
3. 等你完善文档后我可以尝试写一个。同理qq等其他平台的歌单也就都可以弄了
---
### 评论 7 - hanxi
等有空我写个修改歌单内容的插件示例吧。
---
### 评论 8 - dissipator
```
import requests
def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=None,uid=None):
"""
Purpose:
"""
global log, xiaomusic
if type == "netease":
if uid:
api_url = f"{api_host}/user/playlist?uid={uid}"
# 发起请求
response = requests.get(api_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
# log.info(f"getmy_playlist url:{api_url} response:{response.text}")
music_list = response.json()
for item in music_list['playlist']:
list_name = item.get("name")
log.info(f"getmy_playlist name:{list_name}")
# if item.get("id") in [12709941656,]:
songs_url = f"{api_host}/playlist/detail?id={item['id']}"
# 发起请求
response = requests.get(songs_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
# log.info(f"getmy_playlist url:{api_url} response:{response.text}")
musics = response.json()
one_music_list = []
for music in musics['playlist']['tracks']:
if (not music):
continue
# try:
name = music['name']
picUrl = music['al']['picUrl']
artist = music['ar'][0]['name']
album = music['al']['name']
name = music.get("name")
url = f"{api_host}/song/url?id={music['id']}&br=350000&realIP=211.161.244.70&proxy=HTTP:%2F%2F127.0.0.1:8080"
if (not name) or (not url):
continue
xiaomusic.all_music[name] = url
xiaomusic.all_music_tags[name] = {
"title": name,
"artist": artist,
"album": album,
"year": "",
"genre": "",
"picture": picUrl,
"lyrics": ""
}
one_music_list.append(name)
log.debug(f"getmy_playlist name:{list_name}")
log.debug(one_music_list)
# 歌曲名字相同会覆盖
xiaomusic.music_list[list_name] = one_music_list
xiaomusic.try_save_tag_cache()
log.debug(xiaomusic.all_music)
log.debug(xiaomusic.music_list)
return
if playlist_id:
songs_url = f"{api_host}/playlist/detail?id={playlist_id}"
# 发起请求
response = requests.get(songs_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
# log.info(f"getmy_playlist url:{api_url} response:{response.text}")
musics = response.json()
list_name = musics['playlist']['name']
one_music_list = []
for music in musics['playlist']['tracks']:
if (not music):
continue
# try:
name = music['name']
picUrl = music['al']['picUrl']
artist = music['ar'][0]['name']
album = music['al']['name']
name = music.get("name")
url = f"{api_host}/song/url?id={music['id']}&br=350000&realIP=211.161.244.70&proxy=HTTP:%2F%2F127.0.0.1:8080"
if (not name) or (not url):
continue
xiaomusic.all_music[name] = url
xiaomusic.all_music_tags[name] = {
"title": name,
"artist": artist,
"album": album,
"year": "",
"genre": "",
"picture": picUrl,
"lyrics": ""
}
one_music_list.append(name)
log.debug(f"getmy_playlist name:{list_name}")
log.debug(one_music_list)
# 歌曲名字相同会覆盖
xiaomusic.music_list[list_name] = one_music_list
xiaomusic.try_save_tag_cache()
log.debug(xiaomusic.all_music)
log.debug(xiaomusic.music_list)
return
else:
log.error(f"getmy_playlist type:{type} not support")
```
---
### 评论 9 - dissipator
> 等有空我写个修改歌单内容的插件示例吧。
不用拉,插件我已经写出来了
![image](https://github.hanxi.cc/proxy/user-attachments/assets/53e593e7-1439-4968-9549-8c84b2fee42c)
---
### 评论 10 - hanxi
发下你的 setting.json 配置吧,方便他人知道怎么配。
---
### 评论 11 - dissipator
我还在测试,设备到了能用了再发吧
---
### 评论 12 - guitarbug
也需要网易歌单功能, 坐等教程
---
### 评论 13 - dissipator
# 成功了
![image](https://github.hanxi.cc/proxy/user-attachments/assets/33e22665-b1cc-4069-9e8c-46e466679b30)
# 最好是在setting.json里去配置我测试老是不匹配在setting.json里去配置终于成功。可以直接调用 [NeteaseCloudMusicApi](http://localhost:3000/docs/#/?id=neteasecloudmusicapi) 接口甚至使用UnblockNeteaseMusic 解锁灰色,但是代码需要小调整。
setting.json
```json
{
"account": "",
"password": "",
"mi_did": "",
"miio_tts_command": "",
"cookie": "",
"verbose": false,
"music_path": "music",
"download_path": "music/download",
"conf_path": "conf",
"cache_dir": "cache",
"hostname": "192.168.2.5",
"port": 8090,
"public_port": 0,
"proxy": "",
"search_prefix": "bilisearch:",
"ffmpeg_location": "./ffmpeg/bin",
"active_cmd": "play,set_random_play,playlocal,play_music_list,play_music_list_index,stop_after_minute,stop,获取歌单",
"exclude_dirs": "@eaDir,tmp",
"music_path_depth": 10,
"disable_httpauth": true,
"httpauth_username": "",
"httpauth_password": "",
"music_list_url": "",
"music_list_json": "",
"custom_play_list_json": "",
"disable_download": false,
"key_word_dict": {
"播放歌曲": "play",
"播放本地歌曲": "playlocal",
"关机": "stop",
"下一首": "play_next",
"上一首": "play_prev",
"单曲循环": "set_play_type_one",
"全部循环": "set_play_type_all",
"随机播放": "set_random_play",
"分钟后关机": "stop_after_minute",
"播放列表": "play_music_list",
"刷新列表": "gen_music_list",
"加入收藏": "add_to_favorites",
"收藏歌曲": "add_to_favorites",
"取消收藏": "del_from_favorites",
"播放列表第": "play_music_list_index",
"本地播放歌曲": "playlocal",
"放歌曲": "play",
"暂停": "stop",
"停止": "stop",
"停止播放": "stop",
"播放歌单": "play_music_list",
"测试自定义口令": "exec#code1(\"hello\")",
"测试链接": "exec#httpget(\"https://github.com/hanxi/xiaomusic\")",
"获取歌单": "exec#getmy_playlist(playlist_id=12758992225)"
},
"key_match_order": [
"分钟后关机",
"播放歌曲",
"下一首",
"上一首",
"单曲循环",
"全部循环",
"随机播放",
"关机",
"刷新列表",
"播放列表第",
"播放列表",
"加入收藏",
"收藏歌曲",
"取消收藏",
"播放本地歌曲",
"本地播放歌曲",
"放歌曲",
"暂停",
"停止",
"停止播放",
"播放歌单",
"测试自定义口令",
"测试链接",
"获取歌单"
],
"use_music_api": false,
"use_music_audio_id": "1582971365183456177",
"use_music_id": "355454500",
"log_file": "/tmp/xiaomusic.txt",
"fuzzy_match_cutoff": 0.6,
"enable_fuzzy_match": true,
"stop_tts_msg": "收到,再见",
"enable_config_example": false,
"keywords_playlocal": "播放本地歌曲,本地播放歌曲",
"keywords_play": "播放歌曲,放歌曲",
"keywords_stop": "关机,暂停,停止,停止播放",
"keywords_playlist": "播放列表,播放歌单",
"user_key_word_dict": {
"测试自定义口令": "exec#code1(\"hello\")",
"测试链接": "exec#httpget(\"https://github.com/hanxi/xiaomusic\")",
"获取歌单": "exec#getmy_playlist(playlist_id=12758992225)"
},
"enable_force_stop": false,
"devices": {
" ": {
"did": " ",
"device_id": " -17c6-4204- - ",
"hardware": "L05C",
"name": "小黑你好",
"play_type": "",
"cur_music": "",
"cur_playlist": ""
}
},
"group_list": "",
"remove_id3tag": false,
"convert_to_mp3": false,
"delay_sec": 3,
"continue_play": false,
"pull_ask_sec": 1,
"crontab_json": "",
"enable_yt_dlp_cookies": false,
"get_ask_by_mina": false
}
```
getmy_playlist.py
```python
import requests
async def getmy_playlist(type="netease",api_host="http://127.0.0.1/api", playlist_id=None,uid=None):
"""
Purpose:
"""
global log, xiaomusic
if type == "netease":
if uid:
api_url = f"{api_host}/user/playlist?uid={uid}"
# 发起请求
response = requests.get(api_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
# log.info(f"getmy_playlist url:{api_url} response:{response.text}")
music_list = response.json()
for item in music_list['playlist']:
list_name = item.get("name")
log.info(f"getmy_playlist name:{list_name}")
# if item.get("id") in [12709941656,]:
songs_url = f"{api_host}/playlist/detail?id={item['id']}"
# 发起请求
response = requests.get(songs_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
# log.info(f"getmy_playlist url:{api_url} response:{response.text}")
musics = response.json()
one_music_list = []
for music in musics['playlist']['tracks']:
if (not music):
continue
# try:
name = music['name']
picUrl = music['al']['picUrl']
artist = music['ar'][0]['name']
album = music['al']['name']
name = music.get("name")
url = f"{api_host}/song/url?id={music['id']}&br=350000&realIP=211.161.244.70&proxy=HTTP:%2F%2F127.0.0.1:8080"
if (not name) or (not url):
continue
xiaomusic.all_music[name] = url
xiaomusic.all_music_tags[name] = {
"title": name,
"artist": artist,
"album": album,
"year": "",
"genre": "",
"picture": picUrl,
"lyrics": ""
}
one_music_list.append(name)
log.debug(f"getmy_playlist name:{list_name}")
log.debug(one_music_list)
# 歌曲名字相同会覆盖
xiaomusic.music_list[list_name] = one_music_list
xiaomusic.try_save_tag_cache()
log.debug(xiaomusic.all_music)
log.debug(xiaomusic.music_list)
return
if playlist_id:
songs_url = f"{api_host}/playlist/detail?id={playlist_id}"
# 发起请求
response = requests.get(songs_url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200引发HTTPError异常
musics = response.json()
list_name = musics['playlist']['name']
log.info(f"getmy_playlist list_name:{list_name} ")
one_music_list = []
for music in musics['playlist']['tracks']:
if (not music):
continue
# try:
name = music['name']
picUrl = music['al']['picUrl']
artist = music['ar'][0]['name']
album = music['al']['name']
name = music.get("name")
url = f"{api_host}/song/url?id={music['id']}&br=350000&proxy=HTTP:%2F%2F127.0.0.1:8080"
if (not name) or (not url):
continue
xiaomusic.all_music[name] = url
xiaomusic.all_music_tags[name] = {
"title": name,
"artist": artist,
"album": album,
"year": "",
"genre": "",
"picture": picUrl,
"lyrics": ""
}
one_music_list.append(name)
log.debug(f"getmy_playlist name:{list_name}")
log.debug(one_music_list)
# 歌曲名字相同会覆盖
xiaomusic.music_list[list_name] = one_music_list
xiaomusic.try_save_tag_cache()
return
else:
log.error(f"getmy_playlist type:{type} not support")
```
---
### 评论 14 - dissipator
![image](https://github.hanxi.cc/proxy/user-attachments/assets/7412eec4-f7d3-4a86-b186-0118d6f331ff)
![image](https://github.hanxi.cc/proxy/user-attachments/assets/2215e520-0d40-4c2c-8d46-d3106d65fc51)
---
### 评论 15 - dludream
NeteaseCloudMusicApi似乎获取不到播放地址其他信息倒是有。
![2024-11-28_151952](https://github.hanxi.cc/proxy/user-attachments/assets/c7e7a748-aa82-47f0-8784-f6469cc3e99b)
---
### 评论 16 - hanxi
看代码是另一个接口获取url的 `url = f"{api_host}/song/url?id={music['id']}&br=350000&realIP=211.161.244.70&proxy=HTTP:%2F%2F127.0.0.1:8080"`
---
### 评论 17 - dludream
> 看代码是另一个接口获取url的 `url = f"{api_host}/song/url?id={music['id']}&br=350000&realIP=211.161.244.70&proxy=HTTP:%2F%2F127.0.0.1:8080"`
是的我用的是这个接口https://registry.hub.docker.com/r/gnehs/neteasecloudmusicapi-docker/
可能网易修改了api这些获取不了播放地址了。
我倒不是要这个功能只是感兴趣看看。我不获取我直接用yt把歌全下载下来播放。
---
### 评论 18 - dissipator
这个不是网易的接口,是[NeteaseCloudMusicApi](http://localhost:3000/docs/#/?id=neteasecloudmusicapi) 接口。proxy=HTTP:%2F%2F127.0.0.1:8080"是UnblockNeteaseMusic 解锁灰色;
完整的使用方式和docker 可以到 https://github.com/dissipator/xiaomusic/tree/dev 看README.md目前没有教程。本人就在群2有问题可以找我。
---
[链接到 GitHub Issue](https://github.com/hanxi/xiaomusic/issues/269)