Playing live audio from a website using PyAudio - python

I want to build a small application capable of playing audio streams from internet radio services.
I already found this code that saves the code as a mp3-File, but I'd like to instantly play the sound.
import requests
stream_url = "http://uk5.internet-radio.com:8097/;stream"
r = requests.get(stream_url, stream=True)
with open('stream.wav', 'wb') as f:
try:
for block in r.iter_content(1024):
f.write(block)
except KeyboardInterrupt:
pass
This code doesn't work as it doesn't produce any useable sound and a lot underflowed errors occur:
stream_url = 'http://149.56.147.197:8064/;stream/1'#"""
r = requests.get(stream_url, stream=True)
pya = pyaudio.PyAudio()
stream = pya.open(format=pyaudio.paInt16, frames_per_buffer=2048, channels=2, rate=44100, output=True)
for block in r.iter_content(2048):
data = array.array("h", block)
stream.write(data,exception_on_underflow=True)
stream.stop_stream()
stream.close()
The error message:
Traceback (most recent call last):
File "/Users/bahe007/Desktop/pythonRadio.py", line 15, in <module>
stream.write(data,exception_on_underflow=True)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyaudio.py", line 586, in write
exception_on_underflow)
IOError: [Errno -9980] Output underflowed
Does anybody have ideas how I could achieve my live-streaming feature for internet radio in Python?

Related

saving data interferes with streaming

im trying to create a server script that accepts audio packets, plays them and saves the data in real time. The problem is that saving the data causes the streaming to hold until the data is saved. this happens with both Multiprocessing and Threading. Appreciate any help!
# stream audio recieved
def stream_audio():
global recording
# instantiating streaming service
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(sample_size),
channels=channel_num,
rate=sample_rate,
output=True,
frames_per_buffer=CHUNK)
#playing and saving
while recording :
try:
frame = PrePlayQue.get(True, timer)
stream.write(frame)
SaveQue.put(frame)
print("streamed a frame")
# if queue is empty for longer then timer
except queue.Empty:
print("queue is empty")
recording=False
# saving data - saving if it exceeds 3MB or after prolonged lack of audio input
finally:
if (SaveQue.qsize()>3*1024 or not recording) and (SaveQue.qsize()>1) :
print("saving to file")
#save_data = threading.Thread(target=save_audio_data(), args=())
#save_data.start()
save_data=process = multiprocessing.Process(target=save_audio_data(),
args=())
save_data.start()
# closing streaming service
stream.stop_stream()
stream.close()
p.terminate()
return
# fucntion to save data in a file
def save_audio_data():
# creates file directory if it does not exist yet
file_dir=os.path.abspath(os.sep)+"Audio recordings"
if not os.path.exists(file_dir):
try:
os.makedirs(file_dir)
# checks for file creation errors not caused by file already existing
except OSError as e:
if e.errno != errno.EEXIST:
raise
# retrieving audio from save queue
audio=SaveQue.get()
FrameNo=SaveQue.qsize()
for i in range(FrameNo):
audio+=SaveQue.get()
# saving audio data
t=datetime.datetime.now()
file_name='record'+' '+str(t.year)+'_'+str(t.month)+'_'+str(t.day)+' '+str(t.hour)+'_'+str(t.minute)+'_'+str(t.second)
data=wave.open(file_dir+ '/' +file_name+'.wav', 'wb')
data.setnchannels(channel_num)
data.setframerate(sample_rate)
data.setsampwidth(sample_size)
data.writeframes(audio)
data.close()
# making sure memory is freed
del audio
print("saved!")
return
important to note that saving works, the stream plays fine. but the as soon as the thread/process that handles the writing part is started, the streaming function is halted until it is saved.

How to solve "Audio file is corrupted or in another format" while I can listen the file, and the file is in the right format?

I'am working on a Speech to text assignment. I have an example working with an example audio file, but when I try my own audio file I receive this error:
Traceback (most recent call last):
File "<ipython-input-27-43c56c192b14>", line 1, in <module>
with input_audio as source:
File "C:\Users\AppData\Local\Continuum\anaconda3\lib\site-packages\speech_recognition\__init__.py", line 236, in __enter__
raise 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")
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
My Question: What can I do, to analyze my Audio file? Since It looks like it is in the right format..
I googled, and found another question on Stackoverflow. The author was mentioning that probably, the type of WAV file is wrong. However, when I check the type of my audio, it looks right:
import fleep
with open("my_own_audio.wav", "rb") as file:
info = fleep.get(file.read(128))
print(info.extension)
['wav']
My code so far (it is the same as the Ultimate Guide To Speech Recognition)
import os
import speech_recognition as sr
os.chdir(r'C:\Desktop\Speech_to_Text')
r = sr.Recognizer()
input_audio = sr.AudioFile('harvard.wav') # The example works!
input_audio = sr.AudioFile('my_own_audio.wav') # Will throw the error!
type(input_audio) # For both, it will print Out[29]: speech_recognition.AudioFile
# This chunk will throw the error!
with input_audio as source:
# If the data has a lot of noise.
r.adjust_for_ambient_noise(source)
audio = r.record(source)
r.recognize_google(audio, show_all = True)

Convert mp4 sound to text in python

I want to convert a sound recording from Facebook Messenger to text.
Here is an example of an .mp4 file send using Facebook's API:
https://cdn.fbsbx.com/v/t59.3654-21/15720510_10211855778255994_5430581267814940672_n.mp4/audioclip-1484407992000-3392.mp4?oh=a78286aa96c9dea29e5d07854194801c&oe=587C3833
So this file includes only audio (not video) and I want to convert it to text.
Moreover, I want to do it as fast as possible since I'll use the generated text in an almost real-time application (i.e. user sends the .mp4 file, the script translates it to text and shows it back).
I've found this example https://github.com/Uberi/speech_recognition/blob/master/examples/audio_transcribe.py
and here is the code I use:
import requests
import speech_recognition as sr
url = 'https://cdn.fbsbx.com/v/t59.3654-21/15720510_10211855778255994_5430581267814940672_n.mp4/audioclip-1484407992000-3392.mp4?oh=a78286aa96c9dea29e5d07854194801c&oe=587C3833'
r = requests.get(url)
with open("test.mp4", "wb") as handle:
for data in r.iter_content():
handle.write(data)
r = sr.Recognizer()
with sr.AudioFile('test.mp4') as source:
audio = r.record(source)
command = r.recognize_google(audio)
print command
But I'm getting this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Asterios\Anaconda2\lib\site-packages\speech_recognition\__init__.py", line 200, in __enter__
self.audio_reader = aifc.open(aiff_file, "rb")
File "C:\Users\Asterios\Anaconda2\lib\aifc.py", line 952, in open
return Aifc_read(f)
File "C:\Users\Asterios\Anaconda2\lib\aifc.py", line 347, in __init__
self.initfp(f)
File "C:\Users\Asterios\Anaconda2\lib\aifc.py", line 298, in initfp
chunk = Chunk(file)
File "C:\Users\Asterios\Anaconda2\lib\chunk.py", line 63, in __init__
raise EOFError
EOFError
Any ideas?
EDIT: I want to run the script on the free-plan of pythonanywhere.com, so I'm not sure how I can install tools like ffmpeg there.
EDIT 2: If you run the above script substituting the url with this one "http://www.wavsource.com/snds_2017-01-08_2348563217987237/people/men/about_time.wav" and change 'mp4' to 'wav', the it works fine. So it is for sure something with the file format.
Finally I found an solution. I'm posting it here in case it helps someone in the future.
Fortunately, pythonanywhere.com comes with avconv pre-installed (avconv is similar to ffmpeg).
So here is some code that works:
import urllib2
import speech_recognition as sr
import subprocess
import os
url = 'https://cdn.fbsbx.com/v/t59.3654-21/15720510_10211855778255994_5430581267814940672_n.mp4/audioclip-1484407992000-3392.mp4?oh=a78286aa96c9dea29e5d07854194801c&oe=587C3833'
mp4file = urllib2.urlopen(url)
with open("test.mp4", "wb") as handle:
handle.write(mp4file.read())
cmdline = ['avconv',
'-i',
'test.mp4',
'-vn',
'-f',
'wav',
'test.wav']
subprocess.call(cmdline)
r = sr.Recognizer()
with sr.AudioFile('test.wav') as source:
audio = r.record(source)
command = r.recognize_google(audio)
print command
os.remove("test.mp4")
os.remove("test.wav")
In the free plan, cdn.fbsbx.com was not on the white list of sites on pythonanywhere so I could not download the content with urllib2. I contacted them and they added the domain to the white list within 1-2 hours!
So a huge thanks and congrats to them for the excellent service even though I'm using the free tier.
Use Python Video Converter
https://github.com/senko/python-video-converter
import requests
import speech_recognition as sr
from converter import Converter
url = 'https://cdn.fbsbx.com/v/t59.3654-21/15720510_10211855778255994_5430581267814940672_n.mp4/audioclip-1484407992000-3392.mp4?oh=a78286aa96c9dea29e5d07854194801c&oe=587C3833'
r = requests.get(url)
c = Converter()
with open("/tmp/test.mp4", "wb") as handle:
for data in r.iter_content():
handle.write(data)
conv = c.convert('/tmp/test.mp4', '/tmp/test.wav', {
'format': 'wav',
'audio': {
'codec': 'pcm',
'samplerate': 44100,
'channels': 2
},
})
for timecode in conv:
pass
r = sr.Recognizer()
with sr.AudioFile('/tmp/test.wav') as source:
audio = r.record(source)
command = r.recognize_google(audio)
print command

How to record twitch stream in python, preferably using livestreamer?

Currently all I have is:
from livestreamer import Livestreamer
session = Livestreamer()
stream = session.streams('http://www.twitch.tv/riotgames')
stream = stream['source']
fd = stream.open()
As I'm still a newbie to python I'm at complete loss on what I should do next. How do I continuously save, let's say, last 40 seconds of the stream to file?
Here's a start:
from livestreamer import Livestreamer
session = Livestreamer()
stream = session.streams('http://www.twitch.tv/riotgames')
stream = stream['source']
fd = stream.open()
with open("/tmp/stream.dat", 'wb') as f:
while True:
data = fd.read(1024)
f.write(data)
I've tried it. You can open the /tmp/stream.dat in VLC, for example. The example will read 1 kb at a time and write it to a file.
The program will run forever so you have to interrupt it with Ctrl-C, or add some logic for that. You probably need to handle errors and the end of a stream somehow.

MP3 with Pyaudio

import pyaudio
import wave
chunk = 1024
wf = wave.open('yes.mp3', '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.close()
p.terminate()
No matter how I put this, while trying multiple methods I seem to keep getting the following error in terminal:
raise Error, 'file does not start with RIFF id'
I would use pyglet but media and all other modules aren't detected even though I'm able to import pyglet.
Any help?
You're using wave to attempt to open a file that is not wav. Instead, you're attempting to open an mp3 file. The wave module can only open wav files, so you need to convert the mp3 to wav. Here's how you can use pyglet to play an mp3 file:
import pyglet
music = pyglet.resource.media('music.mp3')
music.play()
pyglet.app.run()
It would be much simpler than the method you're trying. What errors are you getting with pyglet?

Categories