I am building a "guitar tuner" app with ReactJS for frontend and Python Flask as the backend.
This is what the app does so far:
1. The React app (client side) records audio using react library react-mic
2. Sends the recording via. a fetch POST request to to Flask API, which picks it up and send as response back.
PROBLEM: The file being sent is on the form in the screenshot, which is a list with one Blob element consisting of a webm audio file.
When I send this blob file of a webM audio file in the fetch function it comes out as undefined in the Flask app, and I am unsure about how to read the blob/webm audio in Python.
The POST function in ReactJS:
uploadFile(file) {
var form = new FormData();
form.append('file',file)
form.append('title',"Guitar recording")
fetch('http://127.0.0.1:5000/audio_record', {
// content-type header should not be specified!
method: 'POST',
body: form
}).then(function (response){
return (response.text())
}).then(function(text){
console.log(text) // The text the endpoint returns
})
.catch(error => console.log(error)
);
}
Python flask app (where I try reading the file, does not work..):
import audioread
from flask import Flask, request #import main Flask class and request object
from flask_cors import CORS
import logging
from pydub import AudioSegment
from pydub.playback import play
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('HELLO WORLD')
app = Flask(__name__) #create the Flask app
CORS(app)
#app.route('/')
def landing():
return 'Landing page'
# Get the blob of type "audio/webm;codecs=opus"
#app.route('/audio_record', methods=['POST'])
def save_record():
logger.info("welcome to upload`")
# file = request.files['file']
#filename = secure_filename(file.title)
file = request.form['file']
print('File from the POST request is: {}'.format(file))
try:
read_audio_file(file[0])
return "****** Audio Read ******"
except:
print("In the except", file[0]) # Gets printed as undefined
title = request.form['title']
print(title) # Able to print title
return "Request received and responded"
# app.logger.debug(request.files['file'].filename)
def read_audio_file(audio_from_post):
print("Tring to read audio..")
with audioread.audio_open(audio_from_post) as f:
print(f.channels, f.samplerate, f.duration)
for buf in f:
print(buf)
if __name__ == '__main__':
app.run(debug=True, port=5000) #run app in debug mode on port 5000
I saw here that it might be smart to convert the Blob to an Audio object in ReactJS, but I am not sure how that would make the reading of the file in Flask any easier.
Any idea as to how I should do this?
I want to read the file in Python and do a Fast Fourier Transform (numpy.fft.fft), to determine the frequencies in the audio clip.
Thanks in advance!
UPDATE
I decided that I wanted to try recording the audio with another library, MediaRecorder- to be able to record audio in WAV, not webm. I think I will encode the WAV file in base64, send it in a form to Flask and read it with the wave library.
One way you could approach is by sending the data from the frontend is sending the blob of the recording instead of the whole object by making the following change to your POST function in React
form.append('file',file.blob)
Then, on the server-side, you could simply do the following
request.files['file'].filename
And then proceeding to save it by using the built-in save method for further processing. Documentation for request.files can be found here
Related
I used the sample code to receive a call from a number to twilio number.
Now I need to save the recording as mp3. I cant understand how to do it. I tried to call various parameters but failed. I am new to twilio.
> `from flask import Flask
from twilio.twiml.voice_response import VoiceResponse
app = Flask(__name__)
#app.route("/record", methods=['GET', 'POST'])
def record():
"""Returns TwiML which prompts the caller to record a message"""
# Start our TwiML response
response = VoiceResponse()
# Use <Say> to give the caller some instructions
response.say('Hello. Please leave a message after the beep.')
# Use <Record> to record the caller's message
response.record()
# End the call with <Hangup>
response.hangup()
return str(response)
def record(response):
# function to save file to .wav format
if __name__ == "__main__":
app.run(debug = True)
I followed the link but cant understand how to link it with flask to save the file.
https://www.twilio.com/docs/voice/api/recording?code-sample=code-filter-recordings-with-range-match&code-language=Python&code-sdk-version=6.x
Twilio developer evangelist here.
When you use <Record> to record a user, you can provide a URL as the recordingStatusCallback attribute. Then, when the recording is ready, Twilio will make a request to that URL with the details about the recording.
So, you can update your record TwiML to something like this:
# Use <Record> to record the caller's message
response.record(
recording_status_callback="/recording-complete",
recording_status_callback_event="completed"
)
Then you will need a new route for /recording-complete in which you receive the callback and download the file. There is a good post on how to download files in response to a webhook but it covers MMS messages. However, we can take what we learn from there to download the recording.
First, install and import the requests library. Also import request from Flask
import requests
from flask import Flask, request
Then, create the /recording-complete endpoint. We'll read the recording URL from the request. You can see all the request parameters in the documentation. Then we'll open a file using the recording SID as the file name, download the recording using requests and write the contents of the recording to the file. We can then respond with an empty <Response/>.
#app.route("/recording-complete", methods=['GET', 'POST'])
def recording_complete():
response = VoiceResponse()
# The recording url will return a wav file by default, or an mp3 if you add .mp3
recording_url = request.values['RecordingUrl'] + '.mp3'
filename = request.values['RecordingSid'] + '.mp3'
with open('{}/{}'.format("directory/to/download/to", filename), 'wb') as f:
f.write(requests.get(recording_url).content)
return str(resp)
Let me know how you get on with that.
I am trying to make an API that when a POST request is made, it will accept images and then save them, and if a GET request is made then it will send back a URL to where you'd be able to download that image. How would that be possible?
This is the Flask app running on localhost for testing:
from flask import Flask, send_file
app = Flask(__name__)
#app.route("/upload_image/<filename>", methods=["POST"])
def upload_image(filename):
# receive the image here
# ...
#app.route("/get_image", methods=["GET"])
def get_image():
filename = "encoded_image.png"
return send_file(filename, mimetype="image/png")
if __name__ == "__main__":
app.run(host="localhost", port=5000)
I think sending the image is easy but I don't know how to go about receiving it and using requests to send it.
This is the idea behind the main code:
import requests
option = input()
if option == "get image":
print("Download the image at: https://localhost:5000/get_image")
elif option == "upload image":
post = requests.post("https://localhost:5000/upload_image/encoded_image.png")
i don't want the images to change names. I always want to send the file encoded_image.png and receive it, because I want it to be overwritten when the POST is made. This is for a discord bot but that doesn't really affect anything, I just thought I'd mention it. Thanks in advance :)
I have created a flask api and it is currently running in local machine
From one machine I ran the python script to post the text file:
import json
import requests
datas = {'var1' : 'var1','var2' : 'var2',}
#my file to be sent
local_file_to_send = 'C:\\Users\\tmp.txt'
with open(local_file_to_send, 'w') as f:
f.write('I am a file\n')
url = "http://127.0.0.1:5000/customerupdate"
files = [
('document', (local_file_to_send, open(local_file_to_send, 'rb'), 'application/octet')),
('datas', ('datas', json.dumps(datas), 'application/json')),
]
r = requests.post(url, files=files)
print("sd")
print(str(r.content, 'utf-8'))
Python flask API:
import json
from flask import Flask, request
from flask import send_file
app = Flask(__name__)
#app.route('/',methods=['GET'])
def hello_world():
return 'Hello World!'
#app.route('/customerupdate',methods=['GET','POST'])
def customerupdate():
posted_file = str(request.files['document'].read(), 'utf-8')
posted_data = json.load(request.files['datas'])
print(posted_file)
print(posted_data)
return '{}\n{}\n'.format(posted_file, posted_data)
if __name__=='__main__':
app.run(debug='true',threaded=True)
And the python get method to receive the file:
import requests
r = requests.get('http://127.0.0.1:5000')
print(r.text)
But here in get method I have received the contents of the file.But I want it for csv file.I tried by making that .csv instead of .txt.But can't able to send the file to api .So, Is it possible to send the csv file from one machine and receive the csv file in another machine via flask and please post the code if solutions available.
Already tried with this link:Python Flask: Send file and variable
I struggling lot to resolve it.
I am new to API, and get a tasks of creating POST API. I have created a code somehow.
I want to add data to the hello.txt through post API, So how will I do it?
Here is my code:
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
app.config["DEBUG"] = True
#app.route('/api/v1/resources/messages', methods = ['POST'])
def api_message():
if request.headers['Content-Type'] == 'text/plain':
return "Text Message: " + request.data
elif request.headers['Content-Type'] == 'application/octet-stream':
return "Binary message written!"
elif request.headers['Content-Type'] == 'application/json':
f = open('F:\Asif_Ahmed\Projects\api\hello.txt',"w")
f.write(request.data)
f.close()
return "JSON Message: " + json.dumps(request.json)
else:
return "415 Unsupported Media Type ;)"
app.run()
from flask import Flask, jsonify, render_template, request #import flask library
from flask_basicauth import BasicAuth # import flask library for create basic authentication if needed
from flask_cors import CORS # import flask library Cross-Origin Resource Sharing that is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin
app = Flask(__name__)
CORS(app) #set-up cors for my app
#if you want use basic authentication you need set-up username and password
app.config['BASIC_AUTH_USERNAME'] = 'admin'
app.config['BASIC_AUTH_PASSWORD'] = 'password'
basic_auth = BasicAuth(app)#set-up username and password for my app but in this case I'm not specifying yet in which API use them
#app.route('/api/v1/resources/add_messages', methods=['POST'])#create my POST api
#basic_auth.required# set-up basic authentication for this API, comment out if not needed
def update_credential ():
json_credential=request.get_json()#get the JSON sent via API
print (json_credential["message"])#get the node "message" of my JSON
###########
#code to write in your file, you need write the json_credential["message"]
###########
return ("ok")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1024, threaded=True)#start my flask app with local_host IP and specific port, if you don't specify the port it will run in the default port
In this case the JSON Input should be:
{"message":"your text"}
Please let me know if something is not clear, I even try this code on my local and the JSON is passed without problems.....
So you need run your python script and see that the API is running, if you had no JSON to send and was just a simple API that give back information you should have used even Chrome but in this case that you need send some JSON data I would advice you to use Postman.
See screenshot example:
this is a two-part question: I have seen individual pieces discussed, but can't seem to get the recommended suggestions to work together. I want to create a web service to store images and their metadata passed from a caller and run a test call from Postman to make sure it is working. So to pass an image (Drew16.jpg) to the web service via Postman, it appears I need something like this:
For the web service, I have some python/flask code to read the request (one of many variations I have tried):
from flask import Flask, jsonify, request, render_template
from flask_restful import Resource, Api, reqparse
...
def post(self, name):
request_data = request.get_json()
userId = request_data['UserId']
type = request_data['ImageType']
image = request.files['Image']
Had no problem with the data portion and straight JSON but adding the image has been a bugger. Where am I going wrong on my Postman config? What is the actual set of Python commands for reading the metadata and the file from the post? TIA
Pardon the almost blog post. I am posting this because while you can find partial answers in various places, I haven't run across a complete post anywhere, which would have saved me a ton of time. The problem is you need both sides to the story in order to verify either.
So I want to send a request using Postman to a Python/Flask web service. It has to have an image along with some metadata.
Here are the settings for Postman (URL, Headers):
And Body:
Now on to the web service. Here is a bare bones service which will take the request, print the metadata and save the file:
from flask import Flask, request
app = Flask(__name__)
# POST - just get the image and metadata
#app.route('/RequestImageWithMetadata', methods=['POST'])
def post():
request_data = request.form['some_text']
print(request_data)
imagefile = request.files.get('imagefile', '')
imagefile.save('D:/temp/test_image.jpg')
return "OK", 200
app.run(port=5000)
Enjoy!
Make sure `request.files['Image'] contains the image you are sending and follow http://flask.pocoo.org/docs/1.0/patterns/fileuploads/ to save the file to your file system. Something like
file = request.files['Image']
file.save('./test_image.jpg')
might do what you want, while you will have to work out the details of how the file should be named and where it should be placed.