600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 全网首个tk网络音乐播放器!支持歌词滚动!你看我吊不?

全网首个tk网络音乐播放器!支持歌词滚动!你看我吊不?

时间:2022-04-11 16:52:07

相关推荐

全网首个tk网络音乐播放器!支持歌词滚动!你看我吊不?

这是一个用 Python 的 tkinter 库做的一个网络音乐播放器。我不说它的 UI 设计的有多好看,但是它的功能绝对是全站首个!坚持看到底,你不点赞算我输!

成果展示

程序截图

前期准备

程序结构:

​​​

所需第三方库(requirement.txt):

mutagen==1.45.1pygame==2.0.1requests==2.26.0Pillow==8.3.1

安装:

pip install mutagen# 查看歌曲长度pip install pygame# 播放音乐pip install requests# 爬取音乐pip install pillow# 显示图片

或者:

pip install -r requirements.txt

一、爬取音乐

下面的代码为 get.py 里的内容。

import requestssearch_url = '/api/www/search/searchMusicBykeyWord'search_headers = {'Referer': '/search/list?key=','Cookie': '_ga=GA1.2.12......','csrf': 'YO4OH2VYH1A'}search_params = {'key': 'str', # 查找关键字'pn': '1', # 页数'rn': '20', # 项数'httpsStatus': '1','reqId': '6e028fc0-db8f-11eb-b6f5-ff7d54a57f2b'}from_url = '/url'from_params = {'rid': '148526468', # 歌曲 rid'type': 'convert_url3','br': '128kmp3',}lrc_url = '/newh5/singles/songinfoandlrc?musicId={rid}'headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.59'}class Kuwo:def search_kuwo(self, kw):#search_params.update({'key': kw})response = requests.get(search_url,params=search_params,headers={**headers, **search_headers},timeout=2,).json()datas = response.get('data', {}).get('list', {})result = [[r.get('name', ''),r.get('artist', ''),r.get('album', ''),r.get('songTimeMinutes', ''),r.get('pic', ''),r.get('pic120', ''),r.get('rid', '')]for r in datas]return resultdef get_music_url(self, rid):#from_params['rid'] = ridurl = requests.get(from_url, params=from_params, headers=headers, timeout=2).json()['url']return urldef get_music_content(self, rid):url = self.get_music_url(rid)content = requests.get(url, headers=headers, timeout=2).contentreturn contentdef get_music_lrc(self, rid):lrc_data = requests.get(lrc_url.format(rid=rid), headers=headers, timeout=2).json()lrc_list = lrc_data.get('data', {}).get('lrclist', [{1: '无歌词', 2: '0'}])lrc = [list(l.values()) for l in lrc_list]return lrcdef get_pic(self, url):pic = requests.get(url, headers=headers).contentreturn pic

二、歌词操作

下面代码为 lrc.py 里的代码。

import reclass Lrc:def __init__(self):self.LRC = [[0.0, '无歌词']]self.Times = [0.0]self.Words = ['无歌词']def decode_from_str(self, lrc: str):lrc = lrc.strip('\n')res1 = self.SP_DTWDSTR.findall(lrc)res2 = list()res3 = dict()result = dict()for r in res1:res2.append([self.SP_DTSTR.findall(r[0]), r[1]])for r in res2:for t in r[0]:res3[self.tosec(t)] = r[1]result = sorted(list(res3.items()), key=lambda x: x[0])self.decode(result)return self.LRCdef decode(self, lrcs):self.LRC = lrcsr = list(zip(*lrcs))self.Words = list(r[0])self.Times = list(map(self.tosec, list(r[1])))# 将字符串时间变为秒def tosec(self, t:str):res1 = t.split(':')[::-1]res2 = [float(r) * (60 ** i) for i, r in enumerate(res1)]result = sum(res2)return result# 根据浮点数播放进度获取对应歌词索引def get_index(self, t:float):times = [*self.Times, t]times.sort()return times.index(t) - 1

三、播放器

下面代码为 player.py 里的内容。

播放器的方法其实和 pygame.mixer.music 的方法差别不大。但要注意的是第 1~2 行代码是用于去除导入 pygame 模块时自动打印的信息。

from os import environenviron['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'import pygamefrom io import BytesIOclass Player:def __init__(self):pygame.mixer.init()self.music = pygame.mixer.musicdef reset(self):self.music.stop()pygame.mixer.pre_init()def load(self, filename):self.music.load(filename)def play(self):self.music.play()def pause(self):self.music.pause()def unpause(self):self.music.unpause()def stop(self):self.music.stop()def get_length(self):return self.music.get_length()def get_pos(self):return self.music.get_pos()def set_pos(self, value=0):self.music.rewind()self.music.set_pos(value)def get_volume(self):return self.music.get_volume()def set_volume(self, value=0.5):return self.music.get_volume(value)def addsong(self, filename):self.music.quene(filename)

四、GUI 界面

下面代码为 gui.py 中的代码。

进度条查看、控制滚动歌词pygame 播放网络音乐

from tkinter import *from tkinter import ttkfrom io import BytesIOfrom mutagen.mp3 import MP3from PIL import Image, ImageTkimport getimport playerimport lrcclass Window(Tk):ischanging = Falselast_pos = 0words = ['']times = [0]def __init__(self):Tk.__init__(self)self.title('JIE 音乐')self.geometry('650x400')self.resizable(0, 0)self.set_notebook()self.set_control()self.set_weight()self.update()self.after(100, self.timer)self.mainloop()def set_notebook(self):self.nb = ttk.Notebook(self)self.nb.grid(row=0, column=0, sticky='nswe', padx=2, pady=1)self.set_search_frame()self.set_lrc_frame()self.nb.add(self.search_frame, text=' 搜索 ')self.nb.add(self.lrc_frame, text=' 歌词 ')# 控制框def set_control(self):self.control_frame = Frame(self)self.control_frame.grid(row=1, column=0, sticky='nswe', padx=2, pady=1)self.ctrl_pic = Canvas(self.control_frame, height=40, width=40)self.ctrl_pic.grid(row=0, column=0)self.play_btn = Label(self.control_frame, text='▶', font=('宋体', 24, 'bold'), width=2, height=1, relief='flat')self.play_btn.bind('<Enter>', lambda event: self.play_btn.configure(fg='orange'))self.play_btn.bind('<Leave>', lambda event: self.play_btn.configure(fg='black'))self.play_btn.bind('<Button-1>', self.play_or_pause)self.play_btn.grid(row=0, column=1, sticky='nswe')self.var = IntVar()self.var.set(0)self.bar = Scale(self.control_frame, label='无歌曲', orient='horizontal', variable=self.var, showvalue=False, from_=0, to=0, command=self.change, width=10, length=500)self.bar.grid(row=0, column=2, sticky='nwe')self.download_btn = Label(self.control_frame, text='↓', font=('微软雅黑', 15), width=2)self.download_btn.bind('<Enter>', lambda event: self.download_btn.configure(fg='orange'))self.download_btn.bind('<Leave>', lambda event: self.download_btn.configure(fg='black'))self.download_btn.bind('<Button-1>', self.download)self.download_btn.grid(row=0, column=3, sticky='nswe')# 搜索界面def set_search_frame(self):self.search_frame = Frame(self.nb)self.inputbox = ttk.Entry(self.search_frame, width=14)self.inputbox.bind('<Return>',lambda event: self.get_datas(self.inputbox.get()))self.inputbox.grid(row=0, column=0, sticky='nswe', padx=(2, 0), pady=2)self.surebtn = ttk.Button(self.search_frame, text='搜索', width=6, command=lambda: self.get_datas(self.inputbox.get()))self.surebtn.grid(row=0, column=1, columnspan=2, sticky='nswe', padx=(0, 2), pady=2)columns = [0, 1, 2, 3, 4]self.songstable = ttk.Treeview(self.search_frame, columns=columns, show='headings')self.songstable.column(0, width=25, anchor='w', stretch='no')self.songstable.heading(0, text='')self.songstable.column(1, width=200, anchor='w')self.songstable.heading(1, text='歌曲')self.songstable.column(2, width=70, anchor='w')self.songstable.heading(2, text='歌手')self.songstable.column(3, width=100, anchor='w')self.songstable.heading(3, text='专辑')self.songstable.column(4, width=45, anchor='w', stretch='no')self.songstable.heading(4, text='时长')self.songstable.grid(row=1, column=0, columnspan=2, sticky='nswe')self.songstable.bind('<Double-Button-1>', lambda event: self.selected(self.songstable.item(self.songstable.selection()[0], 'value')))self.songscroll = ttk.Scrollbar(self.search_frame, orient='vertical', command=self.songstable.yview)self.songscroll.grid(row=1, column=2, sticky='nswe')self.songstable.configure(yscrollcommand=self.songscroll.set)# 歌词界面def set_lrc_frame(self):self.lrc_frame = Frame(self.nb)self.lrc_title = Label(self.lrc_frame, text='无歌曲', font=('微软雅黑', 15), anchor='w')self.lrc_title.grid(row=0, column=1, sticky='nswe', padx=(0, 40), pady=(40, 0))self.lrc_title2 = Label(self.lrc_frame, text='佚名', font=('微软雅黑', 10), fg='grey', anchor='w')self.lrc_title2.grid(row=1, column=1, sticky='nswe', padx=(0, 40))self.lrc_list = Listbox(self.lrc_frame, relief='flat', font=('微软雅黑', 12), highlightthickness=0, selectmode='single',bg='SystemButtonFace', fg='#303030',selectbackground='SystemButtonFace', selectforeground='orange')self.lrc_list.grid(row=2, column=1, sticky='nswe', padx=(0, 40), pady=(10, 40))self.lrc_list.insert('end', *([''] * 3), '无歌词')self.lrc_pic = Canvas(self.lrc_frame, width=240, height=240, relief='flat')self.lrc_pic.grid(row=0, column=0, rowspan=3, padx=40, pady=40)def set_weight(self):self.grid_rowconfigure(0, weight=1)self.grid_columnconfigure(0, weight=1)self.search_frame.grid_rowconfigure(1, weight=1)self.search_frame.grid_columnconfigure(0, weight=1)self.lrc_frame.grid_rowconfigure(2, weight=1)self.lrc_frame.grid_columnconfigure(1, weight=1)# 搜索def get_datas(self, kw='str'):t = self.songstable.get_children()for item in t:self.songstable.delete(item)datas = kuwo.search_kuwo(kw)for index, value in enumerate(datas):self.songstable.insert('','end',value=[index+1, *value])# 选中歌曲def selected(self, datas):player.reset()self.mdatas = datasself.last_pos = 0self.index = 0self.lrc = lrcdecoder.decode(kuwo.get_music_lrc(datas[-1]))self.words = lrcdecoder.Wordsself.times = lrcdecoder.Timesself.content = kuwo.get_music_content(datas[-1])self.song_name = datas[1]self.song_artist = datas[2]self.pic_small = self.Tkpic(kuwo.get_pic(datas[-2]), 40)self.pic_large = self.Tkpic(kuwo.get_pic(datas[-3]), 240)self.ctrl_pic.create_image(0, 0, anchor='nw', image=self.pic_small)self.lrc_pic.create_image(0, 0, anchor='nw', image=self.pic_large)self.play_btn.configure(text='||')self.lrc_title.configure(text=self.song_name)self.lrc_title2.configure(text=self.song_artist)self.lrc_list.delete(0, 'end')self.lrc_list.insert('end', *[*([''] * 2), *self.words])byte = BytesIO(self.content)self.bar.configure(from_=0, to=MP3(byte).info.length, label=f'{datas[1]} - {datas[2]}')player.load(byte)player.play()# 将网络 png 图片用于 tkinter 中def Tkpic(self, pic, res):byte_obj = BytesIO(pic)pic = Image.open(byte_obj)pic = pic.resize((res, res), Image.ANTIALIAS)pic = ImageTk.PhotoImage(pic)return pic# 拖动进度条时def change(self, value):self.ischanging = True# 暂停、继续def play_or_pause(self, event):if self.play_btn['text'] == '||' :player.pause()self.play_btn.configure(text='▶')else:player.unpause()self.play_btn.configure(text='||')# 下载音乐def download(self, event):with open(f'musics/{self.song_name} - {self.song_artist}.mp3', 'wb+') as f:f.write(self.content)# 定时器def timer(self):# 歌词同步if self.ischanging:self.ischanging = Falseself.last_pos = self.var.get() - player.get_pos() / 1000player.set_pos(self.var.get())else:self.var.set(player.get_pos() / 1000 + self.last_pos)# 歌词高亮index = lrcdecoder.get_index(player.get_pos() / 1000 + self.last_pos)self.lrc_list.selection_clear(0, 'end')self.lrc_list.selection_set(index + 2)# 滚动到指定位置index = index / len(self.words)index = index if index >= 0 else 0self.lrc_list.yview_moveto(index)self.after(200, self.timer)kuwo = get.Kuwo()player = player.Player()lrcdecoder = lrc.Lrc()

五、启动程序

下面代码为 main.pyw 中的代码。双击此文件可以直接运行。

import guiif __name__ == '__main__':gui.Window()

后记

这个音乐播放器还有一些不完善的地方,比如只能在有网络的情况下搜索,否则会报错;没有播放列表等等。

⑥项目源码案例分享有

如果你用得到的话可以直接拿走,在我的QQ技术交流群里群号:948351247(纯技术交流和资源共享,广告勿入)以自助拿走

点击这里 领取

此文转载文,著作权归作者所有,如有侵权联系小编删除哈!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。