猫史档案馆


本地音乐播放器,2-300行代码

用户:卡塔欧尼酱卡塔欧尼酱查看:3 回复:4 评论:3 创建时间:2024-08-26T15:23:08


# ⭐将“ ”中的路径改为您的音乐所在文件夹的路径     代码只需要改这个
folder_path = "D:\CloudMusic\铜钟\8-11"  # 这是作者的绝对路径。     推荐绝对路径,相对路径也行~


# 操作提示:
"""
⭐音乐命名规则:歌手 + " - " + 歌名
            ⭐中间这必须是 空格+“-”+空格

一、键盘操作:(不是很灵敏,不推荐)
    1.长按空格输入本地歌曲编号⭐
    2.按下←键播放上一首
    3.按下→键播放下一首
二、鼠标操作:(比较灵敏)
    1.点击屏幕左半区/滚轮上滑→上一首歌
    2.点击屏幕右半区/滚轮下滑→下一首歌
"""




# 库文件
import pygame
import os
import keyboard
import io
from pynput.mouse import Listener   # 滚轮滑动
from mutagen.id3 import ID3
from mutagen import File
from PIL import Image, ImageFilter, ImageEnhance

# 初始化 pygame 音频
pygame.mixer.init()
# 初始化 pygame
pygame.init()

# 屏幕尺寸
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

# 创建屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("本地音乐播放器")  # 窗口名字

# 获取文件夹中的所有音乐文件
music_files = [os.path.join(folder_path, f) for f in os.listdir(
    folder_path) if f.endswith(('.mp3', '.wav'))]

# 加载字体
# font = pygame.font.SysFont(None, 36)  # 创建默认字体
# 创建自定义字体(路径、字体大小)
# font_path = "NotoSansCJKjp-Regular.otf"
font_path = "SourceHanSansCN-Regular.otf"
font = pygame.font.Font(font_path, 25)  # 兼容中文、日文等

# 播放索引
current_index = 0

# 获取音频时长
def get_audio_duration(audio_file_path):
    audio = File(audio_file_path)
    return audio.info.length  # 返回音频时长(秒)


# 绘制进度条
def draw_progress_bar(current_time, duration, x, y, width, height):
    progress = current_time / duration
    pygame.draw.rect(screen, (255, 255, 255), (x, y, width * progress, height))
    pygame.draw.rect(screen, (70, 70, 70), (x, y, width, height), 2)


# 打印播放时间和时长
def print_time_info(current_time, duration, x, y):
    time_text = f"{format(current_time, '.0f')}/{format(duration, '.0f')}s"
    font = pygame.font.Font(font_path, 15)  # 兼容中文、日文等
    text_surface = font.render(time_text, True, (255, 255, 255))
    text_rect = text_surface.get_rect()
    text_rect.right = x + progress_bar_width
    text_rect.top = y
    screen.blit(text_surface, text_rect)


# 获取音频封面并处理背景
def get_and_show_cover(audio_file_path):
    global scaled_value
    audio = File(audio_file_path)
    image_size = 300   # 边长为 300
    for key in audio.keys():
        if key.startswith('APIC:'):
            cover_data = audio[key].data
            cover_intial_image = Image.open(io.BytesIO(cover_data))
            # 调整封面图像的大小为 (300, 300)
            cover_image = cover_intial_image.resize((image_size, image_size))

            # 虚化背景图片
            cover_background_image = cover_intial_image.filter(
                ImageFilter.GaussianBlur(radius=5))
            # 降低亮度
            enhancer = ImageEnhance.Brightness(cover_background_image)
            cover_background_image = enhancer.enhance(
                0.7)  # 0.7 为降低后的亮度,可根据需要调整
            # 放大图片以填充背景
            cover_background_length = max(SCREEN_WIDTH, SCREEN_HEIGHT)
            cover_background_image = cover_background_image.resize(
                (cover_background_length, cover_background_length))
            cover_pygame = pygame.image.fromstring(cover_background_image.tobytes(
            ), cover_background_image.size, cover_background_image.mode)
            screen.blit(cover_pygame, (0, 0))  # 显示图片

            # 将调整大小后的图像转换为 pygame 可处理的格式
            cover_pygame = pygame.image.fromstring(
                cover_image.tobytes(), cover_image.size, cover_image.mode)
            # 计算图像在屏幕上的水平中心位置
            image_x = (SCREEN_WIDTH - cover_pygame.get_width()) // 2
            # 计算图像在屏幕上的垂直中心位置
            image_y = (SCREEN_HEIGHT - cover_pygame.get_height()) // 2
            # 在指定位置显示封面图像
            screen.blit(cover_pygame, (image_x, image_y - 120))
            break  # 获取完信息,直接走人~~~
        else:  # 如果没有封面
            screen.fi喵))  # 设置淡蓝色背景色
            # 计算图像在屏幕上的水平中心位置
            image_x = (SCREEN_WIDTH - image_size) // 2
            # 计算图像在屏幕上的垂直中心位置
            image_y = (SCREEN_HEIGHT - image_size) // 2
            # 在指定位置画蓝色
            pygame.draw.rect(screen, (135, 206, 250),(image_x, image_y - 120, 300, 300))

# 打印一些信息
def printing(audio_file_path):
    file_name = os.path.basename(music_files[current_index])
    audio = File(audio_file_path)

    file_name_get_print = os.path.splitext(file_name)[0]  # 获取文件名字 【0】:名字  【1】:后缀名   不带【】:都有
    # 获取标题
    title = audio.get('TIT2')
    if title:
        print(f"Title: {title.text[0]}")
        file_name_print = title.text[0]
    else:
        print("No title found.{},{}".format(file_name_get_print,current_index))
        file_name_print = file_name_get_print.split(" - ")[1]

    # 获取艺术家
    artist = audio.get('TPE1')
    if artist:
        print(f"Artist: {artist.text[0]}")
        singer_name_print = artist.text[0]
    else:
        print("No artist found.")
        singer_name_print = file_name_get_print.split(" - ")[0]
    
    font = pygame.font.Font(font_path, 25)
    song_name_text = font.render(
        file_name_print, True, (255, 255, 255))  # 在屏幕上绘制曲名
    font = pygame.font.Font(font_path, 16)
    singer_name_text = font.render(
        singer_name_print, True, (255, 255, 255))  # 在屏幕上绘制歌手
    screen.blit(song_name_text, ((SCREEN_WIDTH -
                song_name_text.get_width()) // 2, SCREEN_HEIGHT // 2 + 70))
    screen.blit(singer_name_text, ((SCREEN_WIDTH -
                song_name_text.get_width()) // 2, SCREEN_HEIGHT // 2 + 45))


def print_progress_bar(width):
    global progress_bar_width
    progress_bar_width = width
    current_time = pygame.mixer.music.get_pos() / 1000  # 毫秒转秒
    duration = get_audio_duration(music_files[current_index])
    draw_progress_bar(current_time, duration, 100, 500,
                      progress_bar_width, 10)  # 调整位置和大小
    print_time_info(current_time, duration, 100, 510)  # 打印时间信息


# 打印歌曲列表


def print_song_list():
    list_x = 5  # 列表起始 x 坐标
    list_spacing = 30  # 列表项之间的间距
    text_color = (255, 255, 255)
    for i in range(min(8, len(music_files))):
        if i == 0:
            text = "上一首:"
            text_color = (255, 255, 255)
        elif i == 1:
            text = "当前:"
            text_color = (25, 255, 255)
        else:
            text = "   "
            text_color = (255, 255, 255)
        if current_index + i > len(music_files):
            ID = current_index + i - len(music_files)
        elif current_index + i == 0:
            ID = len(music_files)
        else:
            ID = current_index + i
        song_name = text + str(ID) + "." + os.path.splitext(os.path.basename(
            music_files[(current_index + i - 1) % len(music_files)]))[0]
        if len(song_name) > 15:
            song_name = song_name[:15] + "..."
        font = pygame.font.Font(font_path, 15)
        text_surface = font.render(song_name, True, text_color)
        text_rect = text_surface.get_rect()
        text_rect.left = list_x  # 靠左显示
        text_rect.top = 50 + (i - 1) * list_spacing
        screen.blit(text_surface, text_rect)


# ⭐音频处理区:


def sing():
    global current_index, file_name
    if keyboard.is_pressed('right'):  # 检测是否按下"←"键
        current_index = (current_index + 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        file_name = os.path.basename(music_files[current_index])  # 直接获取了指定路径
        print(f"正在播放:{file_name}")  # 打印歌曲信息
        pygame.mixer.music.play()
    elif keyboard.is_pressed('left'):  # 检测是否按下"→"键
        current_index = (current_index - 1) % len(music_files)
        if current_index < 0:
            current_index = len(music_files) - 1
        pygame.mixer.music.load(music_files[current_index])
        file_name = os.path.basename(music_files[current_index])
        print(f"正在播放:{file_name}")  # 打印歌曲信息
        pygame.mixer.music.play()
    elif keyboard.is_pressed('space'):  # 检测是否按下"空格"键
        num = input("播放歌曲编号:")
        try:  # 尝试转换  对应 except ValueError:
            num = int(num) - 1
            if 0 <= num < len(music_files):
                current_index = num
                pygame.mixer.music.load(music_files[current_index])
                file_name = os.path.basename(music_files[current_index])
                print(f"正在播放:{file_name}")  # 打印歌曲信息
                pygame.mixer.music.play()
            else:
                print("输入的编号无效。(范围【1~" + str(len(music_files)) + "】)")
        # 在无法将输入的值转换为指定的数据类型时执行    对应 try: num = int(num)
        except ValueError:
            print("输入不是有效的数字。")
    if not pygame.mixer.music.get_busy():  # 当前歌曲播放结束
        current_index = (current_index + 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        file_name = os.path.basename(music_files[current_index])
        print(f"正在播放:{file_name}")  # 打印歌曲信息
        pygame.mixer.music.play()
    pygame.time.Clock().tick(100)  # 帧数


# 鼠标滚轮事件处理函数
def on_scroll(x, y, dx, dy):
    global current_index, scroll_wheel_push
    scroll_wheel_push = 1
    if dy > 0:
        current_index = (current_index - 1) % len(music_files)
        if current_index < 0:
            current_index = len(music_files) - 1
        pygame.mixer.music.load(music_files[current_index])
        file_name = os.path.basename(music_files[current_index])
        print(f"正在播放:{file_name}")
        pygame.mixer.music.play()
    else:
        current_index = (current_index + 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        file_name = os.path.basename(music_files[current_index])
        print(f"正在播放:{file_name}")
        pygame.mixer.music.play()


# 鼠标点击
scroll_wheel_push = 0
def handle_button_click(event):
    global current_index, scroll_wheel_push
    if scroll_wheel_push == 0:  # 如果不是滚轮触发的
        if event.pos[0] < SCREEN_WIDTH//2:
            current_index = (current_index - 1) % len(music_files)
            if current_index < 0:
                current_index = len(music_files) - 1
            pygame.mixer.music.load(music_files[current_index])
            file_name = os.path.basename(music_files[current_index])
            print(f"正在播放:{file_name}")
            pygame.mixer.music.play()
        elif event.pos[0] > SCREEN_WIDTH//2:
            current_index = (current_index + 1) % len(music_files)
            pygame.mixer.music.load(music_files[current_index])
            file_name = os.path.basename(music_files[current_index])
            print(f"正在播放:{file_name}")
            pygame.mixer.music.play()
    else:
        scroll_wheel_push = 0



# ⭐⭐⭐主函数
def play():
    global current_index, file_name, progress_bar_width, playing
    # 加载当前音乐
    pygame.mixer.music.load(music_files[current_index])
    file_name = os.path.basename(music_files[current_index])
    print("1.长按空格输入本地歌曲编号\n2.按下←键播放上一首\n3.按下→键播放下一首")  # 打印提示
    print(f"正在播放:{file_name}")  # 打印歌曲信息
    # 播放音乐
    pygame.mixer.music.play()
    running = True
    playing = True
    # 创建鼠标喵
    with Listener(on_scroll=on_scroll) as listener:
        while running:
            # ⭐音频执行区:
            sing()
            # ⭐窗口执行区:
            get_and_show_cover(music_files[current_index])
            printing(music_files[current_index])
            print_song_list()  # 打印歌曲列表
            print_progress_bar(600)

            pygame.display.flip()  # 更新屏幕显示

            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONDOWN:
                    handle_button_click(event)
                if event.type == pygame.QUIT:
                    running = False
                    pygame.quit()



# 运行!!!
play()


回复

上一页1 页 / 共 1下一页
卡塔欧尼酱卡塔欧尼酱

之前的效果展示视频:  评论区有最新的zip下载网址,还需要字体文件哟 www.bilibili.com/video/BV1n1WSefEjw/?spm_id_from=333.999.0.0

点赞1


评论


code猫的code猫的

import pygame
import os
import keyboard
import io
from mutagen import File
from PIL import Image, ImageFilter, ImageEnhance


# Initialize Pygame
pygame.mixer.init()
pygame.init()

# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Local Music Player")

# Define the music folder path
folder_path = "path/to/your/music/directory"  # Update this path

# Load music files
music_files = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.endswith(('.mp3', '.wav'))]

# Font for rendering text
font_path = "SourceHanSansCN-Regular.otf"
font = pygame.font.Font(font_path, 25)
current_index = 0


def get_audio_duration(audio_file_path):
    audio = File(audio_file_path)
    return audio.info.length


def draw_progress_bar(current_time, duration, x, y, width, height):
    if duration > 0:
        progress = current_time / duration
        pygame.draw.rect(screen, (255, 255, 255), (x, y, width * progress, height))
    pygame.draw.rect(screen, (70, 70, 70), (x, y, width, height), 2)


def sing():
    global current_index
    if keyboard.is_pressed('right'):
        current_index = (current_index + 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        pygame.mixer.music.play()
    elif keyboard.is_pressed('left'):
        current_index = (current_index - 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        pygame.mixer.music.play()


running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    sing()

    if not pygame.mixer.music.get_busy() and music_files:
        current_index = (current_index + 1) % len(music_files)
        pygame.mixer.music.load(music_files[current_index])
        pygame.mixer.music.play()

    screen.fill((0, 0, 0))  # Clear the screen
    draw_progress_bar(pygame.mixer.music.get_pos() / 1000, get_audio_duration(music_files[current_index]), 100, 500, 600, 10)
    pygame.display.flip()
    pygame.time.delay(100)

pygame.quit()

点赞0


评论


朴pu朴pu

良作无人

点赞1


评论


LarmooLarmoo

imgsrc="https://static.codemao.cn/emoji/codemao/%E7%BC%96%E7%A8%8B%E7%8C%AB_%E7%82%B9%E8%B5%9E.gif"alt="emotion_编程猫_点赞"

点赞0


评论