简体   繁体   中英

How can I Iterate through a list of songs and play them one after eachother

I am looking to iterate through a list of songs such as Songs = ["Song1.mp3", "Song2.mp3", "Song3.mp3"] and I want to play each song one after each other.

I have tried various methods, the most suggested seemed to use pygame, however, I have not been able to debug the tremendous amount of errors that come with using it. My main source code and attempt at this is as shown below:

from tkinter import *
import pygame
from random import choice
import os

pygame.mixer.init()

Songs = os.listdir("Music\\")

def Play():
       Song = choice(Songs)
       pygame.mixer.music.load("Music\\" + Song)
       pygame.mixer.music.play()

while True:
    play()

Upon running this I receive error pygame.error: ModPlug_Load failed .

I am running this concurrently inside of a slideshow program I have, I want this code to run as background music and I plan on checking for the end of the song in a Function I already have set.

If it's a desktop app, you have multiple options to play a file, usually, it depends:

在此处输入图像描述

Also to avoid Tkinter being stuck, you need to use threads or multiprocess. I recommend you soundfile player, you will find examples here https://realpython.com/playing-and-recording-sound-python/

Use pygame.mixer.music.get_busy() to detect if a music stream is actively playing. Play the next song from the list when no stream is active. eg:

import pygame

play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []

pygame.init()
clock = pygame.time.Clock()

window_center = window.get_rect().center
title_surf = None

run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    
    if not pygame.mixer.music.get_busy():
        if not current_list:
           current_list[:]
        current_song = current_list.pop(0)
        pygame.mixer.music.load(current_song)
        pygame.mixer.music.play()

pygame.quit()
exit()

You can register a custom event which will be triggered when the music is done playing using pygame.mixer.music.set_endevent() .

Also you need to run the while loop in a child thread if you want to run concurrently with main application.

Below is an example:

import os
import random
import threading
import tkinter as tk
import pygame

pygame.init()
# create a custom event
MUSIC_DONE = pygame.event.custom_type()
# register the event
pygame.mixer.music.set_endevent(MUSIC_DONE)

folder = "Music\\"
Songs = os.listdir(folder)

def next_song():
    try:
        song = random.choice(Songs)
        pygame.mixer.music.load(os.path.join(folder, song))
        pygame.mixer.music.play()
        # update song name
        song_var.set(song)
    except Exception as e:
        print(e)

def pygame_loop():
    next_song()
    while pygame.get_init():
        for event in pygame.event.get():
            if event.type == MUSIC_DONE:
                # current song done playing, play next song
                next_song()

root = tk.Tk()

# label to show the current song being played
song_var = tk.StringVar()
tk.Label(root, textvariable=song_var).pack()

# start the pygame loop in a child thread
threading.Thread(target=pygame_loop).start()

root.mainloop()
# quit pygame
pygame.quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM