feat: add WebRTC streaming via str0m + portal session persistence

- Add src/webrtc.rs: HTTP signaling server + str0m Sans-IO WebRTC transport
  with H.264 Annex-B → RTP packetization and key-frame request handling
- avhw: introduce FrameOutput enum (Muxer | Channel) so SwEncState can
  output to either MP4 muxer or crossbeam channel for WebRTC
- cap_portal: support portal session restore tokens (PersistMode::ExplicitlyRevoked)
  to skip re-authorization dialog; add --no-persist flag to force fresh dialog
- args: make --output optional when --port is used for WebRTC mode
- state_portal: integrate WebRTC pipeline (encoder channel → RTP forwarding)
  with shorter GOP for WebRTC (fps/2, min 10)
- main: redirect tracing to stderr; validate --output or --port required
- Add dependencies: str0m 0.20, serde_json 1, dirs 6
This commit is contained in:
dailz
2026-06-04 20:54:16 +08:00
parent 74f4dc826d
commit b0ed6548a6
10 changed files with 1611 additions and 70 deletions

View File

@@ -18,6 +18,7 @@ mod fps_limit; // 帧率限制器
mod state; // wlr-screencopy 后端的主状态机
mod state_portal; // Portal/PipeWire 后端的主状态机
mod transform; // 图像变换(旋转/翻转)
mod webrtc; // WebRTC 传输str0m Sans-IO
use crate::args::Args;
use crate::cap_wlr_screencopy::CapWlrScreencopy;
@@ -49,6 +50,7 @@ fn main() -> Result<()> {
} else {
tracing::Level::INFO
})
.with_writer(std::io::stderr)
.init();
tracing::info!("wl-webrtc starting");
@@ -59,6 +61,10 @@ fn main() -> Result<()> {
anyhow::bail!("HEVC not supported in MVP. Use --codec h264");
}
if args.output.is_none() && args.port == 0 {
anyhow::bail!("Either --output or --port is required");
}
// 自动检测当前桌面环境可用的截屏后端
// 会尝试列举 Wayland 全局对象,判断合成器是否支持 wlr-screencopy 协议
let backend = crate::backend_detect::detect_backend(&args)?;