I'm using AWS Lex to generate a response to my sound (http://boto3.readthedocs.io/en/latest/reference/services/lex-runtime.html).
The response audioStream is a StreamingBody object from boto3 (https://botocore.readthedocs.io/en/latest/reference/response.html#botocore.response.StreamingBody).
The question is how can I turn the returned byte array to a wav file that I can play with sox?
I have tried the following:
audio_stream = response['audioStream'].read()
f = open('response.wav', 'wb')
f.write(audio_stream)
f.close()
But then I get an error with sox and aplay that the format is invalid (RIFF header was not found)
I also tried to use the wave library with the following code
audio_stream = response['audioStream'].read()
f = wave.open('response.wav', 'wb')
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(16000)
f.writeframesraw(audio_stream)
f.close()
But then I only get white noise when I play the file and the length is very short.
The answer was to close the stream before writing it to the file. The working code looks like this:
audio_stream = response['audioStream'].read()
response['audioStream'].close()
f = wave.open(self.response_fname, 'wb')
f.setnchannels(2)
f.setsampwidth(2)
f.setframerate(16000)
f.setnframes(0)
f.writeframesraw(audio_stream)
f.close()
Related
I am merging videos in python.(ffmpeg,moviepy)
But it is very slow.
So, I am trying to encode a 1.mp4 file and a 2.mp4 file using base64 and combine them.
I have the code below.
import base64
with open('1.mp4', "rb") as videoFile:
text = base64.b64encode(videoFile.read())
with open("2.mp4", "rb") as videoFile:
texts = base64.b64encode(videoFile.read())
fh = open("dfghhffdssdf.mp4", "wb")
fh.write(base64.b64decode(text+texts))
fh.close()
I tried running the code and the video didn't merge.
So I created a new code like below.
import base64
with open('1.mp4', "rb") as videoFile:
text = base64.b64encode(videoFile.read())
with open("2.mp4", "rb") as videoFile:
texts = base64.b64encode(videoFile.read())
text = str(text).replace("=","") + str(texts)
fh = open("dfghhffdssdf.mp4", "wb")
fh.write(base64.b64decode(text+texts))
fh.close()
Then, the following error is displayed.
can only concatenate str (not "bytes") to str
Therefore, if you replace the "text" variable with bytes with the bytes function, you will get the following error:
string argument without an encoding
What should I do?
If that's not possible, please tell me how to quickly merge video files.
I have audio recordings saved on a server as base64, webm format and want to decode them with python into a wav file. I tried both suggested ways from a simliar question found here: How to decode base64 String directly to binary audio format. But I'm facing different problems with both suggestions:
The version using file.write resulted in a wav file that I could play with the VLC player and which included the expected content. But I got an error message when I tried to read it with matlab or python saying "unknown format" or "missing riff".
fin = open(dirName + file, "r")
b64_str = fin.read()
fin.close()
# decode base64 string to original binary sound object
decodedData = base64.b64decode(b64_str)
webmfile = (outdir + file.split('.')[0] + ".webm")
wavfile = (outdir + file.split('.')[0] + ".wav")
with open(webmfile , 'wb') as wm:
wm.write(decodedData)
with open(webmfile, 'rb') as wm:
webmdata = pcm.read()
with open(wavfile, 'wb') as file:
file.write(webmdata)
The version using writeframes with setting the parameters result in a file I could read with matlab or python but this one does not contain the expected content and is way shorter than expected.
with wave.open(wavfile, 'wb') as wav:
wav.setparams((1, 2, 48000, 0, 'NONE', 'NONE'))
wav.writeframes(webmdata)
Any ideas on how to solve this problem? The file itself is fine. Converting it with an online converter worked.
In case someone has the same problem at some point, here is the solution which worked for me:
The following code creates a webm file from the base64 str:
import base64
decodedData = base64.b64decode(b64_str)
webmfile = (outdir + file.split('.')[0] + ".webm")
with open(webmfile, 'wb') as file:
file.write(decodedData)
And for the conversion I used ffmpy:
from ffmpy import FFmpeg
ff = FFmpeg(
executable = 'C:/Program Files/ffmpeg-2020/bin/ffmpeg.exe',
inputs={file:None},
outputs = {outfile:'-c:a pcm_f32le'})
ff.cmd
ff.run()
After those two steps, I was able to read the resulting wav file with matlab or any other program.
i have 2 microservices, A is written in java and sending a video in the form of bytes[ ] to B which is written in python.
B is doing some treatement over the video using openCV and this command in particular
stream = cv2.VideoCapture(video)
the command works fine when provided by a streaming or a ready local video, but when i give it my request.data which java is sending it says
TypeError: an integer is required (got type bytes)
so my question is :
is there any way to save a video to disk from that bytes i'm receiving from java or can i just give the bytes to cv2.capture ?
Thank you.
Just a slight improvement to your own solution: using the with context-manager closes the file for you even if something unexpected happens:
FILE_OUTPUT = 'output.avi'
# Checks and deletes the output file
# You cant have a existing file or it will through an error
if os.path.isfile(FILE_OUTPUT):
os.remove(FILE_OUTPUT)
# opens the file 'output.avi' which is accessable as 'out_file'
with open(FILE_OUTPUT, "wb") as out_file: # open for [w]riting as [b]inary
out_file.write(request.data)
i solved my problem like this :
FILE_OUTPUT = 'output.avi'
# Checks and deletes the output file
# You cant have a existing file or it will through an error
if os.path.isfile(FILE_OUTPUT):
os.remove(FILE_OUTPUT)
out_file = open(FILE_OUTPUT, "wb") # open for [w]riting as [b]inary
out_file.write(request.data)
out_file.close()
I want to take a video - take the video contents - and turn it into base64. Then, I want to take that text file - decode it from base64 - and then turn it back into a video.
Currently, I have been able to turn the video into a text file, but when I try to convert it back into a video I get an empty text file instead of a video file.
How do I fix this?
import base64
with open("al.mp4", "rb") as videoFile:
text = base64.b64encode(videoFile.read())
print(text)
file = open("textTest.txt", "wb")
file.write(text)
file.close()
fh = open("video.mp4", "wb")
fh.write(base64.b64decode(str))
fh.close()
import base64
with open("al.mp4", "rb") as videoFile:
text = base64.b64encode(videoFile.read())
print(text)
file = open("textTest.txt", "wb")
file.write(text)
file.close()
fh = open("video.mp4", "wb")
fh.write(base64.b64decode(text))
fh.close()
This is the code that works.
You were trying to write str to the file. Now str in python is the name of the string class. You can do something like str = "assda" but that is not recommended. And furthermore, str is not the stuff you just read from the file. That is text. Just write text and you're good.
I have a local python file that decodes binary files. This python file first reads from the file, opens it as binary and then saves it in a buffer and interprets it. Reading it is simply:
with open(filepath, 'rb') as f:
buff = f.read()
read_all(buff)
This works fine locally. Now I'd like to setup a Azure Python job where I can send the file, approx. 100kb, over a HTTP POST and then read the interpreted meta data which my original python script does well.
I've first removed the read function so that I'll now work with the buffer only.
In my Azure Python Job I have the following, triggered by a HttpRequest
my_data = reader.read_file(req.get_body())
To test my sending I've tried the following in python
import requests
url = 'http://localhost:7071/api/HttpTrigger'
files = {'file': open('test', 'rb')}
with open('test', 'rb') as f:
buff = f.read()
r = requests.post(url, files=files) #Try using files
r = requests.post(url, data=buff) #Try using data
I've also tried in Postman adding the file to the body as a binary and setting the headers to application/octet-stream
All this doesn't send the binary file the same way as the original f.read() did. So I'm getting a wrong interpretation of the binary file.
What is file.read doing differently to how I'm sending it over as a HTTP Body message?
Printing out the first line from the local python read file gives.
b'\n\n\xfe\xfe\x00\x00\x00\x00\\\x18,A\x18\x00\x00\x00(\x00\x00\x00\x1f\x00\x00\
Whereas printing it out at the req.get_body() shows me
b'\n\n\xef\xbf\xbd\xef\xbf\xbd\x00\x00\x00\x00\\\x18,A\x18\x00\x00\x00(\x00\x00\x00\x1f\x00\
So something is clearly wrong. Any help why this could be different?
Thanks
EDIT:
I've implemented a similar function in Flask and it works well.
The code in flask is simply grabbing the file from a POST. No encoding/decoding.
if request.method == 'POST':
f = request.files['file']
#f.save(secure_filename(f.filename))
my_data = reader.read_file(f.read())
Why is the Azure Function different?
You can try UTF-16 to decode and do the further action in your code.
Here is the code for that:
with open(path_to_file,'rb') as f:
contents = f.read()
contents = contents.rstrip("\n").decode("utf-16")
Basically after doing re.get_body, perform the below operation:
contents = contents.rstrip("\n").decode("utf-16")
See if it gives you the same output as your receive in local python file.
Hope it helps.