HTTP实时音频流服务器 [英] HTTP realtime audio streaming server

查看:142
本文介绍了HTTP实时音频流服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为概念验证,我需要创建一个HTTP服务器,该服务器应在GET请求时启动连续的非编码/非压缩音频数据流-WAV,PCM16.假设音频数据是44.1kHz采样率下的4096个随机生成的单声道音频样本的大块.

As a proof-of-concept I need to create a HTTP server which on GET request should start continuous stream of non-encoded/non-compressed audio data - WAV, PCM16. Let's assume the audio data are chunks of 4096 randomly generated mono audio samples @44.1kHz sampling rate.

我应该在HTTP响应标头中放什么,以便另一端的浏览器在其UI中启动播放器以供用户实时收听?

What should I put in the HTTP response header in order to browser on the other end start a player in its UI for the user to listen in realtime?

我正在阅读"Transfer-Encoding:chunked","multipart",mimetype ="audio/xwav",但仍然不建议使用什么以及如何使用...

I was reading about "Transfer-Encoding: chunked", "multipart", mimetype="audio/xwav", but still not sute what and how to use...

如果有人可以给我一个关于Python/Flask的确切例子,那太好了,因为我对Web开发的信心不足.

Great would be if someone can give me an exact example on Python/Flask because I'm not so confident with the web development.

PS1:将PoC之后的下一阶段是用硬件功率有限的嵌入式设备替换HTTP服务器.

PS1: Replacing HTTP server with an embedded device with limited HW power will be the next stage after the PoC.

PS2:这是实际起作用的代码,并将WAV块作为单个HTTP响应发送:

PS2: This is the code which actually works and sends an WAV chunk as a single HTTP response:

from flask import Flask, Response,render_template
import pyaudio
import audio_processing as audioRec

app = Flask(__name__)

def genHeader(sampleRate, bitsPerSample, channels, samples):
    datasize = samples * channels * bitsPerSample // 8
    o = bytes("RIFF",'ascii')                                               # (4byte) Marks file as RIFF
    o += (datasize + 36).to_bytes(4,'little')                               # (4byte) File size in bytes excluding this and RIFF marker
    o += bytes("WAVE",'ascii')                                              # (4byte) File type
    o += bytes("fmt ",'ascii')                                              # (4byte) Format Chunk Marker
    o += (16).to_bytes(4,'little')                                          # (4byte) Length of above format data
    o += (1).to_bytes(2,'little')                                           # (2byte) Format type (1 - PCM)
    o += (channels).to_bytes(2,'little')                                    # (2byte)
    o += (sampleRate).to_bytes(4,'little')                                  # (4byte)
    o += (sampleRate * channels * bitsPerSample // 8).to_bytes(4,'little')  # (4byte)
    o += (channels * bitsPerSample // 8).to_bytes(2,'little')               # (2byte)
    o += (bitsPerSample).to_bytes(2,'little')                               # (2byte)
    o += bytes("data",'ascii')                                              # (4byte) Data Chunk Marker
    o += (datasize).to_bytes(4,'little')                                    # (4byte) Data size in bytes
    return o

FORMAT = pyaudio.paInt16
CHUNK = 102400 #1024
RATE = 44100
bitsPerSample = 16 #16
CHANNELS = 1
wav_header = genHeader(RATE, bitsPerSample, CHANNELS, CHUNK)

audio = pyaudio.PyAudio()

# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS,
    rate=RATE, input=True, input_device_index=10,
    frames_per_buffer=CHUNK)
# print "recording..."

@app.route('/')
def index():
    """Video streaming home page."""
    return render_template('index2.html')

@app.route('/audio_unlim')
def audio_unlim():
    # start Recording
    def sound():

        #while True:
        #    data = wav_header + stream.read(CHUNK)
        #    yield(data)
        data = wav_header + stream.read(CHUNK)
        yield(data)

    return Response(sound(),
                    mimetype="audio/x-wav")


if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True, threaded=True,port=5000)

和index2.html

and the index2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <audio controls>
        <source src="{{ url_for('audio_unlim') }}" type="audio/x-wav;codec=pcm">
        Your browser does not support the audio element.
    </audio
</body>
</html>

为了实现连续的块流而需要进行哪些更改?

What to change in order to achieve continuous stream of chunks?

推荐答案

实际上,我已经对以下代码(没有任何index.html)进行了一种变通,并且工作正常,没有任何中断:

Actually I've made a kind of workaround with the following code (without any index.html) and it works fine without any interruptions:

from flask import Flask, Response,render_template
import pyaudio
import audio_processing as audioRec

app = Flask(__name__)

def genHeader(sampleRate, bitsPerSample, channels, samples):
    datasize = 10240000 # Some veeery big number here instead of: #samples * channels * bitsPerSample // 8
    o = bytes("RIFF",'ascii')                                               # (4byte) Marks file as RIFF
    o += (datasize + 36).to_bytes(4,'little')                               # (4byte) File size in bytes excluding this and RIFF marker
    o += bytes("WAVE",'ascii')                                              # (4byte) File type
    o += bytes("fmt ",'ascii')                                              # (4byte) Format Chunk Marker
    o += (16).to_bytes(4,'little')                                          # (4byte) Length of above format data
    o += (1).to_bytes(2,'little')                                           # (2byte) Format type (1 - PCM)
    o += (channels).to_bytes(2,'little')                                    # (2byte)
    o += (sampleRate).to_bytes(4,'little')                                  # (4byte)
    o += (sampleRate * channels * bitsPerSample // 8).to_bytes(4,'little')  # (4byte)
    o += (channels * bitsPerSample // 8).to_bytes(2,'little')               # (2byte)
    o += (bitsPerSample).to_bytes(2,'little')                               # (2byte)
    o += bytes("data",'ascii')                                              # (4byte) Data Chunk Marker
    o += (datasize).to_bytes(4,'little')                                    # (4byte) Data size in bytes
    return o

FORMAT = pyaudio.paInt16
CHUNK = 1024 #1024
RATE = 44100
bitsPerSample = 16 #16
CHANNELS = 1
wav_header = genHeader(RATE, bitsPerSample, CHANNELS, CHUNK)

audio = pyaudio.PyAudio()

# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS,
    rate=RATE, input=True, input_device_index=10,
    frames_per_buffer=CHUNK)
# print "recording..."

@app.route('/audio_unlim')
def audio_unlim():
    # start Recording
    def sound():
        data = wav_header
        data += stream.read(CHUNK)
        yield(data)
        while True:
            data = stream.read(CHUNK)
            yield(data)

    return Response(sound(), mimetype="audio/x-wav")


if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True, threaded=True,port=5000)

我刚开始发送WAV标头,但其中写的大小是veerery大号,告诉播放器等待veeery大数据缓冲区.直到结束"播放器毫无问题地播放即将到来的数据块为止(不再有WAV标头,而只是音频数据块!).这没有任何传输编码:分块"或其他任何东西!只需将mimetype设置为"audio/x-wav". HTTP响应非常简单,如下所示:

I've just started with sending a WAV header, but the size written there is veeery big number telling the player to wait veeery big buffer of data. Until the "end" player plays the coming chunks of data without any problem (no WAV headers anymore just chunks of audio data!). This is without any "Transfer-encoding: chunked" or anything else! Just set the mimetype to "audio/x-wav". And the HTTP response is extremely simple as follows:

这篇关于HTTP实时音频流服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆