如何根据音频文件的位置更改 tkinter 音阶?

问题描述 投票:0回答:1

在下面发布的代码中,我有一个 tkinter 音阶,我可以通过向右或向左滚动音阶来更改音乐的时间。它工作得很好,但不会改变以适应 mp3 或 wav 文件中当前点的位置,它在

set_time
函数中都是手动的。这个结果是预期的,但我想知道是否有办法每秒更新一次以适应文件中的当前位置,同时仍然能够使用其他功能?可能通过线程?包含刻度当前位置的变量是
music_time
,它也在
set_time
函数中。抱歉,这个问题相当广泛,但如果您需要用我的蹩脚代码进行澄清,只需 lmk

# 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
import librosa
import random
from tkinter import Tk, filedialog, messagebox
from tkinter import ttk
from tkinter import Listbox
from mutagen.mp3 import MP3
from threading import Timer


# Initialize the mixer
pygame.mixer.init()

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

# Global variables
m = 0
t = 0
length = 0
current_file = ""
playlist = []
current_index = 0
is_playing = False
music_time = 0.0  # Default time
volume = 0.5  # Default volume


# Function to select a file
def select_file():
    file_path = filedialog.askopenfilenames(filetypes=[
        ("Audio/Video Files", "*.mp3;*.wav;")
    ])
    #("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):
    for files in file_path:
        playlist.append(files)
        playlist_box.insert("end", os.path.basename(files[:-4]))

# Find song length
def song_length(file_path):
    'abuba.mp3'
    if file_path[-4:] == '.mp3':
        audio = MP3(file_path)
        return audio.info.length
    if file_path[-4:] == '.wav':
        print(librosa.get_duration(path=file_path))
        return librosa.get_duration(path=file_path)


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

# Function to clear the playlist
def clear_playlist():
    global current_index
    playlist.clear()
    playlist_box.delete(0, "end")
    if is_playing:
        stop_music()
    current_index = 0

# Function to play the selected file or playlist
def play_music(file_path=None):
    global current_file, current_index, is_playing, length, t
    
    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)
    length = round(song_length(file_path), 3) * 1000
    time_scale.set(0)
    time_scale.config(to=(length/10))
    pygame.mixer.music.play()
    current_file = file_path
    is_playing = True
    t = Timer(((length/10) - music_time)/100, play_next)
    t.start()
    update_status()

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

    if is_playing:
        pygame.mixer.music.pause()
        is_playing = False
        t.cancel()
    else:
        pygame.mixer.music.unpause()
        is_playing = True
        t = Timer(((length/10) - music_time)/100, play_next)
        t.start()
        
    update_status()

# Function to stop the music
def stop_music():
    pygame.mixer.music.stop()
    update_status()
    play_pause_button.config(text="Play", command=play_music)

# Function to shuffle songs in playlist
def shuffle_playlist():
    global playlist, t
    randomized_playlist = random.sample(playlist, len(playlist))
    clear_playlist()
    if t != 0:
        t.cancel()
        
    for file_path in randomized_playlist:
        playlist.append(file_path)
        playlist_box.insert("end", os.path.basename(file_path[:-4]))

# Function to play next song
def play_next():
    global current_index
    pygame.mixer.music.stop()
    update_status()
    if current_index + 1 <= len(playlist) - 1:
        current_index += 1
    else:
        current_index = 0
    play_music(playlist[current_index])
    
def play_previous():
    global current_index
    pygame.mixer.music.stop()
    update_status()
    if current_index + 1 <= len(playlist) - 1:
        current_index += -1
    else:
        current_index = 0
    play_music(playlist[current_index])
    
# Function to play next song
def play_next():
    global current_index
    pygame.mixer.music.stop()
    update_status()
    if current_index + 1 <= len(playlist) - 1:
        current_index += 1
    else:
        current_index = 0
    play_music(playlist[current_index])

# Function to set the volume
def set_volume(volume_level):
    global volume
    print(volume_level)
    volume = float(volume_level)
    pygame.mixer.music.set_volume(volume)
    
# Function to set the time
def set_time(music_time_level):
    global music_time, m, t
    music_time = float(music_time_level)
    if m != 0:
        m.cancel()
    if is_playing:
        m = Timer(1, pygame.mixer.music.set_pos(music_time/100))
        m.start()
    if t != 0:
        t.cancel()
        print((length/10) - music_time)
        print(((length/10) - music_time)/100)
        t = Timer(((length/10) - music_time)/100, play_next)
        t.start()

# 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 music_time >= (length/10):
        play_pause_button.config(text="Play", command=play_music)
    elif 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)
skip_button = ttk.Button(window, text="Skip", command=lambda: play_next())
rewind_button = ttk.Button(window, text="Rewind", command=lambda: play_previous())

# 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)
shuffle_button = ttk.Button(window, text="Shuffle", command=shuffle_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 time control
time_label = ttk.Label(window, text="Time")
time_scale = ttk.Scale(window, from_=0.0, to=1.0, orient="horizontal", command=set_time)
time_scale.set(music_time)  # 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)
skip_button.grid(row=0, column=5, padx=10, pady=10)
rewind_button.grid(row=0, column=6, 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")
shuffle_button.grid(row=2, column=6, padx=5, pady=10, sticky="w")
clear_button.grid(row=5, 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")
time_label.grid(row=7, column=0, padx=10, pady=5, sticky="w")
time_scale.grid(row=7, column=1, columnspan=4, padx=10, pady=5, sticky="we")
status_label.grid(row=8, 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()

python multithreading tkinter pygame
1个回答
0
投票

您可以通过执行以下操作来设置由

root.mainloop()
维护的递归循环:

def repeat(arguments_here):
    <Code to change slider length>
    root.after(500, repeat)

这里的500是指500毫秒内重复。

希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.