如何在 javascript 中将 blob 转换为 wav 文件并连接 python flask

how to convert blob to wav file in javascript and connect python flask

我想通过 python flask 使用 STT 模型创建网络应用程序。 当用户录制语音并将其发送到服务器时,将其转换为网络上的文本。

这是我的 javascript 部分:

<html>
  <head>
    <title>STT</title>

  </head>
  <div style="text-align: center;">
    <h2>STT</h2>
    <p>
      <button type="button" id="record">record</button>
      <button type="button" id="stopRecord" disabled>stop</button>
      <input type="button" id="sendRecord" value="trans to text">
    </p>
    <p>
      <audio id=recordedAudio></audio>
    </p>
  </div>
</html>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
    let recordBlob;
  
    navigator.mediaDevices.getUserMedia({audio:true})
                          .then(stream => {handlerFunction(stream)})
  
    function handlerFunction(stream) {
      rec = new MediaRecorder(stream);
      rec.ondataavailable = e => {
        audioChunks.push(e.data);
        if (rec.state == "inactive") {
          recordBlob = new Blob(audioChunks, {type:'audio/wav; codecs=MS_PCM'});
          recordedAudio.src = URL.createObjectURL(blob);
          recordedAudio.controls=true;
          recordedAudio.autoplay=true;
        }
      }
    }
  
    record.onclick = e => {
        record.disabled = true;
        record.style.backgroundColor = "blue"
        stopRecord.disabled=false;
        audioChunks = [];
        rec.start();
    }
  
    stopRecord.onclick = e => {
      record.disabled = false;
      stop.disabled=true;
      record.style.backgroundColor = "red"
      rec.stop();
    }

    sendRecord.onclick = e => {
      let formData = new FormData();
      
      formData.append('data', recordBlob);
  
      console.log('blob', recordBlob);
  
      $.ajax({
        type: 'POST',
        url: '/result',
        data: formData,
        contentType: false,
        processData: false,
        success: function(result) {
          console.log('success', result);
  
          $("#chatbox").append(`<p class ="userText"><audio style="background-color:white;" controls> <source src="${Url}" type="audio/wav"></audio></p>`);
          $("#chatbox").append(`<p class ="botText"><span>${result.emotion}</span></p>`);
          $("#textInput").val("")
        },
        error: function(result) {
          alert('sorry an error occured');
        }
      });
    }
  </script>

还有烧瓶部分:

from flask import Flask, render_template, request
import requests, json
import soundfile
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)
UPLOAD_FOLDER = "./"
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER

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

@app.route('/result', methods=['POST'])
def result():
    url = "https://kakaoi-newtone-openapi.kakao.com/v1/recognize"
    key = 'REST API KEY'
    headers = {
        "Content-Type": "application/octet-stream",
        "Transfer-Encoding":"chunked",
        "Authorization": "KakaoAK " + key,
    }

    blobData = request.files['data']
    filename = secure_filename(blobData.filename)
    filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename)
    blobData.save(filepath)
    
    app.logger.info('blob data : ', blobData)
    data, samplerate = soundfile.read(blobData)

    soundfile.write('new.wav', data, samplerate, subtype='PCM_16')

    with open("new.wav", 'rb') as fp:
        audio = fp.read()

    res = requests.post(url, headers=headers, data=audio)
    
    return res.text

if __name__=='__main__':
    app.debug=True
    app.run('0.0.0.0', port=5001)

出现错误

[2022-02-25 19:27:51,895] ERROR in app: Exception on /result [POST]
Traceback (most recent call last):
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\flask\app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\flask\app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\flask\app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\flask\app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "C:\Users\LJH\Documents\코드스테이츠\개인프로젝트\webapp\flaskapp2\app.py", line 31, in result
    data, samplerate = soundfile.read(blobData)
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\soundfile.py", line 372, in read
    with SoundFile(file, 'r', samplerate, channels,
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\soundfile.py", line 740, in __init__
    self._file = self._open(file, mode_int, closefd)
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\soundfile.py", line 1264, in _open
    _error_check(_snd.sf_error(file_ptr),
  File "C:\users\ljh\appdata\local\programs\python\python39\lib\site-packages\soundfile.py", line 1455, in _error_check
    raise RuntimeError(prefix + _ffi.string(err_str).decode('utf-8', 'replace'))
RuntimeError: Error opening <FileStorage: 'blob' ('audio/wav; codecs=ms_pcm')>: File contains data in an unknown format.
127.0.0.1 - - [25/Feb/2022 19:27:51] "POST /result HTTP/1.1" 500 -

我不知道为什么 blob 没有转换为 wav...我该如何解决? 可能我的 javascript 代码中有很多不必要的部分。我不知道 javascript。我很抱歉。

你把数据写入一个文件,文件中的位置移动到它的末尾。如果您随后 re-read 使用 soundfile 的文件,您必须先跳回到文件的开头。

import io

@app.route('/result', methods=['POST'])
def result():
    if 'data' in request.files:
        file = request.files['data']
        
        # Write the data to a file.
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename)
        file.save(filepath)
    
        # Jump back to the beginning of the file.
        file.seek(0)
        
        # Read the audio data again.
        data, samplerate = soundfile.read(file)
        with io.BytesIO() as fio:
            soundfile.write(
                fio, 
                data, 
                samplerate=samplerate, 
                subtype='PCM_16', 
                format='wav'
            )
            data = fio.getvalue()
        
        # ...

   return '', 400