简体   繁体   English

从前端发送.wav 文件到 Flask 后端

[英]Sending .wav file from frontend to Flask backend

I am trying to capture audio from the microphone in the browser, convert it to a wav format and send it to flask backend in order to transcribe it and perform intent classificatio on the request.我正在尝试从浏览器中的麦克风捕获音频,将其转换为 wav 格式并将其发送到 flask 后端,以便对其进行转录并对请求执行意图分类。 However this error occurs:但是会发生此错误:

werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'audio_data'

Traceback (most recent call last)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\Admin\Desktop\Voice Assistant web\voice_assistant.py", line 17, in result
data = request.files['audio_data']
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\flask\debughelpers.py", line 96, in __getitem__
return oldcls.__getitem__(self, key)
File "C:\Users\Admin\Desktop\Voice Assistant web\virtualenv\lib\site-packages\werkzeug\datastructures.py", line 442, in __getitem__
raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'audio_data'

This is my python code:这是我的 python 代码:

from flask import Flask, render_template, request, redirect, url_for
from intent_classification import ICModel
from voice_to_text import VTTModel

IC = ICModel()
VTT = VTTModel()

app=Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/result", methods=['POST','GET'])
def result():
    if(request.method=='POST'):
        data = request.data['audio_data']
        text = VTT.infer(data)
        print(text)
        intent = IC.predict(text)
        print(intent)
        return render_template("result.html", pred = intent, text = text)
    else:
        return redirect(url_for('home'))

if __name__ == "__main__":
    app.run(debug=True)

And this is my frontend:这是我的前端:

{% extends "base.html" %}

{% block content %}
    <h1 class="font-bold text-5xl text-white mt-5 mb-10">What is on your mind?</h1>
    <div class="flex items-center">
        <img id="record" src="/static/images/record.jpg" alt="record" 
            width="150px" height="150px" class="rounded-xl mx-10" 
            onClick="startRecording()">
        <img id="stop" src="/static/images/stop.jpg" alt="stop" 
            width="150px" height="150px" class="rounded-xl mx-10"
            onClick="stopRecording()">
    </div>
    <a id="check" href="/result" method="POST" 
        class="rounded-lg bg-green-400 hover:bg-green-600 shadow-lg text-xl text-white font-bold my-6 px-16 py-1"
        onclick="upload()">Check intent</a>
    <h2 id="prompt" class="font-bold text-3xl text-white my-10">Listening...</h2>
    <div>
        <h3 class="text-3xl text-white mt-10 mb-5">
            You can request the following:
        </h3>
        <ul class="text-xl text-white text-center">
            <li>adding a song to a playlist</li>
            <li>playing music</li>
            <li>booking a table at a restaurant</li>
            <li>getting the weather</li>
            <li>searching for creative work</li>
            <li>rating a book</li>
            <li>searching for a screening event</li>
        </ul>
    </div>
    <script>
        URL = window.URL || window.webkitURL;
        var gumStream;
        var rec;
        var input;
        var AudioContext = window.AudioContext || window.webkitAudioContext;
        var audioContext = new AudioContext;
        var constraints = {
            audio: true,
            video: false
        } 

        var recordButton = document.getElementById("record");
        var stopButton = document.getElementById("stop");
        var checkButton = document.getElementById("check")
        var promptMessage = document.getElementById("prompt");

        recordButton.disabled=false;
        stopButton.disabled=true;
        checkButton.disabled=true;
        promptMessage.hidden = true;

        function startRecording()
        {
            console.log("Recording started.")
            recordButton.disabled = true;
            stopButton.disabled = false;
            promptMessage.hidden=false;

            navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
                console.log("getUserMedia() success, stream created, initializing Recorder.js ..."); 
                gumStream = stream;
                input = audioContext.createMediaStreamSource(stream);
                rec = new Recorder(input, {
                    numChannels: 1
                }) 
                rec.record()
            }).catch(function(err) {
                recordButton.disabled = false;
                stopButton.disabled = true;
                promptMessage.hidden=true;
            });
        }

        function stopRecording()
        {
            console.log("Recording stopped.")
            stopButton.disabled = true;
            recordButton.disabled = false;
            checkButton.disabled = false;
            promptMessage.hidden=true;
            rec.stop();
            gumStream.getAudioTracks()[0].stop();
        }

        function upload()
        {
            console.log("Audio being exported.")
            checkButton.disabled = true;

            var filename = new Date().toISOString();
            rec.download()
            rec.exportWAV(function(blob) {
                /* var xhr = new XMLHttpRequest();
                xhr.onload = function(e) {
                    if (this.readyState === 4) {
                        console.log("Server returned: ", e.target.responseText);
                    }
                }; */
                var fd = new FormData();
                fd.append('audio_data', blob, filename);
                try {
                    let r = await fetch('/result', {method: "POST", body: fd}); 
                    console.log('HTTP response code:',r.status); 
                } catch(e) {
                    console.log(e);
                }
                /* var xhr = new XMLHttpRequest();
                xhr.open('POST', '/result', true);
                xhr.send(fd); */
            });
        }
    </script>
{% endblock %}

As you can see I have also tried doing it with XMLHttpRequest but without success - the same error occurs.如您所见,我也尝试过使用 XMLHttpRequest 进行此操作,但没有成功 - 发生相同的错误。 I can't tell whether it is from the backend or the frontend.我不知道它是来自后端还是前端。 I have looked other simular questions and it looks like I haven't done anything wrong.我看过其他类似的问题,看起来我没有做错任何事情。 I would really appreciate any help.我真的很感激任何帮助。

I think you should use request.files to access the transmitted data on the server side.我认为您应该使用request.files来访问服务器端传输的数据。

@app.route('/result', methods=['GET', 'POST'])
def result():
    if request.method == 'POST':
        print(request.files)
        data = request.files['audio_data'].read()
        print(data)
        
        # ...
        
        return render_template('result.html', **locals())
    else:
        return redirect(url_for('home'))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM