When I want to start to play an mp4 file from python using python-vlc, I will do
import vlc
from time import sleep
movie = "/path/to/movie.mp4"
subs = "/path/to/subs.srt"
i = vlc.Instance()
media_player = i.media_player_new()
media = i.media_new(movie)
media.slaves_add(vlc.MediaSlaveType.subtitle, 1, "file://{}".format(subs))
media_player.set_media(media)
media_player.play()
sleep(10)
However, I now have an mkv file which includes an srt file. How would I start playing this file using python-vlc with the included srt file?
One way to do it is to give options when you create the Instance. E.g.:
i = vlc.Instance((' --sub-file <your srt file> '))
I have gotten this to work.
Related
I created script which one downloading video and sound from Youtube, and after that merging sound and video with ffmpeg, i wondering is another way to make same result but in faster way? Because this script takes about 7 min ~ depends on Video quality and duration. My code bellow:
from pytube import YouTube
import sys
import ffmpeg
import os
class Downloader(YouTube):
def __init__(self, link):
self.link = YouTube(link)
self.hq = []
self.best_video = []
self.best_sound = []
def stream_objects(self):
q = [self.hq.append(x) for x in self.link.streams.all()]
self.best_video.append(str(self.hq[1]).split()[1].split('\"')[1])
self.best_sound.append(str(self.hq[-1]).split()[1].split('\"')[1])
return self.best_video, self.best_sound
def downloady(self):
vid = self.link.streams.get_by_itag(str(self.best_video).strip("['']"))
audio = self.link.streams.get_by_itag(str(self.best_sound).strip("['']"))
self.vid_title = (f"{vid.title}"+".mp4")
vid.download(filename='video')
audio.download(filename='audio')
print('Downloaded, Now Starting Merge \n\n\n\n\n')
print(f'{self.vid_title}'+'\n')
def merge(self):
ffmpeg.output(ffmpeg.input('video.mp4'), ffmpeg.input('audio.webm'), self.vid_title).run()
os.remove('video.mp4')
os.remove('audio.webm')
if __name__=='__main__':
a = Downloader(link = sys.argv[1])
a.stream_objects()
a.downloady()
a.merge()
OKE UPDATE:
Now code looks like that..Second problem is slow downloading mp4 files from YouTube server, i have 10Gb/s internet. Good connection with YT servers, but why so poor downloading ? ? ? :)
from pytube import YouTube
import sys
import ffmpeg
import os
import subprocess
class Downloader(YouTube):
def __init__(self, link):
self.link = YouTube(link)
self.hq = []
def stream_objects(self):
self.best = self.link.streams.filter(file_extension='mp4')
q = [self.hq.append(x) for x in self.best.all()]
self.best_vid_itag = str(self.best.all()[1]).split()[1].split('\"')[1]
self.best_audio_itag = str(self.best.all()[-1]).split()[1].split('\"')[1]
def downloader(self):
vid = self.link.streams.get_by_itag(self.best_vid_itag)
aud = self.link.streams.get_by_itag(self.best_audio_itag)
print('Donwloading Video file...\n')
vid.download(filename='video')
print('Video file downloaded... Now Trying download Audio file..\n')
aud.download(filename='audio')
print('Audio file downloaded... Now Trying to merge audio and video files...\n')
def merger(self):
lin = str(self.link.title).rstrip()
lin2 = (lin+'.mp4')
subprocess.run(f'ffmpeg -i video.mp4 -i audio.mp4 -c copy "{lin2}"', shell=True)
os.remove('video.mp4')
os.remove('audio.mp4')
print('Done....\n')
if __name__=='__main__':
a = Downloader(link = sys.argv[1])
a.stream_objects()
a.downloader()
a.merger()
First of all you download a video file and audio file with different encoding
In your case it is mp4 and webm
You should for example download an mp4 video and m4a audio
Or a webm video and a webm audio
Then it comes to ffmpeg, you should pass a parameter “-c copy”
Example for ffmpeg comand line:
ffmpeg -i myvideo.mp4 -i myaudio.m4a -c copy output.mp4
Here is a link to a python project on github use same technique
https://github.com/pyIDM/pyIDM
Check video.py file
Further explanation:
When you use “-c copy” parameter, ffmpeg will just copy the audio track and merge it with video provided that both audio and video has same codec container, this process take less than 2 seconds
Otherwise it will process every frame in video and every bit in audio then convert them to a desired format, which takes very long time
I am new with Python and I thought that it would be funny to play with music by creating a playlist. The code I wrote plays the mp3 files saved in my Music folder. Now I want to pause/resume while the script is running.
Any tips and recommendations are well received.
import vlc
from mutagen.mp3
import MP3
from glob import glob
import time
##Directory for Music Files########
audio_dir = '/path/to/Music'
files = glob (audio_dir + '/*.mp3')
####################################
for filename in files:
current_song = vlc.MediaPlayer(filename)
audio_specs = MP3(filename)
current_song.play()
time.sleep(audio_specs.info.length)
current_song.stop()
You can use Keyboard library to catch input from your keyboard and map that to the player.
import keyboard
keyboard.add_hotkey('p', current_song.pause, args=None)
keyboard.add_hotkey('r', current_song.play, args=None)
I have a video file named 'video.mp4'. I am trying to seperate a section of audio from the video and save it as a wav file that can be used with other Python modules. I want to do this with MoviePy.
I send parameters to the write_audiofile function, specifying the filename, fps, nbyte, and codec.
Following the MoviePy AudioClip docs, I specified the codec as ‘pcm_s32le’ for a 32-bit wav file.
from moviepy.editor import *
sound = AudioFileClip("video.mp4")
newsound = sound.subclip("00:00:13","00:00:15") #audio from 13 to 15 seconds
newsound.write_audiofile("sound.wav", 44100, 2, 2000,"pcm_s32le")
This code generates a .wav file, named 'sound.wav'.
Opening the audio file in Audacity
The resulting file, sound.wav, can be opened in Audacity, however I run into problems when I try to use it as a wav file with other Python modules.
Playing the sound file in pygame
import pygame
pygame.mixer.init()
sound=pygame.mixer.Sound("sound.wav")
The third line gives the following error:
pygame.error: Unable to open file 'sound.wav'
Determining type of sound file using sndhdr.what()
import sndhdr
sndhdr.what("sound.wav")
The sndhdr method returned none
. According to the docs, when this happens, the method failed to determine the type of sound data stored in the file.
Reading the file with Google Speech Recognition
import speech_recognition as sr
r = sr.Recognizer()
audio = "sound.wav"
with sr.AudioFile(audio) as source:
audio = r.record(source)
text= r.recognize_google(audio)
print(text)
This code stops execution on the second to last line:
ValueError: Audio file could not be read as PCM WAV, AIFF/AIFF-C, or Native FLAC; check if file is corrupted or in another format
Why does the audio file open in Audacity, if sndhdr.what() can not recognize it as an audio file type?
How can I properly export a MoviePy AudioClip as a wav file?
I had the same issue with no codec specified or with codec = 'pcms32le', the one that worked for me was pcm_s16le.
Note that I am using "fr-FR" language, you should probably adapt to yur needs.
here is the entire code :
# Python code to convert video to audio
import moviepy.editor as mp
import speech_recognition as sr
# Insert Local Video File Path
clip = mp.VideoFileClip("/tmp/data/test.mp4")
# Insert Local Audio File Path
clip.audio.write_audiofile("/tmp/data/test.wav",codec='pcm_s16le')
# initialize the recognizer
r = sr.Recognizer()
# open the file
with sr.AudioFile("/tmp/data/test.wav") as source:
# listen for the data (load audio to memory)
audio_data = r.record(source)
# recognize (convert from speech to text)
text = r.recognize_google(audio_data, language = "fr-FR")
print(text)
I had the same issue. I was trying to get a mp4 file from URL, then convert It into wav file and call Google Speech Recognition over It. Instead I used pydub to handle conversion and it worked! Here's a sample of the code:
import requests
import io
import speech_recognition as sr
from pydub import AudioSegment
# This function translate speech to text
def speech_to_text(file):
recognizer = sr.Recognizer()
audio = sr.AudioFile(file)
with audio as source:
speech = recognizer.record(source)
try:
# Call recognizer with audio and language
text = recognizer.recognize_google(speech, language='pt-BR')
print("Você disse: " + text)
return text
# If recognizer don't understand
except:
print("Não entendi")
def mp4_to_wav(file):
audio = AudioSegment.from_file(file, format="mp4")
audio.export("audio.wav", format="wav")
return audio
def mp4_to_wav_mem(file):
audio = AudioSegment.from_file_using_temporary_files(file, 'mp4')
file = io.BytesIO()
file = audio.export(file, format="wav")
file.seek(0)
return file
url = ''
r = requests.get(url, stream=True)
file = io.BytesIO(r.content)
file = mp4_to_wav_mem(file)
speech_to_text(file)
Note that I wrote two functions: mp4_to_wav and mp4_to_wav_mem. The only difference is mp4_to_wav_mem handle all files in memory and mp4_to_wav generates .wav file.
I read the docs of MoviePy and found that the parameter nbyte should be consistent with codec. nbyte is for the Sample width (set to 2 for 16-bit sound, 4 for 32-bit sound). Hence, it better set nbyte=4, when you set codec=pcm_s32le.
i think this is the right method:
import os
from moviepy.editor import AudioFileClip
PATH= "files/"
fileName = "nameOfYourFile.mp4"
newFileName = "nameOfTheNewFile"
Ext = "wav"
AudioFileClip(os.path.join(PATH, f"{fileName}")).write_audiofile(os.path.join(PATH, f"{newFileName}.{Ext}"))
I think this approach is very easy to understand.
from moviepy.editor import *
input_file = "../Database/myvoice.mp4"
output_file = "../Database/myvoice.wav"
sound = AudioFileClip(input_file)
sound.write_audiofile(output_file, 44100, 2, 2000,"pcm_s32le")
I am getting an error when writing to an audio file.
Basically, I am overwriting the data in the mp3 whenever my function gets called and then playing it.
It works the first time through, but then gives me [Errno 13] Permission denied: 'file.mp3' then on.
Here is the code:
def speech(self, response):
audio_file = "response.mp3"
tts = gTTS(text=str(response), lang="en")
tts.save(audio_file)
pygame.mixer.init()
pygame.mixer.music.load(audio_file)
pygame.mixer.music.play()
Error is on the tts.save line.
More info:
Traceback (most recent call last):
File "myprojectpath", line 63, in speech
tts.save(audio_file)
File "C:\Python35\lib\site-packages\gtts\tts.py", line 93, in save
with open(savefile, 'wb') as f:
Thanks!
from gtts import gTTS
import playsound
import os
x = ['sunny', 'sagar', 'akhil']
tts = 'tts'
for i in range(0,3):
tts = gTTS(text= x[i], lang = 'en')
file1 = str("hello" + str(i) + ".mp3")
tts.save(file1)
playsound.playsound(file1,True)
print 'after'
os.remove(file1)
change the file name every time you save it, this worked for me.
You should name your file for a unique name each time , so the solution that I realized is to name your file with date like this ==>
date_string = datetime.now().strftime("%d%m%Y%H%M%S")
filename = "voice"+date_string+".mp3"
tts.save(filename)
playsound.playsound(filename)
You can create another file in the same folder, just copy and rename it.
File you want to use: ("C:/.../file.mp3")
copied file: ("C:/.../file_copy.mp3")
You can change the file loaded in mixer.music.load("C:/.../file.mp3") to mixer.music.load("C:/.../file_copy.mp3") and delete delete the ("C:/.../file.mp3") without problem using this:
from pygame import mixer
import os
mixer.music.load("C:/.../file.mp3")
mixer.music.play()
mixer.music.load("C:/.../file_copy.mp3")
os.remove("C:/.../file.mp3")
but the code above will remove the file before even playing it, so you can use a method to await it play:
from pygame import mixer
import os
mixer.music.load("C:/.../file.mp3")
mixer.music.play()
while mixer.music.get_busy(): # check if the file is playing
pass
mixer.music.load("C:/.../file_copy.mp3")
os.remove("C:/.../file.mp3")
try to save the fi open an other file whitout playing, then you will have the permission to delete it here is the talk function:
def Talk (mytext, language= "fr" ):
myobj = gTTS(text=mytext, lang=language, slow=False)
myobj.save("1.mp3")
mixer.init()
mixer.music.load("1.mp3")
mixer.music.set_volume(1)
mixer.music.play()
mixer.music.get_endevent()
while mixer.music.get_busy():
continue
mixer.music.load("Talker\empty.mp3")
os.remove("1.mp3")
You are getting this error because the mixer is not releasing that audio file. If you want to mixer release that file you can load a useless or empty file into a mixer. Then you can overwrite that audio file.
E. g.. Mixer.load("C:/...../empty.mp3")
After this previously loaded file is released.
if you don't want the file before saved anymore, you can delete the audio file before saving the next file. so, you can save the new file with the same name.
bellow is the code I ran successfully
import speech_recognition as ram
from playsound import playsound
from gtts import gTTS
import os
r=ram.Recognizer()
with ram.Microphone() as source:
while True:
r.adjust_for_ambient_noise(source,duration=1)
print("I'm Listening....")
playsound('audio/listen.mp3')
audio=r.listen(source, timeout=5)
text=r.recognize_google(audio)
tts = gTTS("Boss. you said "+str(text)+". i'm opening it")
tts.save('audio/text.mp3')
print("you said "+text+".")
playsound('audio/text.mp3')
os.remove('audio/text.mp3')
a much better solution is this, if i had the time i would also calculate the probability of ever landing a same file
from gtts import gTTS
from playsound import playsound
import random
import os
#creating a super random named file
r1 = random.randint(1,10000000)
r2 = random.randint(1,10000000)
randfile = str(r2)+"randomtext"+str(r1) +".mp3"
tts = gTTS(text='hey, STOP It!!', lang='en', slow=True)
tts.save(randfile)
playsound(randfile)
print(randfile)
os.remove(randfile)
I have faced the same problem, then figure it out that the file is pointing to the previous position so I have to release it. It works fine and important thing is that it does not create an mp3 file also. If you don't release it, it will work fine for the first time and save the audio file then the error occurs for the second time.
from gtts import gTTS
import os
import playsound
def tts(text, lang):
file = gTTS(text = text, lang = lang)
file.save("audio/speak_func.mp3")
playsound.playsound('audio/speak_func.mp3', True)
os.remove("audio/speak_func.mp3")
Basically what i want is TTS in python 3...
I already tried pyttsx but aparently it only works with python 2
I already tried other things too...
Now i'm trying with the api from voicerss.org but i can't figure out how can HTTP GET it and then play it with python with pyglet...
here is my code so far:
import pyglet
import urllib3
http = urllib3.PoolManager()
speechrequest = http.request('GET', 'http://api.voicerss.org/?key=04f49802d32d442ca997d4d2ea76d3d5&hl=pt-pt&c=wav&src=texto')
speech = pyglet.media.load(speechrequest)
speech.play()
pyglet.app.run()
The errors are:
Traceback (most recent call last):
File "C:/Users/Diogo/Documents/test.py", line 6, in <module>
speech = pyglet.media.load(speechrequest)
File "C:\Users\Diogo\AppData\Local\Programs\Python\Python35\lib\site-packages\pyglet\media\__init__.py", line 1429, in load
source = get_source_loader().load(filename, file)
File "C:\Users\Diogo\AppData\Local\Programs\Python\Python35\lib\site-packages\pyglet\media\__init__.py", line 1410, in load
return riff.WaveSource(filename, file)
File "C:\Users\Diogo\AppData\Local\Programs\Python\Python35\lib\site-packages\pyglet\media\riff.py", line 185, in __init__
file = open(filename, 'rb')
TypeError: invalid file: <urllib3.response.HTTPResponse object at 0x0000002EB0730D30>
i guess its not returning an wav file to python don't know why because. If i enter 'http://api.voicerss.org/?key=04f49802d32d442ca997d4d2ea76d3d5&hl=pt-pt&c=wav&src=texto' in internet explorer it returns a wav file...
So, my questions are:
what i am doing wrong with the code or if is impossible this way how can python speak?
Please be patient with me, i'm only 18 years old and i can't speak english properly, because i'm portuguese...
You could save the remote wav file locally and play it using a default application:
#!/usr/bin/env python3
from urllib.request import urlretrieve
import webbrowser
filename = 'speech.wav'
urlretrieve("http://api.voicerss.org/?key=04f49802d32d442ca997d4d2ea76d3d5"
"&hl=pt-pt&c=wav&src=texto", filename)
webbrowser.open(filename) # play the file using default application
On Windows, you could use os.startfile() instead of webbrowser.open() or to play the wav file directly in Python without an external application:
import winsound
winsound.PlaySound('speech.wav', winsound.SND_FILENAME)
Your code have at least two issues:
You should pass a filename (a string) to pyglet.media.load() function, not an HTTPResponse object.
pyglet may fail to play it anyway: I get pyglet.media.riff.RIFFFormatException: Size of format chunk is incorrect. error on my system.
You could also play a remote wav file without saving it to disk i.e., you can play streaming content:
#!/usr/bin/env python3
from urllib.parse import quote
from urllib.request import urlopen
api_key = open('api.key', encoding='ascii').read().strip()
language = 'pt-pt'
text = quote("1 2 3")
playwav(urlopen('https://api.voicerss.org/?c=wav&f=8khz_8bit_mono&ssml=false&'
'key={api_key}&src={text}&hl={language}'.format(**vars())))
where playwav():
import wave
from contextlib import closing
import pyaudio # Windows: py -m pip install pyaudio
# $ sudo apt-get install python{,3}-pyaudio
player = None
def playwav(path_or_file):
global player
if player is None:
player = pyaudio.PyAudio()
with closing(wave.open(path_or_file, 'rb')) as wavfile, \
closing(player.open(
format=player.get_format_from_width(wavfile.getsampwidth()),
channels=wavfile.getnchannels(),
rate=wavfile.getframerate(),
output=True)) as stream:
while True:
data = wavfile.readframes(1024) # read 1024 frames at once
if not data: # EOF
break
stream.write(data)