You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyGame媒体播放器快进按钮仅生效一次问题求助

PyGame媒体播放器快进按钮失效问题解决

问题描述

开发的PyGame媒体播放器中,Fast Forward按钮仅能执行一次10秒快进操作,后续点击不再生效。问题出在fast_forward_music函数:通过pygame.mixer.music.get_pos()获取current_time,加10秒后调用set_pos()设置播放位置,但get_pos()返回的时间并未正确更新,导致后续快进计算错误。

问题原因

pygame.mixer.music.get_pos()的返回值是从当前音频开始播放以来的累计毫秒数,该计数不会因set_pos()跳转操作而重置。比如第一次快进10秒后,实际播放位置已经跳转,但get_pos()仍会从最初的播放起点继续累加,导致后续计算的new_time是基于原始播放时长,而非实际跳转后的位置,最终重复设置同一个无效位置,看起来快进失效。

解决方案

通过维护一个全局变量跟踪手动调整的播放偏移量,结合get_pos()的原始值计算实际播放位置,替代单纯依赖get_pos()的方式:

  1. 添加全局变量playback_offset,记录手动快进/快退的总偏移(单位:秒),初始值为0。
  2. 修改fast_forward_music函数,基于get_pos()和playback_offset计算实际当前位置,更新偏移量后调用set_pos()。
  3. 在播放新文件、停止播放时,重置playback_offset为0,确保新音频的偏移量从头计算。

修改后的完整代码

# Now you can increase or decrease the volume here, you can also select multiple songs at once and listen to your favorite songs, delete and add songs as needed.
# Remember only this files *.mp3;*.wav;*.ogg;*.mp4;*.avi;*.mkv;*.flv;*.mov;*.wmv;*.webm

import os
import pygame
from tkinter import Tk, filedialog, messagebox
from tkinter import ttk
from tkinter import Listbox

# Initialize the mixer
pygame.mixer.init()

# Create a Tkinter window to select media files
root = Tk()
root.withdraw()

# Global variables
current_file = ""
playlist = []
current_index = 0
is_playing = False
volume = 0.5  # Default volume
playback_offset = 0  # 新增:记录手动播放偏移量(秒)

# Function to select a file
def select_file():
    file_path = filedialog.askopenfilename(filetypes=[
        ("Audio/Video Files", "*.mp3;*.wav;*.ogg;*.mp4;*.avi;*.mkv;*.flv;*.mov;*.wmv;*.webm")
    ])
    if file_path:
        add_to_playlist(file_path)

# Function to add a file to the playlist
def add_to_playlist(file_path):
    playlist.append(file_path)
    playlist_box.insert("end", os.path.basename(file_path))

# Function to remove a file from the playlist
def remove_from_playlist():
    selected_index = playlist_box.curselection()
    if selected_index:
        playlist.pop(selected_index[0])
        playlist_box.delete(selected_index)

# Function to clear the playlist
def clear_playlist():
    global current_index, playback_offset
    playlist.clear()
    playlist_box.delete(0, "end")
    stop_music()
    current_index = 0
    playback_offset = 0  # 重置偏移量

# Function to play the selected file or playlist
def play_music(file_path=None):
    global current_file, current_index, is_playing, playback_offset

    if not file_path:
        selected_index = playlist_box.curselection()
        if not selected_index:
            messagebox.showinfo("Error", "No file selected.")
            return
        current_index = selected_index[0]
        file_path = playlist[current_index]

    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()
    current_file = file_path
    is_playing = True
    playback_offset = 0  # 播放新文件时重置偏移量

    update_status()

# Function to pause/resume the music
def pause_resume_music():
    global is_playing

    if is_playing:
        pygame.mixer.music.pause()
        is_playing = False
    else:
        pygame.mixer.music.unpause()
        is_playing = True

    update_status()

# Function to stop the music
def stop_music():
    global playback_offset
    pygame.mixer.music.stop()
    update_status()
    play_pause_button.config(text="Play", command=play_music)
    playback_offset = 0  # 停止时重置偏移量

# Function to rewind the music
def rewind_music():
    global playback_offset
    pygame.mixer.music.rewind()
    playback_offset = 0  # 重置偏移量

# Function to fast forward the music
def fast_forward_music(seconds):
    global playback_offset
    # 计算实际当前播放位置:get_pos的原始时长(秒) + 手动偏移量
    current_raw_time = pygame.mixer.music.get_pos() / 1000
    actual_current_time = current_raw_time + playback_offset
    new_time = actual_current_time + seconds
    print(f'Raw get_pos: {current_raw_time:.2f}s, Actual current: {actual_current_time:.2f}s, New time: {new_time:.2f}s')
    pygame.mixer.music.set_pos(new_time)
    # 更新偏移量:新位置 - 最新的原始get_pos时长
    new_raw_time = pygame.mixer.music.get_pos() / 1000
    playback_offset = new_time - new_raw_time
    print(f'New raw get_pos: {new_raw_time:.2f}s, Updated offset: {playback_offset:.2f}s')

# Function to set the volume
def set_volume(volume_level):
    global volume
    volume = float(volume_level)
    pygame.mixer.music.set_volume(volume)

# Function to update the status label
def update_status():
    global current_file, current_index, is_playing

    if current_file:
        status_label.config(text=f"Now playing: {os.path.basename(current_file)}")
    else:
        status_label.config(text="")

    if is_playing:
        play_pause_button.config(text="Pause", command=pause_resume_music)
    else:
        play_pause_button.config(text="Resume")

    playlist_box.selection_clear(0, "end")
    playlist_box.selection_set(current_index)

# Main GUI window
window = Tk()
window.title("Media Player")

# Create buttons
select_button = ttk.Button(window, text="Select File", command=select_file)
play_pause_button = ttk.Button(window,text="Play", command=play_music)
stop_button = ttk.Button(window, text="Stop", command=stop_music)
rewind_button = ttk.Button(window, text="Rewind", command=rewind_music)
fast_forward_button = ttk.Button(window, text="Fast Forward", command=lambda: fast_forward_music(10))

# Create playlist controls
playlist_label = ttk.Label(window, text="Playlist")
playlist_box = Listbox(window, selectbackground="#3498db", selectforeground="white")
remove_button = ttk.Button(window, text="Remove", command=remove_from_playlist)
clear_button = ttk.Button(window, text="Clear", command=clear_playlist)

# Create volume control
volume_label = ttk.Label(window, text="Volume")
volume_scale = ttk.Scale(window, from_=0.0, to=1.0, orient="horizontal", command=set_volume)
volume_scale.set(volume)  # Set initial volume value

# Create status label
status_label = ttk.Label(window, text="", anchor="center")

# Position the buttons and widgets
select_button.grid(row=0, column=0, padx=10, pady=10)
play_pause_button.grid(row=0, column=1, padx=10, pady=10)
stop_button.grid(row=0, column=2, padx=10, pady=10)
rewind_button.grid(row=0, column=3, padx=10, pady=10)
fast_forward_button.grid(row=0, column=4, padx=10, pady=10)
playlist_label.grid(row=1, column=0, padx=10, pady=10, sticky="w")
playlist_box.grid(row=2, column=0, rowspan=4, columnspan=5, padx=10, pady=10, sticky="nsew")
remove_button.grid(row=2, column=5, padx=5, pady=10, sticky="w")
clear_button.grid(row=3, column=5, padx=5, pady=10, sticky="w")
volume_label.grid(row=6, column=0, padx=10, pady=5, sticky="w")
volume_scale.grid(row=6, column=1, columnspan=4, padx=10, pady=5, sticky="we")
status_label.grid(row=7, column=0, columnspan=6, padx=10, pady=5, sticky="we")

# Configure grid weights
window.grid_rowconfigure(2, weight=1)
window.grid_columnconfigure(0, weight=1)

# Start the GUI event loop
window.mainloop()

# Quit the mixer
pygame.mixer.quit()

关键修改说明

  • 新增全局变量playback_offset,用于累计手动调整的播放偏移量。
  • fast_forward_music函数中,先计算实际播放位置(原始get_pos值 + 偏移量),再计算新位置,最后更新偏移量以匹配跳转后的实际位置。
  • 在play_music、stop_music、rewind_music、clear_playlist函数中重置playback_offset,确保新音频或重置操作后偏移量正确。

内容的提问来源于stack exchange,提问作者Starwarsdan3000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:39:52