目录

一、总述

二、文件结构

三、打包方式

四、使用pydub进行音乐播放

main2.py

all_music.py

show2.py

五、pydub使用中遇到的一些问题

六、新的尝试——pyaudio

mian3.py

all_music3.py

show3.py


一、总述

这是一个学习笔记。市面上的播放器很多,所以为什么要做这件事呢,一点是希望在做这个软件的过程中学到一些知识,还有是因为像酷狗、QQ音乐这些软件经常在网上被爆出恶意删除本地音频的行为,而groove没办法播放歌词,千千静听算是比较好的一个本地播放设备了,但是总归没有自己写来的自由。

本文实现了一个在ubuntu平台及win11平台下正常可执行文件封装的几乎全格式音乐播放器(主要是看ffmpeg能支持到什么格式);在win平台下由于pydub的FFmpeg依赖会弹出命令行,由于水平限制,目前仅能实现有命令行窗口的exe封装。(在最近的尝试中,在win11平台下,命令行已经不会弹出,其具体步骤为,把pydub库的所有subprocess.Popen函数加上shell = True,pydub用到subprocess的其他地方也要修改,具体不记得了,可以参考python封装exe可执行文件后屏蔽去除cmd黑色命令框解决方案_呆呆熊的世界的博客-CSDN博客_pyinstaller 禁止cmd,并且禁止自己代码的print输出)。

在win平台下,需要下载ffmpeg并将其exe文件的对应目录加入系统环境变量中,在Linux环境下,需要安装ffmpeg。对于本文的不足,希望各位指教。

二、文件结构

总共分为三个文件:

all_music.py 基于pydub,用于获得音乐类,可实现歌曲载入、播放、长度获取、播放时间获取、倍速播放、暂停、终结所有播放进程、播放状态获取等功能

show2.py 基于tkinter,用于播放器界面的可视化,之后预期添加音量加减,喜欢列表等功能。

main2.py 居中调度,用于传递文件路径,获取歌词和歌曲列表等功能。

三、打包方式

使用pyinstaller -w -F -n 目标名称 文件名称的方式(比如这里是pyinstaller -w -F -n my_music main2.py)进行打包。

笔者经过了很多次的尝试,在网上也找了很多的方法,但都没办法修改这个图标,我看到一篇文章,貌似是因为Ubuntu系统限制,无法修改这个图标,不知道大家有没有什么办法。

笔者直接在/usr/share/application这儿新建了一个My_Music.desktop 文件链接了这个可执行文件和图片。

My_Music.desktop设置如下:

[Desktop Entry]    #必须要的,告诉系统这是什么
Version=1.0        #可选,显示版本信息
Name=My_Music        #软件名称
Comment=A Music Player    #鼠标放在图标上时显示的文字
Exec=/home/xiaobai/Desktop/my_music/my_music    #可执行文件路径(绝对路径)
Icon=/home/xiaobai/Desktop/my_music/My_Music.jpeg    #希望作为软件图标使用的图片,这张是百度的,最好是正方形,也可以下下来自己裁
Encoding=UTF-8        #可选,编码方式
StartupNotify=true    #现在还不清楚有什么用
Terminal=false        #是否打开命令行
Type=Application    #类型
Categories=Audio;Player    #类别,这里选的是音乐播放器,具体可选值可自行百度

四、使用pydub进行音乐播放

main2.py

from tkinter import filedialog
import show2
import os
import numpy as np
import copy
import all_music
import time
import random
import chardet
import platform
import multiprocessing
list_music=[]
flag_list_music=0
def openfile():global list_music,flag_list_musicfilenames=filedialog.askopenfilenames(title = "音乐播放器",\filetypes =[("常见文件",\["*.wma","*.wav","*.mp3","*.flac",\"*.ape","*.mp4","*.m4a","*.ogg",\"*.flv"]),\("MP3文件","*.mp3"),\("FLAC文件","*.flac"),\("APE文件","*.ape"),\("WAV文件","*.wav"),\("MP4文件","*.mp4"),\("M4A文件","*.m4a"),\("OGG文件","*.ogg"),\("FLV文件","*.flv"),\("AIFF文件","*.aiff"),\("WMA文件","*.wma"),\("所有文件","*.*")])if filenames:for f in filenames:     #将音乐列表导入list_music.append(f)if (not music.get_busy()) and len(list_music):try:music.unload()except:passtry:music.load(list_music[0])except:passmusic.play()elif not len(list_music):assert False,"未导入任何歌曲"flag_list_music=1       #成功导入音乐
def openpath():global list_music,flag_list_musicpath=filedialog.askdirectory(title = "音乐播放器")if path:        #如果选择了文件list_music1=os.listdir(path)#保存选择的音乐列表并修正为绝对路径for i in range(len(list_music1)):list_music1[i]=path+"/"+list_music1[i]list_music2=copy.deepcopy(list_music1)#深拷贝for f in list_music2:       #移除不支持的格式的音乐extension = os.path.splitext(f)[-1]if not (extension==".mp3" or\extension==".wma" or\extension==".wav" or\extension==".ogg" or\extension==".flv" or\extension==".mp4" or\extension==".aiff" or\extension==".ape" or\extension==".m4a" or\extension==".flac"):list_music1.remove(f)#print(f+"因为不被支持被移除了")list_music=list_music+list_music1if (not music.get_busy()) and len(list_music):try:music.unload()except:passtry:music.load(list_music[0])except:passmusic.play()elif not len(list_music):assert False,"未导入任何歌曲"flag_list_music=1           #成功导入音乐
def next_music():           #下一首歌global list_music,flag_list_musicmusic.stop()music.unload()way=show1.play_way.get()        #获取设定的播放方式if way==2:              #列表播放list_music.pop(0)elif way==1:            #单曲循环if len(list_music)>1:list_music.pop(0)print("单曲循环中")elif way==3:            #列表循环list_music.append(list_music.pop(0))elif way==4:            #随机播放random.shuffle(list_music)else:assert False,"播放方式出错"flag_list_music=1               #刷新显示if len(list_music):music.load(list_music[0])music.play()else:assert False,"没有下一首了"
def stop():                 #停止播放并清空播放列表global list_music,flag_list_musiclist_music=[]music.stop()music.unload()flag_list_music=1       #刷新显示
def code(path):    #判断文件的编码方式 f = open(path, 'rb')f_read = f.read()f_charInfo = chardet.detect(f_read)return f_charInfo
lrc_dict={}
def get_lrc_geci():global lrc_dict,list_musicif list_music:path=copy.deepcopy(list_music[0])#深拷贝for i in range(len(path)-1,-1,-1):if path[i]==".":path=path[:i]+".lrc"breaktry:file=open(path, "r", encoding=code(path)['encoding'])try:lrc_list = file.readlines()except:if code(path)['encoding']==('GB2312' or 'GBK'):file=open(path, "r", encoding='GB18030')lrc_list = file.readlines()lrc_dict = {}for i in lrc_list:lrc_word = i.replace("[", "]").strip().split("]")for j in range(len(lrc_word) - 1):if lrc_word[j]:time=0flag=0for k in range(len(lrc_word[j])):try:if lrc_word[j][k]==":":time=int(lrc_word[j][:k])*60*1000+timeflag=kelif flag!=0 and lrc_word[j][k]==".":time=int(lrc_word[j][flag+1:k])*1000+timetime=int(lrc_word[j][k+1:])+timebreakelif flag!=0 and k==len(lrc_word[j])-1:time=int(lrc_word[j][flag+1:k+1])*1000+timebreakexcept:time=0breakif time in lrc_dict.keys():if flag==0:lrc_dict[time] = lrc_dict[time]+' '+lrc_word[1]else:lrc_dict[time] = lrc_dict[time]+' '+lrc_word[-1]else:if flag==0:lrc_dict[time] = lrc_word[1]else:lrc_dict[time] = lrc_word[-1]time_list=list(lrc_dict.keys())time_list.sort()lrc_dict["time"]=time_listprint("get_lrc")file.close()except:lrc_dict = {}
now_word=0
def get_word():global lrc_dict,now_wordif lrc_dict and music.get_busy():for i in range(len(lrc_dict["time"])):if lrc_dict["time"][i]<=get_real_time()*music.speed\and ((len(lrc_dict["time"])==lrc_dict["time"].index(lrc_dict["time"][i])+1\or (len(lrc_dict["time"])>lrc_dict["time"].index(lrc_dict["time"][i])+1 \and lrc_dict["time"][i+1]>get_real_time()*music.speed))):now_word=lrc_dict["time"][i]word=[]word.append(lrc_dict[now_word])if len(lrc_dict["time"])>=lrc_dict["time"].index(lrc_dict["time"][i])+2:word.append(lrc_dict[lrc_dict["time"][lrc_dict["time"].\index(now_word)+1]])return wordelif not lrc_dict:return ["暂无歌词"]else:return []def get_real_time():return music.get_play_time()
def my_mainloop():global list_music,flag_list_musicglobal event1,now_wordword=get_word()if word:show1.get_word(lrc_word=word)event1=music.pop_event()if event1:          #仅当歌曲正常结束时,event1事件触发print("over")flag_list_music=1       #载入新歌歌词if len(list_music):     #如果还有歌show1.set_time=0way=show1.play_way.get()#获取设定的播放方式if way==2:      #列表播放list_music.pop(0)elif way==1:    #单曲循环print("单曲循环中")elif way==3:    #列表播放list_music.append(list_music.pop(0))elif way==4:    #随机播放random.shuffle(list_music)else:assert False,"播放方式出错"print("pop")if len(list_music):if way==1:music.replay()else:music.unload()music.load(list_music[0])music.play()else:print("歌单空了")if flag_list_music:         #如果需要读入歌单now_word=0get_lrc_geci()          #获得歌词list_music_change=copy.deepcopy(list_music)#深拷贝path=""for j in range(len(list_music_change)): #得到歌曲名称f=list_music_change[j]x=-1for i in range(len(f)):if f[i]=="/":x=iif x>=0:path=list_music_change[j][:x+1]list_music_change[j]=list_music_change[j][x+1:]show1.get_music_list(path=path,list_music=list_music_change)flag_list_music=0if get_real_time()>=0:if ((get_real_time()!=show1.music_time_scale.get()))and \not show1.mouse_left_click1:#print("set_time2")show1.set_length_and_now_time(now_time=get_real_time())show1.music_time_scale.set(get_real_time())show1.win.after(100,my_mainloop)
def main():global show1global musicmusic=all_music.all_music()music.set_event(event=1)show1=show2.show()show1.get_music(music=music,\openfile=openfile,openpath=openpath,\next_music=next_music,stop=stop)event1=Falseshow1.win.after(100,my_mainloop)show2.mainloop()try:music.stop()except:pass
if __name__ == '__main__':if('Windows'==platform.system()):#防止在win平台下打包出现多窗口multiprocessing.freeze_support()main()

all_music.py

from pydub import AudioSegment
from pydub.playback import play
import multiprocessing
import time
import psutil
import copy
def terminate(process_pid):process=psutil.Process(process_pid)p_child=process.children() # 子进程列表for p_c in p_child:p_c.kill()p_c.join()process.kill()process.join()
def suspend(process):p_child=process.children() # 子进程列表for p_c in p_child:p_c.suspend()process.suspend()
def resume(process):p_child=process.children() # 子进程列表for p_c in p_child:p_c.resume()process.resume()
class all_music():def __init__(self):self.volume=100self.song_path=[]self.song=[]                    #绝对self.song1=[]                   #相对self.process1=[]self.suffix=[]self.now_time=-1        #当前播放歌曲的时长self.start_time=-1      #计时器开始计时的时间self.excursion_time=0self.length=-1self.load_flag=0self.busy=0         #0:空闲;1:播放中;2:暂停中;3:暂停准备继续播放self.event=0self.speed=1self.volume_limuit=20def set_event(self,event):      #设置事件返回值,触发时返回event,未触发返回0self.event=eventdef pop_event(self):            #查看当前事件状态try:result=self.q.get(block=False)self.busy=0return resultexcept:return 0def pydub_play(self):           #播放音乐并在结束时触发事件play(self.song1)self.q.put(self.event,block=True)def get_busy(self):             #查看是否忙碌     return self.busydef get_length(self):           #得到歌曲长度return self.lengthdef pos_set(self,time):         #设置歌曲播放位置if self.load_flag:self.stop()self.play(start=time)else:assert False,"未载入歌曲"def get_play_time(self):        #获得当前歌曲播放到的位置if self.start_time!=-1:if self.busy==1:    #判断是否在暂停状态#当前歌曲播放了多少毫秒self.now_time=self.excursion_time+int((time.time()-self.start_time)*1000)return self.now_timeelse:return self.now_timeelse:return -1def load(self,file_path):       #获得路径if not self.load_flag:   #判断是否已经加载了歌曲if file_path:   #判断路径是否为空self.song_path=file_path    #将歌曲路径给到selffor i in range(len(self.song_path)-1,-1,-1):    #寻找文件后缀if self.song_path[i]==".":breakif self.song_path[i]==".":                      #将歌曲后缀给到selfself.suffix=self.song_path[i+1:]self.load_flag=1else:assert False,"未发现文件后缀"else:assert False,"load(file_path)需要一个歌曲路径"else:assert False,"已经加载了一个歌曲"def unload(self):           #解除加载状态if self.load_flag:   #判断是否已经加载了歌曲self.load_flag=0self.song_path=[]self.suffix=[]else:assert False,"未加载歌曲"def set_speed(self,speed):self.speed=speeddef set_volume(self,volume):self.volume=volumedef get_volume(self):return self.volume    def replay(self,start=0):if self.busy:   #判断歌曲是否在播放或者暂停状态try:terminate(self.process1.pid)    #终结歌曲进程except:pass self.process1=[]self.now_time=-1self.start_time=-1self.excursion_time=0self.length=-1self.busy=0#判断歌曲是否在播放或者暂停状态if (self.busy==0 or self.busy==3)and self.load_flag:self.song1=copy.deepcopy(self.song)if self.volume==0:self.song1=self.song1-100else:self.song1=self.song1-self.volume_limuit*(1.0-self.volume/100)if self.speed!=1:self.song1 = self.song1._spawn(self.song1.raw_data, \overrides={"frame_rate": int(self.song1.frame_rate * self.speed)})\.set_frame_rate(self.song1.frame_rate)if start>len(self.song1):assert False,"设置的时间超过歌曲的时长"self.excursion_time=start         #设置偏移时间归零self.now_time=self.excursion_time#设置播放时间归零print(self.now_time)self.busy=1self.length=len(self.song1)   #设置歌曲时长print(self.length)if self.now_time:self.song1=self.song1[self.now_time:]print(len(self.song1))self.q = multiprocessing.Queue(maxsize=1)self.process1 = multiprocessing.Process(target =self.pydub_play,name="my_process1")self.process1.start()self.start_time=time.time()else:assert False,"歌曲未载入或占用中,请先load或stop"def play(self,start=0):                 #播放歌曲#判断歌曲是否在播放或者暂停状态if (self.busy==0 or self.busy==3)and self.load_flag:if self.suffix:#是否有下标if self.suffix=="mp3":      #导入mp3歌曲self.song = AudioSegment.from_mp3(self.song_path) elif self.suffix=="ogg":    #导入ogg歌曲self.song = AudioSegment.from_ogg(self.song_path) elif self.suffix=="flv":    #导入flv歌曲self.song = AudioSegment.from_flv(self.song_path) else:#导入其他支持的格式的歌曲try:self.song = AudioSegment.from_file(self.song_path,self.suffix)except:assert False,"不支持的文件或不存在此文件"self.song1=copy.deepcopy(self.song)if self.volume==0:self.song1=self.song1-100else:self.song1=self.song1-self.volume_limuit*(1-self.volume/100)if self.speed!=1:self.song1 = self.song1._spawn(self.song1.raw_data, \overrides={"frame_rate": int(self.song1.frame_rate * self.speed)})\.set_frame_rate(self.song1.frame_rate)if start>len(self.song1):assert False,"设置的时间超过歌曲的时长"self.excursion_time=start         #设置偏移时间归零self.now_time=self.excursion_time#设置播放时间归零self.busy=1self.length=len(self.song1)   #设置歌曲时长if self.now_time:self.song1=self.song1[self.now_time:]self.q = multiprocessing.Queue(maxsize=1)self.process1 = multiprocessing.Process(target =self.pydub_play,name="my_process1")self.process1.start()self.start_time=time.time()else:assert False,"未载入任何歌曲"else:assert False,"歌曲未载入或占用中,请先load或stop"def stop(self):     #结束播放但不unloadif self.busy:   #判断歌曲是否在播放或者暂停状态try:terminate(self.process1.pid)    #终结歌曲进程except:passself.song=[]self.process1=[]self.now_time=-1self.start_time=-1self.excursion_time=0self.length=-1self.busy=0else:assert False,"歌曲不在播放或暂停状态"def pause(self):    #暂停播放if self.busy==1:   #判断歌曲是否在播放状态self.get_play_time()        #获得当前时间p=psutil.Process(self.process1.pid)suspend(p)self.busy=2else:assert False,"无歌曲正在播放"def unpause(self):  #继续暂停的播放if self.busy==2:   #判断歌曲是否在播放状态self.busy=3p=psutil.Process(self.process1.pid)resume(p)self.excursion_time=self.now_time   #设置偏移时间归零self.start_time=time.time()self.busy=1#self.play(start=self.now_time)else:assert False,"歌曲不在暂停状态"

show2.py

from tkinter import *
from PIL import Image
import tkinter.font as tkFont
from tkinter import ttk
import platform
def color(color_255):color_16=0x0color_16=color_16+0x10000*(color_255[0])color_16=color_16+0x100*(color_255[1])color_16=color_16+0x1*(color_255[2])if color_16>0xFFFFF:return '#%0x'%color_16elif color_16>0xFFFF:return '#0%0x'%color_16elif color_16>0xFFF:return '#00%0x'%color_16elif color_16>0xFF:return '#000%0x'%color_16elif color_16>0xF:return '#0000%0x'%color_16else:return '#00000%0x'%color_16
openfiles=[]
openpaths=[]
next_musics=[]
stop=[]
typeface=u"华文行楷"if(platform.system()=='Windows'):size_word_win='1000x80'
elif(platform.system()=='Linux'):size_word_win='1000x100'
else:assert False,'暂未支持Windows和Linux之外的系统'class show():def __init__(self): #主窗口self.mouse_left_click1=0#鼠标左键点击时间轴状态self.mouse_left_click2=0#鼠标左键点击音量状态self.set_time=0self.flag_replay=0self.win = Tk()ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.win.title(u"我的音乐")self.win.bind("<Key>",self.key_event)self.screenwidth=self.win.winfo_screenwidth()self.screenheight=self.win.winfo_screenheight()self.win.resizable(width=False,height=False)#False表示不可以缩放,True表示可以缩放try:self.win.iconphoto(True, PhotoImage(file='/home/xiaobai/Desktop/my_music/My_Music_tk.png'))except:passself.frame= Frame (self.win, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,heigh=600,width=1280,cursor='arrow')self.frame.pack(side=TOP, fill=BOTH, ipadx=0, ipady=0, expand=1)#音乐列表frameself.frame2= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame2.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)self.frame21= Frame (self.frame2,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame21.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=1)self.frame22= Frame (self.frame2,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame22.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)#按钮frameself.frame1= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame1.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)#歌词frameself.frame3= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame3.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=0)#按钮ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"暂停",command =self.pause)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"播放",command =self.play)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"重新播放",command =self.replay)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"下一首",command =self.next_music)\.pack (side=LEFT, padx=13, pady=13)self.frame11= Frame (self.frame1,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame11.pack(side=LEFT,fill=Y,ipadx=20,ipady=0,expand=0)Button (self.frame1,font=ft,bg=color([59,210,61])\,activebackground="white",\text=u"清空",command =self.stop)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([242,203,46])\,activebackground="white",\text=u"文件夹",command =self.openpath)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([242,169,0])\,activebackground="white",\text=u"文件",command =self.openfile)\.pack (side=LEFT, padx=13, pady=13)#一些文本显示#显示“播放列表”文本ft = tkFont.Font(family=typeface, size=20, weight=tkFont.BOLD)self.frame221= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame221.pack(side=LEFT)Label(self.frame221,font=ft,\text=u"播",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"放",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"列",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"表",bg=color([135,206,250])).pack(anchor='w')#显示“倍速”文本ft = tkFont.Font(family=typeface, size=10, weight=tkFont.BOLD)self.frame222= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame222.pack(anchor='w')Label_b=Label(self.frame222,font=ft,\text=u"   倍速",bg=color([135,206,250]))Label_b.pack(side=LEFT)#倍速设置self.set_comvalue=StringVar()#窗体自带的文本,新建一个值self.set_templist=ttk.Combobox(self.frame222,font=ft,\textvariable=self.set_comvalue,\state='readonly',\width=3) #初始化    self.set_templist["values"]=("0.8","0.9","1","1.2","1.4")self.set_templist.current(2) #选择第一个self.set_templist['state'] = 'readonly'#只读self.set_templist.bind("<<ComboboxSelected>>",self.music_speed) #绑定事件,(下拉列表框被选中时,绑定go()函数)self.set_templist.pack(side=LEFT)#列表#音乐列表self.frame224= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame224.pack(side="left")self.list_music1_sb = Scrollbar(self.frame224)self.list_music1_sb.pack(side="right", fill="y")ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.list_music1=Listbox(self.frame224,bg=color([255,255,255]),\cursor='plus',font=ft,\fg=color([0,0,0]),height=5,width=40,\yscrollcommand= self.list_music1_sb.set)self.list_music1.pack(side="left", fill="both")self.list_music1_sb.config(command=self.list_music1.yview)#播放模式设置self.frame222= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame222.pack(side=LEFT)WAY_SET = [("单曲循环", 1),("列表播放", 2),("列表循环", 3),("随机播放", 4)]self.play_way = IntVar()self.play_way.set(2)for way, num in WAY_SET:Radiobutton(self.frame222, text=way, variable=self.play_way,\indicatoron=False, value=num,\font=ft,bg=color([135,206,250]),\activebackground=color([255,192,203]),\cursor='circle',selectcolor=color([192,192,192]),\).pack(anchor="w")#音量self.frame223= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame223.pack(side=LEFT,padx=5)Label_c=Label(self.frame223,font=ft,\text=u"音量",bg=color([135,206,250]))Label_c.pack(anchor="w")self.volume_text = IntVar()self.volume_text.set(100)self.music_volume=Scale(self.frame223,from_=100, to=0, \length=100, \orient="vertical",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False,variable=self.volume_text)self.music_volume.pack(after=Label_c,padx=10)if(platform.system()=='Windows'):self.music_volume.bind("<MouseWheel>",self.mouse_middle_motion_volume)elif(platform.system()=='Linux'):self.music_volume.bind("<Button-4>",self.mouse_middle_motion_volume)self.music_volume.bind("<Button-5>",self.mouse_middle_motion_volume)else:assert False,'暂未支持Windows和Linux之外的系统'self.music_volume.bind("<Button-1>",self.mouse_left_click_volume)self.music_volume.bind("<ButtonRelease-1>",self.mouse_left_release_volume)Label(self.frame223,font=ft,textvariable=self.volume_text,\bg=color([135,206,250])).pack(after=self.music_volume)#当前时间self.now_time_text = StringVar()self.now_time_text.set("0"+":"+"00")ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD)Label(self.frame21,font=ft,textvariable=self.now_time_text,\bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5)#歌曲进度self.music_time_scale_length=600ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.frame211= Frame (self.frame21,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame211.pack(side=LEFT)self.music_time_scale=Scale(self.frame211,from_=0, to=180000, \length=self.music_time_scale_length, cursor="circle",\orient="horizontal",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False)self.music_time_scale.pack(side=LEFT,padx=5, pady=0)self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun)self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun)#总时间self.length_text = StringVar()self.length_text.set("0"+":"+"00")ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD)Label(self.frame21,font=ft,textvariable=self.length_text,\bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5)#歌词'''self.lrc_word_length=40ft = tkFont.Font(family=u"宋体", size=25, weight=tkFont.BOLD)self.lrc_word=Listbox(self.frame3,bg=color([255,255,255]),\cursor='plus',font=ft,\fg=color([0,0,0]),height=2,width=self.lrc_word_length)self.lrc_word.pack(side=BOTTOM,fill=Y,ipadx=0,ipady=0,expand=0)'''ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.son_win=Toplevel(master=self.win)      #子窗口self.son_win.title("我的歌词")self.son_win.geometry(size_word_win+'+'+str(self.screenwidth//2-500)+'+'+str(self.screenheight-120))     #大小和位置self.son_win.wm_attributes('-topmost',1)    #置顶self.son_win.overrideredirect(boolean=True)#去掉边框和按钮if platform.system()=='Linux':self.son_win.wait_visibility(self.son_win)self.son_win.attributes('-alpha',0.9)       #整体透明self.son_win.bind("<B1-Motion>", self.move)self.son_win.bind("<Button-1>", self.get_point)'''--将回调函数func与相应的规则name绑定--name参数可以是“WM_DELETE_WINDOW”:窗口被关闭的时候--name参数可以是“WM_SAVE_YOURSELF”:窗口被保存的时候--name参数可以是“WM_TAKE_FOCUS”:窗口获得焦点的时候'''#withdraw()#将窗口从屏幕上移除(并没有销毁)'''--需要重新显示窗口,使用deiconify()方法--该方法会使得state()返回"withdraw"'''self.frame_son_win= Frame (self.son_win,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame_son_win.pack(fill=BOTH,expand=1)self.lrc_word_length=40ft = tkFont.Font(family=typeface, size=20, weight=tkFont.BOLD)self.lrc_word=Text(self.frame_son_win,font=ft,\relief='flat',width=self.lrc_word_length,\bg=color([135,206,250]),height=2)self.lrc_word.tag_config("tag_1", backgroun="yellow", foreground="red")self.lrc_word.pack()self.lrc_word.config(state=DISABLED)self.word_win_state = IntVar()self.word_win_state_button=Checkbutton(self.frame1,font=ft,bg=color([135,206,250]),\text=u"词",variable=self.word_win_state,\command=self.show_or_hide_word,indicatoron=False,\activebackground=color([255,192,203]),\selectcolor=color([192,192,192]))self.word_win_state_button.pack (side=LEFT, padx=13, pady=13)self.word_win_state_button.select()def key_event(self,event):key=event.keysymif key=='space':if self.music.get_busy()==1:self.pause()elif self.music.get_busy()==2:self.play()elif key=='Up':self.mouse_middle_motion_volume([],1)elif key=='Down':self.mouse_middle_motion_volume([],-1)def show_or_hide_word(self):if self.word_win_state.get():self.son_win.deiconify()else:self.son_win.withdraw()#print(self.word_win_state.get())def get_point(self, event):"""获取当前窗口位置并保存"""self.x, self.y = event.x, event.ydef move(self, event):"""窗口移动事件"""new_x = (event.x - self.x) + self.son_win.winfo_x()new_y = (event.y - self.y) + self.son_win.winfo_y()s = size_word_win+f"+{new_x}+{new_y}"     self.son_win.geometry(s)def mouse_middle_motion_volume(self,event,key=None):if(platform.system()=='Windows'):x=120if key==None:flag=event.delta//xelif(platform.system()=='Linux'):x=4if key==None:if(event.num==x):flag=1elif event.num==x+1:flag=-1else:assert False,'Linux下事件错误'else:assert False,'暂未支持Windows和Linux之外的系统'if key!=None:if key==1:flag=1elif key==-1:flag=-1else:assert False,'key输入错误'if flag>0:print("volume="+str(self.music.get_volume())+"dB")if self.music.get_volume()!=120:if 100==self.music_volume.get():volume=self.music.get_volume()+10*flagself.volume_text.set(volume)else:volume=self.music_volume.get()+10*flagself.music_volume.set(volume)self.volume_text.set(volume)self.music.set_volume(volume)self.win.update()       #强制刷新self.set_time=self.music.get_play_time()self.music.replay(start=self.set_time)self.win.update()       #强制刷新else:if self.music.get_volume()!=0:if 100<self.music.get_volume():volume=self.music.get_volume()+10*flagself.volume_text.set(volume)else:volume=self.music_volume.get()+10*flagif volume<0:volume=0self.music_volume.set(volume)self.volume_text.set(volume)self.music.set_volume(volume)self.win.update()       #强制刷新self.set_time=self.music.get_play_time()self.music.replay(start=self.set_time)self.win.update()       #强制刷新def mouse_left_click_volume(self,event):state=self.music_volume.identify(event.x,event.y)if state!='slider':volume=100-event.yself.music_volume.set(volume)self.volume_text.set(volume)self.win.update()       #强制刷新self.mouse_left_click2=1print("mouse_set_volume")else:self.mouse_left_click2=1print("slide_scale")def mouse_left_release_volume(self,event):if self.mouse_left_click2==1:volume=self.music_volume.get()self.volume_text.set(volume)self.music_volume.set(volume)self.music.set_volume(volume)self.set_time=self.music.get_play_time()self.win.update()       #强制刷新self.music.replay(start=self.set_time)self.win.update()       #强制刷新print("slide_scale_set_volume")self.mouse_left_click2=0def music_speed(self,*args):speed=float(self.set_templist.get())self.set_time=int(self.music.get_play_time()*self.music.speed/speed)self.music.set_speed(speed)#self.music.stop()self.music.replay(start=self.set_time)self.music_time_scale.pack_forget()     #时间进度条重画ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.music_time_scale=Scale(self.frame211,from_=0, \to=self.music.get_length(), \length=self.music_time_scale_length, cursor="circle",\orient="horizontal",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False)self.music_time_scale.pack(side=LEFT,padx=5, pady=0)self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun)self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun)self.music_time_scale.set(self.set_time)self.set_length_and_now_time(now_time=self.set_time,music_length=self.music.get_length())self.win.update()       #强制刷新def set_length_and_now_time(self,now_time,music_length=None):if music_length!=None:self.length_text.set(str(int(music_length*self.music.speed//(1000*60))).zfill(1)\+":"+str(int(music_length*self.music.speed//1000%60)).zfill(2))time=int(now_time*self.music.speed)self.now_time_text.set(str(time//(1000*60)).zfill(1)\+":"+str(time//1000%60).zfill(2))def mouse_left_click_fun(self,event):state=self.music_time_scale.identify(event.x,event.y)if state!='slider':self.set_time=int(event.x/self.music_time_scale_length*self.music.get_length())self.music_time_scale.set(self.set_time)self.win.update()       #强制刷新#self.music.stop()self.music.replay(start=self.set_time)self.mouse_left_click1=2print("mouse_set_time")else:self.mouse_left_click1=1print("slide_scale")def mouse_left_release_fun(self,event):if self.mouse_left_click1==1:if event.x<0:event_x=0elif event.x>self.music_time_scale_length:event_x=self.music_time_scale_lengthelse:event_x=event.xself.set_time=int(event_x/self.music_time_scale_length*self.music.get_length())self.music_time_scale.set(self.set_time)self.win.update()       #强制刷新#self.music.stop()self.music.replay(start=self.set_time)print("slide_scale_set_time")self.mouse_left_click1=0def get_music(self,music,openfile,openpath,next_music,stop):self.music=musicglobal openfilesopenfiles=openfileglobal openpathsopenpaths=openpathglobal next_musicsnext_musics=next_musicglobal stop1stop1=stopdef get_music_list(self,path,list_music):self.list_music1.delete(0,"end")for item in list_music:self.list_music1.insert("end", item)self.music_time_scale.pack_forget()if path:ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.music_time_scale=Scale(self.frame211,from_=0, \to=self.music.get_length(), \length=self.music_time_scale_length, cursor="circle",\orient="horizontal",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False)self.music_time_scale.pack(side=LEFT,padx=5, pady=0)self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun)self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun)self.set_length_and_now_time(now_time=self.set_time,music_length=self.music.get_length())def get_word(self,lrc_word):self.lrc_word.config(state=NORMAL)try:self.lrc_word.delete(1.0,"end")except:passlength=0length1=0if len(lrc_word)==1 or lrc_word[1]=='':for ch in lrc_word[0]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1length=int(length)else:for i in range(len(lrc_word)):if i:length1=round(length/2)length=length1for ch in lrc_word[i]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1else:for ch in lrc_word[i]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1length=int(length)if self.lrc_word_length!=length:self.lrc_word.pack_forget()self.lrc_word_length=int(length)ft = tkFont.Font(family=typeface, size=25, weight=tkFont.BOLD)self.lrc_word=Text(self.frame_son_win,font=ft,\relief='flat',width=self.lrc_word_length,\bg=color([135,206,250]),height=2)self.lrc_word.pack()self.lrc_word.tag_config("tag_1", backgroun="yellow", foreground="red")for i in range(len(lrc_word)):if i:self.lrc_word.insert("end", " "*length1+lrc_word[i])else:self.lrc_word.insert("end", lrc_word[i],"tag_1")self.lrc_word.insert("end", '\n')self.lrc_word.config(state=DISABLED)def pause(self):self.music.pause()print("pause")def stop(self):self.set_time=0stop1()print("stop")def play(self):self.music.unpause()print("play")def replay(self):self.set_time=0self.music_time_scale.set(0)self.music.replay()print("replay")def openfile(self):self.set_time=0openfiles()print("openfile")def set_times(self):time=self.music_time_scale.get()print(time)self.set_time=timeself.music.replay(start=time)print("set_time")def openpath(self):self.set_time=0openpaths()print("openpath")def next_music(self):self.set_time=0next_musics()print("next_music")

五、pydub使用中遇到的一些问题

在使用pydub的过程中,我发现这个库似乎有点问题,在播放24位的flac音乐时,会出现播放没有声音的情况(只是偶尔有一两声尖锐的声音),后来我又尝试使用pyaudio库进行播放,发现还是有这个问题,但是查看pydub读取到的数据是正常的。

因为发现pyaduio获得的函数返回输入的fomate是1,这是有问题的后来从pyaduio这条线往下查,发现pyaudio.py文件的return paFloat32这一句似乎有问题,因为上面几句都是Int,只有这个是Float,结果改完后,pydub和pyaudio库都播放正常了,就无语。。。

后来因为使用pydub库不好控制播放和暂停点(可能是我不会),我又使用了pyaudio库进行了尝试,效果还挺好,就是Ubuntu 20.04的pyaudio太难装了。。。

还有一个问题,就是当遇到音乐文件的名字有一个&(三个是没事的,其他个数没试过)时,pydub在读入歌曲数据时会报路径错误,往下面查,发现是pydub在调用Popen函数调用ffmpeg功能时,如果路径字符串没有双引号且有&,命令行那边会直接报错,我自己用命令行调用ffmpeg,加上""就能正常跑,但是我去改pydub的底层,给字符串加"",也会报找不到路径的错,就很。。。不知道大家有什么别的办法不,欢迎大家交流。

这里再贴一下使用pyaudio进行播放的代码。

六、新的尝试——pyaudio

mian3.py

from tkinter import filedialog
import show3 as show
import os
import sys
import numpy as np
import copy
import all_music3 as all_music
import time
import random
import chardet
import platform
import multiprocessing
import warnings
list_music=[]
flag_list_music=0
event2 = 0
def get_event2():global event2if event2:event2 = 0return 1return 0
def which(program):#别人的源码这里用来判断ffmpeg是否存在"""Mimics behavior of UNIX which command."""# Add .exe program extension for windows supportif os.name == "nt" and not program.endswith(".exe"):program += ".exe"envdir_list = [os.curdir] + os.environ["PATH"].split(os.pathsep)for envdir in envdir_list:program_path = os.path.join(envdir, program)if os.path.isfile(program_path) and os.access(program_path, os.X_OK):return program_path
if not which("ffmpeg"):if ('Windows'==platform.system()):assert False,"This program need ffmpeg to run! \nPlease download ffmpeg and put it on the same path of the program or set a Windows system path to your ffmpeg path."if ('Linux'==platform.system()):assert False,"This program need ffmpeg to run! \nPlease update ffmpeg!"else:assert False,"This system is nonsupport!"def openfile():global list_music,flag_list_musicfilenames=filedialog.askopenfilenames(title = "音乐播放器",\filetypes =[("常见文件",\["*.wma","*.wav","*.mp3","*.flac",\"*.ape","*.mp4","*.m4a","*.ogg",\"*.flv"]),\("MP3文件","*.mp3"),\("FLAC文件","*.flac"),\("APE文件","*.ape"),\("WAV文件","*.wav"),\("MP4文件","*.mp4"),\("M4A文件","*.m4a"),\("OGG文件","*.ogg"),\("FLV文件","*.flv"),\("AIFF文件","*.aiff"),\("WMA文件","*.wma"),\("所有文件","*.*")])if filenames:for f in filenames:     #将音乐列表导入list_music.append(f)if (not music.get_busy()) and len(list_music):#music.play(list_music[0])play_song(list_music[0])elif not len(list_music):assert False,"未导入任何歌曲"flag_list_music=1       #成功导入音乐list_music1_num_set()
def openpath(key=None):global list_music,flag_list_musicpath=filedialog.askdirectory(title = "音乐播放器")if path:        #如果选择了文件#非递归查找#list_music1=os.listdir(path)#保存选择的音乐列表并修正为绝对路径#for i in range(len(list_music1)):#    list_music1[i]=path+"/"+list_music1[i]list_music1=[]  #递归查找for dirpath, dirnames, filenames in os.walk(path):for filename in filenames:list_music1.append(os.path.join(dirpath, filename))list_music2=copy.deepcopy(list_music1)#深拷贝for f in list_music2:       #移除不支持的格式的音乐extension = os.path.splitext(f)[-1]if not (extension==".mp3" or\extension==".wma" or\extension==".wav" or\extension==".ogg" or\extension==".flv" or\extension==".mp4" or\extension==".aiff" or\extension==".ape" or\extension==".m4a" or\extension==".flac"):list_music1.remove(f)#print(f+"因为不被支持被移除了")list_music=list_music+list_music1if (not music.get_busy()) and len(list_music):#music.play(list_music[0])play_song(list_music[0])elif not len(list_music):assert False,"未导入任何歌曲"flag_list_music=1           #成功导入音乐list_music1_num_set()def list_music1_num_set():print("\nnum="+str(len(list_music)))show1.list_music1_num_text.set(len(list_music))def next_music():           #下一首歌music.stop()def play_song(song_path):global event2try:music.play(song_path)except:warnings.warn("The song could not be play")event2 = 1passdef stop():                 #停止播放并清空播放列表global list_music,flag_list_musiclist_music=[]flag_list_music=1       #刷新显示list_music1_num_set()try:music.stop()except:passdef code(path):    #判断文件的编码方式 f = open(path, "rb")f_read = f.read()f_charInfo = chardet.detect(f_read)return f_charInfo
lrc_dict={}
def get_lrc_geci():global lrc_dict,list_musicif list_music:path=copy.deepcopy(list_music[0])#深拷贝for i in range(len(path)-1,-1,-1):if path[i]==".":path=path[:i]+".lrc"breaktry:file=open(path, "r", encoding=code(path)["encoding"])try:lrc_list = file.readlines()except:if code(path)["encoding"]==("GB2312" or "GBK"):file=open(path, "r", encoding="GB18030")lrc_list = file.readlines()lrc_dict = {}for i in lrc_list:lrc_word = i.replace("[", "]").strip().split("]")for j in range(len(lrc_word) - 1):if lrc_word[j]:time=0flag=0for k in range(len(lrc_word[j])):try:if lrc_word[j][k]==":":time=int(lrc_word[j][:k])*60*1000+timeflag=kelif flag!=0 and lrc_word[j][k]==".":time=int(lrc_word[j][flag+1:k])*1000+timetime=int(lrc_word[j][k+1:])+timebreakelif flag!=0 and k==len(lrc_word[j])-1:time=int(lrc_word[j][flag+1:k+1])*1000+timebreakexcept:time=0breakif time in lrc_dict.keys():if flag==0:lrc_dict[time] = lrc_dict[time]+" "+lrc_word[1]else:lrc_dict[time] = lrc_dict[time]+" "+lrc_word[-1]else:if flag==0:lrc_dict[time] = lrc_word[1]else:lrc_dict[time] = lrc_word[-1]time_list=list(lrc_dict.keys())time_list.sort()lrc_dict["time"]=time_listprint("get_lrc")file.close()except:lrc_dict = {}
now_word=0
def get_word():global lrc_dict,now_wordif lrc_dict and music.get_busy():for i in range(len(lrc_dict["time"])):if lrc_dict["time"][i]<=get_real_time()*music.speed\and ((len(lrc_dict["time"])==lrc_dict["time"].index(lrc_dict["time"][i])+1\or (len(lrc_dict["time"])>lrc_dict["time"].index(lrc_dict["time"][i])+1 \and lrc_dict["time"][i+1]>get_real_time()*music.speed))):now_word=lrc_dict["time"][i]word=[]word.append(lrc_dict[now_word])if len(lrc_dict["time"])>=lrc_dict["time"].index(lrc_dict["time"][i])+2:word.append(lrc_dict[lrc_dict["time"][lrc_dict["time"].\index(now_word)+1]])return wordelif not lrc_dict:return ["暂无歌词"]else:return []def get_real_time():return music.get_play_time()
def my_mainloop():global list_music,flag_list_musicglobal now_wordword=get_word()if word:show1.get_word(lrc_word=word)event1 = music.end_event()if get_event2():    #如果歌曲播放异常list_music.pop(0)print("list="+str(list_music))event1 = 1if event1:          #当歌曲结束时,event1事件触发print("over")flag_list_music=1       #载入新歌歌词if len(list_music):     #如果还有歌show1.set_time=0way=show1.play_way.get()#获取设定的播放方式if way==2:      #列表播放list_music.pop(0)elif way==1:    #单曲循环print("单曲循环中")elif way==3:    #列表循环list_music.append(list_music.pop(0))elif way==4:    #随机播放random.shuffle(list_music)else:assert False,"播放方式出错"print("pop")if len(list_music):if way==1:music.replay()else:#music.play(list_music[0])play_song(list_music[0])else:print("歌单空了")if flag_list_music:         #如果需要读入歌单now_word=0get_lrc_geci()          #获得歌词list_music_change=copy.deepcopy(list_music)#深拷贝path=""for j in range(len(list_music_change)): #得到歌曲名称f=list_music_change[j]x=-1for i in range(len(f)):if f[i]=="/":x=iif x>=0:path=list_music_change[j][:x+1]list_music_change[j]=list_music_change[j][x+1:]show1.get_music_list(path=path,list_music=list_music_change)flag_list_music=0if get_real_time()>=0:if ((get_real_time()!=show1.music_time_scale.get()))and \not show1.mouse_left_click1:#print("set_time2")show1.set_length_and_now_time(now_time=get_real_time())show1.music_time_scale.set(get_real_time())show1.win.after(100,my_mainloop)
def main():global show1global musicmusic=all_music.all_music()show1=show.show()show1.get_music(music=music,\openfile=openfile,openpath=openpath,\next_music=next_music,stop=stop)show1.win.after(100,my_mainloop)'''#The other computer settry:openpath(True)#载入默认目录show1.pause()except:pass'''show.mainloop()try:music.stop()except:passtry:wait_times = 0while(not music.end_event()):all_music.time.sleep(0.5)music.play_flag = music.flag_enum[3]wait_times += 1if (wait_times > 120):breakexcept:pass
if __name__ == '__main__':sys.stdout = open(os.devnull, "w")if('Windows'==platform.system()):multiprocessing.freeze_support()  main()

all_music3.py

from pydub import AudioSegment
import pyaudio
#import multiprocessing
from threading import Thread
import time
#import psutil
import copy
import platform
class all_music():def __init__(self):self.volume=100self.song_path = []self.song = []                    #绝对self.song1 = []   self.process1 = []self.suffix = []self.now_time = -1        #当前播放歌曲的时长self.pos_time_set = -1  #歌曲点击播放的位置self.plat_form = platform.system()self.length = -1self.now_state = 1self.len_frame = 0self.busy = 0         #0:空闲;1:播放中;2:暂停中;3:暂停准备继续播放self.flag_end = 0self.speed = 1self.volume_limit = 20self.flag_enum=[0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0111]self.play_flag=self.flag_enum[0]def end_event(self):if self.flag_end == 0:return self.flag_endelse:self.flag_end = 0return 1def get_busy(self):             #查看是否忙碌     return self.busydef get_length(self):           #得到歌曲长度return self.lengthdef pos_set(self,time):         #设置歌曲播放位置self.pos_time_set = int(time / self.length * self.len_frame)self.play_flag = self.flag_enum[2]def get_play_time(self):        #获得当前歌曲播放到的位置if self.len_frame == 0:return 0else:return int(self.length * self.now_time / self.len_frame)def set_speed(self,speed):self.speed=speedself.play_flag = self.flag_enum[5]def set_volume(self,volume):self.volume=volumeself.play_flag = self.flag_enum[6]def get_volume(self):return self.volume    def replay(self):if self.busy:   #判断歌曲是否在播放或者暂停状态self.play_flag = self.flag_enum[4]self.busy=1else:assert False,"歌曲未载入或占用中,请先load或stop"def play_song(self):self.now_state = 0print("play_song")print(self.song_path)p = pyaudio.PyAudio()if self.volume == 0:self.song1 = self.song - 255else:self.song1 = self.song - self.volume_limit * ( 1.0 - self.volume / 100 )# 读取音频帧并进行播放if "Windows" == self.plat_form:#其实windows也可以用下面的raw方式播放,这一段其实有没有都行index = 0stream = p.open(format = p.get_format_from_width(self.song1.sample_width),channels = self.song1.channels,rate = int(self.song1.frame_rate*self.speed),output = True)self.len_frame = int(self.song1.frame_count())while(index <= self.len_frame):stream.write(self.song1.get_frame(index))self.now_time = indexif(self.play_flag >0):print(2)if self.play_flag == self.flag_enum[1]:#暂停print(3)while(1):time.sleep(0.5)if self.play_flag != self.flag_enum[1]:breakif self.play_flag == self.flag_enum[2]:#点击播放print(4)index = self.pos_time_setself.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[3]:#终止播放print(5)index = self.len_frameself.play_flag = self.flag_enum[0]breakif self.play_flag == self.flag_enum[4]:#重新播放print(6)index = 0self.now_time = 0self.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[5]:#速度变化print(7)#stream.stop_stream()#stream.close()stream = p.open(format = p.get_format_from_width(self.song1.sample_width),channels = self.song1.channels,rate = int(self.song1.frame_rate*self.speed),output = True)self.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[6]:#音量变化print(8)if self.volume == 0:self.song1 = self.song - 255else:self.song1 = self.song - self.volume_limit * ( 1.0 - self.volume / 100 )self.play_flag = self.flag_enum[0]index += 1else:#对于某些系统,如ubuntu,似乎只能用raw方式播放frames_per_buffer = 1024stream = p.open(format = p.get_format_from_width(self.song1.sample_width),channels = self.song1.channels,rate = int(self.song1.frame_rate*self.speed),output = True,frames_per_buffer = frames_per_buffer)self.len_frame = int(len(self.song1.raw_data))per_index = 0index = frames_per_bufferwhile(index <= self.len_frame):stream.write(self.song1.raw_data[per_index:index])self.now_time = indexper_index = indexif(self.play_flag >0):print(2)if self.play_flag == self.flag_enum[1]:#暂停print(3)while(1):time.sleep(0.5)if self.play_flag != self.flag_enum[1]:breakif self.play_flag == self.flag_enum[2]:#点击播放print(4)index = self.pos_time_setif index % 2 :index -= 1per_index = index - frames_per_bufferif per_index < 0:per_index = 0index = frames_per_bufferself.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[3]:#终止播放print(5)index = self.len_frameself.play_flag = self.flag_enum[0]breakif self.play_flag == self.flag_enum[4]:#重新播放print(6)index = frames_per_bufferper_index = 0self.now_time = 0self.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[5]:#速度变化print(7)#stream.stop_stream()#stream.close()stream = p.open(format = p.get_format_from_width(self.song1.sample_width),channels = self.song1.channels,rate = int(self.song1.frame_rate*self.speed),output = True,frames_per_buffer = frames_per_buffer)self.play_flag = self.flag_enum[0]if self.play_flag == self.flag_enum[6]:#音量变化print(8)if self.volume == 0:self.song1 = self.song - 255else:self.song1 = self.song - self.volume_limit * ( 1.0 - self.volume / 100 )self.play_flag = self.flag_enum[0]index += frames_per_bufferif self.len_frame > index:stream = p.open(format = p.get_format_from_width(self.song1.sample_width),channels = self.song1.channels,rate = int(self.song1.frame_rate*self.speed),output = True,frames_per_buffer = self.len_frame - index)stream.write(self.song1.raw_data[index:])print(9)print(index)print(self.len_frame)self.busy = 0# 停止数据流stream.stop_stream()stream.close()# 关闭 PyAudiop.terminate()self.flag_end = 1while(0 != self.flag_end):time.sleep(1)self.now_state = 1def play(self, file_path):                 #播放歌曲#判断歌曲是否在播放或者暂停状态if ( self.busy == 0 ):if file_path:   #判断路径是否为空self.song_path = file_path    #将歌曲路径给到selffor i in range(len(self.song_path)-1,-1,-1):    #寻找文件后缀if self.song_path[i] == ".":breakif self.song_path[i]==".":                      #将歌曲后缀给到selfself.suffix=self.song_path[i+1:]else:assert False,"未发现文件后缀"else:assert False,"load(file_path)需要一个歌曲路径"if self.suffix:#是否有下标if self.suffix=="mp3":      #导入mp3歌曲try:self.song = AudioSegment.from_mp3(self.song_path)except:assert False,"不支持的文件或不存在此文件:"+self.song_pathelif self.suffix=="ogg":    #导入ogg歌曲try:self.song = AudioSegment.from_ogg(self.song_path)except:assert False,"不支持的文件或不存在此文件:"+self.song_pathelif self.suffix=="flv":    #导入flv歌曲try:self.song = AudioSegment.from_flv(self.song_path)except:assert False,"不支持的文件或不存在此文件:"+self.song_pathelif self.suffix=="wav":    #导入wav歌曲try:self.song = AudioSegment.from_wav(self.song_path)except:assert False,"不支持的文件或不存在此文件:"+self.song_path else:                       #导入其他支持的格式的歌曲try:self.song = AudioSegment.from_file(self.song_path,self.suffix)except:assert False,"不支持的文件或不存在此文件:"+self.song_pathself.song1=copy.deepcopy(self.song)self.busy = 1self.length=len(self.song1)   #设置歌曲时长self.process1 = Thread(target =self.play_song,name="my_process1")self.process1.start()else:assert False,"未载入任何歌曲"else:assert False,"歌曲未载入或占用中,请先load或stop"def stop(self):     if self.busy:   #判断歌曲是否在播放或者暂停状态self.play_flag = self.flag_enum[3]self.process1 = []self.now_time = 0self.pos_time_set = 0self.length = 0else:assert False,"歌曲不在播放或暂停状态"def pause(self):    #暂停播放if 1 == self.busy:   #判断歌曲是否在播放状态self.play_flag = self.flag_enum[1]self.busy = 2else:assert False,"无歌曲正在播放"def unpause(self):  #继续暂停的播放if 2 == self.busy:   #判断歌曲是否在播放状态self.busy=3self.play_flag = self.flag_enum[0]self.busy = 1else:assert False,"歌曲不在暂停状态"

show3.py

from tkinter import *
from PIL import Image
import tkinter.font as tkFont
from tkinter import ttk
import platform
def color(color_255):color_16=0x0color_16=color_16+0x10000*(color_255[0])color_16=color_16+0x100*(color_255[1])color_16=color_16+0x1*(color_255[2])if color_16>0xFFFFF:return '#%0x'%color_16elif color_16>0xFFFF:return '#0%0x'%color_16elif color_16>0xFFF:return '#00%0x'%color_16elif color_16>0xFF:return '#000%0x'%color_16elif color_16>0xF:return '#0000%0x'%color_16else:return '#00000%0x'%color_16
openfiles=[]
openpaths=[]
next_musics=[]
stop=[]
typeface=u"华文行楷"if(platform.system()=='Windows'):size_word_win='1000x80'
elif(platform.system()=='Linux'):size_word_win='1000x100'
else:assert False,'暂未支持Windows和Linux之外的系统'class show():def __init__(self): #主窗口#anchor must be n, ne, e, se, s, sw, w, nw, or centerself.mouse_left_click1=0#鼠标左键点击时间轴状态self.mouse_left_click2=0#鼠标左键点击音量状态self.set_time=0self.flag_replay=0self.win = Tk()self.volume_limit = 120ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.win.title(u"我的音乐")try:self.win.iconbitmap('My_Music_tk.ico') # 更改窗口图标except:passself.win.bind("<Key>",self.key_event)self.screenwidth=self.win.winfo_screenwidth()self.screenheight=self.win.winfo_screenheight()self.win.resizable(width=False,height=False)#False表示不可以缩放,True表示可以缩放try:self.win.iconphoto(True, PhotoImage(file='/home/xiaobai/Desktop/my_music/My_Music_tk.png'))except:passself.frame= Frame (self.win, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,heigh=600,width=1280,cursor='arrow')self.frame.pack(side=TOP, fill=BOTH, ipadx=0, ipady=0, expand=1)#音乐列表frameself.frame2= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame2.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)self.frame21= Frame (self.frame2,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame21.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=1)self.frame22= Frame (self.frame2,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame22.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)#按钮frameself.frame1= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame1.pack(side=TOP,fill=X,ipadx=0,ipady=0,expand=1)#歌词frameself.frame3= Frame (self.frame, relief=RAISED, bg=color([135,206,250]),\borderwidth=2,cursor='arrow')self.frame3.pack(side=BOTTOM,fill=X,ipadx=0,ipady=0,expand=0)#按钮ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"暂停",command =self.pause)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"播放",command =self.play)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"重新播放",command =self.replay)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([135,206,250])\,activebackground="white",\text=u"下一首",command =self.next_music)\.pack (side=LEFT, padx=13, pady=13)self.frame11= Frame (self.frame1,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame11.pack(side=LEFT,fill=Y,ipadx=20,ipady=0,expand=0)Button (self.frame1,font=ft,bg=color([59,210,61])\,activebackground="white",\text=u"清空",command =self.stop)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([242,203,46])\,activebackground="white",\text=u"文件夹",command =self.openpath)\.pack (side=LEFT, padx=13, pady=13)Button (self.frame1,font=ft,bg=color([242,169,0])\,activebackground="white",\text=u"文件",command =self.openfile)\.pack (side=LEFT, padx=13, pady=13)#一些文本显示#显示“播放列表”文本ft = tkFont.Font(family=typeface, size=20, weight=tkFont.BOLD)self.frame221= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame221.pack(side=LEFT)Label(self.frame221,font=ft,\text=u"播",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"放",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"列",bg=color([135,206,250])).pack(anchor='w')Label(self.frame221,font=ft,\text=u"表",bg=color([135,206,250])).pack(anchor='w')#显示“倍速”文本ft = tkFont.Font(family=typeface, size=10, weight=tkFont.BOLD)self.frame222= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame222.pack(anchor='w')Label_b=Label(self.frame222,font=ft,\text=u"   倍速",bg=color([135,206,250]))Label_b.pack(side=LEFT)#倍速设置self.set_comvalue=StringVar()#窗体自带的文本,新建一个值self.set_templist=ttk.Combobox(self.frame222,font=ft,\textvariable=self.set_comvalue,\state='readonly',\width=3) #初始化    self.set_templist["values"]=("0.8","0.9","1","1.2","1.4")self.set_templist.current(2) #选择第一个self.set_templist['state'] = 'readonly'#只读self.set_templist.bind("<<ComboboxSelected>>",self.music_speed) #绑定事件,(下拉列表框被选中时,绑定go()函数)self.set_templist.pack(side=LEFT,padx=10)#列表#音乐列表self.frame224= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame224.pack(side="left")self.list_music1_sb = Scrollbar(self.frame224)self.list_music1_sb.pack(side="right", fill="y")ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.list_music1=Listbox(self.frame224,bg=color([255,255,255]),\cursor='plus',font=ft,\fg=color([0,0,0]),height=5,width=40,\yscrollcommand= self.list_music1_sb.set)self.list_music1.pack(side="left", fill="both")self.list_music1_sb.config(command=self.list_music1.yview)ft = tkFont.Font(family=typeface, size=10, weight=tkFont.BOLD)self.list_music1_num_text = IntVar()self.list_music1_num_text.set(0)Label_c=Label(self.frame222,font=ft,\text=u"歌曲总数:",bg=color([135,206,250]))\.pack(side=LEFT)Label(self.frame222,font=ft,textvariable=self.list_music1_num_text,\bg=color([135,206,250])).pack(side=LEFT)ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)#播放模式设置self.frame222= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame222.pack(side=LEFT)WAY_SET = [("单曲循环", 1),("列表播放", 2),("列表循环", 3),("随机播放", 4)]self.play_way = IntVar()self.play_way.set(2)for way, num in WAY_SET:Radiobutton(self.frame222, text=way, variable=self.play_way,\indicatoron=False, value=num,\font=ft,bg=color([135,206,250]),\activebackground=color([255,192,203]),\cursor='circle',selectcolor=color([192,192,192]),\).pack(anchor="w")#音量self.frame223= Frame (self.frame22,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame223.pack(side=LEFT,padx=5)Label_c=Label(self.frame223,font=ft,\text=u"音量",bg=color([135,206,250]))Label_c.pack(anchor="w")self.volume_text = IntVar()self.volume_text.set(100)self.music_volume=Scale(self.frame223,from_=100, to=0, \length=100, \orient="vertical",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False,variable=self.volume_text)self.music_volume.pack(after=Label_c,padx=10)if(platform.system()=='Windows'):self.music_volume.bind("<MouseWheel>",self.mouse_middle_motion_volume)elif(platform.system()=='Linux'):self.music_volume.bind("<Button-4>",self.mouse_middle_motion_volume)self.music_volume.bind("<Button-5>",self.mouse_middle_motion_volume)else:assert False,'暂未支持Windows和Linux之外的系统'self.music_volume.bind("<Button-1>",self.mouse_left_click_volume)self.music_volume.bind("<ButtonRelease-1>",self.mouse_left_release_volume)Label(self.frame223,font=ft,textvariable=self.volume_text,\bg=color([135,206,250])).pack(after=self.music_volume)#当前时间self.now_time_text = StringVar()self.now_time_text.set("0"+":"+"00")ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD)Label(self.frame21,font=ft,textvariable=self.now_time_text,\bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5)#歌曲进度self.music_time_scale_length=600ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.frame211= Frame (self.frame21,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame211.pack(side=LEFT)self.music_time_scale=Scale(self.frame211,from_=0, to=180000, \length=self.music_time_scale_length, cursor="circle",\orient="horizontal",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False)self.music_time_scale.pack(side=LEFT,padx=5, pady=0)self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun)self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun)#总时间self.length_text = StringVar()self.length_text.set("0"+":"+"00")ft = tkFont.Font(family=u"微软雅黑", size=10, weight=tkFont.BOLD)Label(self.frame21,font=ft,textvariable=self.length_text,\bg=color([135,206,250])).pack(side=LEFT, padx=0, pady=5)#歌词'''self.lrc_word_length=40ft = tkFont.Font(family=u"宋体", size=25, weight=tkFont.BOLD)self.lrc_word=Listbox(self.frame3,bg=color([255,255,255]),\cursor='plus',font=ft,\fg=color([0,0,0]),height=2,width=self.lrc_word_length)self.lrc_word.pack(side=BOTTOM,fill=Y,ipadx=0,ipady=0,expand=0)'''ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.son_win=Toplevel(master=self.win)      #子窗口self.son_win.title("我的歌词")self.son_win.geometry(size_word_win+'+'+str(self.screenwidth//2-500)+'+'+str(self.screenheight-120))     #大小和位置self.son_win.wm_attributes('-topmost',1)    #置顶self.son_win.overrideredirect(boolean=True)#去掉边框和按钮if platform.system()=='Linux':self.son_win.wait_visibility(self.son_win)self.son_win.attributes('-alpha',0.9)       #整体透明#self.son_win.attributes("-transparentcolor","white")#此处将white颜色设置为透明,可以替换不同的颜色。#self.son_win.attributes("-transparentcolor",color([135,206,250]))#此处将white颜色设置为透明,可以替换不同的颜色。self.son_win.bind("<B1-Motion>", self.move)self.son_win.bind("<Button-1>", self.get_point)#self.son_win.attributes("-toolwindow", True)#实现menu点击虚线(tearoff)后的窗口效果#protocol(name=None, func=None)#指定窗口关闭时调用的函数'''--将回调函数func与相应的规则name绑定--name参数可以是“WM_DELETE_WINDOW”:窗口被关闭的时候--name参数可以是“WM_SAVE_YOURSELF”:窗口被保存的时候--name参数可以是“WM_TAKE_FOCUS”:窗口获得焦点的时候'''#withdraw()#将窗口从屏幕上移除(并没有销毁)'''--需要重新显示窗口,使用deiconify()方法--该方法会使得state()返回"withdraw"'''self.frame_son_win= Frame (self.son_win,relief=RAISED, \bg=color([135,206,250]),\borderwidth=0)self.frame_son_win.pack(fill=BOTH,expand=1)self.lrc_word_length=40ft = tkFont.Font(family=typeface, size=20, weight=tkFont.BOLD)self.lrc_word=Text(self.frame_son_win,font=ft,\relief='flat',width=self.lrc_word_length,\bg=color([135,206,250]),height=2)self.lrc_word.tag_config("tag_1", backgroun="yellow", foreground="red")self.lrc_word.pack()self.lrc_word.config(state=DISABLED)self.word_win_state = IntVar()self.word_win_state_button=Checkbutton(self.frame1,font=ft,bg=color([135,206,250]),\text=u"词",variable=self.word_win_state,\command=self.show_or_hide_word,indicatoron=False,\activebackground=color([255,192,203]),\selectcolor=color([192,192,192]))self.word_win_state_button.pack (side=LEFT, padx=13, pady=13)self.word_win_state_button.select()def key_event(self,event):key=event.keysymif key=='space':if self.music.get_busy()==1:self.pause()elif self.music.get_busy()==2:self.play()elif key=='Up':self.mouse_middle_motion_volume([],1)elif key=='Down':self.mouse_middle_motion_volume([],-1)def show_or_hide_word(self):if self.word_win_state.get():self.son_win.deiconify()else:self.son_win.withdraw()#print(self.word_win_state.get())def get_point(self, event):"""获取当前窗口位置并保存"""self.x, self.y = event.x, event.ydef move(self, event):"""窗口移动事件"""new_x = (event.x - self.x) + self.son_win.winfo_x()new_y = (event.y - self.y) + self.son_win.winfo_y()s = size_word_win+f"+{new_x}+{new_y}"     self.son_win.geometry(s)def mouse_middle_motion_volume(self,event,key=None):if('Windows'==platform.system()):x=120if key==None:flag = event.delta//xelif('Linux'==platform.system()):x=4if key==None:if(event.num==x):flag=1elif event.num==x+1:flag=-1else:assert False,'Linux下事件错误'else:assert False,'暂未支持Windows和Linux之外的系统'if key!=None:if key==1:flag=1elif key==-1:flag=-1else:assert False,'key输入错误'if flag>0:print("get_volume="+str(self.music.get_volume())+"dB")if self.music.get_volume() < self.volume_limit:if 100 == self.music_volume.get():volume=self.music.get_volume()+10*flagself.volume_text.set(volume)else:volume = self.music_volume.get() + 10 * flagself.music_volume.set(volume)self.volume_text.set(volume)if volume > self.volume_limit:      #防止win系统flag轰炸volume = self.volume_limitself.music.set_volume(volume)self.win.update()       #强制刷新else:if self.music.get_volume()!=0:if 100<self.music.get_volume():volume=self.music.get_volume()+10*flagself.volume_text.set(volume)else:volume=self.music_volume.get()+10*flagif volume<0:volume=0self.music_volume.set(volume)self.volume_text.set(volume)self.music.set_volume(volume)self.win.update()       #强制刷新def mouse_left_click_volume(self,event):state=self.music_volume.identify(event.x,event.y)if state!='slider':volume=100-event.y#self.music.set_volume(volume)self.music_volume.set(volume)self.volume_text.set(volume)self.win.update()       #强制刷新self.mouse_left_click2 = 1print("mouse_set_volume")else:self.mouse_left_click2=1print("slide_scale")def mouse_left_release_volume(self,event):if self.mouse_left_click2==1:volume=self.music_volume.get()self.volume_text.set(volume)self.music_volume.set(volume)self.music.set_volume(volume)self.set_time=self.music.get_play_time()self.win.update()       #强制刷新print("slide_scale_set_volume")self.mouse_left_click2=0def music_speed(self,*args):speed=float(self.set_templist.get())self.set_time=self.music.get_play_time()self.music.set_speed(speed) self.win.update()       #强制刷新def set_length_and_now_time(self,now_time,music_length=None):if music_length!=None:#self.length_text.set(str(int(music_length*self.music.speed//(1000*60))).zfill(1)\#                     +":"+str(int(music_length*self.music.speed//1000%60)).zfill(2))self.length_text.set(str(int(music_length//(1000*60))).zfill(1)\+":"+str(int(music_length//1000%60)).zfill(2))#time=int(now_time*self.music.speed)time=int(now_time)self.now_time_text.set(str(time//(1000*60)).zfill(1)\+":"+str(time//1000%60).zfill(2))def mouse_left_click_fun(self,event):state=self.music_time_scale.identify(event.x,event.y)if state!='slider':self.set_time=int(event.x/self.music_time_scale_length*self.music.get_length())self.music_time_scale.set(self.set_time)self.win.update()       #强制刷新#self.music.stop()self.music.pos_set(self.set_time)self.mouse_left_click1=2print("mouse_set_time")else:self.mouse_left_click1=1print("slide_scale")#print(f"鼠标左键点击了一次坐标是:x={event.x},y={event.y}")def mouse_left_release_fun(self,event):if self.mouse_left_click1==1:if event.x<0:event_x=0elif event.x>self.music_time_scale_length:event_x=self.music_time_scale_lengthelse:event_x=event.xself.set_time=int(event_x/self.music_time_scale_length*self.music.get_length())self.music_time_scale.set(self.set_time)self.win.update()       #强制刷新#self.music.stop()self.music.pos_set(self.set_time)print("slide_scale_set_time")self.mouse_left_click1=0#print(f"鼠标左键释放坐标是:x={event.x},y={event.y}")def get_music(self,music,openfile,openpath,next_music,stop):self.music=musicglobal openfilesopenfiles=openfileglobal openpathsopenpaths=openpathglobal next_musicsnext_musics=next_musicglobal stop1stop1=stopdef get_music_list(self,path,list_music):self.list_music1.delete(0,"end")for item in list_music:self.list_music1.insert("end", item)self.music_time_scale.pack_forget()if path:ft = tkFont.Font(family=typeface, size=15, weight=tkFont.BOLD)self.music_time_scale=Scale(self.frame211,from_=0, \to=self.music.get_length(), \length=self.music_time_scale_length, cursor="circle",\orient="horizontal",\activebackground=color([128,128,128]),\bg=color([200,200,200]),font=ft,\bd=0,sliderrelief="ridge",sliderlength=20,\showvalue=False)self.music_time_scale.pack(side=LEFT,padx=5, pady=0)self.music_time_scale.bind("<Button-1>",self.mouse_left_click_fun)self.music_time_scale.bind("<ButtonRelease-1>",self.mouse_left_release_fun)self.set_length_and_now_time(now_time=self.set_time,music_length=self.music.get_length())def get_word(self,lrc_word):self.lrc_word.config(state=NORMAL)try:self.lrc_word.delete(1.0,"end")except:passlength=0length1=0if len(lrc_word)==1 or lrc_word[1]=='':for ch in lrc_word[0]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1length=int(length)else:for i in range(len(lrc_word)):if i:length1=round(length/2)length=length1for ch in lrc_word[i]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1else:for ch in lrc_word[i]:if u'\u4e00'<=ch<=u'\u9fff':length=length+2.8else:length=length+1length=int(length)if self.lrc_word_length!=length:self.lrc_word.pack_forget()self.lrc_word_length=int(length)ft = tkFont.Font(family=typeface, size=25, weight=tkFont.BOLD)self.lrc_word=Text(self.frame_son_win,font=ft,\relief='flat',width=self.lrc_word_length,\bg=color([135,206,250]),height=2)self.lrc_word.pack()self.lrc_word.tag_config("tag_1", backgroun="yellow", foreground="red")for i in range(len(lrc_word)):if i:self.lrc_word.insert("end", " "*length1+lrc_word[i])else:self.lrc_word.insert("end", lrc_word[i],"tag_1")self.lrc_word.insert("end", '\n')self.lrc_word.config(state=DISABLED)def pause(self):self.music.pause()print("pause")def stop(self):self.set_time=0stop1()print("stop")def play(self):self.music.unpause()print("play")def replay(self):self.set_time=0self.music_time_scale.set(0)#self.music.stop()self.music.replay()print("replay")def openfile(self):self.set_time=0openfiles()print("openfile")def set_times(self):time=self.music_time_scale.get()print(time)self.set_time=time#self.music.stop()self.music.pos_set(time)print("set_time")def openpath(self):self.set_time=0openpaths()print("openpath")def next_music(self):self.set_time=0next_musics()print("next_music")
#show1=show()
#mainloop()

就先到这吧,想到什么再写,有什么问题欢迎留言。

学习笔记:在WIN11及UBUNTU平台下的基于Tkinter、pydub、pyaudio的音乐播放器相关推荐

  1. Linux下基于Libmad库的MP3音乐播放器编写

    linux下基于Libmad库的MP3音乐播放器编写 libmad是一个开源mp3解码库,其对mp3解码算法做了很多优化,性能较好,很多播放器如mplayer.xmms等都是使用这个开源库进行解码的: ...

  2. linux下的网络音乐播放器,Linux_Songbird离开后 Linux下可以替代它的10个音乐播放器推荐,正如我们早先提到的一样, Son - phpStudy...

    Songbird离开后 Linux下可以替代它的10个音乐播放器推荐 正如我们早先提到的一样, Songbird 已经离开了Linux羊群而开源的牧草地将变得更加翠绿.但是,Linux将用什么来取代这 ...

  3. Linux用命令安装音乐软件,在Ubuntu 18.04系统中使用命令安装Qmmp音乐播放器的方法...

    在Ubuntu 18.04操作系统中安装Qmmp音乐播放器非常简单,只需要两段命令就可以搞定.下面介绍其方法. Qmmp音乐播放器介绍 Qmmp是一款开源基于Qt的多媒体播放器,提供Qt4及Qt5支持 ...

  4. alin的学习之路:嵌入式课程设计总结(基于Linux的Qt版MP3播放器)

    嵌入式课程设计总结(基于Linux的Qt版MP3播放器) 废话不多写直接上图上代码,其中有很多不规范的地方,希望大佬们指正. 1.课设题目 设计一个MP3播放器,要求:使用Linux下的madplay ...

  5. inceptionV3(TensorFlow)+SVM+迁移学习 实现基于人脸表情识别的音乐播放器

    介绍 本项目使用深度神经网络对人面进行特征提取,再通过SVM进行表情分类,先判断出人表现出的表情,再通过隐马尔科夫模型,判断人的情绪状态,进而根据人物的情绪来播放相应的音乐,使使用者能获得更好的音乐享 ...

  6. 音乐播放器的设计与实现 功能要求:设计一款基于HTML5音频技术的音乐播放器,要求实现音乐的播放、暂停、音量大小调节、上一首和下一首切换,运行效果如图所示

    本地资源在谷歌浏览器上是无法快进的.这个是重点!!!有很多解决方法,我直接用火狐就ok了 https://www.gaitubao.com/# 改图宝链接 用于修改歌曲头像 大小标准显示才正常 我用的 ...

  7. Linux下使用mpg123实现简单的MP3音乐播放器(记录自己的学习路程)

    主要功能及实现: 1,播放,暂停及继续,上一曲下一曲和退出 2,实现顺序循环播放等功能 3,可根据不同格式(.mp3)导入歌曲 完整代码: #include <stdio.h> #incl ...

  8. 前端学习小demo:使用HTML+CSS+bootstrap+Vue2.0编写一个简易的音乐播放器(仿网易云)

    具体的操作流程(实现步骤): 1.歌曲搜索 2.歌曲播放 3.歌曲评论 4.播放歌曲的MV(有的歌曲没有MV) 代码编写过程: 1.创建一个Vue项目(前提是安装好了node.js.npm.vue) ...

  9. Ubuntu下安装Audacious音乐播放器详细配置方法(中文化,歌词显示等)

    Windows下有不少比较有名气的音乐播放器,例如千千静听,Kugou,foobar和QQ音乐等,但是ubuntu下的音乐播放器则没有这么丰富,但是现在则给大家介绍一款ubuntu下的"千千 ...

最新文章

  1. java case switch,Java中Switch Case的替代方案
  2. Java中 Character方法练习:字符串中英文字母个数 5435abc54abc3AHJ5 正则:matches([a-zA-Z0-9]{1})...
  3. 使用PowerDesigner生成Access数据库
  4. html提交表单原理,HTML表单、HTTP Get与Post杂谈
  5. CVPR2019接收结果公布了,但CVPR 2018的那些论文都怎么样了?
  6. Dragonboard 410c fastboot刷入android
  7. 2021 Chrome Devtools 新特性
  8. 针对《关于郝培强的《为什么我们招聘的时候绝不要传智播客的学生?》》的看法
  9. cmake2 配合1
  10. linux系统yum提示注册,Linux:redhat6.5使用yum时提示需要注册问题解决方案
  11. 网页前端:JavaScript编程
  12. 带你了解关系网络在反欺诈领域的常见应用
  13. 海思码率控制器各参数说明
  14. 如视技术副总裁杨永林:当传统产业遇到“数字空间”
  15. U盘启动盘制作(步骤详细)
  16. 万字HTTP学习笔记
  17. 汇率兑换程序python按温度转换_python复习+实例编写(1)——温度转换、汇率转换...
  18. SQL千万级大数据量查询优化
  19. mysql数据库读写文件
  20. 一些通用 编程变量 单词(常用变量名;持续更新...)

热门文章

  1. Win10创建原始套接字失败原因及解决方法
  2. 快速搭建自己的微信小程序商城【免费(无需积分/C币)】
  3. ajax接口500错误,djangoajax请求返回500个内部服务器错误
  4. 原来不一样的2007是这样的不一样!
  5. 第三篇 KinectV2骨骼获取原理和获取方法及源代码
  6. 2018中国互联网安全大会9月举行!
  7. PON无源光网络的接入技术-EPON和GPON特点
  8. Beehive UVALive - 7528 (找规律+数学思维)
  9. 用idea学习HTML
  10. java中的线程同步机制讲解