Skip to content
Advertisement

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

I want to create web app using STT model by python flask. when user record the voice and send it server, trans it to text on web.

there is my javascript part:

<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>

and there is flask part:

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)

it comes out error

[2022-02-25 19:27:51,895] ERROR in app: Exception on /result [POST]
Traceback (most recent call last):
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagesflaskapp.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagesflaskapp.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagesflaskapp.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagesflaskapp.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "C:UsersLJHDocuments코드스테이츠개인프로젝트webappflaskapp2app.py", line 31, in result
    data, samplerate = soundfile.read(blobData)
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagessoundfile.py", line 372, in read
    with SoundFile(file, 'r', samplerate, channels,
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagessoundfile.py", line 740, in __init__
    self._file = self._open(file, mode_int, closefd)
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagessoundfile.py", line 1264, in _open
    _error_check(_snd.sf_error(file_ptr),
  File "C:usersljhappdatalocalprogramspythonpython39libsite-packagessoundfile.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 -

I don’t know why blob didn’t convert to wav…how can I fix it? probably there are many no necessary parts on my javascript code.. I don’t know about javascript. I’m sorry for that.

Advertisement

Answer

You write the data in a file, the position within the file moves to the end of it. If you then re-read the file using soundfile, you must first jump back to the beginning of the file.

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
Advertisement