import gradio as gr import json import torch from sentence_transformers import SentenceTransformer, util import os import urllib.request from tools.song_download import SongDownloadHelper song_download_helper = SongDownloadHelper() song_mid_list, song_emb_list = list(), list() song_info_map = {} MAX_REC_CNT = 10 def load_song_info(singer_mid_list: list): cnt = 0 with open('source/music_sub', 'r', encoding='utf-8') as f: for line in f: obj = json.loads(line) inter = [i for i in list(obj['singer_mid']) if i in singer_mid_list] if len(inter) > 0: cnt += 1 song_info_map[obj['song_mid']] = obj print('loaded song info,cnt = ', cnt) load_song_info(['000CK5xN3yZDJt', # 许嵩 '002J4UUk29y8BY', # 薛之谦 '003Nz2So3XXYek', # 陈奕迅 '001BLpXF2DyJe2', # 林俊杰 '0025NhlN2yWrP4', # 周杰伦 '000Sp0Bz4JXH0o', # 五月天 '004COQ9L4X13uj', # 吴青峰 '001f0VyZ1hmWZ1', # 林宥嘉 '000Q4W691sMvLG', # 苏打绿 '001pWERg3vFgg8', # 孙燕姿 ]) def load_song_emb(): global song_mid_list, song_emb_list cnt = 0 with open('source/song_emb', 'r', encoding='utf-8') as f: for line in f: obj = json.loads(line) if obj['song_mid'] in song_info_map.keys(): cnt += 1 song_mid_list.append(obj['song_mid']) song_emb_list.append(obj['text_emb']) print('loaded song emb,cnt = ', cnt) load_song_emb() embedder = SentenceTransformer('model', device='cuda') song_emb_list = torch.tensor(song_emb_list) def download_mp3(song_mid: str): file_dir = 'source/mp3/{}.mp3'.format(song_mid) if not os.path.exists(file_dir): song_download_helper.download(song_mid) # vip音乐下载不了,文件为空,则不进行推荐 return os.path.getsize(file_dir) def get_singer_intro(singer_mid: str): url_ = 'https://y.qq.com/n/ryqq/singer/{}'.format(singer_mid) res_ = urllib.request.urlopen(url_) html_ = str(res_.read().decode('utf-8')) return '\n'.join(str(html_).split('shortdesc":"')[1].split('","')[0].split('\\n'))[0:64] def get_album_intro(song_mid: str): try: url_ = 'https://y.qq.com/n/ryqq/songDetail/{}'.format(song_mid) print(url_) res_ = urllib.request.urlopen(url_) html_ = str(res_.read().decode('utf-8')) print(html_) album_id = str(html_).split('albumDetail/')[1].split('"')[0] url_ = 'https://y.qq.com/n/ryqq/albumDetail/{}'.format(album_id) print(url_) res_ = urllib.request.urlopen(url_) html_ = str(res_.read().decode('utf-8')) print(html_) return album_id, '\n'.join(str(html_).split('简介')[1].split('

')[1].split('

')[0].split('\\n'))[0:64] except Exception as e: return None, None def generate_playlist(prompt): prompt_embedding = embedder.encode(prompt, convert_to_tensor=True) hits = util.semantic_search(prompt_embedding, song_emb_list, top_k=100) song_names = list() for hit_info in hits[0]: song_mid = song_mid_list[hit_info['corpus_id']] song_info = song_info_map[song_mid] if not download_mp3(song_mid): continue print(song_mid, hit_info['score'], song_info) song_names.append('✨'.join( [str(song_info['song_name']), '/'.join(list(song_info['singer_name'])), str(song_mid)])) if len(song_names) >= MAX_REC_CNT: break return gr.Radio.update(label='点击选择一首歌吧', show_label=True, choices=song_names) def set_song_info(full_title): song_name, singer_name, song_mid = str(full_title).split('✨') print(song_name, singer_name, song_mid) song_info = song_info_map[song_mid] title_markdown_ = gr.Markdown.update( value='✨**播放歌曲**✨ [歌曲详情]({})'.format(song_info['song_url'])) hot_comment = list(song_info['hot_comments'])[0] comment_textbox_ = gr.Textbox.update( value='来自用户 ✨{}✨:\n\n{}'.format(hot_comment['comment_name'], hot_comment['comment_text'])) lyrics_textbox_ = gr.Textbox.update(value='\n'.join(str(song_info['lyric']).split('\\n'))) return [title_markdown_, comment_textbox_, lyrics_textbox_] def set_singer_info(full_title): song_name, singer_name, song_mid = str(full_title).split('✨') print(song_name, singer_name, song_mid) song_info = song_info_map[song_mid] singer_mid = list(song_info['singer_mid'])[0] singer_markdown_ = gr.Markdown.update( value='{}:{}… [更多]({})'.format(list(song_info['singer_name'])[0], get_singer_intro(singer_mid), 'https://y.qq.com/n/ryqq/singer/{}'.format(singer_mid))) singer_image_ = gr.Image.update(value='https://y.qq.com/music/photo_new/T001R300x300M000{}.jpg'.format(singer_mid) , visible=True, show_label=False) return [singer_markdown_, singer_image_] def set_album_info(full_title): song_name, singer_name, song_mid = str(full_title).split('✨') album_id, album_tro = get_album_intro(song_mid) song_info = song_info_map[song_mid] if album_id: album_markdown_ = gr.Markdown.update( value='《{}》:{}… [更多]({})'.format(song_info['album_name'], album_tro, 'https://y.qq.com/n/ryqq/albumDetail/{}'.format(album_id))) album_image_ = gr.Image.update(value='https://y.qq.com/music/photo_new/T002R300x300M000{}.jpg'.format(album_id), visible=True, show_label=False) else: album_markdown_ = gr.Markdown.update(value='无专辑') album_image_ = gr.Image.update(visible=False) return [album_markdown_, album_image_] def set_mp3_audio(full_title): song_name, singer_name, song_mid = str(full_title).split('✨') mp3_audio_ = gr.Audio.update(label=song_name, value='source/mp3/{}.mp3'.format(song_mid), show_label=True) return mp3_audio_ def set_example_prompt(example): return gr.TextArea.update(value=example[0]) demo = gr.Blocks() with demo: gr.Markdown( """ # 播放列表生成器 📻 🎵 """) with gr.Row(): with gr.Column(): song_prompt = gr.TextArea( value="狂野而自由地奔跑", label="输入你的此刻的心情(或选择示例)" ) gr.Markdown(value='✨**推荐歌单**✨:') song_option = gr.Radio(show_label=False, interactive=True, choices=None) with gr.Row(): fetch_songs = gr.Button(value="点击为您推荐播放列表 🧑 🏽 ‍🎤").style(full_width=True) example_prompts = gr.Dataset( label='选择示例', components=[song_prompt], samples=[ ["我怀念过去"], ["狂野而自由地奔跑"], ["有时候觉得没人懂"], ] ) with gr.Column(): title_markdown = gr.Markdown(value='✨**播放歌曲**✨') mp3_audio = gr.Audio(show_label=False) gr.Markdown(value='✨**热评**✨:') comment_textbox = gr.Textbox(show_label=False, placeholder="选择一首歌曲以查看其歌热评") gr.Markdown(value='✨**歌词**✨:') lyrics_textbox = gr.Textbox(show_label=False, placeholder="选择一首歌曲以查看其歌词") with gr.Column(): gr.Markdown(value='✨**歌手介绍**✨:') with gr.Row(): singer_markdown = gr.Markdown() singer_image = gr.Image(show_label=False, visible=True) gr.Markdown(value='✨**专辑介绍**✨:') with gr.Row(): album_markdown = gr.Markdown() album_image = gr.Image(show_label=False, visible=True) fetch_songs.click( fn=generate_playlist, inputs=[song_prompt], outputs=song_option ) example_prompts.click( fn=set_example_prompt, inputs=example_prompts, outputs=example_prompts.components, ) song_option.change( fn=set_song_info, inputs=song_option, outputs=[title_markdown, comment_textbox, lyrics_textbox] ) song_option.change( fn=set_mp3_audio, inputs=song_option, outputs=mp3_audio ) song_option.change( fn=set_singer_info, inputs=song_option, outputs=[singer_markdown, singer_image] ) song_option.change( fn=set_album_info, inputs=song_option, outputs=[album_markdown, album_image] ) demo.launch()