【发布时间】:2019-07-21 20:06:40
【问题描述】:
我正在开发一个软件,使用 Flask 网络服务通过 HTTP 从源流式传输音频。我可以通过sounddevice 获取声音帧,并通过带有yield 和正确mimetype 的Flask 路由将它们路由到浏览器,但是原始音频格式对于远程流式传输来说非常麻烦,并且在涉及到时并不是最好的客户端兼容性。
我很想使用 pydub 将原始音频帧转换为像 mp3 或 ogg 这样的格式,但无论从 the documentation 还是从 the source code 我都不清楚如何实现在线播放飞格式转换而不通过.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')
如何将audio_callback 中的原始AudioSegment 对象转换为适合网络流媒体的压缩mp3/ogg?我知道可以从 mp3 到AudioSegment.from_file 创建一个片段,或者通过.export() 将其转储到一个 mp3 文件中,但这并不是一个真正的选择,因为这样的 I/O 操作会引入不可忽略的延迟.我认为可能理论上可以破解 .export() 以使其转储到套接字或 fifo 文件描述符,但这对我来说听起来有点像 hacky 解决方法,而且我不确定文件描述符是否足以提供.write() 方法,或者它是否会因为需要其他方法(例如seek)而中断。
【问题讨论】:
-
我从 2014 年就遇到了这个问题:stackoverflow.com/questions/25469161/…。最后一条评论似乎证实了我的怀疑,即即时导出(而不是文件)不是 pydub 中的一个选项。我不确定在此期间是否取得了任何进展,或者是否某些用户已经进行了分叉来支持它。如果不是这样,我可能会试一试并向 pydub 提交 PR。
-
你找到怎么做了吗?我正在尝试将文件保存在 BytesIO 中以删除持久性方面
标签: python audio streaming pydub