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

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.

Related

How can I play audio (playsound) in the background of a Python script?

I am just writing a small Python game for fun and I have a function that does the beginning narrative.
I am trying to get the audio to play in the background, but unfortunately the MP3 file plays first before the function continues.
How do I get it to run in the background?
import playsound
def displayIntro():
playsound.playsound('storm.mp3',True)
print('')
print('')
print_slow('The year is 1845, you have just arrived home...')
Also, is there a way of controlling the volume of the playsound module?
I am using a Mac, and I am not wedded to using playsound. It just seems to be the only module that I can get working.
Just change True to False (I use Python 3.7.1)
import playsound
playsound.playsound('storm.mp3', False)
print ('...')
In Windows:
Use winsound.SND_ASYNC to play them asynchronously:
import winsound
winsound.PlaySound("filename", winsound.SND_ASYNC | winsound.SND_ALIAS )
To stop playing
winsound.PlaySound(None, winsound.SND_ASYNC)
On Mac or other platforms:
You can try this Pygame/SDL
pygame.mixer.init()
pygame.mixer.music.load("file.mp3")
pygame.mixer.music.play()
There is a library in Pygame called mixer and you can add an MP3 file to the folder with the Python script inside and put code like this inside:
from pygame import mixer
mixer.init()
mixer.music.load("mysong.mp3")
mixer.music.play()
Well, you could just use pygame.mixer.music.play(x):
#!/usr/bin/env python3
# Any problems contact me on Instagram, #vulnerabilties
import pygame
pygame.mixer.init()
pygame.mixer.music.load('filename.extention')
pygame.mixer.music.play(999)
# Your code here
A nice way to do it is to use vlc. Very common and supported library.
pip install python-vlc
Then writing your code
import vlc
#Then instantiate a MediaPlayer object
player = vlc.MediaPlayer("/path/to/song.mp3")
#And then use the play method
player.play()
#You can also use the methods pause() and stop if you need.
player.pause()
player.stop
#And for the super fancy thing you can even use a playlist :)
playlist = ['/path/to/song1.mp3', '/path/to/song2.mp3', '/path/to/song3.mp3']
for song in playlist:
player = vlc.MediaPlayer(song)
player.play()
You could try just_playback. It's a wrapper I wrote around miniaudio that plays audio in the background while providing playback control functionality like pausing, resuming, seeking and setting the playback volume.
from pygame import mixer
mixer.music.init()
mixer.music.load("audio.mp3") # Paste The audio file location
mixer.play()
Use vlc
import vlc
player = None
def play(sound_file):
global player
if player is not None:
player.stop()
player = vlc.MediaPlayer("file://" + sound_file)
player.play()
This is a solution to reproduce similar length sounds. This solution worked to me to solve the error:
The specified device is not open or recognized by MCI.
Here follow the syntax as a class method, but you can change it to work even without a class.
Import these packages:
import multiprocessing
import threading
import time
Define this function:
def _reproduce_sound_nb(self, str_, time_s):
def reproduce_and_kill(str_, time_sec=time_s):
p = multiprocessing.Process(target=playsound, args=(str_,))
p.start()
time.sleep(time_sec)
p.terminate()
threading.Thread(target=reproduce_and_kill, args=(str_, time_s), daemon=True).start()
In the main program/method:
self._reproduce_sound_nb(sound_path, 3) # path to the sound, seconds after sound stop -> to manage the process end
I used a separate thread to play the sound without blocking the main thread. It works on Ubuntu as well.
from threading import Thread
from playsound import playsound
def play(path):
"""
Play sound file in a separate thread
(don't block current thread)
"""
def play_thread_function:
playsound(path)
play_thread = Thread(target=play_thread_function)
play_thread.start()

Music player for Python not working

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)

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