How to play pause audio file in python? - python

I am trying to create a media player with Python that will play mp3 files one after the other and allow me to play and pause the music at any time (similar to spotify).
I have used the vlc library and pygame music function to play the files, but my problem comes when the song has finished and I want it to play the next file. I have manged to do this but not with a play and pause functionality.
My rough code:
import pygame
import time
#plays first mp3 file
file = '4c68Z9wLdHc36y3CNjwQKM.ogg'
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(file)
pygame.mixer.music.play()
#play and pause funtionnality
while pygame.mixer.music.get_busy():
timer = pygame.mixer.music.get_pos()
time.sleep(1)
control = input()
pygame.time.Clock().tick(10)
if control == "pause":
pygame.mixer.music.pause()
elif control == "play" :
pygame.mixer.music.unpause()
elif control == "time":
timer = pygame.mixer.music.get_pos()
timer = timer/1000
print (str(timer))
elif int(timer) > 10:
print ("True")
pygame.mixer.music.stop()
break
else:
pass
#next mp3 file
file = '3qiyyUfYe7CRYLucrPmulD.ogg'
pygame.mixer.music.load(file)
pygame.mixer.music.play()
When I run this my hope is that it will play the first file and allow me to play and pause, but it stops when a song ends and not play the next one, as it gets stuck waiting for an input.
I want it to play the first file, allowing me to pause and resume it at any time, and then when the song has finished, it automatically plays the next file.
Thanks in advance.
To narrow it down I would like to know how to create a while that has a user input that will always check for a condition and not just at the start of the while loop.

I'm not sure why you tagged this question vlc if you are using pygame as arguably vlc.py has this functionallity pretty much built in.
However, all you need to do is use a double while statement.
The first controls the file to be played and the second performs your play/pause control. e.g.
import pygame
import time
files = ['./vp1.mp3','./vp.mp3']
pygame.init()
pygame.mixer.init()
stepper = 0
#file loading
while stepper < len(files):
pygame.mixer.music.load(files[stepper])
print("Playing:",files[stepper])
stepper += 1
pygame.mixer.music.play()
#play and pause
while pygame.mixer.music.get_busy():
timer = pygame.mixer.music.get_pos()
time.sleep(1)
control = input()
pygame.time.Clock().tick(10)
if control == "pause":
pygame.mixer.music.pause()
elif control == "play" :
pygame.mixer.music.unpause()
elif control == "time":
timer = pygame.mixer.music.get_pos()
timer = timer/1000
print (str(timer))
elif int(timer) > 10:
print ("True")
pygame.mixer.music.stop()
break
else:
continue

Related

How can I play another music list with Pygame? [duplicate]

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.
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. e.g:
import pygame
play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []
pygame.init()
clock = pygame.time.Clock()
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 = play_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()
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/

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.
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. e.g:
import pygame
play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []
pygame.init()
clock = pygame.time.Clock()
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 = play_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()
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/

pygame sound not playing after time.sleep() function

Any ideas why the code below does not play the sound? If the s.play() were to be outside the clock() function, it work.
import time
import pygame
pygame.init()
s = pygame.mixer.Sound("0614.wav")
def clock ():
x = input("How long to start the alarm for? ")
delay = float(x)
print ("Alarm Started")
time.sleep(delay)
print ("!!!!ALARM!!!!!")
s.play()
clock()
Is your file "0614.wav" in the same folder as form the program is executed?.
To see the error use try-except block and then print the error.

Playing videos one after the other using Pygame

I have written some Python code in an attempt to show one video after the other where I want to in Pygame:
import pygame
import time
def playvid(vidfile, runtime, FPS):
print("playing" + vidfile)
playmovie = pygame.movie.Movie(vidfile)
movie_screen = pygame.Surface(playmovie.get_size()).convert()
playmovie.set_display(movie_screen)
playmovie.play()
thentime = time.time()
playing = True
while playing:
screen.blit(movie_screen,(0,0))
pygame.display.update()
clock.tick(FPS)
nowtime = time.time()
#Play the video for 5s
if nowtime - thentime > runtime + 1: playing = False
print("done this one")
#FPS = 29.97
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((0, 0),pygame.FULLSCREEN)
run = True
while run:
playvid('snowdone.mpg', 10, 29.97)
playvid('snowdone1.mpg', 10, 29.97)
run = False
pygame.quit()
Playing the first video is fine, however, playing the second gives the warning:
"Runtime Error!
Program: C:\Python27\pythonw.exe
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information."
Both videos play fine on their own so this is not an mpg problem. Any suggestions?
I do not know the specific reason as to why the change I am suggesting works, but apparently it works.
Using your code as is, my first movie would not run for more than 4-5 seconds no matter what (it always stopped at roughly the same point) and then the pygame window would crash.
Adding a simple piece of pygame.event.get code in the while playing loop, however, fixed everything
while playing:
for event in pygame.event.get():
pass
screen.blit(movie_screen,(0,0))
pygame.display.update()
clock.tick(FPS)
nowtime = time.time()
#Play the video for 5s
if nowtime - thentime > runtime + 1: playing = False
It seems strange that even doing nothing in the loop for events runs the code without an issue.

Pygame another thread not getting QUIT event?

I'm making an game for ending my programming course and I sometimes have some longer scenes displayed and the loop ain't checking for if there is QUIT event and then stop everything and close the loop. So I thought multi-threading would help, but apparently it doesn't seem to get events, I have tried printing out - it gets events, but it simply aint getting QUIT event.
Here is the code:
from pygame import *
from threading import Thread
def closesearcher():
global running
while running:
for i in event.get():
if i.type == QUIT:
print ("QUIT event in closesearcher")
running = False
quit()
exit()
clock.tick(60)
def main():
init()
#True while game is running
global running
running = True
global window
window = display.set_mode([640, 480])
global clock
clock = time.Clock()
#Let's start closesearcher
searcherclose = Thread(target = closesearcher)
searcherclose.start()
scenegame = gamescene()
def gamescene():
#Render some scenery, wait for user to press button, etc in the following loop
while running:
for i in event.get():
if i.type == QUIT:
print ("QUIT event in game loop")
clock.tick(60)
if __name__ == "__main__":
main()
Any solutions that would be similiar to the structure of my current code?
Note: I use Python 3.2
How about actually exiting the loops with return instead of only printing that you got the quit event?
Currently, you only exit the loop in closesearcher but not in gamescene.
Also, I think event.get() will remove the event. So calling get in the other loop will not return anything. You need to set a global flag playerWantsToQuit and use that instead of the local running variables.

Categories

Resources