编写一个歌词随音乐播放滚动的播放器

提问:你平常都是如何听歌和下载歌曲的?官网?软件?

简介:作为计算机的爱好者,对计算的使用已经是非常熟悉了解的了,当然对编程语言也是有些许了解。听周围人说,无法听取某些歌曲或下载某些歌曲,身为脚本小子的我,分析了对应网页,编写了一个音乐播放器,并且歌曲对应的歌词也会随音乐的播放进行滚动。

一、导入需要的库

        工欲善其事必先利其器,在开始编写时,先分析好大概的结构和所需的功能,导入对应的第三方库。

import tkinter as tk      GUI 界面搭建
import time               计时
import requests            网页请求库
import urllib.parse as parse      格式化字符编码
import json              json数据分析
import os                系统库
from pygame import mixer    #音乐播放
from mutagen.mp3 import MP3  # 用来的到一个.mp3文件的时长

        二、构建GUI界面

        这里使用的是tkinter来创建界面,这个库,搭建界面简单便捷,小巧,并且容易打包

 tk.Tk()    创建一个主窗口

title        标题 

geometry("长x宽")                设置窗口的长宽

geometry("长x宽+x轴位置+y轴位置")          设置窗口的长宽以及在窗口的显示位置

font             字体     字号

grid            布局     行   列

StringVar()           字符串变量类型

command                调用函数

mainloop()                显示窗口

root = tk.Tk()
root.title("######音乐播放器")
root.geometry("800x400")

input_lable = tk.Label(root,text="请输入歌名或作者:",font=('楷体',12))
input_lable.grid(row=1,column=0)

input_en = tk.StringVar()
input_entry = tk.Entry(root,textvariable=input_en,font=("楷体",12))
input_entry.grid(row=1,column=1)


index_input = tk.Button(root,text="搜索",command=select_1)
index_input.grid(row=1,column=2)


#歌曲列表
list_box = tk.Listbox(root,font=('楷体',12),width=43,height=21)
list_box.grid(row=2,column=0,columnspan=3,rowspan=5)


#歌词
text = tk.Text(root,width=63,height=20)
text.grid(row=2,column=3,rowspan=3,columnspan=5)

b_buttom = tk.Button(root,text="播放",command=select_2)
b_buttom.grid(row=5,column=3)


tk.mainloop()

二、歌曲id和歌曲名下载

with open(f'{zuoze}.mp3', 'wb') as f:    

with open('文件名和后缀','读取或写入方式')  as 小名

打开的文件如果不存在,便会新建一个        WB   二进制写入

def M_musci(music_name):
    file = open("m1.txt", 'w').close()
    print(music_name)    #音乐名称
    keyword = parse.urlencode({'keyword': music_name})      #构建参数
    keyword = keyword[keyword.find('=') + 1:]      #去除建
    #请求头
    headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
    #拼接网址
    url = f"https://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={keyword}&type=1&offset=0&total=true&limit=20"
    #文本数据
    response = requests.get(url, headers=headers).json()
    json_list = response["result"]["songs"]
    for i in json_list:
        print(i)
        ID = i['id']
        name = i['name']
        str_zuozhe = i['artists']
        for j in str_zuozhe:
            str_zuozhe=j['name']

        with open("m1.txt",'a',encoding='utf-8') as f:
            f.write(str_zuozhe+'\t'+name+'\t'+str(ID)+'\n')

三、文件处理函数

read    读取文件

split()      去除尾部不需要的字符

def Information_from_file():     #文件处理函数
    with open('m1.txt','r',encoding='utf-8') as f:    #读取保存的歌曲文件
        str_1=f.read()    #读取
        # print(str_1)
    list_1=str_1.split('\n')[:-1]     #去除换行符    取0到末尾
    print(list_1)
    song_names=[];song_name=[];song_id=[]     #三个列表变量     歌曲名    歌曲哈希值   歌曲ID
    for str_2 in list_1:    #遍历读取的字符
        str_2=str_2.split('\t')    #去除格式符
        print(str_2)

        song_names.append(str_2[0])    #作者
        song_name.append(str_2[1])     #名称
        song_id.append(str_2[2])       #歌曲ID

    return song_names,song_name,song_id     #返回这三个列表

四、歌曲下载函数

append        数据添加进列表

writer          文件写入

time.time()     获取当前时间

def Downlad(zuoze,music_id):     #音乐的下载传递两个参数     音乐哈希值    音乐ID
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
    # 发送请求

    url = f'https://music.163.com/api/song/lyric?id={music_id}&lv=1&kv=1&tv=-1'
    response = requests.get(url, headers=headers).json()
    # print(response['lrc'])
    list = response['lrc']['lyric']
    list_1 = list.split('\n')[:-1]
    print(list_1)
    song_list = []
    time_list = []
    for str_1 in list_1:
        # 歌曲时间
        str_2 = str_1[:str_1.find(']') + 1]
        time_list.append(str_2)

        str_1 = str_1[str_1.find(']') + 1:]
        song_list.append(str_1)
    print(song_list)
    print(time_list)

    time_list = Get_Time(time_list)  # 时间列表
    new_url = f"http://music.163.com/song/media/outer/url?id={music_id}.mp3"
    response = requests.get(new_url, headers=headers).content
    with open(f'{zuoze}.mp3', 'wb') as f:
        f.write(response)
    start_time = time.time()
    audio = MP3(f'{zuoze}.mp3')
    untime = time.time()
    time_music = audio.info.length
    mixer.init()
    mixer.music.load(f'{zuoze}.mp3')
    mixer.music.play()
    mixer.stop()
    return True, time_list, song_list, time_music

五、歌曲搜索函数

delete(从0位开始,结尾结束)

get()      获取输入的值

insert(开始位置,插入的字符串)

def select_1():   #选择
    list_box.delete(0,tk.END)
    M_musci(input_en.get())    #输入的值

    list_1=Information_from_file()[1]    #歌曲名
    for i in range(len(list_1)):   #遍历歌曲名
        list_box.insert(tk.END,str(list_1[i]))    #显示歌曲名

六、播放函数

update      数据更新

def select_2():
    dict_id={}
    dict_name={}    #定义两个变量
    text.delete(0.0,tk.END)
    list_1=Information_from_file()[0] # 作者
    list_2=Information_from_file()[1]  # 名称
    list_3=Information_from_file()[2]  # id
    for i in range(len(list_2)):  #遍历歌曲名
        print(list_2[i])
        dict_id[list_2[i]]=list_2[i]    #将哈希  传递给对应的音乐名   name:哈希值
        dict_name[list_2[i]]=list_3[i]  #将ID  传递给对应的name    name:ID
    print(dict_name,dict_id)
    name_1 = list_box.get(tk.ACTIVE)
    zuoze = dict_id[name_1]  # 获取对应的音乐ID
    print(zuoze)
    id1 = dict_name[name_1]  # 获取对应的音乐哈希值
    bool_1=Downlad(zuoze,id1)
    # 显示一个进度条
    for i in range(1, 101):
        tk.Label(root, text='{}%|{}'.format(i, int(i / 4 % 26) * '■')).grid(row=5, columnspan=2, column=6, sticky=tk.W)
        root.update()  # 更新
    time_list = bool_1[1]  # 时间列表
    song_list = bool_1[2]  # 歌曲列表
    music_time = bool_1[3]  # 音乐时间
    i = 0
    T = 0

    while True:
        # end_time = time.time()
        try:
            # time.sleep(((time_list[T]) - time_list[T])+1)
            text.insert('{}.0'.format(i + 1), (song_list[i] + '\n').center(56, ' '))  # 将第一行插入歌曲列表的第i个   居中显示
            text.update()
            # text.send(tk.END)
            text.see(tk.END)
            i += 1


            if T == 0:  # 真
                time.sleep(time_list[T])  # 暂停几秒
            elif T == len(time_list)-1:  #
                time.sleep(4)
            else:
                time.sleep(time_list[T+1] - time_list[T])

            T += 1

            root.update()

        except:
            break

七、音乐播放歌词时间函数

def Get_Time(time_list):
    for i in range(len(time_list)):   #遍历时间列表
        minute = time_list[i][1:3]    #分
        second = time_list[i][4:6]    #秒
        h_second = time_list[i][7:9]   #毫秒
        time_list[i] = int(minute) * 60 + int(second) + float('0.' + h_second)   #时间列表
    return time_list

八、全部源码

# -*- coding:utf-8 -*-
"""
File name : main.PY
Program IDE : PyCharm
Create file time: 2022/10/19 11:46
File Create By Author : 小梦
"""

import tkinter as tk

import tkinter as tk
import time
import requests
import urllib.parse as parse
import json
import os
from pygame import mixer    #音乐播放
from mutagen.mp3 import MP3  # 用来的到一个.mp3文件的时长
def M_musci(music_name):
    file = open("m1.txt", 'w').close()
    keyword = parse.urlencode({'keyword': music_name})      #构建参数
    keyword = keyword[keyword.find('=') + 1:]      #去除建

    headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}

    url = f"https://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={keyword}&type=1&offset=0&total=true&limit=20"

    response = requests.get(url, headers=headers).json()
    json_list = response["result"]["songs"]
    for i in json_list:
        ID = i['id']
        name = i['name']
        str_zuozhe = i['artists']
        for j in str_zuozhe:
            str_zuozhe=j['name']
        with open("m1.txt",'a',encoding='utf-8') as f:
            f.write(str_zuozhe+'\t'+name+'\t'+str(ID)+'\n')


num=0
id_1=True

def Get_Time(time_list):
    for i in range(len(time_list)):   #遍历时间列表
        minute = time_list[i][1:3]    #分
        second = time_list[i][4:6]    #秒
        h_second = time_list[i][7:9]   #毫秒
        time_list[i] = int(minute) * 60 + int(second) + float('0.' + h_second)   #时间列表
    return time_list


def Information_from_file():     #文件处理函数
    with open('m1.txt','r',encoding='utf-8') as f:    #读取保存的歌曲文件
        str_1=f.read()    #读取

    list_1=str_1.split('\n')[:-1]     #去除换行符    取0到末尾
    song_names=[];song_name=[];song_id=[]     #三个列表变量     歌曲名    歌曲哈希值   歌曲ID
    for str_2 in list_1:    #遍历读取的字符
        str_2=str_2.split('\t')    #去除格式符

        song_names.append(str_2[0])    #作者
        song_name.append(str_2[1])     #名称
        song_id.append(str_2[2])       #歌曲ID

    return song_names,song_name,song_id     #返回这三个列表


def Downlad(zuoze,music_id):     #音乐的下载传递两个参数     音乐哈希值    音乐ID
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}

    url = f'https://music.163.com/api/song/lyric?id={music_id}&lv=1&kv=1&tv=-1'
    response = requests.get(url, headers=headers).json()

    list = response['lrc']['lyric']
    list_1 = list.split('\n')[:-1]
    print(list_1)
    song_list = []
    time_list = []
    for str_1 in list_1:

        str_2 = str_1[:str_1.find(']') + 1]
        time_list.append(str_2)

        str_1 = str_1[str_1.find(']') + 1:]
        song_list.append(str_1)

    time_list = Get_Time(time_list)  # 时间列表
    new_url = f"http://music.163.com/song/media/outer/url?id={music_id}.mp3"
    response = requests.get(new_url, headers=headers).content
    with open(f'{zuoze}.mp3', 'wb') as f:
        f.write(response)
    start_time = time.time()
    audio = MP3(f'{zuoze}.mp3')
    untime = time.time()
    time_music = audio.info.length
    mixer.init()
    mixer.music.load(f'{zuoze}.mp3')
    mixer.music.play()
    mixer.stop()
    return True, time_list, song_list, time_music

def select_1():   #选择
    list_box.delete(0,tk.END)
    M_musci(input_en.get())    #输入的值

    list_1=Information_from_file()[1]    #歌曲名
    for i in range(len(list_1)):   #遍历歌曲名
        list_box.insert(tk.END,str(list_1[i]))    #显示歌曲名

def select_2():
    dict_id={}
    dict_name={}    #定义两个变量
    text.delete(0.0,tk.END)
    list_1=Information_from_file()[0] # 作者
    list_2=Information_from_file()[1]  # 名称
    list_3=Information_from_file()[2]  # id
    for i in range(len(list_2)):  #遍历歌曲名
        print(list_2[i])
        dict_id[list_2[i]]=list_2[i]    #将哈希  传递给对应的音乐名   name:哈希值
        dict_name[list_2[i]]=list_3[i]  #将ID  传递给对应的name    name:ID

    name_1 = list_box.get(tk.ACTIVE)
    zuoze = dict_id[name_1]  # 获取对应的音乐ID

    id1 = dict_name[name_1]  # 获取对应的音乐哈希值
    bool_1=Downlad(zuoze,id1)

    for i in range(1, 101):
        tk.Label(root, text='{}%|{}'.format(i, int(i / 4 % 26) * '■')).grid(row=5, columnspan=2, column=6, sticky=tk.W)
        root.update()  # 更新
    time_list = bool_1[1]  # 时间列表
    song_list = bool_1[2]  # 歌曲列表
    music_time = bool_1[3]  # 音乐时间
    i = 0
    T = 0

    while True:
        try:
            text.insert('{}.0'.format(i + 1), (song_list[i] + '\n').center(56, ' '))  # 将第一行插入歌曲列表的第i个   居中显示
            text.update()
            text.see(tk.END)
            i += 1
            if T == 0:  # 真
                time.sleep(time_list[T])  # 暂停几秒
            elif T == len(time_list)-1:  #
                time.sleep(4)
            else:
                time.sleep(time_list[T+1] - time_list[T])
            T += 1
            root.update()
        except:
            break

root = tk.Tk()
root.title("#####音乐播放器")
root.geometry("800x400")

input_lable = tk.Label(root,text="请输入歌名或作者:",font=('楷体',12))
input_lable.grid(row=1,column=0)

input_en = tk.StringVar()
input_entry = tk.Entry(root,textvariable=input_en,font=("楷体",12))
input_entry.grid(row=1,column=1)

index_input = tk.Button(root,text="搜索",command=select_1)
index_input.grid(row=1,column=2)

list_box = tk.Listbox(root,font=('楷体',12),width=43,height=21)
list_box.grid(row=2,column=0,columnspan=3,rowspan=5)

text = tk.Text(root,width=63,height=20)
text.grid(row=2,column=3,rowspan=3,columnspan=5)

b_buttom = tk.Button(root,text="播放",command=select_2)
b_buttom.grid(row=5,column=3)

tk.mainloop()

效果图

 

缺点:

        1、部分代码过于冗余,不够规范,运行有些卡顿

        1、点击播放时,会先将歌曲下载到本地,然后播放,待优化

        3、只能单首播放,且只有一次

        4、不能暂停

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一些基本的实现思路。 首先,您需要选择一个适合您的音乐播放库,例如pygame.mixer或pyglet。然后,您需要编写一个GUI界面,用于控制音乐播放、暂停、停止等功能,并在其中添加一个文本框用于显示歌词。 接下来,您需要编写一个歌词解析器,用于解析歌词文件,并将其与歌曲同步。歌词解析器应该能够处理常见的歌词格式,例如LRC格式,同时还应该能够处理歌曲中的时间信息。 最后,您需要编写一个歌词滚动器,用于实现歌词滚动效果。您可以使用Python的多线程模块或异步编程技术来实现歌词滚动,以确保歌曲和歌词的同步性。 下面是一个简单的示例代码,用于实现基本的歌词滚动效果: ```python import time import threading class LyricScroller: def __init__(self, lyrics, timecodes): self.lyrics = lyrics self.timecodes = timecodes self.index = 0 self.running = False def start(self): self.running = True t = threading.Thread(target=self.scroll) t.start() def stop(self): self.running = False def scroll(self): while self.running and self.index < len(self.lyrics): current_time = time.time() if self.timecodes[self.index] <= current_time: print(self.lyrics[self.index]) self.index += 1 else: time.sleep(0.01) ``` 该代码定义了一个LyricScroller类,该类接受歌词和时间码列表作为参数,并启动一个线程用于滚动歌词。scroll方法定期检查当前时间,并在到达下一个时间码时输出相应的歌词。 希望这可以帮助您开始编写自己的歌词滚动器!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值