Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
dissipator opened this issue Nov 20, 2024 · 18 comments
Open

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

dissipator opened this issue Nov 20, 2024 · 18 comments
Labels
文档 帮助文档

Comments

@dissipator
Copy link

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

@hanxi
Copy link
Owner

hanxi commented Nov 20, 2024

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

@qiujie8092916
Copy link

qiujie8092916 commented Nov 20, 2024

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

老哥在实现插件了吗?我也急需播放歌单
我诉求是:我用网易云音乐单独新建了一个歌单,我往里面扔歌曲,以更新歌单。希望创建一个自定义的语音命令,让小爱同学随机播放这个歌单里的音乐。然后我通过在米家里执行,比如触发了「我回来了」的智能场景时,就让小爱音箱执行这个自定义的语音命令,就会自动播放我新建的这个歌单里的音乐了。
现在的小爱音箱虽然能勉强实现,但是很垃圾。随机播放的随机性有问题,并且只能选择歌单里的 30 首歌。
(老哥如果没实现的话,我可以尝试搞搞)

@dissipator
Copy link
Author

dissipator commented Nov 20, 2024

我都能直接利用这个直接播放NeteaseCloudMusicApi这上的歌了。在配合unblk,无敌。我就是没设备,还在路上
通过插件实现,非常好,就是不知道怎么开发,有文档我可以尝试一下。

@dissipator
Copy link
Author

dissipator commented Nov 20, 2024

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

配置处直接填了api的接口
http://127.0.0.1:3000/playlist/detail?id=12758992226
我是直接再你歌单保存上强改的。

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] + "]}]"

照着你的说明。而且能成功播发

@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']

播放处加了一个判断

@hanxi
Copy link
Owner

hanxi commented Nov 20, 2024

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

你的修改我看了,不太通用。生成json,再用现有的接口提交json更通用。

@dissipator
Copy link
Author

dissipator commented Nov 21, 2024

是的,不通用。最好是用插件实现。

  1. 就是不知道你插件的逻辑。
  2. 如果用插件就考虑直接读取网易账号下所有歌单。然后选择一个导入,或者全部导入。
  3. 等你完善文档后我可以尝试写一个。同理,qq等其他平台的歌单也就都可以弄了

@hanxi
Copy link
Owner

hanxi commented Nov 21, 2024

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

@dissipator
Copy link
Author

dissipator commented Nov 21, 2024

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")


@dissipator
Copy link
Author

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

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

@hanxi
Copy link
Owner

hanxi commented Nov 21, 2024

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

@dissipator
Copy link
Author

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

@guitarbug
Copy link

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

@dissipator
Copy link
Author

dissipator commented Nov 22, 2024

成功了

image

最好是在setting.json里去配置,我测试老是不匹配,在setting.json里去配置终于成功。可以直接调用 NeteaseCloudMusicApi 接口,甚至使用UnblockNeteaseMusic 解锁灰色,但是代码需要小调整。

setting.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

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")

@dissipator
Copy link
Author

image
image

@hanxi hanxi added the 文档 帮助文档 label Nov 22, 2024
@dludream
Copy link
Contributor

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

2024-11-28_151952

@hanxi
Copy link
Owner

hanxi commented Nov 28, 2024

看代码是另一个接口获取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"

@dludream
Copy link
Contributor

看代码是另一个接口获取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把歌全下载下来播放。

@dissipator
Copy link
Author

dissipator commented Dec 2, 2024

这个不是网易的接口,是NeteaseCloudMusicApi 接口。proxy=HTTP:%2F%2F127.0.0.1:8080"是UnblockNeteaseMusic 解锁灰色;
完整的使用方式和docker 可以到 https://github.com/dissipator/xiaomusic/tree/dev 看README.md;目前没有教程。本人就在群2,有问题可以找我。

@hanxi hanxi changed the title 能否考虑添加 网易云音乐playlist 如何添加 网易云音乐playlist Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
文档 帮助文档
Projects
None yet
Development

No branches or pull requests

5 participants