WebSocket流式WebM音频分片无法播放:如何补充后续分片音频元信息?
问题根源
WebM是带容器结构的音频格式,只有第一个由MediaRecorder生成的分片包含完整的容器元数据(EBML头、轨道编码信息等),后续分片仅包含裸音频帧数据,没有容器识别所需的头部信息,所以ffmpeg、pydub等工具无法解析,抛出Invalid data found when processing input错误。
解决方案
后端为每个WebSocket会话保存第一个分片的WebM容器头,后续每个分片写入文件时,先拼接这个头部再写入数据,让每个分片都成为完整可识别的WebM文件。
后端代码修改
在WebSocket处理类中维护会话级的头部缓存,修改接收逻辑:
# 初始化WebSocket会话时添加头部缓存 def __init__(self): self.webm_header = None # 其他原有初始化逻辑... async def receive(self, text_data=None, bytes_data=None): if bytes_data: audio_filename = f"audio_{datetime.now().strftime('%Y%m%d%H%M%S')}.webm" self.audio_file_path = os.path.join("audio/", audio_filename) os.makedirs(os.path.dirname(self.audio_file_path), exist_ok=True) with open(self.audio_file_path, "wb") as audio_file: if self.webm_header is None: # 处理第一个分片:提取并保存WebM容器头 # WebM中Cluster(存储音频帧的单元)的标识字节是\x1F\x43\xB6\x75 cluster_magic = b'\x1F\x43\xB6\x75' cluster_start_pos = bytes_data.find(cluster_magic) if cluster_start_pos != -1: # 截取Cluster之前的所有字节作为容器头 self.webm_header = bytes_data[:cluster_start_pos] # 写入完整的第一个分片 audio_file.write(bytes_data) else: # 处理后续分片:先写入缓存的容器头,再写入音频数据 audio_file.write(self.webm_header) audio_file.write(bytes_data)
前端优化建议
明确指定WebM的编码格式,避免浏览器兼容性问题:
this.mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm;codecs=opus" });
验证方法
修改后,用ffmpeg测试后续分片:
ffplay audio_xxxxxx.webm
若能正常播放,说明头部补全成功,pydub的转换代码也能正常执行。
内容的提问来源于stack exchange,提问作者de-bugged
相关产品推荐
相关产品推荐

