WhepProbe
whepprobe 是一个类似 ffprobe 的 WHEP 端点诊断工具。它订阅 WHEP 流,验证流是否可达,并通过 rsmpeg crate 调用 FFmpeg 实际解码媒体。支持 VP8、VP9、H.264、H.265、AV1 视频以及 Opus、G.722、PCMU、PCMA 音频。纯视频流保持原有成功语义;只要收到音频 RTP,就必须至少成功解码一个音频帧。
如果需要基于真实浏览器的播放验证,请查看 WhepWright。
获取
whepprobe 已包含在 all-in-one 的 live777-all 镜像中:
bash
docker run --rm --network host ghcr.io/binbat/live777-all:latest \
whepprobe -w http://localhost:7777/whep/live镜像内置的 smoke-test 命令在 WHEP 验证环节使用的就是 whepprobe——见快速开始。
构建
bash
# 需要 FFmpeg 开发库
cargo build --bin whepprobe --features rsmpegAV1 软件解码需要 FFmpeg 启用 libdav1d 或 libaom。探针会优先使用这些 解码器,而不是 FFmpeg 面向硬件解码的原生 AV1 解码器。
用法
探测一个 WHEP 端点:
bash
whepprobe -w http://localhost:7777/whep/live指定预期编码和超时时间:
bash
whepprobe -w http://localhost:7777/whep/live --codec h264 --timeout 60输出 JSON 格式,方便脚本或 CI 使用:
bash
whepprobe -w http://localhost:7777/whep/live --output json选项
| 选项 | 默认值 | 说明 |
|---|---|---|
-w, --whep | 必填 | WHEP 端点 URL |
-t, --token | 无 | WHIP/WHEP 认证使用的 Bearer token |
-v | warn | 提高日志级别(-v info,-vv debug,-vvv trace) |
--codec | 自动检测 | 预期视频编码:vp8、vp9、h264、h265、av1。rsmpeg 后端会从 WHEP 会话自动检测编码,因此该选项仅影响报告结果。 |
--sprop-params | 无 | H.265 sprop 参数(sprop-vps=...;sprop-sps=...;sprop-pps=...) |
--decode-duration | 5 | WHEP 连接成功后持续解码的秒数;实际窗口受剩余 --timeout 预算限制,并为清理预留 2 秒。 |
--output | human | 输出格式:human、json |
--timeout | 30 | 整体超时时间(秒) |
--ice-server | 无 | ICE 收集使用的服务器,可重复指定;格式 <url>[,<username>[,<credential>]]。默认为空——仅使用 host candidate(WHIP/WHEP 端点会通过 Link 头通告自己的 ICE 服务器) |
JSON 音频字段
所有报告(包括失败报告和无音频流)都包含 audio_frame_count、 audio_sample_rate 和 audio_channels。零值表示没有解码出音频帧;成功解码后, 这些字段分别表示音频帧数、实际采样率(G.722 的 RTP 时钟为 8000 Hz,但实际 采样率为 16000 Hz)和声道数。
退出码
0:WHEP 已连接且视频已解码;如果收到音频 RTP,音频也已成功解码。1:探测失败或发生错误。
核心库
探测逻辑位于 livetwo::probe,可以被集成测试或其他 Rust 工具复用:
rust
use cli::Codec;
use livetwo::probe::{ProbeBackend, ProbeConfig};
use livetwo::probe::rsmpeg::RsmpegProbe;
// RsmpegProbe 需要 `livetwo` 启用 `rsmpeg` feature 才能使用。
let config = ProbeConfig {
whep_url: "http://localhost:7777/whep/live".to_string(),
video_codec: Some(Codec::Vp8),
..Default::default()
};
let result = RsmpegProbe::default().probe(&config).await?;
assert!(result.success);