I am building a web application with ReactJS and Django framework.
In this web application, there is a part where I record an audio file and send it to the backend to save it.
This is the blob data from ReactJS that I send:
BlobĀ {
size: 29535,
type: "audio/wav; codecs=0"
}
And this is the code I am using in the backend:
#api_view(['POST'])
#csrf_exempt
def AudioModel(request):
try:
audio = request.FILES.get('audio')
except KeyError:
return Response({'audio': ['no audio ?']}, status=HTTP_400_BAD_REQUEST)
destination = open('audio_name.wav', 'wb')
for chunk in audio.chunks():
destination.write(chunk)
destination.close() # closing the file
return Response("Done!", status=HTTP_200_OK)
When I play the file I saved, it plays some sound but it crashes when it achieves the end.
This problem makes me look for some information about the file I saved (extension,...).
For this reason I used fleep library:
import fleep
with open("audio_name.wav", "rb") as file:
info = fleep.get(file.read(128))
print(info.type)
print(info.extension)
print(info.mime)
OUTPUT:
['video']
['webm']
['video/webm']
But getting video in output!
Am I doing something wrong?
How can I fix this issue?
Is there anything I can use to save my file in the desired format?
Any help is appreciated.
EDIT:
Output of first 128 bytes of the saved file:
b'\x1aE\xdf\xa3\x9fB\x86\x81\x01B\xf7\x81\x01B\xf2\x81\x04B\xf3\x81\x08B\x82\x84webmB\x87\x81\x04B\x85\x81\x02\x18S\x80g\x01\xff\xff\xff\xff\xff\xff\xff\x15I\xa9f\x99*\xd7\xb1\x83\x0fB#M\x80\x86ChromeWA\x86Chrome\x16T\xaek\xbf\xae\xbd\xd7\x81\x01s\xc5\x87\xbd\x8d\xc0\xd5\xc6\xaf\xd0\x83\x81\x02\x86\x86A_OPUSc\xa2\x93OpusHead\x01\x01\x00\x00\x80\xbb\x00\x00'
Use SciPy to read data from and write data to a variety of file formats.
Usage examples:
Writing wav file in Python with wavfile.write from SciPy
scipy.io.wavfile.write
Looks like inside react-voice-recorder uses MediaRecorder object with default options. But in options you can set correct mimeType, for example audio/webm; codecs=opus
Related
I have Django project on Cloud Run. When I download small file from page which has below code.
def download_view(request,pk):
file_path = f'media/{pk}.mp3'
name = f'{pk}.mp3'
with open(file_path, 'rb') as f:
response = HttpResponse(f.read(), content_type='audio/wav')
response['Content-Disposition'] = f'attachment; filename={name}'
return response
It's works fine. However, when I download a file (50MB). I got this picture's error.
Cloud run's log is like this. I couldn't find any log of traceback.
2021-05-06 12:00:35.668 JSTGET500606 B66 msChrome 72 https://***/download/mp3/2500762/
2021-05-06 11:49:49.037 JSTGET500606 B61 msChrome 72 https://***/download/mp3/2500645/
I'm not sure. Is this error related with download error.
2021-05-06 16:48:32.570 JSTResponse size was too large. Please consider reducing response size.
I think this is upload file size error. So this is not related with this subject of download error.
When I run Django at local, then download same 50MB file. I can download it. I think this download error related with Cloud run. It's stop after request/response. So I think this error coused by Cloud Run. Which was stoped, when I'm still downloading file.
I don't know how to solve this download error. If you have any solution, please help me!
The Cloud Run HTTP request/response size is limited to 32Mb. Use a multipart/form-data to send chunks of your big file and not the whole file directly.
Thank you #guillaume blaquiere! I solved download error. I post my code for othres.
def _file_iterator(file, chunk_size=512):
with open(file, 'rb') as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
def download_view(request,pk):
file_path = f'media/{pk}.mp3'
file_name = f'{pk}.mp3'
response = StreamingHttpResponse(_file_iterator(file_path))
response['Content-Type'] = 'audio/mpeg'
response['Content-Disposition'] = f'attachment;filename="{file_name}"'
return response
I think StreamingHttpResponse is key point of this problem. It's return big file by chunks. It dose not over Cloud Run's limit.
When I used multipart/form-data for Content-Type, I could download file. But it's couldn't open on smart phone, because It couldn't select application. When I download on PC, it's can't show audio file icon. We should select exact content type.
first of all sorry for my English. I have an Azure Function Linux Consuption Plan using Python and I need to generate an html, transform to pdf using wkhtmltopdf and send it by email.
#generate temporally pdf
config = pdfkit.configuration(wkhtmltopdf="binary/wkhtmltopdf")
pdfkit.from_string(pdf_content, 'report.pdf',configuration=config, options={})
#read pdf and transform to Bytes
with open('report.pdf', 'rb') as f:
data = f.read()
#encode bytes
encoded = base64.b64encode(data).decode()
#Send Email
EmailSendData.sendEmail(html_content,encoded,spanish_month)
Code is running ok in my local development but when I deploy the function and execute the code I am getting an error saying:
Result: Failure Exception: OSError: wkhtmltopdf reported an error: Loading pages (1/6) [> ] 0% [======> ] 10% [==============================> ] 50% [============================================================] 100% QPainter::begin(): Returned false Error: Unable to write to destination
I think that error is reported because for any reason write permission is not available. Can you help me to solve this problem?
Thanks in advance.
The tempfile.gettempdir() method returns a temporary folder, which on Linux is /tmp. Your application can use this directory to store temporary files generated and used by your functions during execution.
So use /tmp/report.pdf as the file directory to save temporary file.
with open('/tmp/report.pdf', 'rb') as f:
data = f.read()
For more details, you could refer to this article.
Final correct code:
config = pdfkit.configuration(wkhtmltopdf="binary/wkhtmltopdf")
local_path = os.path.join(tempfile.gettempdir(), 'report.pdf')
logger.info(tempfile.gettempdir())
pdfkit.from_string(pdf_content, local_path,configuration=config, options={})
I am currently working on a django project, in which i need to record the users audio and sent it to the server for processing. i have successfully recorded the audio using webRTC and passed it to views using an ajax request. But when i try to load the audio file using librosa for prosessing it gives an error for unknown file format.
in my console i can clearly see that the wav file is received but it cannot load the file for processing
to check what if i wrong with the file formats while recording tried different file formats which are supported by librosa and webRTC both
audio/wav;codec=MS_PCM
audio/wav;codec=MS_GSM610
to check if i had a problem with the file in receiving it on server i did upload the file on the server and i found that the file gets uploaded on the server and can be played on player directly.
code that i used to upload the file and retrive it (note: i directly gave the path to the file to any recorded file just to check)
def voice2(request):
if request.method=='GET':
return render(request,'record3.html')
else:
if request.method == 'POST' :
print(request.FILES)
audio=request.FILES.get("audioData")
print(audio)
file = request.FILES['audioData']
path = default_storage.save('media/somename.wav', ContentFile(file.read()))
(os.path.join(settings.MEDIA_ROOT, path))
sig, samplerate = librosa.load(r'C:\Users\KRISHNA DAVE\project\tempproject\media\media\somename.wav')
return render(request, 'record3.html')
now to check librosa couldn't read the file or the file had problem, this time i downloaded a sample audio file from the internet, then i created a new audio.py file in which i made a attempt to load both the files(the one i uploaded and the one i downloaded)
import librosa
#downloaded from internet
a,b=librosa.load(r"C:\Users\KRISHNA DAVE\Music\samplewav.wav")
print(a,b)
#recorded file
y, sr = librosa.load(r"C:\Users\KRISHNA DAVE\project\tempproject\media\media\somename.wav")
print(y,sr)
here i found that the downloaded file was loaded successfully but the file i recorded was still not loaded(i still get the error that the file is in unknown format)
I am still unable to understand how should i solve this problem. Should i replace using webRTC with something else or should i change the audio codec or there is a need to use different libraries(note: i already used librosa which also indirectly use soundfile and also tried soundfile directly, and i cannot use pyAudioAnalysis because i am using python 3.6 and pyAudioAnalysis is incompatible with this version)?
I am using a Flask app to receive a mutipart/form-data request with an uploaded file (a video, in this example).
I don't want to save the file in the local directory because this app will be running on a server, and saving it will slow things down.
I am trying to use the file object created by the Flask request.files[''] method, but it doesn't seem to be working.
Here is that portion of the code:
#bp.route('/video_upload', methods=['POST'])
def VideoUploadHandler():
form = request.form
video_file = request.files['video_data']
if video_file:
s3 = boto3.client('s3')
s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4')
return json.dumps('DynamoDB failure')
This returns an error:
TypeError: must be encoded string without NULL bytes, not str
on the line:
s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4')
I did get this to work by first saving the file and then accessing that saved file, so it's not an issue with catching the request file. This works:
video_file.save(form['video_id']+".mp4")
s3.upload_file(form['video_id']+".mp4", S3_BUCKET, form['video_id']+".mp4")
What would be the best method to handle this file data in memory and pass it to the s3.upload_file() method? I am using the boto3 methods here, and I am only finding examples with the filename used in the first parameter, so I'm not sure how to process this correctly using the file in memory. Thanks!
First you need to be able to access the raw data sent to Flask. This is not as easy as it seems, since you're reading a form. To be able to read the raw stream you can use flask.request.stream, which behaves similarly to StringIO. The trick here is, you cannot call request.form or request.file because accessing those attributes will load the whole stream into memory or into a file.
You'll need some extra work to extract the right part of the stream (which unfortunately I cannot help you with because it depends on how your form is made, but I'll let you experiment with this).
Finally you can use the set_contents_from_file function from boto, since upload_file does not seem to deal with file-like objects (StringIO and such).
Example code:
from boto.s3.key import Key
#bp.route('/video_upload', methods=['POST'])
def VideoUploadHandler():
# form = request.form <- Don't do that
# video_file = request.files['video_data'] <- Don't do that either
video_file_and_metadata = request.stream # This is a file-like object which does not only contain your video file
# This is what you need to implement
video_title, video_stream = extract_title_stream(video_file_and_metadata)
# Then, upload to the bucket
s3 = boto3.client('s3')
bucket = s3.create_bucket(bucket_name, location=boto.s3.connection.Location.DEFAULT)
k = Key(bucket)
k.key = video_title
k.set_contents_from_filename(video_stream)
I would like to know, how to upload a file from memory to Flickr.
I am using the Python Flickr API kit (http://stuvel.eu/flickrapi).
Does the file in memory have a path that can be passed as filename?
Code
response = flickr.upload(filename=f.read(), callback=None, **keywords)
Error
TypeError at /image/new/
must be encoded string without NULL bytes, not str
Thanks in advance
You can try using the tempfile module to write it to disk before uploading it
import tempfile
with tempfile.NamedTemporaryFile(delete=True) as tfile:
tfile.write(f.read())
tfile.flush()
response = flickr.upload(filename=tfile.name,callback=None,**keywords)