Music player for Python not working - python

I want to be able to play multiple songs through a playlist using python, but it will only play the last song on the list. Please help.
from pygame import mixer # Load the required library
from os import listdir
k = listdir('C:/LOCAL')
print(k)
mixer.init()
for x in k:
y = "C:/LOCAL/" + x
print y
mixer.music.queue(y)
mixer.music.load(y)
mixer.music.play()

Your problem is that you assume that playing music with pygame will pause the program until the music is finished - which is not the case. As a result, it tries starting a song, and then it's starting another, and another, etc.
There are a few ways of trying to correct this. You could either:
Use pygame events and "tell" pygame to fire an event when the song finishes (though this requires a display surface (window) to be opened within pygame), or
Detect the length of the song, and sleep for that amount of time (which is more compatible with your current code).
I'm going to assume that you would like to do option 2, since your code works better with it.
To get the length of an MP3 file (I've not tried it with any other types), you could use the Mutagen library.
Some example code to get the length of an MP3 file (in seconds):
from mutagen.mp3 import MP3
tracklength = MP3("/path/to/song.mp3").info.length
Then you could substitute the path with y, and time.sleep for the amount of time returned, before continuing to the next iteration of the loop.
Hope that helps.
(also, you don't need to queue a file before loading it - just load and play)

Related

How do I get inputs from a MIDI device through Pygame?

I'm somewhat new to both Python and Pygame, and trying to simply read MIDI controls live from a Windows computer. I've looked into Pygame and have set up what I think to be most of the right syntaxes, but the shell seems to crash or at least reset at the line pygame.midi.Input(input_id) every time.
import pygame.midi
import time
pygame.init()
pygame.midi.init()
print("The default input device number is " + str(pygame.midi.get_default_input_id()))
input_id = int(pygame.midi.get_default_input_id())
clock = pygame.time.Clock()
crashed = False
while (crashed == False):
print("input:")
pygame.midi.Input(input_id)
print(str(pygame.midi.Input.read(10)))
clock.tick(2)
I am also new to both Python and and Pygame.
I also tried for quite some time to get the midi input reading to work. In another forum I was pointed to an included sample file in the library. You can see the answer here.
Side note:
On my computer there are several Midi devices active. So it maybe would be a good idea to not rely on the default input id. You can get a list of your Midi devices like this:
import pygame
from pygame.locals import *
from pygame import midi
def printMIDIDeviceList():
for i in range(pygame.midi.get_count()):
print(pygame.midi.get_device_info(i), i)

Python gtts vlc plays too quickly to hear the first couple words

In python, using the module gTTS and VLC-python, I've created a Text to speech program, which is quite simple to do.
But the thing which is bugging me is when I get to playing the mp3 file created by gTTS it skips the first word or two.
So if I have the string "The weather today will be cloudy". It'll speak out "today will be cloudy"
Even if I adjust the string, it seems to miss out the first word or two, sometimes it starts mid word.
When I play the audio file outside of the code, it plays normally, sometimes it stutters on the first word but if I rewind and have it wait a second, it plays perfectly.
Is there a way to load the audio clip or buffer it before playing so it starts smoothly?
In your code you are going to have something along the lines of:
self.Media = self.Instance.media_new_path('my.mp3')
self.player.set_media(self.Media)
self.player.set_xwindow(self.panel1.GetHandle())
which defines what is going to be played.
Then you will have something like:
if self.player.play() == -1:
print("Error playing file")
else:
pass
where you tell vlc to start playing the file.
put a time.sleep(3) before that play command or actuate the play function from a separate button or something.
This is the equivalent of the:
vlc --no-playlist-autostart vp.mp3
or
vlc --start-paused vp.mp3 command line options.
i.e. load the file but don't start playing it, until I tell you.
I found another library called playsound which plays the audio files back without any clipping:
from gtts import gTTS
from playsound import playsound
text = "Say something."
speech = gTTS(text = text, lang = 'en', slow = False)
mp3_file = 'text.mp3'
speech.save(mp3_file)
playsound(mp3_file)
I think this is a better solution than VLC, even if there was no clipping of audio in VLC, because using the vlc library requires you to have VLC Media Player installed on your computer, whereas this playsound library doesn't require you to install anything else for it to work.

What is preventing the sound files from being played in this pygame Mixer set up?

I'm trying to write a small bit of code to play music files in the background of a game. The problem I'm coming across is that despite all the code being laid out and phrased properly no sound files will play. I put several print statements in the code and it seems to suggest that the sound file is either not loading or is simply not playing once it loads?
import pygame
def musicPlayer():
print "Playing music now"
pygame.init()
pygame.mixer.music.load('01ANightOfDizzySpells.mp3')
print "load song1"
pygame.mixer.music.play(loops=0, start=0.0)
print "play song1"
pygame.mixer.music.queue('01HHavok-intro.mp3')
pygame.mixer.music.queue('02HHavok-main.mp3')
pygame.mixer.music.queue('02Underclockedunderunderclockedmix.mp3')
pygame.mixer.music.queue('03ChibiNinja.mp3')
pygame.mixer.music.queue('04AllofUs.mp3')
pygame.mixer.music.queue('05ComeandFindMe.mp3')
pygame.mixer.music.queue('06Searching.mp3')
pygame.mixer.music.queue('07WeretheResistors.mp3')
pygame.mixer.music.queue('08Ascending.mp3')
pygame.mixer.music.queue('09ComeandFindMe-Bmix.mp3')
pygame.mixer.music.queue('10Arpanauts.mp3')
pygame.mixer.music.queue('DigitalNative.mp3')
pygame.mixer.music.set_endevent()
#musicPlayer()
musicPlayer()
Am I missing something basic? Or could it have to do with my computer not the code?
Edit: this is the output from running the code
Playing music now
load song1
play song1
As you can see it throws no errors.
I tried your code with a mid file, it works fine, but there's some adjustments:
import pygame
def musicPlayer():
pygame.init()
pygame.mixer.music.load('test.mid')
print "load song1"
pygame.mixer.music.play()
print "play song1"
pygame.mixer.music.queue('test_2.mid')
musicPlayer()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
print "DONE"
if the script ends the play won't happend, for that you need to get_busy() in a while loop.
in the documentation of pygame.music it states: Be aware that MP3 support is limited [...] Consider using OGG instead.
I played a little with the Sound class.
Here's what I came up:
import pygame
def musicPlayer():
pygame.mixer.init()
channel = pygame.mixer.Channel(1)
sound = pygame.mixer.Sound('test.ogg')
channel.play(sound)
musicPlayer()
while pygame.mixer.get_busy():
pygame.time.Clock().tick(10)
print "DONE"
I'm not very familiar with pygame and its methods, but my guess is that either it cannot find the file correctly, or it's not able to correctly handle the file that it finds.
I would suggest putting the full path to audio files to see if that helps. That would rule out the issue of it not finding the files properly (although hardcoding this is obviously not a good idea long-term as any changes you make to the organizational structure of your program will likely break those paths).
And according to their documentation, their MP3 support is limited. You might try using .ogg files instead (http://www.pygame.org/docs/ref/music.html) as it could just be an issue with the encoding not being fully supported.

Stop Winsound / Stop a thread on Python

Im writing a litle game on python using Tkinter (And by the way, i am not allowed to use any other non built in modules) and I want to play a background song when on the main window, wich is the one that holds the title, and the buttons to go to other windows and stuff...
So the thing is that I need that sound to stop when I enter to another window, but when I hit the button to go, to another window, the song keeps playing...
I'm using the winsound module, and had define a couple of functions, (That by the way, are wicked as hell) to play the song when I first run the program using threads...
So here is the deal, I want something to put in the function "killsound" so that I can add it to every button, and then when I press any button to open any other window, the sound will be killed.
I was hoping something like 'a.kill()' or 'a.stop()' but it didnt worked.
And I really don´t know how to use the SND_PURGE thing on winsound... Although I understand that SND_PURGE is no longer working on new windows OS (Got Win8.1)
Could you please help me?
Thank You! (And Sorry for the creepy english...)
def Play(nombre): #This function Is the core of the winsound function
ruta = os.path.join('Audio',nombre)
Reproducir= winsound.PlaySound(ruta,winsound.SND_FILENAME)
return Reproducir
def PlayThis():
while flag_play:
try:
return Play('prettiest weed.wav')
except:
return "Error"
def PlayThisThread():
global flag_play
flag_play= True
a=Thread(target=PlayThis, args=())
a.daemon = True
a.start()
PlayThisThread()
def killsound(): #This is the function I want, for killing sound.
global flag_play
flag_play = False
There are 2 major problems in your code:
global variable flag_play has to be placed inside the sound playback loop, in your case within the PlayThis() function
the Winsound module is aiming simple non-threaded usage. while the sound is playbacked, there is no chance to "softly" interrupt. It does not support any playback status reporting e.g. .isPlaying() nor any kind of .stop() that you need in order to kill it.
Solution:
try PyMedia package. Pymedia allows lower-level audio manipulation therefore more details have to be provided at the initialisation:
import time, wave, pymedia.audio.sound as sound
# little to do on the proper audio setup
f= wave.open( 'prettiest weed.wav', 'rb' )
sampleRate= f.getframerate() # reads framerate from the file
channels= f.getnchannels()
format= sound.AFMT_S16_LE # this sets the audio format to most common WAV with 16-bit codec PCM Linear Little Endian, use either pymedia or any external utils such as FFMPEG to check / corvert audio into a proper format.
audioBuffer = 300000 # you are able to control how much audio data is read
with the following assigment the "snd" becomes an instance of the class sound.Output and gives you bunch of useful audio methods:
snd= sound.Output( sampleRate, channels, format )
s= f.readframes( audioBuffer )
snd.play( s )
and finally your threaded playback loop might look as follows:
while snd.isPlaying():
global flag_play
if not flag_play: snd.stop() #here is where the playback gets interupted.
time.sleep( 0.05 )
f.close()
Please, let me know if you need more support on this.
I also created a 0.5 sec wavfile in Adobe Audition containing silence and attached it to the stop button, and this basically "stopped" playback of the previously played audio clip.
I found a way to do it, by adding a 0.5sec sound to a button, so that when I press the button it stops the background one to play the button one, and then stops all sounds on program.

Find the Length of a Song with Pygame

I'm building an Radio Automation Program, but I can't figure out how to have a timer countdown the number of seconds left in the song. I'm currently using Pygame and don't really want to load another toolkit just for this. So far I can make a timer count up using this:
import pygame
#setup music
track = "Music/Track02.wav"
pygame.mixer.music.load(track)
pygame.mixer.music.play()
print("Playing Music")
while(pygame.mixer.music.get_busy()):
print "\r"+str(pygame.mixer.music.get_pos()),
But I have no idea how to get the total length of the song and countdown without having played the song already.
You could also load the song as a normal sound and then check the length while using mixer.music for playing it.
a = pygame.mixer.Sound("test.wav")
print("length",a.get_length())
The mutagen.mp3 can be used to find the length of music.
Firstly: pip install mutagen
-> İmport:
from pygame import *
from mutagen.mp3 import MP3
-> Use:
mixer.music.load('example.mp3')
song = MP3('example.mp3')
songLength = song.info.length
Check the Documentation. According to the site, this function returns the length of a sound object in seconds. So, time remaining is simply (pygame.mixer.music.get_length() - pygame.mixer.music.get_pos())*-1.
That way, it displays as a negative number like most time remaining counters do in a music player. Note, I don't have pygame on this computer, so I can't test it. So, check it just to make sure.

Categories

Resources