HLS音频流在iOS及Mac Safari卡顿,Chrome与VLC正常的排查求助
问题描述
我们的HLS音频流存在随机中断后自动恢复的异常:
- 仅在iOS设备、macOS的Safari浏览器中出现;桌面端VLC播放正常,iOS端VLC也无此问题
- 多名开发者在不同设备同步播放时,中断与恢复完全同步,确认问题根源在流本身
当前使用FFmpeg同时生成DASH与HLS流,转码配置如下:
transcoder // Right now this is the max we'll get .audioBitrate('64k') // We only have 1 channel .audioChannels(1) // Enable experimental features ldash/lhls .outputOption('-strict', 'experimental') // Set url for syncing UTC timestamps with client .outputOption('-utc_timing_url', 'https://time.akamai.com/?iso') .outputOption('-write_prft', '1') // Streaming mode .outputOption('-streaming', '1') // Use segment file template so we dont list all segments in the manifest .outputOption('-use_template', '1') // Must be disabled for index_correction which is suggested for streaming use case .outputOption('-use_timeline', '0') // Fix up segment indexes if they drift due to bandwidth changes .outputOption('-index_correction', '1') // Use 6 second segments, for live this shouldn't matter but this is Apple's suggested // value for HLS .outputOption('-seg_duration', '6') // Push the frames out as fast as they come in .outputOption('-frag_type', 'every_frame') // Use mp4 segments .outputOption('-dash_segment_type', 'mp4') // Enabled low-latency mode .outputOption('-ldash', '1') // Output an HLS playlist too .outputOption('-hls_playlist', this.options.hlsEnabled ? '1' : '0') // HLS manifest name .outputOption('-hls_master_name', 'index.m3u8') // Use persistent HTTP connection .outputOption('-http_persistent', '1') // Do PUTs to the upload endpoint .outputOption('-method', 'PUT') // Dont let an output error hold up the stream .outputOption('-ignore_io_errors', '1') // Set a timeout for output .outputOption('-timeout', '1') // DASH format .format('dash');
下一步排查方向建议
检查HLS Manifest与片段的时间戳连续性
抓取中断前后的index.m3u8,核对每个片段的EXTINF时长、EXT-X-PROGRAM-DATE-TIME是否连续,有无时间戳跳变;用ffprobe -show_packets -select_streams a:0 [segment_file]检查音频片段的PTS/DTS,确认是否存在时间断层——Safari对HLS时间线的连续性要求极高,微小异常都会引发中断。验证低延迟HLS的兼容性
当前开启了-ldash和实验性特性,FFmpeg的LL-HLS实现与Safari可能存在细节兼容问题。尝试暂时关闭-ldash与-strict experimental,切换到标准HLS模式生成流,观察是否仍有中断;同时检查Manifest中是否包含LL-HLS特有标签(如EXT-X-SERVER-CONTROL),确认Safari能否正确解析。排查音频编码与封装的兼容性
Safari对HLS的AAC编码有明确要求,建议明确指定-c:a aac -profile:a LC(低复杂度AAC),避免使用实验性编码或高profile;当前用MP4片段封装HLS,虽Safari支持,但可尝试切换到TS封装(添加-hls_segment_type mpegts),验证是否解决问题。检查Segment上传与存储的完整性
配置中开启了-ignore_io_errors和-timeout 1,若上传Segment时出现IO错误,FFmpeg会忽略继续,可能导致服务器上的Segment损坏或缺失。检查服务器上的Segment文件大小是否符合预期,有无零字节或损坏文件;同时验证-method PUT的上传逻辑,确认服务器是否正确接收所有Segment。排查时间同步配置的影响
暂时移除-utc_timing_url与-write_prft配置,观察中断是否消失——若时间同步出现偏差,Safari可能误判片段过期或时间线不匹配,引发播放中断。分析FFmpeg详细日志
给FFmpeg添加-v verbose或-v debug输出选项,查看中断时间段内的日志,重点关注音频编码、Segment生成、Manifest写入相关的警告或错误信息,定位具体异常点。
内容的提问来源于stack exchange,提问作者Elliot

