# 如何添加 网易云音乐playlist | XiaoMusic
XiaoMusic doc

Skip to content

# 如何添加 网易云音乐playlist ​

利用 NeteaseCloudMusicApi 获取歌单和播放地址 我在你基础上改了一下，但是我的逻辑不合理 https://github.com/dissipator/xiaomusic

## 评论 ​

### 评论 1 - hanxi ​

建议通过插件实现或者新增一个页面工具把歌单导出 json 。 歌单的 json 格式见 /issues/78.html

### 评论 2 - qiujie8092916 ​

> 利用 NeteaseCloudMusicApi 获取歌单和播放地址 我在你基础上改了一下，但是我的逻辑不合理 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 ​

> 等有空我写个修改歌单内容的插件示例吧。

不用拉，插件我已经写出来了

### 评论 10 - hanxi ​

发下你的 setting.json 配置吧，方便他人知道怎么配。

### 评论 11 - dissipator ​

我还在测试，设备到了能用了再发吧

### 评论 12 - guitarbug ​

也需要网易歌单功能, 坐等教程

### 评论 13 - dissipator ​

# 成功了 ​

# 最好是在setting.json里去配置，我测试老是不匹配，在setting.json里去配置终于成功。可以直接调用 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 ​

### 评论 15 - dludream ​

NeteaseCloudMusicApi似乎获取不到播放地址？其他信息倒是有。

### 评论 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 接口。proxy=HTTP:%2F%2F127.0.0.1:8080"是UnblockNeteaseMusic 解锁灰色； 完整的使用方式和docker 可以到 https://github.com/dissipator/xiaomusic/tree/dev 看README.md；目前没有教程。本人就在群2，有问题可以找我。

链接到 GitHub Issue