【问题标题】:Stream audio from pyaudio with Flask to HTML5使用 Flask 将音频从 pyaudio 流式传输到 HTML5
【发布时间】:2017-11-04 01:11:12
【问题描述】:

我想通过 Flask 将麦克风的音频(通过 pyaudio 录制)流式传输到任何连接的客户端。

这是音频的来源:

    def getSound(self):
        # Current chunk of audio data
        data = self.stream.read(self.CHUNK)
        self.frames.append(data)
        wave = self.save(list(self.frames))

        return data

这是我的烧瓶代码:

@app.route('/audiofeed')
def audiofeed():
    def gen(microphone):
        while True:
            sound = microphone.getSound()
            #with open('tmp.wav', 'rb') as myfile:
            #   yield myfile.read()

            yield sound

    return Response(stream_with_context(gen(Microphone())))

这是客户端:

    <audio controls>
        <source src="{{ url_for('audiofeed') }}" type="audio/x-wav;codec=pcm">
        Your browser does not support the audio element.
    </audio>

它有时确实有效,但大多数时候我得到“[Errno 32] Broken pipe

当使用 open("tmp.wav")-part 取消注释时(self.save() 可以选择获取所有先前的帧并将它们保存在 tmp.wav 中),我有点得到一个流,但是所有的出来扬声器的声音是“咔哒”声。

我愿意接受任何建议。如何将麦克风的输入实时流式传输(没有预先录制!)到网络浏览器?

谢谢!

【问题讨论】:

    标签: python html audio flask pyaudio


    【解决方案1】:

    试试这对我有用。 shell cmd "cat" 运行良好,查看代码 我正在使用 FLASK

    import subprocess
    import os
    import inspect
    from flask import Flask
    from flask import Response
    
    @app.route('/playaudio')
        def playaudio():
            sendFileName=""
            def generate():
    
                #  get_list_all_files_name this function gives all internal files inside the folder
    
       filesAudios=get_list_all_files_name(currentDir+"/streamingAudios/1")
    
                # audioPath is audio file path in system 
                for audioPath in filesAudios:
                    data=subprocess.check_output(['cat',audioPath])
                    yield data
            return Response(generate(), mimetype='audio/mp3')
    

    【讨论】:

    • 谢谢,这对现有的 mp3 非常有用,并且可能也会派上用场,但现在我正在尝试直播麦克风。我考虑过将实时数据连续写入 wav 文件,然后以某种方式流式传输 - 对此有何建议?
    • 请查看此链接:developers.google.com/web/fundamentals/media/recording-audio 它对您有很大帮助,请阅读完整文档,最后在文档中可以将数据转换为 WAV
    • 感谢您的链接,但据我了解,他们从用户的麦克风中获取输入,然后将其转换为 WAV 并将其发送到服务器。我实际上正试图做相反的事情。
    • 您必须将“apache kafka”与在全局级别使用的python一起使用.....所有类型的实时流处理均由“apache kafka”处理。
    • 使用这个开源 github 代码进行任何类型的蒸汽...github.com/umbrashia/power-streaming-project
    【解决方案2】:

    这个问题很久以前就被问过了,但是由于我花了一整天的时间来弄清楚如何实现它,所以我想给出答案。也许它会对某人有所帮助。

    “[Errno 32] Broken pipe” 错误来自客户端无法播放音频并关闭此流的事实。 由于数据流中没有标头,因此无法播放音频。您可以使用代码 here 中的 genHeader(sampleRate, bitsPerSample, channels, samples) 函数轻松创建标题。此标头必须至少附加到发送数据的第一块 (chunck=header+data)。请注意,音频可以播放,直到客户端下载的文件大小达到您必须在标题中指定的大小。因此,解决方法是在标题中设置一些大文件大小,例如2Gb。

    【讨论】:

    • 感谢您抽出宝贵时间!在我的示例中,我会将 chunk=header+data 部分放在哪里?你知道如何在header中设置文件大小吗?
    【解决方案3】:

    在标头函数中写datasize = 2000*10**6,而不是datasize = len(samples) * channels * bitsPerSample

    def gen_audio():
    
        CHUNK = 512
        sampleRate = 44100
        bitsPerSample = 16
        channels = 2
        wav_header = genHeader(sampleRate, bitsPerSample, channels)
    
        audio = AudioRead()
        data = audio.get_audio_chunck()
        chunck = wav_header + data
        while True:
            yield (chunck)
            data = audio.get_audio_chunck()
            chunck = data
    

    【讨论】:

      【解决方案4】:

      经过大量研究和修补,我终于找到了解决方案。

      基本上它归结为使用 Flask 的 SocketIO 实现通过 WebSockets 提供 pyaudio.paFloat32 音频数据,并使用 HTML5 的 AudioContext 在 JavaScript 中接收/播放数据。

      因为这需要相当多的代码,所以我认为将其全部发布在这里并不是一个好主意。相反,请随意查看我正在使用它的项目:simpleCam

      相关代码在: -noise_detector.py(录音) - server.py (WebSocket 传输) - static/js/player.js(接收/播放)

      感谢大家的支持!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-24
        • 2012-08-23
        • 2011-04-18
        • 1970-01-01
        • 2011-04-26
        • 2014-08-12
        • 2012-05-30
        相关资源
        最近更新 更多