如何在没有中间音频文件的情况下将 pydub `AudioSegment` 转换为流媒体目的?

问题描述 投票:0回答:2

我正在开发一款软件,使用 Flask Web 服务通过 HTTP 从源流式传输音频。我可以通过

sounddevice
获取声音帧,并通过具有
yield
和正确的 mimetype 的 Flask 路由将它们路由到浏览器,但是原始音频格式对于远程流式传输来说非常麻烦,并且在涉及到时并不是最好的客户端兼容性。

我很想使用

pydub
将原始音频帧转换为 mp3 或 ogg 等格式,但无论是从 文档还是从 源代码,我都不清楚如何实现 on-the - 进行格式转换,无需通过
.export()
将输出转储到文件。

到目前为止我的代码框架是这样的:

### audio.py

import queue
import sounddevice as sd
from pydub.audio_segment import AudioSegment


def input_stream(device, sample_width=2, sample_rate=44100,
        channels=1, latency=0, blocksize=2048, timeout=5.0):
    audio_queue = queue.Queue()

    def audio_callback(indata, frames, time_duration, status):
        audio = AudioSegment(indata, sample_width=sample_width,
                channels=channels, frame_rate=sample_rate)

        # Some pydub magic should happen here to convert the raw frame to mp3/ogg

        audio_queue.put(audio.raw_data)


    with sd.InputStream(samplerate=sample_rate, device=device,
                        channels=channels, callback=audio_callback,
                        latency=latency, blocksize=blocksize):
        while not recording_terminated():
            yield audio_queue.get(block=True, timeout=timeout)


### web.py

from flask import route, request, Response

from audio import input_stream


@route('/sound/stream', methods=['GET'])
def get_sound_feed():
    device = request.args.get('device')
    return Response(input_stream(device), mimetype='audio/ogg')

如何将

AudioSegment
中的原始
audio_callback
对象转换为适合网络流媒体的压缩 mp3/ogg?我知道可以通过
AudioSegment.from_file
从 mp3 创建片段,或者通过
.export()
将其转储到 mp3 文件,但这并不是一个真正的选择,因为此类 I/O 操作会引入不可忽略的延迟。我认为理论上可能可以破解 .export() 以将其转储到套接字或 fifo 文件描述符,但这对我来说听起来有点像一个 hacky 解决方法,而且我不确定它是否足以满足文件描述符以提供
.write()
方法,或者如果它因需要其他方法(例如
seek
)而中断。
    

python audio streaming pydub
2个回答
2
投票
.export()

函数在执行结束时返回文件对象。


convert_file = audio_file.export(format="flac")

我已经这样做了,我可以像使用 
open()

函数一样处理 Convert_file 。 (我为自己的项目转换为 flac,但你可以做任何格式)

我发现,如果您不提供文件名,
.export()
函数甚至无法将文件写入磁盘而不出现任何错误。
我希望您能找到解决问题的方法。


0
投票

# Load input song song = from_mp3("my_song.mp3") # create new empty BytesIO exported_io = BytesIO() # export to BytesIO object song.export(exported_io, format="wav")

然后可以对此 BytesIO 对象执行任何操作。使用此方法不会创建任何物理文件。

© www.soinside.com 2019 - 2024. All rights reserved.