Audio file input from node file to python file - python

I want to upload a .wav file from react frontend to node server and then send the file to a python file for speech recognition.
I used multer to get the file in the post route. The file I get looks like this.
{
"fieldname": "file",
"originalname": "00f0204f_nohash_0.wav",
"encoding": "7bit",
"mimetype": "audio/wave",
"destination": "./public/",
"filename": "IMAGE-1635358708022.wav",
"path": "public\\IMAGE-1635358708022.wav",
"size": 32044
}
Now I want to fork a child process for python from index.js and want to sent the file for ASR.
The python file code looks like this:
import speech_recognition as sr
def read_in():
lines = sys.stdin.readlines()
return json.loads(lines[0])
def main():
a = read_in()
r = sr.Recognizer()
with sr.AudioFile(a) as source:
audio_text = r.listen(source)
try:
text = r.recognize_google(audio_text)
print('Conversion Started')
print(text)
except:
print('Error Occurred - Try Again')
How should I send the uploaded file from node to this python file for computation? I am new at this, so I am really confused.

if you are post processing the file, then get the file content with REST API:
# Postman generated
import http.client
host = "ur ip"
path = "server path:port" # port match as the express server
def webhooktriggered(path): # i haven't done any project about py web before, so goodluck
conn = http.client.HTTPSConnection(host)
payload = ''
headers = {}
conn.request("GET", path, payload, headers)
res = conn.getresponse()
data = res.read()
return (data.decode("utf-8"))
before, stream your media with express:
// Original: https://www.codegrepper.com/code-examples/javascript/node+js+express+sendfile+fs+filestream
var http = require('http'),
fileSystem = require('fs'),
path = require('path');
http.createServer(function(request, response) {
var filePath = path.join(__dirname, 'pathto/yourfilehere.wav');
var stat = fileSystem.statSync(filePath);
response.writeHead(200, {
'Content-Type': 'audio/x-wav', // change to whatever u want
'Content-Length': stat.size
});
var readStream = fileSystem.createReadStream(filePath);
// We replaced all the event handlers with a simple call to readStream.pipe()
readStream.pipe(response);
})
.listen(2000); //as soon we will use this port in rest client
Trigger when process, using axios
const axios = require('axios')
function uploadSuccess(path){ // must be the streamed express media path, so python rest can download it then
axios.get('http://pythonbackserverip/?path=' + encodeURI(path))
.then({
console.log("upload successfully!")
})
}
note: my code is not accurate, modify it before use

Related

HTTP POST a python file using dart

I want to send a python file via http post in dart. I can do it in CURL the following way:
curl -X POST -F 'file=#/home/user/file.py' http://192.168.80.1:9888/dir/file.py
I am also able to do it in python like this:
import requests
url = 'http://192.168.80.1:9888/dir/file.py'
files = {'file': open('file.py', 'rb')}
print(files)
r = requests.post(url, files=files)
But in dart I am not able to send the post. I have tried several methods but is at this on currently:
import 'package:http/http.dart' as http;
import 'dart:io';
void main(List<String> arguments) async {
var response;
var file;
var url = 'http://192.168.80.1:9888/dir/file.py';
file = File('file.py').readAsStringSync();
var files = {'file': file};
response = await http.post(url, body: files);
}
Which result in the following exception: Exception has occurred.
ClientException (Connection closed before full header was received)
I know that the server is working due to CURL and python. How do I mimic the functionality in CURL/python using dart?
I was able to send the python file via a POST using dio.
import 'package:dio/dio.dart' as dio;
Future<dio.FormData> FormData3() async {
return dio.FormData.fromMap({
'file': await dio.MultipartFile.fromFile(
'files/file.py',
filename: 'file.py',
),
});
}
Future<dio.Response> sendFile() async {
dio.Response response;
response = await dio.Dio().post('http://192.168.80.1:9888/dir/file.py',
data: await FormData2(), onSendProgress: (received, total) {
if (total != -1) {
print((received / total * 100).toStringAsFixed(0) + '%');
}
},
options: dio.Options(
method: 'POST',
responseType: dio.ResponseType.plain,
));
return response;
}
void main() async {
response = await sendFile();
}

Upload video file from Unity to Python over Http

I am trying to upload a video file from an Unity client to a python server, but when I have tried to do it with UnityWebRequest in Unity and http module in python, but the server receives invalid video file.
My question is how to upload a video file from Unity to python over Http?
This is my code in Unity:
IEnumerator StartUploadCoroutine()
{
// Show a load file dialog and wait for a response from user
yield return FileBrowser.WaitForLoadDialog(false, null, "Load File", "Load");
isOpen = false;
// Upload File to movie server
if (FileBrowser.Success)
{
StreamReader reader = new StreamReader(FileBrowser.Result);
StartCoroutine(UploadCoroutine(reader)); // upload file to server;
}
}
/* Upload the chosen video file to the movie server */
IEnumerator UploadCoroutine(StreamReader reader)
{
UnityWebRequest www = UnityWebRequest.Post(videoPlayerManager.GetServerIp() + ":" + port.ToString(), reader.ReadToEnd());
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
And this is my Python code:
from http.server import BaseHTTPRequestHandler, HTTPServer
class HandleRequests(BaseHTTPRequestHandler):
def do_POST(self):
'''Reads post request body'''
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
self.send_response(200)
self.end_headers()
outF = open("myOutFile.mp4", "wb")
outF.write(body)
host = "127.0.0.1"
port = 9999
HTTPServer((host, port), HandleRequests).serve_forever()
I think in uploading a file (any extension) to a server, Encodings are not important.
Look for two things:
Check that your local video file and uploaded video file have the same Size. if they don't match, it means that you have a problem with uploading progress. (Check here)
You are using POST method to upload the video. It means that the whole of the file will upload to your server and then your python script can use it on 'body' variable. I files size match, I can suggest you use a framework like Flask as server-side python script.
I figured it out thanks to > MohammadReza Arashiyan
My problem was sending the file from Unity as string instead of a bytes array.
I have changed my python code to Flask server so I could easily get the file from the post request, and I ended up with these codes:
This is my code in Unity:
IEnumerator StartUploadCoroutine()
{
// Show a load file dialog and wait for a response from user
yield return FileBrowser.WaitForLoadDialog(false, null, "Load File", "Load");
isOpen = false;
// Upload File to movie server
if (FileBrowser.Success)
{
StartCoroutine(UploadCoroutine(FileBrowser.Result)); // upload file to server;
}
}
/* Upload the chosen video file to the movie server */
IEnumerator UploadCoroutine(string filePath)
{
WWWForm form = new WWWForm();
form.AddBinaryData("vidFile", File.ReadAllBytes(filePath));
UnityWebRequest www = UnityWebRequest.Post(videoPlayerManager.GetServerUrl(), form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
And this is my Python code:
import os
from flask import Flask, request, send_from_directory
from gevent.pywsgi import WSGIServer
IP = "127.0.0.1"
PORT = 9999
# set the project root directory as the static folder
app = Flask(__name__)
#app.route('/', methods=['POST'])
def DownloadFile():
# request.form to get form parameter
vidFile = request.files["vidFile"].read()
outF = open("myOutFile.mp4", "wb")
outF.write(vidFile)
return ''
if __name__ == "__main__":
http_server = WSGIServer((IP, PORT), app)
http_server.serve_forever()

Uploading file and data from Python to Node.js in POST

How do I send a file to Node.js AND parameter data in POST. I am happy to use any framework. I have attempted it with formidable but I am happy to change.
In my attempt, the file sends, but req.body is empty
Python code to upload:
with open('fileName.txt', 'rb') as f:
payLoad = dict()
payLoad["data"] = "my_data"
r = requests.post('http://xx.xx.xx.xx:8080/sendFile',json = payLoad, files={'fileName.txt': f})
Server Side Node.js:
var express = require('express');
var formidable = require('formidable');
var app = express();
var bodyParser = require('body-parser');
app.use( bodyParser.json() );
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/sendFile', function (req, res){
console.log(req.body )
// req.body is empty
I don't know how to correctly send the file using python, but to receive file with node.js you can use express-fileupload
var fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', function(req, res) {
if (!req.files)
return res.status(400).send('No files were uploaded.');
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let sampleFile = req.files.sampleFile;
// Use the mv() method to place the file somewhere on your server
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
https://www.npmjs.com/package/express-fileupload

Extract file from POST request nodejs

I am trying nodejs for the first time. I am using it with python shell. I am trying to transfer a file from one PC to another using Post request
app.js (Server PC)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/mytestapp', function(req, res) {
console.log(req)
var command = req.body.command;
var parameter = req.body.parameter;
console.log(command + "|" + parameter)
pyshell.send(command + "|" + parameter);
res.send("POST Handler for /create")
});
python file send file from (Client PC)
f = open(filePath, 'rb')
try:
response = requests.post(serverURL, data={'command':'savefile'}, files={os.path.basename(filePath): f})
I use fiddler and the request seems to contain the file on Client PC, but I can't seem to get the file on Server PC. How can I extract and save the file? Is it because I am missing headers? what should I use? thanks
I'm going to guess and say you're using Express based on the syntax in your question. Express doesn't ship with out of the box support for file uploading.
You can use the multer or busboy middleware packages to add multipart upload support.
Its actually pretty easy to do this, here is a sample with multer
const express = require('express')
const bodyParser = require('body-parser')
const multer = require('multer')
const server = express()
const port = process.env.PORT || 1337
// Create a multer upload directory called 'tmp' within your __dirname
const upload = multer({dest: 'tmp'})
server.use(bodyParser.json())
server.use(bodyParser.urlencoded({extended: true}))
// For this route, use the upload.array() middleware function to
// parse the multipart upload and add the files to a req.files array
server.port('/mytestapp', upload.array('files') (req, res) => {
// req.files will now contain an array of files uploaded
console.log(req.files)
})
server.listen(port, () => {
console.log(`Listening on ${port}`)
})

Python script as server-side for AngularJS app on IIS7

I have directive to display player image. I send player id to small Python script to check if image with such id exists via ajax call. If image exists, I need to return its name.
I succeeded in sending id from fronted to script and finding the image name. The problem is that I am failing to return the file name correctly. I am getting error:
HTTP Error 502.2 - Bad Gateway
The specified CGI application misbehaved by not returning a complete set of HTTP headers. The headers it did return are "HCP_23108_SmithKen.png ".
If I add headers, I am still getting error:
HTTP Error 502.2 - Bad Gateway
The specified CGI application misbehaved by not returning a complete set of HTTP headers. The headers it did return are "Content-type: text/html; charset=utf-8 HCP_23108_SmithKen.png ".
I did enabled cgi in Handler Mappings of IIS7 by following Python on IIS: how?
My question is how to perform Ajax GET request correctly without any Python frameworks? Thanks
Directives:
myDirectives.directive('headshot', function ($http) {
return {
restrict: 'AE',
scope: {
lastProID: '#lastproid'
},
template: '<img ng-src="{{proImg}}" class="headshot">',
link: function (scope, element, attrs) {
//scope.id = scope.lastProID;
attrs.$observe('lastproid', function (id) {
scope.id = id;
var src = 'img/bios/nophoto.png';
scope.proImg = (src);
var url = 'bioPhoto/bioPhoto.py';
$http.get(
url,
{
params: {'id': scope.id}
})
.success(function (data) {
var src = 'img/bios/' + data;
scope.proImg = (src);
})
.error(function (error) {
});
});
}
};
});
bioPhoto.py script:
import fnmatch
import os
rootPath = './img/bios/'
query_string=os.environ["QUERY_STRING"]
id=query_string.split("id=",1)[1]
id=id.strip()
pattern = "*" + id + "*"
print ('Content-type: text/html; charset=utf-8')
for root, dirs, files in os.walk(rootPath):
for filename in fnmatch.filter(files, pattern):
filename=filename.strip()
print(filename)
You need a blank line after your headers.
(See: http://www.oreilly.com/openbook/cgi/ch03_02.html)
Try this:
print ('Content-type: text/html; charset=utf-8\n\n')

Categories