How to play an audio file from python terminal - python

I am using librosa library to do data analysis on an audio file in .wav format. But it seems librosa can only read or write audio file in form of an array apart from feature extraction. I would also like to play the audio file with my analysis code.
In Ipython notebook, I can use Ipython.display.audio to play audio directly in Ipython ntoebook, but when I convert code to .py, I doesn't work, so I need something that can be used for the same purpose.

You could use pydub to load the audio file (mp3, wav, ogg, raw) and simpleaudio for playback. Just do
sound = pydub.AudioSegment.from_wav('audiofile.wav')
playback = simpleaudio.play_buffer(
sound.raw_data,
num_channels=sound.channels,
bytes_per_sample=sound.sample_width,
sample_rate=sound.frame_rate
)
And voila! you finally got your beats going. To stop just call playback.stop()

If you want to use a blacking mode where the execution will wait until the streaming is finished you can use pyaudio blocking mode full documentation
example:
"""PyAudio Example: Play a wave file."""
import pyaudio
import wave
import sys
CHUNK = 1024
if len(sys.argv) < 2:
print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
sys.exit(-1)
wf = wave.open(sys.argv[1], 'rb')
# instantiate PyAudio (1)
p = pyaudio.PyAudio()
# open stream (2)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
# read data
data = wf.readframes(CHUNK)
# play stream (3)
while len(data) > 0:
stream.write(data)
data = wf.readframes(CHUNK)
# stop stream (4)
stream.stop_stream()
stream.close()
# close PyAudio (5)
p.terminate()

Related

Saving audio from mp4 as wav file using Moviepy Audiofile

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")

Play Audio file on Raspberry Pi 3B+ in Python 3 IDLE

Installed pyglet, pygame and other libraries to run the audio file recorded using the pyAudio code. No error occurs and the code runs successfully but no sound is heard in the output speaker/headsets/earphones.
The audio output jack is working otherwise but doesn't play audio when we run any audio file through python shell module coding.
What can be the issue?
import pyaudio
import wave
import sys
CHUNK = 1024
if len(sys.argv) < 2:
print("Plays a wave file.\n\nUsage: %s test2.wav" % sys.argv[0])
sys.exit(-1)
wf = wave.open(sys.argv[1], 'rb')
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
data = wf.readframes(CHUNK)
while data != '':
stream.write(data)
data = wf.readframes(CHUNK)
stream.stop_stream()
stream.close()
p.terminate()

Read in Python a wav file to which data is being appended

I need to transcribe the speech that is being written to a wav file. I've implemented the following iterator to try to incrementally read the audio from the file:
import wave
def read_audio(path, chunk_size=1024):
wave_file = wave.open(open(path, 'rb'))
while True:
data = wave_file.readframes(chunk_size)
if data != "":
yield data
In order to test the generator, I've implemented a function that keeps writing to a wav file the audio captured by the computer's microphone:
import pyaudio
def record_to_file(out_path):
fmt = pyaudio.paInt16
channels = 1
rate = 16000
chunk = 1024
audio = pyaudio.PyAudio()
stream = audio.open(format=fmt, channels=channels,
rate=rate, input=True,
frames_per_buffer=chunk)
wave_file = wave.open(out_path, 'wb')
wave_file.setnchannels(channels)
wave_file.setsampwidth(audio.get_sample_size(fmt))
wave_file.setframerate(rate)
while True:
data = stream.read(chunk)
waveFile.writeframes(data)
Below is the test script:
import threading
import time
WAV_PATH='out.wav'
def record_worker():
record_to_file(WAV_PATH)
if __name__=='__main__':
t = threading.Thread(target=record_worker)
t.setDaemon(True)
t.start()
time.sleep(5)
reader = read_audio(WAV_PATH)
for chunk in reader:
print(len(chunk))
It doesn't work as I'd expect - the reader stops yielding after a while. Since the test is successful if I adapt record_file to set the wav file's nframes to a very large number beforehand and do the writing with writeframesraw, my guess is that wave.open eagerly reads nframes, not trying to read anything after that number of frames has been read.
Is it possible to obtain that incremental read in Python 2.7 without resorting to this setnframes hack? It's worth noting that, contrary to the test script, I have no control of the wav file's generation in the scenario in which I plan to utilize such feature. The writing gets done by a SWIG-adapted C library named pjsip (http://www.pjsip.org/python/pjsua.htm), so I don't expect it to be possible to do any modifications on that end.

Playing music with Python while having an active and interactable GUI

I am testing how to play background music with Python for a school project. I made a clone of the game "simon" and have been trying to add background music to it as testing for when I put the music in my actual project. I have tried this in several ways, but the only one that allowed me to play any music was by using code I found on another site:
#!usr/bin/env python
#coding=utf-8
import pyaudio
import wave
#define stream chunk
chunk = 1024
#open a wav format music
f = wave.open("F:\Python\pythont-testing\SIMON\Heavy Metal Psycho Nu Metal.wav")
#instantiate PyAudio
p = pyaudio.PyAudio()
#open stream H
stream = p.open(format = p.get_format_from_width(f.getsampwidth()), channels = f.getnchannels(), rate = f.getframerate(), output = True)
#read data
data = f.readframes(chunk)
#paly stream
while data != '':
stream.write(data)
data = f.readframes(chunk)
#close PyAudio
p.terminate()
When I added this to the code for the clone I made, the GUI would stop responding. I used a sound editor to cut the code down from its full time to 10 seconds to test whether this fixed itself once the song finished. As it turns out, once the song has finished, the GUI starts responding again, but all of the buttons on the GUI do not function.
How I inserted this code (I assumed that since I was using a function, this would not mess with the "root.mainloop" which runs the GUI.
def play_music():
#define stream chunk
chunk = 1024
#open a wav format music
f = wave.open("F:\Python\pythont-testing\SIMON\Heavy Metal.wav")
#instantiate PyAudio
p = pyaudio.PyAudio()
#open stream
stream = p.open(format = p.get_format_from_width(f.getsampwidth()), channels = f.getnchannels(), rate = f.getframerate(), output = True)
#read data
data = f.readframes(chunk)
#play stream
while data != '':
stream.write(data)
data = f.readframes(chunk)
#close PyAudio
p.terminate()
play_music()
root.mainloop()

POST ".wav" File to URL with Python, print Response How To?

So here we have a Python script:
""" Record a few seconds of audio and save to a WAVE file. """
import pyaudio
import wave
import sys
chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
frames_per_buffer = chunk)
print "* recording"
all = []
for i in range(0, RATE / chunk * RECORD_SECONDS):
data = stream.read(chunk)
all.append(data)
print "* done recording"
stream.close()
p.terminate()
# write data to WAVE file
data = ''.join(all)
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(data)
wf.close()
And this script does what the first comentary line says, if you run it in terminal it will output a ".wav" file in the path you're set in the moment of the execution... What I want to do is to get that file and "manipule" it, instead of outputting it to the Computer, I want to store it in a variable or something like that, and then I would like to POST it to an URL parsing some parametters along with it... I saw some interesting examples of posting multipart-encoded files using requests, as you can see here:
http://docs.python-requests.org/en/latest/user/quickstart/
But I made several attempts of achieving what I'm descripting in this question and I was unlucky... Maybe a little guidance will help with this one :)
Being Brief, what I need is to record a WAV file from microphone and then POST it to an URL (Parsing Data like the Headers with it) and then get the output in a print statement or something like that in the terminal...
Thank You!!
wave.open lets you pass either a file name or a file-like object to save into. If you pass in a StringIO object rather than WAVE_OUTPUT_FILENAME, you'll can get a string object that you can presumably use to construct a POST request.
Note that this will load the file into memory -- if it might be really long, you might prefer to do it into a temporary file and then use that to make your request. Of course, you're already loading it into memory, so maybe that's not an issue.

Categories

Resources