pygame编写音乐播放器

2024-05-06 01:18
文章标签 音乐 编写 播放器 pygame

本文主要是介绍pygame编写音乐播放器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

pygame编写音乐播放器

  • 1、准备工作
  • 2、开始
    • 2.1 设计说明
    • 2.2 代码逻辑
      • 收集某个目录下的所有mp3
      • 显示歌曲名称
      • 播放歌曲
      • 显示播放进度
      • 快进快退功能
      • 画播放控件
      • 主逻辑
  • 3、效果图
  • 4、完整代码
  • 5、打包为exe

1、准备工作

ide:pycharm
python:3.7
三方包:pygame、pyinstaller、mutagen
几首mp3格式的歌

2、开始

2.1 设计说明

1、包含 上一首、下一首、暂停/播放、快进/快退、显示当前播放的歌曲名称、显示播放进度条
2、使用pygame.mixer
3、随机播放磁盘某个目录及其子目录下的mp3文件
4、上一首、下一首用随机选择choice(list) 实现
5、进度条用按照一定速度移动进度图片来实现,过程中处理暂停、快进
6、歌曲快进播放用pygame.mixer.music.play(0,d_song_time) 实现
7、暂停用pygame.mixer.music.pause() 实现
8、播放用pygame.mixer.music.unpause() 实现
9、用mutagen.mp3来获取mp3信息

2.2 代码逻辑

收集某个目录下的所有mp3

# 收集某个目录及子目录下的MP3格式的文件
# 返回歌曲路径、歌曲时长
# [['E:\\musics\\Mirror_Yohee_128K.mp3', 236], ['E:\\musics\\over here_Nobigdyl_128K.mp3', 188], ['E:\\musics\\尘_薛之谦_128K.mp3', 282], ['E:\\musics\\aaa\\尘_薛之谦_128K.mp3', 282]]
def collect_songs(fidir):musics =[]for root, dirs, files in os.walk(fidir):for file in files:tmp =[]if file.endswith('mp3'):file = os.path.join(root,file)song = MP3(file)duration = round(song.info.length)tmp.append(file)tmp.append(duration)musics.append(tmp)return musics

显示歌曲名称

# 把歌曲名字显示在播放器上
def draw_song_name(music):# 取歌曲名music_name = music[0].split("\\")[-1]# print(music_name)wbk_obj = font_obj.render(music_name, True, (0, 255, 255))k_obj = wbk_obj.get_rect()k_obj.center = (340, 200)screen.blit(wbk_obj, k_obj)pygame.display.update()

播放歌曲

# 随机播放一首歌
def sing_a_song(musics):# 随机选择一首音乐music = choice(musics)print(type(musics))pygame.mixer.music.load(music[0])pygame.mixer.music.play()print('开始播放:%s -- %s秒'%(music[0] , str(music[1])))return music

显示播放进度

# 播放进度显示
def move(current_time,start_time,pause_duration_time,c_music):if pause_end_time == 0 and pause_start_time != 0:duration_time = round(pause_start_time - start_time - pause_duration_time)else:duration_time = round(current_time - start_time - pause_duration_time)song_total_time = c_music[1]speed = (end_x-begin_x)/song_total_timecurrent_x = begin_x + duration_time*speedtry:screen.blit(dian,(current_x,148))pygame.display.update()except:print(current_time)print(start_time)print(pause_duration_time)exit()

快进快退功能

# 快进快退功能
def kuaijin(jindu_x,c_music):# 要跳转到的距离d_xd_x = jindu_x - begin_xsong_total_time = c_music[1]# 要跳转到的时间d_song_timed_song_time = round(song_total_time*(d_x/560),1)# 将歌曲快进到d_song_timepygame.mixer.music.play(0,d_song_time)

画播放控件

# 画播放控件
def draw_kongjian(is_sing,is_pause):# 画进度条# 画一条宽度为2的线,y高度为149,x从40到600,颜色为(0,100,100)pygame.draw.line(screen, (0, 100, 100), (40, 149), (600, 149), 2)# 画播放、暂停按钮# 先画圆边框,半径20pygame.draw.circle(screen, (0, 255, 255), (x + 80, 100), 20, 2)# 画三角形,开始播放pygame.draw.line(screen, (0, 255, 255), (x + 73.7, 107.5), (x + 73.7, 93), 2)  # 竖线# 如果正在播放且没有暂停if is_sing and not is_pause:# 隐藏三角形pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 107.5), (x + 87.3, 100), 2)pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 93), (x + 87.3, 100), 2)# 显示第二条竖线pygame.draw.line(screen,(0,255,255),(x+83.7,107.5),(x+83.7,93),2)else:# 隐藏第二条竖线pygame.draw.line(screen, (0, 89, 115), (x + 83.7, 107.5), (x + 83.7, 93), 2)# 显示三角形pygame.draw.line(screen,(0,255,255),(x+73.7,107.5),(x+87.3,100),2)pygame.draw.line(screen,(0,255,255),(x+73.7,93),(x+87.3,100),2)# 画上一首按钮pygame.draw.line(screen, (0, 255, 255), (x - 10, 110), (x - 10, 90), 2)pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 115), 2)pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 85), 2)pygame.draw.line(screen, (0, 255, 255), (x + 10, 115), (x + 10, 85), 2)# 画下一首按钮pygame.draw.line(screen, (0, 255, 255), (x + 170, 110), (x + 170, 90), 2)pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 115), 2)pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 85), 2)pygame.draw.line(screen, (0, 255, 255), (x + 150, 115), (x + 150, 85), 2)

主逻辑

1、画界面
2、如果没有在播放音乐,播放之
3、如果正在播放音乐,刷新播放进度
4、点击了上一首的处理
5、点击了暂停/播放的处理
6、点击了下一首的处理
7、快进/快退的处理

while True:# 第一步画背景screen.fill((0, 0, 0))  # ----------------新添加# 第二步添加背景图片bg = pygame.image.load(music_bg)screen.blit(bg, (0, 0))# 第四步,画控件draw_kongjian(is_sing,is_pause)# print("status:-------" + str(pygame.mixer.music.get_busy()))# 如果正在播放音乐,有bug == 当暂停后返回依旧是1if pygame.mixer.music.get_busy() == 1:is_sing = Trueelse:is_sing = False# 如果没有在播放音乐if not is_sing:# 第五步,开始唱歌c_music = sing_a_song(musics)# 记录开始播放时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置重置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)# 更改播放状态is_sing = not is_sing# 如果正在唱歌else:# 第六步,显示歌名draw_song_name(c_music)current_time = time.time()move(current_time, start_time, pause_duration_time, c_music)for event in pygame.event.get():if event.type == QUIT:pygame.quit()exit()if event.type == MOUSEBUTTONDOWN:# 如果点击了鼠标左键,取到当前鼠标的坐标pressed_array = pygame.mouse.get_pressed()if pressed_array[0] == 1:mouse_x, mouse_y = event.posprint('点击了左键,位置为(%d,%d)'%(mouse_x,mouse_y))# 判断点击了哪个按钮if 80 < mouse_y < 120:if x - 5 < mouse_x < x + 15:# 点击了上一首c_music = sing_a_song(musics)is_pause = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)print('点击了上一首')elif x+60 < mouse_x < x+100:# 修改是否暂停的状态is_pause = not is_pause# 如果没有暂停if not is_pause:# 开始播放pygame.mixer.music.unpause()# 记录结束暂定时间pause_end_time = time.time()# 计算暂停时长pause_duration_time = pause_duration_time + pause_end_time - pause_start_time# 暂停结束,暂停结束开始时间均置为0pause_end_time = pause_start_time = 0# 如果暂停了else:# 暂停播放pygame.mixer.music.pause()# 记录开始暂定时间pause_start_time = time.time()print('点击了暂停')elif x+145 < mouse_x < x+170:# 点击了下一首c_music = sing_a_song(musics)is_pause = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time =0# 进度条开始位置置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)print('点击了下一首')# 如果点了进度条的某个位置elif 155> mouse_y >145:kuaijin(mouse_x,c_music)begin_x = mouse_xpause_end_time = pause_start_time = pause_duration_time = 0move(current_time,start_time,pause_duration_time,c_music)is_kuaijin = Trueprint("快进")pygame.display.update()

3、效果图

刺猬牛逼!!!
刺猬牛逼!!!

4、完整代码

#-*- coding: utf-8 -*-
import os,time,sys
from sys import exit
import pygame
from pygame.locals import *
from mutagen.mp3 import MP3
from random import choicedef rp(relative_path):""" Get absolute path to resource, works for dev and for PyInstaller """try:# PyInstaller creates a temp folder and stores path in _MEIPASSbase_path = sys._MEIPASSexcept Exception:base_path = os.path.abspath(".")return os.path.join(base_path, relative_path)pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)
pygame.display.set_caption("music")
# 初始化音乐播放器
pygame.mixer.init()
# 背景图片
music_bg = rp(os.path.join('src','music_bg.jpg'))
# 进度点图片
dian_filename = rp(os.path.join('src','dian.jpg'))
dian = pygame.image.load(dian_filename)
# 字体
font_obj = pygame.font.Font('C:\Windows\Fonts\simsun.ttc',20)
# 偏移量基础值
x = 80
# 进度条开始x坐标
begin_x = 40
# 进度条结束x坐标
end_x = 600
# 是否正在播放歌曲,默认未播放
is_sing = False
# 是否暂停,默认未暂停
is_pause = False
# 是否快进了
is_kuaijin = False
# 快进后x坐标
jindu_x = -1
# 定义当前歌曲变量
global c_music
# 定义歌曲开始播放时间、当前时间、开始暂停时间、结束暂停时间
global start_time, current_time, pause_start_time, pause_end_time,pause_duration_time
pause_start_time =0
pause_end_time =0
pause_duration_time =0# 把歌曲名字显示在播放器上
def draw_song_name(music):# 取歌曲名music_name = music[0].split("\\")[-1]# print(music_name)wbk_obj = font_obj.render(music_name, True, (0, 255, 255))k_obj = wbk_obj.get_rect()k_obj.center = (340, 200)screen.blit(wbk_obj, k_obj)pygame.display.update()# 收集某个目录及子目录下的MP3格式的文件
# 返回歌曲路径、歌曲时长
# [['E:\\musics\\Mirror_Yohee_128K.mp3', 236], ['E:\\musics\\over here_Nobigdyl_128K.mp3', 188], ['E:\\musics\\尘_薛之谦_128K.mp3', 282], ['E:\\musics\\aaa\\尘_薛之谦_128K.mp3', 282]]
def collect_songs(fidir):musics =[]for root, dirs, files in os.walk(fidir):for file in files:tmp =[]if file.endswith('mp3'):file = os.path.join(root,file)song = MP3(file)duration = round(song.info.length)tmp.append(file)tmp.append(duration)musics.append(tmp)return musicsmusics = collect_songs('E:\\musics')
print(musics)# 随机播放一首歌
def sing_a_song(musics):# 随机选择一首音乐music = choice(musics)print(type(musics))pygame.mixer.music.load(music[0])pygame.mixer.music.play()print('开始播放:%s -- %s秒'%(music[0] , str(music[1])))return music# 画代表当前进度的圆点
# 画一个直径为5个圆点,放在100,150的位置,颜色为(0,255,255)
# dian = pygame.draw.circle(screen,(0,255,255),(begin_x,150),6)# 画播放控件
def draw_kongjian(is_sing,is_pause):# 画进度条# 画一条宽度为2的线,y高度为149,x从40到600,颜色为(0,100,100)pygame.draw.line(screen, (0, 100, 100), (40, 149), (600, 149), 2)# 画播放、暂停按钮# 先画圆边框,半径20pygame.draw.circle(screen, (0, 255, 255), (x + 80, 100), 20, 2)# 画三角形,开始播放pygame.draw.line(screen, (0, 255, 255), (x + 73.7, 107.5), (x + 73.7, 93), 2)  # 竖线# 如果正在播放且没有暂停if is_sing and not is_pause:# 隐藏三角形pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 107.5), (x + 87.3, 100), 2)pygame.draw.line(screen, (0, 89, 115), (x + 73.7, 93), (x + 87.3, 100), 2)# 显示第二条竖线pygame.draw.line(screen,(0,255,255),(x+83.7,107.5),(x+83.7,93),2)else:# 隐藏第二条竖线pygame.draw.line(screen, (0, 89, 115), (x + 83.7, 107.5), (x + 83.7, 93), 2)# 显示三角形pygame.draw.line(screen,(0,255,255),(x+73.7,107.5),(x+87.3,100),2)pygame.draw.line(screen,(0,255,255),(x+73.7,93),(x+87.3,100),2)# 画上一首按钮pygame.draw.line(screen, (0, 255, 255), (x - 10, 110), (x - 10, 90), 2)pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 115), 2)pygame.draw.line(screen, (0, 255, 255), (x - 10, 100), (x + 10, 85), 2)pygame.draw.line(screen, (0, 255, 255), (x + 10, 115), (x + 10, 85), 2)# 画下一首按钮pygame.draw.line(screen, (0, 255, 255), (x + 170, 110), (x + 170, 90), 2)pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 115), 2)pygame.draw.line(screen, (0, 255, 255), (x + 170, 100), (x + 150, 85), 2)pygame.draw.line(screen, (0, 255, 255), (x + 150, 115), (x + 150, 85), 2)# 播放进度显示
def move(current_time,start_time,pause_duration_time,c_music):if pause_end_time == 0 and pause_start_time != 0:duration_time = round(pause_start_time - start_time - pause_duration_time)else:duration_time = round(current_time - start_time - pause_duration_time)song_total_time = c_music[1]speed = (end_x-begin_x)/song_total_timecurrent_x = begin_x + duration_time*speedtry:screen.blit(dian,(current_x,148))pygame.display.update()except:print(current_time)print(start_time)print(pause_duration_time)exit()# 快进快退功能
def kuaijin(jindu_x,c_music):# 要跳转到的距离d_xd_x = jindu_x - begin_xsong_total_time = c_music[1]# 要跳转到的时间d_song_timed_song_time = round(song_total_time*(d_x/560),1)# 将歌曲快进到d_song_timepygame.mixer.music.play(0,d_song_time)while True:# 第一步画背景screen.fill((0, 0, 0))  # ----------------新添加# 第二步添加背景图片bg = pygame.image.load(music_bg)screen.blit(bg, (0, 0))# 第四步,画控件draw_kongjian(is_sing,is_pause)# print("status:-------" + str(pygame.mixer.music.get_busy()))# 如果正在播放音乐,有bug == 当暂停后返回依旧是1if pygame.mixer.music.get_busy() == 1:is_sing = Trueelse:is_sing = False# 如果没有在播放音乐if not is_sing:# 第五步,开始唱歌c_music = sing_a_song(musics)# 记录开始播放时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置重置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)# 更改播放状态is_sing = not is_sing# 如果正在唱歌else:# 第六步,显示歌名draw_song_name(c_music)current_time = time.time()move(current_time, start_time, pause_duration_time, c_music)for event in pygame.event.get():if event.type == QUIT:pygame.quit()exit()if event.type == MOUSEBUTTONDOWN:# 如果点击了鼠标左键,取到当前鼠标的坐标pressed_array = pygame.mouse.get_pressed()if pressed_array[0] == 1:mouse_x, mouse_y = event.posprint('点击了左键,位置为(%d,%d)'%(mouse_x,mouse_y))# 判断点击了哪个按钮if 80 < mouse_y < 120:if x - 5 < mouse_x < x + 15:# 点击了上一首c_music = sing_a_song(musics)is_pause = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time = 0# 进度条开始位置置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)print('点击了上一首')elif x+60 < mouse_x < x+100:# 修改是否暂停的状态is_pause = not is_pause# 如果没有暂停if not is_pause:# 开始播放pygame.mixer.music.unpause()# 记录结束暂定时间pause_end_time = time.time()# 计算暂停时长pause_duration_time = pause_duration_time + pause_end_time - pause_start_time# 暂停结束,暂停结束开始时间均置为0pause_end_time = pause_start_time = 0# 如果暂停了else:# 暂停播放pygame.mixer.music.pause()# 记录开始暂定时间pause_start_time = time.time()print('点击了暂停')elif x+145 < mouse_x < x+170:# 点击了下一首c_music = sing_a_song(musics)is_pause = Falseis_kuaijin = False# 记录开始时间start_time = time.time()# 暂停时长置为0pause_start_time = pause_end_time = pause_duration_time =0# 进度条开始位置置为40begin_x = 40# 第六步,显示歌名draw_song_name(c_music)print('点击了下一首')# 如果点了进度条的某个位置elif 155> mouse_y >145:kuaijin(mouse_x,c_music)begin_x = mouse_xpause_end_time = pause_start_time = pause_duration_time = 0move(current_time,start_time,pause_duration_time,c_music)is_kuaijin = Trueprint("快进")pygame.display.update()

5、打包为exe

请查看另一篇文章
pyinstaller打包exe踩过的坑

这篇关于pygame编写音乐播放器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/963151

相关文章

人工智能做音乐

0 别人做的音乐demo https://yun.baidu.com/share/link?shareid=1799925478&uk=840708891 1 为什么人工智能能做音乐? 最下面蓝色的部分是你输入的音乐。 从上图可以看出,input是一个个的点,然后通过input来相互结合生成灰色的点,经过几层的连接之后,最后的Output就是新生成的音乐,也就是黄色的点。 把黄色的点

BD错误集锦8——在集成Spring MVC + MyBtis编写mapper文件时需要注意格式 You have an error in your SQL syntax

报错的文件 <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.yuan.dao.YuanUserDao"><!

如何利用echarts编写立体的柱状图表

1、引入 import * as echarts from 'echarts' 2、创建图标容器 3、调用渲染 <template><div ref="eachrtsBox" style="width: 200px;height: 200px;"></div></template><script>import * as echarts from 'echarts'export d

AI与音乐:当技术与艺术发生冲突

AI在创造还是毁掉音乐? 在科技日新月异的今天,人工智能(AI)已经渗透到了我们生活的方方面面,音乐领域也不例外。然而,尽管AI为音乐创作带来了前所未有的便利,我却深感其正在毁掉音乐的本质。 首先,AI的介入使得音乐创作过程变得过于机械化。传统的音乐创作往往需要音乐家们经过长时间的思考、尝试和修改,最终才能创作出触动人心的作品。这一过程不仅体现了音乐家的才华和技艺,更蕴含了他们对生活的感悟和对

AI与音乐:共创未来还是艺术终结?

随着人工智能技术的不断进步,AI在音乐创作领域的应用已经成为了一个不可忽视的现象。最近一个月,一系列音乐大模型的推出,不仅极大地降低了普通人创作音乐的门槛,也引发了关于音乐产业未来的广泛讨论。AI是否正在创造音乐的新纪元,还是正在逐渐毁掉这一艺术形式?本文将深入探讨人工智能和音乐人的合作模式,讨论AI在音乐创作中的辅助作用,以及如何实现人机共同创作的可能性。 AI与音乐人的合作模式 在探讨

ssh在本地虚拟机中的应用——解决虚拟机中编写和阅读代码不方便问题的一个小技巧

虚拟机中编程小技巧分享——ssh的使用 事情的起因是这样的:前几天一位工程师过来我这边,他看到我在主机和虚拟机运行了两个vscode环境,不经意间提了句:“这么艰苦的环境写代码啊”。 后来我一想:确实。 我长时间以来都是直接在虚拟机里写的代码,但是毕竟是虚拟机嘛,有时候编辑器没那么流畅,在文件比较多的时候跳转很麻烦,容易卡住。因此,我当晚简单思考了一下,想到了一个可行的解决方法——即用ssh

简单 使用 的makefile编写 框架

1、指定编译器,如海思平台:CROSS_COMPILE=arm-hisiv100nptl-linux-; 2、指定编译工具:GCC=$(CROSS_COMPILE)gcc   CC=$(CROSS_COMPILE)g++; 3、使用 export 导出 子makefile 要用的变量; 4、定义变量的形式  指定 工程源文件 需要使用到的 “宏”,在后面的 LDFLAGS 里面使用 -D将其

(转)Sublime Text 2 (Emmet):HTML/CSS代码快速编写神器

Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生。它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示:   Zen coding下的编码演示   去年年底,该插件已经改名为Emmet。但Emmet不只改名,还带来了一些新特性。本文就来直观地演示给你。 一、快速编写HTML代码 1.

编程精粹—— Microsoft 编写优质无错 C 程序秘诀 07:编码中的假象

这是一本老书,作者 Steve Maguire 在微软工作期间写了这本书,英文版于 1993 年发布。2013 年推出了 20 周年纪念第二版。我们看到的标题是中译版名字,英文版的名字是《Writing Clean Code ─── Microsoft’s Techniques for Developing》,这本书主要讨论如何编写健壮、高质量的代码。作者在书中分享了许多实际编程的技巧和经验,旨在

Linux内核开发-编写一个内核模块

0.前言 上一章(点击返回上一章)已经完成了将ubuntu原始内核替换成了自己编好的内核。本章开始编写一个内核模块。 1.内核模块 1.1 什么是内核模块 Linux内核模块可独立于内核之外进行编译,可以在内核运行时动态加载、卸载。内核模块以.ko为后缀。 1.2 操作内核模块常用的指令 # 查看当前正在运行的模块lsmod#插入一个模块insmod module_name# 卸载