souljoy commited on
Commit
40d108c
1 Parent(s): 929d7c6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +244 -0
app.py ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import torch
4
+ from sentence_transformers import SentenceTransformer, util
5
+ import os
6
+ import urllib.request
7
+ from tools.song_download import SongDownloadHelper
8
+
9
+ song_download_helper = SongDownloadHelper()
10
+ song_mid_list, song_emb_list = list(), list()
11
+ song_info_map = {}
12
+ MAX_REC_CNT = 10
13
+
14
+
15
+ def load_song_info(singer_mid_list: list):
16
+ cnt = 0
17
+ with open('source/music_sub', 'r', encoding='utf-8') as f:
18
+ for line in f:
19
+ obj = json.loads(line)
20
+ inter = [i for i in list(obj['singer_mid']) if i in singer_mid_list]
21
+ if len(inter) > 0:
22
+ cnt += 1
23
+ song_info_map[obj['song_mid']] = obj
24
+ print('loaded song info,cnt = ', cnt)
25
+
26
+
27
+ load_song_info(['000CK5xN3yZDJt', # 许嵩
28
+ '002J4UUk29y8BY', # 薛之谦
29
+ '003Nz2So3XXYek', # 陈奕迅
30
+ '001BLpXF2DyJe2', # 林俊杰
31
+ '0025NhlN2yWrP4', # 周杰伦
32
+ '000Sp0Bz4JXH0o', # 五月天
33
+ '004COQ9L4X13uj', # 吴青峰
34
+ '001f0VyZ1hmWZ1', # 林宥嘉
35
+ '000Q4W691sMvLG', # 苏打绿
36
+ '001pWERg3vFgg8', # 孙燕姿
37
+ ])
38
+
39
+
40
+ def load_song_emb():
41
+ global song_mid_list, song_emb_list
42
+ cnt = 0
43
+ with open('source/song_emb', 'r', encoding='utf-8') as f:
44
+ for line in f:
45
+ obj = json.loads(line)
46
+ if obj['song_mid'] in song_info_map.keys():
47
+ cnt += 1
48
+ song_mid_list.append(obj['song_mid'])
49
+ song_emb_list.append(obj['text_emb'])
50
+ print('loaded song emb,cnt = ', cnt)
51
+
52
+
53
+ load_song_emb()
54
+ embedder = SentenceTransformer('model', device='cuda')
55
+ song_emb_list = torch.tensor(song_emb_list)
56
+
57
+
58
+ def download_mp3(song_mid: str):
59
+ file_dir = 'source/mp3/{}.mp3'.format(song_mid)
60
+ if not os.path.exists(file_dir):
61
+ song_download_helper.download(song_mid)
62
+ # vip音乐下载不了,文件为空,则不进行推荐
63
+ return os.path.getsize(file_dir)
64
+
65
+
66
+ def get_singer_intro(singer_mid: str):
67
+ url_ = 'https://y.qq.com/n/ryqq/singer/{}'.format(singer_mid)
68
+ res_ = urllib.request.urlopen(url_)
69
+ html_ = str(res_.read().decode('utf-8'))
70
+ return '\n'.join(str(html_).split('shortdesc":"')[1].split('","')[0].split('\\n'))[0:64]
71
+
72
+
73
+ def get_album_intro(song_mid: str):
74
+ try:
75
+ url_ = 'https://y.qq.com/n/ryqq/songDetail/{}'.format(song_mid)
76
+ print(url_)
77
+ res_ = urllib.request.urlopen(url_)
78
+ html_ = str(res_.read().decode('utf-8'))
79
+ print(html_)
80
+ album_id = str(html_).split('albumDetail/')[1].split('"')[0]
81
+ url_ = 'https://y.qq.com/n/ryqq/albumDetail/{}'.format(album_id)
82
+ print(url_)
83
+ res_ = urllib.request.urlopen(url_)
84
+ html_ = str(res_.read().decode('utf-8'))
85
+ print(html_)
86
+ return album_id, '\n'.join(str(html_).split('简介')[1].split('<p>')[1].split('</p>')[0].split('\\n'))[0:64]
87
+ except Exception as e:
88
+ return None, None
89
+
90
+
91
+ def generate_playlist(prompt):
92
+ prompt_embedding = embedder.encode(prompt, convert_to_tensor=True)
93
+ hits = util.semantic_search(prompt_embedding, song_emb_list, top_k=100)
94
+ song_names = list()
95
+ for hit_info in hits[0]:
96
+ song_mid = song_mid_list[hit_info['corpus_id']]
97
+ song_info = song_info_map[song_mid]
98
+ if not download_mp3(song_mid):
99
+ continue
100
+ print(song_mid, hit_info['score'], song_info)
101
+ song_names.append('✨'.join(
102
+ [str(song_info['song_name']), '/'.join(list(song_info['singer_name'])), str(song_mid)]))
103
+ if len(song_names) >= MAX_REC_CNT:
104
+ break
105
+ return gr.Radio.update(label='点击选择一首歌吧', show_label=True, choices=song_names)
106
+
107
+
108
+ def set_song_info(full_title):
109
+ song_name, singer_name, song_mid = str(full_title).split('✨')
110
+ print(song_name, singer_name, song_mid)
111
+ song_info = song_info_map[song_mid]
112
+ title_markdown_ = gr.Markdown.update(
113
+ value='✨**播放歌曲**✨ [歌曲详情]({})'.format(song_info['song_url']))
114
+ hot_comment = list(song_info['hot_comments'])[0]
115
+ comment_textbox_ = gr.Textbox.update(
116
+ value='来自用户 ✨{}✨:\n\n{}'.format(hot_comment['comment_name'], hot_comment['comment_text']))
117
+ lyrics_textbox_ = gr.Textbox.update(value='\n'.join(str(song_info['lyric']).split('\\n')))
118
+
119
+ return [title_markdown_, comment_textbox_, lyrics_textbox_]
120
+
121
+
122
+ def set_singer_info(full_title):
123
+ song_name, singer_name, song_mid = str(full_title).split('✨')
124
+ print(song_name, singer_name, song_mid)
125
+ song_info = song_info_map[song_mid]
126
+ singer_mid = list(song_info['singer_mid'])[0]
127
+ singer_markdown_ = gr.Markdown.update(
128
+ value='{}:{}… [更多]({})'.format(list(song_info['singer_name'])[0],
129
+ get_singer_intro(singer_mid),
130
+ 'https://y.qq.com/n/ryqq/singer/{}'.format(singer_mid)))
131
+ singer_image_ = gr.Image.update(value='https://y.qq.com/music/photo_new/T001R300x300M000{}.jpg'.format(singer_mid)
132
+ , visible=True, show_label=False)
133
+
134
+ return [singer_markdown_, singer_image_]
135
+
136
+
137
+ def set_album_info(full_title):
138
+ song_name, singer_name, song_mid = str(full_title).split('✨')
139
+ album_id, album_tro = get_album_intro(song_mid)
140
+ song_info = song_info_map[song_mid]
141
+ if album_id:
142
+ album_markdown_ = gr.Markdown.update(
143
+ value='《{}》:{}… [更多]({})'.format(song_info['album_name'], album_tro,
144
+ 'https://y.qq.com/n/ryqq/albumDetail/{}'.format(album_id)))
145
+ album_image_ = gr.Image.update(value='https://y.qq.com/music/photo_new/T002R300x300M000{}.jpg'.format(album_id),
146
+ visible=True, show_label=False)
147
+ else:
148
+ album_markdown_ = gr.Markdown.update(value='无专辑')
149
+ album_image_ = gr.Image.update(visible=False)
150
+ return [album_markdown_, album_image_]
151
+
152
+
153
+ def set_mp3_audio(full_title):
154
+ song_name, singer_name, song_mid = str(full_title).split('✨')
155
+ mp3_audio_ = gr.Audio.update(label=song_name, value='source/mp3/{}.mp3'.format(song_mid), show_label=True)
156
+ return mp3_audio_
157
+
158
+
159
+ def set_example_prompt(example):
160
+ return gr.TextArea.update(value=example[0])
161
+
162
+
163
+ demo = gr.Blocks()
164
+
165
+ with demo:
166
+ gr.Markdown(
167
+ """
168
+ # 播放列表生成器 📻 🎵
169
+ """)
170
+
171
+ with gr.Row():
172
+ with gr.Column():
173
+ song_prompt = gr.TextArea(
174
+ value="狂野而自由地奔跑",
175
+ label="输入你的此刻的心情(或选择示例)"
176
+ )
177
+ gr.Markdown(value='✨**推荐歌单**✨:')
178
+ song_option = gr.Radio(show_label=False, interactive=True, choices=None)
179
+ with gr.Row():
180
+ fetch_songs = gr.Button(value="点击为您推荐播放列表 🧑 🏽 ‍🎤").style(full_width=True)
181
+ example_prompts = gr.Dataset(
182
+ label='选择示例',
183
+ components=[song_prompt],
184
+ samples=[
185
+ ["我怀念过去"],
186
+ ["狂野而自由地奔跑"],
187
+ ["有时候觉得没人懂"],
188
+ ]
189
+ )
190
+ with gr.Column():
191
+ title_markdown = gr.Markdown(value='✨**播放歌曲**✨')
192
+ mp3_audio = gr.Audio(show_label=False)
193
+ gr.Markdown(value='✨**热评**✨:')
194
+ comment_textbox = gr.Textbox(show_label=False, placeholder="选择一首歌曲以查看其歌热评")
195
+ gr.Markdown(value='✨**歌词**✨:')
196
+ lyrics_textbox = gr.Textbox(show_label=False, placeholder="选择一首歌曲以查看其歌词")
197
+ with gr.Column():
198
+ gr.Markdown(value='✨**歌手介绍**✨:')
199
+ with gr.Row():
200
+ singer_markdown = gr.Markdown()
201
+ singer_image = gr.Image(show_label=False, visible=True)
202
+ gr.Markdown(value='✨**专辑介绍**✨:')
203
+ with gr.Row():
204
+ album_markdown = gr.Markdown()
205
+ album_image = gr.Image(show_label=False, visible=True)
206
+
207
+ fetch_songs.click(
208
+ fn=generate_playlist,
209
+ inputs=[song_prompt],
210
+ outputs=song_option
211
+ )
212
+
213
+ example_prompts.click(
214
+ fn=set_example_prompt,
215
+ inputs=example_prompts,
216
+ outputs=example_prompts.components,
217
+ )
218
+
219
+ song_option.change(
220
+ fn=set_song_info,
221
+ inputs=song_option,
222
+ outputs=[title_markdown, comment_textbox, lyrics_textbox]
223
+ )
224
+
225
+ song_option.change(
226
+ fn=set_mp3_audio,
227
+ inputs=song_option,
228
+ outputs=mp3_audio
229
+ )
230
+
231
+ song_option.change(
232
+ fn=set_singer_info,
233
+ inputs=song_option,
234
+ outputs=[singer_markdown, singer_image]
235
+ )
236
+
237
+ song_option.change(
238
+ fn=set_album_info,
239
+ inputs=song_option,
240
+ outputs=[album_markdown,
241
+ album_image]
242
+ )
243
+
244
+ demo.launch()