Flask socketio不会与> 30秒的录音断开连接

时间:2019-06-12 23:27:29

标签: javascript python azure gunicorn flask-socketio

当音频记录长于30秒左右时,Flask socketio不会断开连接,而仅当Gunicorn在Azure App Services上提供服务时。本地开发人员似乎具有几乎无限的容量,并且较短的录音在Azure环境中可以正常工作。

voice_disconnect_request()触发外,该代码似乎实际上行为正确。尽管disconnect()之后的代码可以运行(即@socketio.on('disconnect', namespace='/voice_enroll') -> voice_test_disconnect()),所以我不确定emit('my_response',{'data': 'Voice Enroll Complete!', 'count': session['receive_count']})为什么不起作用。出于某种原因,如果此操作无法触发,$('form#connect').submit(function(event)将再次运行,这将自动创建新的连接并启动记录器。

站点上的按钮确实正确且立即更改为已禁用/启用,因此似乎“记录”按钮不应处于活动状态,断开连接功能应完全正确,并且不应再次调用$('form#connect').submit(function(event) 。在正确发送了断开连接请求的情况下,一切都会按预期进行。

我尝试在线程中运行voice_enroll()(代码反映在下面),因为它确实需要几秒钟,并且我担心在那里会有一些延迟。

我为audio_context尝试了各种缓冲区大小。

我更改了各种异步模式和gunicorn设置,但实际上我对尝试其他方法一无所知。任何地方都没有错误消息。似乎只是放弃并重新开始。

我已经尝试过将它们设置为Gunicorn

gunicorn --worker-class eventlet -w 1 --bind '0.0.0.0:8000' app:server --timeout 300
gunicorn --worker-class gevent -w 1 --bind '0.0.0.0:8000' app:server --timeout 300
gunicorn -w 1 --threads 12 --bind '0.0.0.0:8000' app:server --timeout 300

python

@socketio.on('my_event', namespace='/voice_enroll')
def voice_message(message):
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response',
         {'data': message['data'], 'count': session['receive_count']})

@socketio.on('disconnect_request', namespace='/voice_enroll')
def voice_disconnect_request():
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response',
         {'data': 'Voice Enroll Complete!', 'count': session['receive_count']})
    disconnect()

@socketio.on('connect', namespace='/voice_enroll')
def voice_test_connect():
    session['audio'] = []
    emit('my_response', {'data': 'Connected', 'count': 0})

@socketio.on('sample_rate', namespace='/voice_enroll')
def voice_handle_my_sample_rate(sampleRate):
    session['sample_rate'] = sampleRate
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my_response', {'data': "sampleRate : %s" % sampleRate, 'count': session['receive_count'] })

@socketio.on('audio', namespace='/voice_enroll')
def voice_handle_my_custom_event(audio):
    """
    """
    values = OrderedDict(sorted(audio.items(), key=lambda t: int(t[0]))).values()
    session['audio'] += values

@socketio.on('disconnect', namespace='/voice_enroll')
def voice_test_disconnect():
    # https://stackoverflow.com/a/18644461/466693
    sample_rate = session['sample_rate']
    my_audio = np.array(session['audio'], np.float32)
    scaled = np.round(32767*np.sin(my_audio))
    scipy.io.wavfile.write('out.wav', sample_rate, scaled.astype(np.int16))
    audio = AudioSegment.from_file('out.wav', format='wav').set_frame_rate(MS_VOICE_FRAMERATE)
    audio.export('temp.wav', format='wav')
    thread = Thread(target=enroll_voice, args=('temp.wav', current_user.username))
    thread.start()
    session['audio'] = []

JS

      var namespace = '/voice_enroll';
      var socket = null;
      var mediaStream = null;

      // prepare button state
      $('#disconnect input')[0].disabled = true;

      // audio functions
      function initializeRecorder(stream){
         // https://stackoverflow.com/a/42360902/466693
         mediaStream = stream;

         // get sample rate
         audio_context = new AudioContext;
         sampleRate = audio_context.sampleRate;
         console.log('<sample_rate>', sampleRate);
         socket.emit('sample_rate', sampleRate);

         var audioInput = audio_context.createMediaStreamSource(stream);

         console.log("Created media stream.");

         var bufferSize = 8192;
         // record only 1 channel
         var recorder = audio_context.createScriptProcessor(bufferSize, 1, 1);
         // specify the processing function
         recorder.onaudioprocess = recorderProcess;
         // connect stream to our recorder
         audioInput.connect(recorder);
         // connect our recorder to the previous destination
         recorder.connect(audio_context.destination);
      }
      function recorderProcess(e) {
        var left = e.inputBuffer.getChannelData(0);
        socket.emit('audio', left);
      }

      $('form#connect').submit(function(event) {
          if(socket == null){
            socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
            socket.on('connect', function() {
                socket.emit('my_event', {data: 'I\'m connected!'});
                navigator.getUserMedia({audio: true}, initializeRecorder, function(a, b, c){
                  console.log(a, b, c);
                });
            });
            socket.on('my_response', function(msg) {
                  $('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());
            });
          }
          else {
            socket.disconnect();
            socket.connect();
          }
          $('#connect input')[0].disabled = true;
          $('#disconnect input')[0].disabled = false;
          return false;
      });
      $('form#disconnect').submit(function(event) {
          mediaStream.getAudioTracks()[0].stop();
          audio_context.close();
          socket.emit('disconnect_request');
          $('#connect input')[0].disabled = false;
          $('#disconnect input')[0].disabled = true;
          return false;
      });

Flask socketio应该正常退出,发出断开连接消息,以警告最终用户该过程成功完成,就像本地开发人员和短音频消息一样。

0 个答案:

没有答案