pure_live HLS 按短轨结束的原生边界控制审计:`-shortest` 候选策略的取舍与证据链

发布时间:2026/10/14 16:23:14
pure_live HLS 按短轨结束的原生边界控制审计:`-shortest` 候选策略的取舍与证据链 音视频直播移动开发【免费下载链接】pure_live纯粹直播:哔哩哔哩/虎牙/斗鱼/快手/抖音/网易cc/YY直播/Twitch直播/SOOP直播/M38自定义源应有尽有。项目地址https://gitcode.com/gh_mirrors/pur/pure_live点击查看免费下载导读本文基于 pure_live 仓库的审计文档 docs/HLS_SHORTEST_BOUNDARY_AUDIT_2026_09_10.md完整还原一次针对 HLS 直播录制共同 A/V 停止边界的原生候选策略实验在首片保全之后固定 3 个视频 / 4 个音频完整分片仍存在约 2 秒音轨尾差团队尝试用 FFmpeg 的-shortest -shortest_buf_duration 10参数让输出随最短轨道自然结束。文中给出四组对照实验的完整设计、两轮探针运行记录、逐轨包数与 PTS 证据、SHA-256 级独立文件核对以及不采用全局-shortest的最终决策与回滚方式。读完你可以掌握如何在录制探针中注入原生 FFmpeg 参数并观察停止时刻、如何用逐包 payload 哈希判定精确前缀/后缀裁剪、以及直播录制中原始内容完整保留与对齐导出副本分离的边界设计思路。背景首片保全之后遗留的尾差问题本审计承接两条主线docs/HLS_SELECTED_START_AUDIT_2026_09_09.md已准入 HLS 缓存的原生起点衔接实验起点ae92681f证明默认选片会丢失已可用的音频前缀并以prefer_x_start1EXT-X-START:TIME-OFFSET0,PRECISENO桥接了起点docs/HLS_RELOAD_CADENCE_AUDIT_2026_09_10.md刷新周期相关实验。起点问题的解决使首片得以保全但实验同时暴露了另一个现象零起点样本的音频末 PTS 仍比视频晚约 1.99 秒见HLS_SELECTED_START_AUDIT剩余边界一节。本轮审计的目标就是处理这个共同停止边界——即首片已对齐后固定 3 个视频 / 4 个音频完整分片仍存在约 2 秒音轨尾差。本轮起点72d40565生产40a2bf8c探针提交a46bccea。需要特别强调的是本轮仅评价原生候选策略生产录制命令与合并命令保持原样探针之外的夹具、应用策略与用户数据一律不动。核心问题-shortest的语义与观察维度FFmpeg 的-shortest高级选项以最短输出流的结束来限制整体输出其副作用是可能引入缓冲且默认缓冲时长为 10 秒。它不是仅在用户点击停止时才触发的规则——这意味着它可能在录制过程中就悄悄截断输出。因此实验不能只观察文件结束时间是否接近而必须同时检验三个维度尾差改善短轨结束是否真的把两轨末包时间拉近内容裁减为换取对齐丢掉了多少已取得的有效包任务退出时刻短轨结束是否真的让任务在手动停止之前自然完成。实验设计四组对照与探针注入固定前提同一固定 CMAFCommon Media Application Format夹具真实 FFmpegManagerlib/domains/recorder/data/ffmpeg/ffmpeg_manager.dart驱动原生执行生产显式预取路径productionPrefetch: true独立 A/V 序号distinctSequences: true已验证的首片提示。四组变体编号变体视频分片音频分片-shortest音轨先结束1long-audio-preserved34否否2long-audio-shortest34是否3ended-audio-preserved43否是音频清单写 ENDLIST4ended-audio-shortest43是是音频清单写 ENDLIST视频清单始终为 LIVE不追加内容每场固定 4 秒观察窗口若任务仍在运行则发手动停止。本实验刻意没有模拟长期增长的视频——它回答的是固定内容下短轨结束能否让任务自然退出这一受控问题而非真实直播的长期行为。探针参数注入与落盘策略探针定义位于 tool/probes/hls_shortest_boundary_probe.dart通过_registerShortestBoundaryProbe注册为 opt-in 测试环境变量PURELIVE_HLS_SHORTEST_BOUNDARY_PROBE1才运行。四组变体的参数化构造如下for (final variant in [ (name: long-audio-preserved, video: 3, audio: 4, shortest: false, audioEnded: false), (name: long-audio-shortest, video: 3, audio: 4, shortest: true, audioEnded: false), (name: ended-audio-preserved, video: 4, audio: 3, shortest: false, audioEnded: true), (name: ended-audio-shortest, video: 4, audio: 3, shortest: true, audioEnded: true), ]) { reports.add(await _capture( (name: variant.name, budget: 5, bodyMs: 0, headerMs: 0, runSeconds: 4), fixture, root, productionPrefetch: true, fixedCounts: (video: variant.video, audio: variant.audio), distinctSequences: true, shortestOutput: variant.shortest, audioEnded: variant.audioEnded, )); }_capture辅助函数见 tool/probes/hls_rolling_delivery_probe_test.dart先用FFmpegCommandBuilder.buildRecordArguments生成生产录制命令再在输出文件参数前插入实验参数if (shortestOutput) { arguments.insertAll(arguments.length - 1, [-shortest, -shortest_buf_duration, 10]); }audioEnded则影响本地源清单当请求的是音频轨variant_1且audioEndedtrue时清单末尾追加#EXT-X-ENDLIST见_RollingOrigin的 584 行附近逻辑从而构造音轨先结束的输入条件。探针的数据纪律值得注意通过startAck留存所属会话、relay 与命令仅落盘布尔/数值参数nativeShortest、nativeStartIndex、nativePreferStartHint、nativeReadTimeoutMicros等绝不落盘完整命令或 URLnativeShortest用正则(?:^|\s)-shortest(?:\s|$)从会话命令中判定用于核对注入是否真正生效支持观察提前自然完成事件流中保留manualStop、inputDrained、forcedCancel、inputCoverageIncomplete、inputIntegrityError、inputTailDiscarded等结束语义标记。第一轮候选假设被反证首轮运行记录为20260909T165318446Z-hls-shortest-boundary-first.json证据目录controls/shortest-1788972762925751。结果四场都完成但核心断言失败——音轨已结束 shortest 会在手动停止前自然完成这一假设被反证实际stopIssuedtrue即任务仍在运行、需要手动停止。该阶段2 PASS / 1 FAIL五个 opt-in 探针未运行严格分析尚未执行。这是典型的候选假设被实验反证而不是生产缺陷红测-shortest确实让输出接近短轨尾边界但它没有带来任务自然退出的行为同时还在裁剪已取得的有效内容。失败本身就是本轮最重要的产出之一。第二轮修订探针后的终局证据修订探针的目标是明确验证实际观察到的截尾与手动停止行为并收紧固定夹具包数生产代码零修订。最终运行20260909T165945246Z-hls-shortest-boundary-observed.json3/3 PASS两项统计 一项含四场原生控制五个其它 opt-in 未运行两个改动 Dart 文件严格分析 PASS。证据目录controls/shortest-1788973152810447。两轮逐轨包数完全一致四场终局数据如下控制视频包视频首/末 PTS秒音频包音频首/末 PTS秒long-audio-preserved1801.421033 / 7.3877003751.400000 / 9.378667long-audio-shortest1801.421033 / 7.3877002821.400000 / 7.394667ended-audio-preserved2401.421033 / 9.3877002821.400000 / 7.394667ended-audio-shortest1791.421033 / 7.3543672821.400000 / 7.394667读表要点末包 PTS 差不是两轨结束时刻或完整唇音同步指标须另计包时长与编码重排不能直接当作对齐质量第一组long-audio-shortest vs preservedshortest 把音频从 375 包裁到 282 包末包 PTS 差约 6.967 ms代价是减少 93 个音频包第二组ended-audio-shortest vs preserved音轨先结束 shortest 把视频从 240 包裁到 179 包减少 61 个视频包约 2 秒有效视频被丢弃。结束语义标记四场统一呈现stopIssuedtrue、manualStoptrue、native code0、drainedtrue、forcedCancelfalse、inputTailDiscardedfalse、coveragefalse、integrityfalse关闭后预取池 entries/bytes0。注意上述输入排空/覆盖标记描述的是输入交付状态不等于输出编码包完整。保留的原始日志仍含 I/O、重复 moov 与pthread_join ESRCH信息团队明确不把它们记为原生日志零警告——这是文档纪律保留真实日志不做粉饰。时间线佐证不是 relay 隐藏了结束音轨先结束 shortest 场次的时间线进一步说明问题音轨 ENDLIST 在 44 ms 就已交付给 native视频仍为 LIVE视频 1000–1003 四段全部完整交付最后一段 107 ms4002 ms 才发出停止指令4134 ms 提供停止视频清单4136 ms 完成。也就是说native 早已知道音轨结束、视频也完整送达但任务仍然等到手动停止才退出。因此可以排除relay 隐藏音轨结束或源视频缺片两类解释。当前证据只支持四秒观察窗内任务未自然完成这一结论团队谨慎地不推断所有 HLS/native 版本都如此。独立文件核对SHA-256 级的前缀裁剪证明四份最终 TS 全文件严格解码均 exit0、stderr0随后逐包 payload SHA-256 对比得到精确裁剪关系long-audio-shortest视频 180 包与保留版完全相同音频 282 包是保留版 375 包的精确前缀丢掉的是尾部 93 包ended-audio-shortest音频 282 包与保留版完全相同视频 179 包是保留版 240 包的精确前缀丢掉的是尾部 61 包。这从内容层面证实-shortest的行为是整体截尾而非重编码对齐——它没有丢中间包、没有改动已交付包只是砍掉了短轨结束点之后的尾部内容。工具/输入哈希与完整证据保存在local-artifacts/hls-shortest-boundary-20260910目录下的observed-source-hashes.json、retained-decode/input-hashes.json、retained-decode/summary.json。固定夹具、FFmpegKit DLL 与 ffprobe/ffmpeg 均按已有固定 SHA 核对包数取自最终文件不以原生进度行的 frame 值替代。资源采样记录阶段资源记录秒采样峰值 CPU采样工作集字节结束活跃重型进程假设反证20260909T165318446Z-hls-shortest-boundary-first.json75.02118.59%50702295040最终控制 严格分析20260909T165945246Z-hls-shortest-boundary-observed.json46.0068.60%52303421440保留文件解码 payload20260909T170029379Z-hls-shortest-boundary-retained-decode.json5.8040%39693025280最后一行是短阶段采样值不代表解码未消耗 CPU。另有一次工具性插曲首次生成解码脚本的 JavaScript 调用存在字符串语法错误在执行 shell 前失败修订调用后仅执行上述一次解码没有遗留任务——这也体现了探针流水线对执行前校验、执行后核对的坚持。生产代码对照为什么-shortest不该进入录制命令把实验参数与生产命令放在一起看能更清楚理解不采用全局-shortest的工程原因。生产录制参数由lib/domains/recorder/data/ffmpeg/ffmpeg_command_builder.dart的buildRecordArguments构建核心特征是-n不覆盖、-analyzeduration 5000000/-probesize 5000000录制优先于播放延迟的完整流发现-map 0:v:0?/-map 0:a:0?可选映射支持纯音频房间与临时缺视频轨道-c copy流拷贝、-f segment-segment_format mpegts分段 mux 与-reset_timestamps 1-segment_listCSV journal 与RecordingSegmentClock.segmentPattern命名保证合并时能按参考时间戳重建。也就是说生产语义是尽可能完整地把输入包写入分段输出并依赖 native 取消回调中断输出 IO、靠flush_packets1:avoid_negative_tsdisabled:max_delay0:output_ts_offset1.4保证已 mux 包不被丢弃。而-shortest的默认 10 秒缓冲语义会在录制过程中主动截断输出流——这与录制语义直接冲突它裁减的是已取得的有效内容而非尚未到达的内容。结束事件的语义在 lib/domains/recorder/data/services/ffmpeg_service.dart 中有明确定义manualStop标记用户显式停止inputDrained表示native 在 finish 后自然结束且没有 forced cancel、输入 relay 无挂起访问单元inputTailDiscarded表示 liveRecording 下 ownedInput 或 inputRelay 判定输入尾部被丢弃。本实验中inputDrainedtrue与stopIssuedtrue并存恰好证明输入已排空与任务是否提前退出是两个独立维度——-shortest并不能把前者转化为后者的自然完成。决策、剩余验收与回滚最终决策不采用全局-shortest作为直播录制修复。理由明确它确实让输出接近短轨尾边界第一组末包 PTS 差约 7 ms但代价是裁减已取得的有效内容93 个音频包或 61 个视频包/约 2 秒有效视频且本次实验中任务仍在手动停止后才退出没有兑现自然完成的预期。由此确认的是候选策略的取舍不是一个已修复的生产 Bug现有共同 A/V 停止边界仍未闭环。分类上这是 native 默认直播选片机制与录制需求的组合差异integration-conflict不宣称 FFmpeg 播放默认值本身是缺陷。下一步边界设计明确原始内容完整保留与对齐导出副本两个独立合同停止后计算两轨包结束边界、报告单轨尾部长度不用静默裁剪、也不仅靠改验收时长来掩盖源差异若生成对齐副本保留原件并以独立文件验证不改变活动期持续录制语义随后再做包含已验证起点/覆盖/周期修订的有界真实录制不反复重录旧输入直到偶然通过。回滚回滚只需撤回探针提交a46bccea探针是实验参数唯一的注入点生产代码零改动。默认预取仍关闭本轮无手机、MT、Root/LSP、线上直播重录、版本、构建或发布动作。宏观验收状态保持20 PASS / 32 RUN / 10 NOT RUN42 组未闭环全平台 3.2.0 交付门禁不变。小结可复用的实验方法论从本审计可以提炼出几条对任何原生参数候选评估都适用的方法参数注入隔离实验参数仅通过探针插入arguments.insertAll(arguments.length - 1, ...)生产buildRecordArguments不动回滚成本降到最低断言要覆盖行为全维度不只检查文件结束时间接近还要查stopIssued/manualStop/inputDrained的组合区分输入排空与任务自然完成内容级验证优于统计级验证逐包 payload SHA-256 能精确证明精确前缀/后缀裁剪比只看末包 PTS 差可靠得多失败记录同样重要第一轮的假设反证被完整保留first.json它正是决策不采用全局-shortest的直接证据不扩大结论范围四秒观察窗的受控结果明确不推断到所有 HLS/native 版本与长期直播场景。至此pure_live 的 HLS 共同停止边界仍然开放但按短轨结束这条候选路径已被证据完整地评估并排除为后续原件保留 对齐副本的双合同设计扫清了决策障碍。更多细节可继续阅读承接文档 docs/HLS_SELECTED_START_AUDIT_2026_09_09.md、docs/HLS_RELOAD_CADENCE_AUDIT_2026_09_10.md 以及探针源码 tool/probes/hls_shortest_boundary_probe.dart。赞分享音视频直播移动开发【免费下载链接】pure_live纯粹直播:哔哩哔哩/虎牙/斗鱼/快手/抖音/网易cc/YY直播/Twitch直播/SOOP直播/M38自定义源应有尽有。项目地址https://gitcode.com/gh_mirrors/pur/pure_live点击查看免费下载相关推荐pure_live HLS 明确选流机制剖析从多画质 master 解析到 niconico 双轨短录实战验证pure_live HLS 明确选流机制剖析从多画质 master 解析到 niconico 双轨短录实战验证 导读 本文以 pure_live纯粹直播仓音视频直播移动开发pure_live HLS 保留清单发布验证从 HlsRetainedWindow 到本地缓存读取的原生链路打通pure_live HLS 保留清单发布验证从 HlsRetainedWindow 到本地缓存读取的原生链路打通 本篇基于 pure_live 仓库 2026音视频直播移动开发pure_live 录制链路 HLS 有界预取池未读响应取消修复与读取租约所有权设计pure_live 录制链路 HLS 有界预取池未读响应取消修复与读取租约所有权设计 导读 本文基于 pure_live纯粹直播仓库中 HLS_PREFE音视频直播移动开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考