将HLS推送到MediaPackage遇问题:401/404错误排查求助
问题描述
- 流应用架构:EMX → EML → S3 → LAMBDA → EMP
- 核心问题1:使用Python向MediaPackage HLS ingest端点发送PUT请求返回201成功,但ingress访问日志显示每个文件被记录两次,一次是401状态码,一次是201状态码
- 核心问题2:将根清单发送到
channel/{根清单名称}.m3u8时返回404;将EML直接连接EMP测试发现,请求格式为:所有文件使用channel_filename、TS文件使用channel_timestamp_sequence.ts、根清单使用.m3u8,但调整后MediaPackage origin端点仍对清单返回404 - 相关Python代码:
def postStreamToMediaPackage(envVariables, fileName, content, contentType): mediaPackageUrl = envVariables["url"] username = envVariables["username"] password = envVariables["password"] ingestUrl = f"{mediaPackageUrl.rstrip('/channel')}/{fileName}" # not sure what mediapackage wants. response = requests.put( ingestUrl, data=content, headers={ "ContentType": contentType }, auth=HTTPDigestAuth(username, password)) if response.status_code != 201: print( f"Error ingesting file {fileName} to {ingestUrl}. error: {response.text}") return {"ingestUrl": ingestUrl, "fileName": fileName, "status": response.status_code}
解决方案
一、401+201重复日志问题
这是requests库HTTPDigestAuth的默认行为:库会先发送不带认证信息的请求,触发服务器返回401并携带Digest认证挑战,随后再发送包含正确认证信息的请求,最终返回201成功。该现象不影响实际 ingest 结果,属于正常流程。
如果需要消除日志中的401记录,可以手动构造Digest认证头:
- 先发送HEAD请求到目标URL,获取服务器返回的
WWW-Authenticate头 - 用
requests.auth._digest_auth模块生成认证头 - 将认证头加入PUT请求的headers中
不过多数场景下无需额外处理,最终 ingest 成功即可。
二、根清单404问题
你的代码存在两个关键错误,导致根清单无法被MediaPackage正确识别:
1. HTTP请求头键名错误
代码中设置的ContentType是错误的HTTP头名称,正确的头应为Content-Type(带横杠)。MediaPackage依赖这个头识别文件类型(HLS清单/TS分片),头名错误会导致服务器无法正确解析根清单。
2. Ingest路径构造错误
根据你测试的EML直接连接EMP的请求格式,根清单的正确路径是{mediaPackageUrl}/.m3u8,而不是去掉/channel后拼接自定义文件名。代码中mediaPackageUrl.rstrip('/channel')错误移除了路径中的channel部分,导致请求发送到了错误端点。
修正后的代码:
def postStreamToMediaPackage(envVariables, fileName, content, contentType): mediaPackageUrl = envVariables["url"] username = envVariables["username"] password = envVariables["password"] # 根据文件类型构造正确的ingest路径 if fileName.endswith('.m3u8') and "root" in fileName: # 假设根清单文件名包含root标识,可根据实际调整判断逻辑 ingestUrl = f"{mediaPackageUrl.rstrip('/')}/.m3u8" else: ingestUrl = f"{mediaPackageUrl.rstrip('/')}/{fileName}" response = requests.put( ingestUrl, data=content, headers={ "Content-Type": contentType # 修正HTTP头名称 }, auth=HTTPDigestAuth(username, password) ) if response.status_code != 201: print(f"Error ingesting file {fileName} to {ingestUrl}. error: {response.text}") return {"ingestUrl": ingestUrl, "fileName": fileName, "status": response.status_code}
额外注意事项
- 根清单必须发送到
{mediaPackageUrl}/.m3u8,不能带自定义文件名,MediaPackage会以此作为HLS流的根入口 - TS分片和子清单的路径应为
{mediaPackageUrl}/{文件名},文件名格式需与EML输出一致(如timestamp_sequence.ts) - 确保
contentType参数正确:清单文件用application/vnd.apple.mpegurl,TS分片用video/MP2T
内容的提问来源于stack exchange,提问作者sakib11
相关产品推荐
相关产品推荐

