如何将Streamlink获取的HLS音频字节实时转为Whisper可处理格式?
HLS流实时音频转写(OpenAI Whisper)解决指南
核心问题解析
你碰到的TypeError: can't handle two datatypes,本质是直接把Streamlink读取的MP3编码字节片段传给Whisper的transcribe方法导致的。Whisper需要的是解码后的音频波形数据(numpy.ndarray格式,单通道16kHz采样率),而非原始的压缩编码字节。
另外解释下1024的意思:这是单次读取的缓冲区大小,单位是字节(即1KB)。设置这个值是为了平衡IO效率和内存占用——太小会导致频繁读写,太大则瞬间占用过多内存,1024是业内常用的默认值。
解决方案:实时解码+管道处理
要实现无文件实时转写,需要通过ffmpeg把HLS流中的音频分离并解码成Whisper能识别的格式,再通过管道实时传递数据。
步骤1:安装依赖
pip install streamlink openai-whisper ffmpeg-python numpy
步骤2:完整代码实现
import streamlink import ffmpeg import numpy as np import whisper # 加载轻量Whisper模型(实时处理推荐base/small) model = whisper.load_model("base") # 获取Twitch的HLS流 link_list = streamlink.streams("TWITCH.TV LINK HERE") streamobj = link_list['worst'] stream_fd = streamobj.open() # 启动ffmpeg管道:从stdin读取HLS流,输出16kHz单通道PCM音频 ffmpeg_process = ( ffmpeg .input("pipe:", format="hls") .audio .output( "pipe:", format="s16le", acodec="pcm_s16le", ac=1, # 单通道 ar=16000 # 16kHz采样率,Whisper要求的标准采样率 ) .run_async(pipe_stdin=True, pipe_stdout=True) ) try: while True: # 从HLS流读取数据,写入ffmpeg输入管道 stream_data = stream_fd.read(4096) # 调大缓冲区到4KB,减少IO次数 if not stream_data: break ffmpeg_process.stdin.write(stream_data) ffmpeg_process.stdin.flush() # 读取ffmpeg解码后的PCM数据(s16le格式,每个样本占2字节) pcm_data = ffmpeg_process.stdout.read(8192) # 对应4096个音频样本 if not pcm_data: continue # 转换为Whisper要求的格式:float32类型,数值范围[-1, 1] audio_wave = np.frombuffer(pcm_data, dtype=np.int16).astype(np.float32) / 32768.0 # 实时转写音频片段 transcribe_result = model.transcribe(audio_wave, fp16=False) print(transcribe_result["text"].strip()) finally: # 关闭资源 stream_fd.close() ffmpeg_process.stdin.close() ffmpeg_process.wait()
为什么之前的尝试无效?
- 直接转numpy:你转的是MP3编码字节的数组,不是解码后的音频波形,Whisper无法解析压缩编码。
- soundfile转换:soundfile需要完整的音频文件结构或可随机访问的流,HLS是分段流式数据,直接喂片段会因缺少文件头报错。
- ffmpeg分离:之前没成功是因为没通过管道实现实时流解码,而是试图先处理文件,不符合实时需求。
注意事项
- 模型选择:实时处理优先选
base或small模型,large模型速度太慢,无法跟上流的节奏。 - 缓冲区大小:可根据网络情况调整读取大小,比如8192字节,进一步减少IO延迟。
- 异常处理:可添加try-except块捕获管道读写异常,避免程序意外崩溃。
内容的提问来源于stack exchange,提问作者SOTERSOTERSOTERSOTERSOTERSOTER
相关产品推荐
相关产品推荐

