Python Requests POST请求异常:发送G.711μ-law音频至设备失败求助
问题排查:Python Requests发送G.711μ-law音频到设备失败
我尝试用Python Requests给设备发送G.711μ-law格式音频,已经把文件转成u-law wav格式。照着设备API的示例(含HTTP/1.0单部分音频传输、gstreamer、curl调用示例)写了代码,请求头参数看起来都配置了,但一直收到错误('Connection aborted.', BadStatusLine('\r\n')),设备只播放2秒蜂鸣声,不播目标音频。Windows环境开发,求排查原因。
设备API示例
Example 1: Single-part audio data transmit with G.711 μ-law (authorization omitted). POST /bha-api/audio-transmit.cgi HTTP/1.0\r\n Content Type: audio/basic\r\n Content Length: 9999999\r\n Connection: Keep Alive\r\n Cache control: no-cache\r\n \r\n <AUDIODATA> <AUDIODATA> <AUDIODATA> ... Example 2: Usage with gstreamer. gst-launch-1.0 alsasrc ! queue ! audioconvert ! audio resample ! "audio/x- raw,format=S16LE,rate=8000,channels=1" ! mulawenc ! "audio/x- mulaw,rate=8000,channels=1" ! curlhttpsink location=http://<device-ip>/bha-api/audio-transmit.cgi content- type="audio/basic" use-content-length=true user=xxxxxx0001 passwd=xxxxxxxx Example 3: Usage with curl. curl -v --http1.0 -H "Content-Type: audio/basic" -H "Content-Length: 9999999" -H "Connection: Keep-Alive" -H "Cache-Control: no-cache" --data- binary "@audio_file.ulaw" 'http://userxx0001:passwordxx@<device-ip>/bha- api/audio-transmit.cgi' --limit-rate 8K
我的Python代码
filepath = Path(os.path.join(full_path, file)) print(filepath) def patch_send(): old_send = HTTPConnection.send def new_send(self, data): print(f'{"-"*9} BEGIN REQUEST {"-"*9}') print(data.decode('utf-8').strip()) print(f'{"-"*10} END REQUEST {"-"*10}') return old_send(self, data) HTTPConnection.send = new_send patch_send() HTTPConnection._http_vsn = 10 HTTPConnection._http_vsn_str = 'HTTP/1.0' HTTPConnection.debuglevel = 0 with open(filepath, mode='r', buffering=128 ) as file: fileobj = file.read() response= requests.post(url= "http://192.168.178.9/bha-api/audio-transmit.cgi", headers={"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0","Content-Type": "audio/basic; ","Connection": "keep-alive", "Cache-Control": "no-cache", "Content-Length": str(len(fileobj))}, auth= ('ghevxxxx', '7vfxxxxx'), stream= True, data = fileobj, timeout=12 )
请求打印信息
--------- BEGIN REQUEST --------- POST /bha-api/audio-transmit.cgi HTTP/1.0 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Type: audio/basic; Cache-Control: no-cache Content-Length: 55844 Authorization: Basic ZxxxxxxxxxxxRo ---------- END REQUEST ----------
问题排查与修复建议
核心问题点
- 文件读取方式错误:音频是二进制文件,用
mode='r'文本模式读取会破坏二进制数据,导致设备无法识别,触发蜂鸣提示。必须用mode='rb'二进制模式读取。 - Content-Type头格式错误:请求头中
Content-Type: audio/basic;多了一个分号,与API示例的标准格式不符,可能导致设备无法正确解析媒体类型。 - 缺少码率限制:curl示例中明确设置了
--limit-rate 8K(G.711μ-law的标准码率是8kbps),未限速会导致数据发送过快,设备处理不及时断开连接。 - stream参数误用:
stream=True用于大文件流式上传,但你已将整个文件读入内存,该参数会干扰发送逻辑,建议移除或直接传递文件对象。 - HTTP/1.0配置细节:直接修改
HTTPConnection属性可能存在覆盖不全的情况,建议结合会话对象确保HTTP/1.0协议生效。
修正后的代码示例
import os from pathlib import Path import requests from http.client import HTTPConnection # 打印请求头(避免二进制音频乱码) def patch_send(): old_send = HTTPConnection.send def new_send(self, data): print(f'--------- BEGIN REQUEST ---------') if b'\r\n\r\n' in data: headers = data.split(b'\r\n\r\n')[0].decode('utf-8') print(headers.strip()) print(f'---------- END REQUEST ----------') return old_send(self, data) HTTPConnection.send = new_send patch_send() # 强制使用HTTP/1.0协议 HTTPConnection._http_vsn = 10 HTTPConnection._http_vsn_str = 'HTTP/1.0' filepath = Path(os.path.join(full_path, file)) print(filepath) # 二进制模式打开文件,获取真实文件大小 file_size = os.path.getsize(filepath) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0", "Content-Type": "audio/basic", "Connection": "keep-alive", "Cache-Control": "no-cache", "Content-Length": str(file_size) } # 创建会话并实现8KB/s限速(匹配G.711μ-law码率) session = requests.Session() try: with open(filepath, mode='rb') as file: response = session.post( url="http://192.168.178.9/bha-api/audio-transmit.cgi", headers=headers, auth=('ghevxxxx', '7vfxxxxx'), data=file, # 直接传递文件对象,流式上传 timeout=12, stream=False ) response.raise_for_status() print("音频发送成功") except requests.exceptions.RequestException as e: print(f"发送失败: {e}")
内容的提问来源于stack exchange,提问作者Bonze
相关产品推荐
相关产品推荐

