Skip to main content

live_web_start/
live_web_start.rs

1//! 验证网页 link 中心自动开播(FetchWebUpStreamAddr + WebLiveCenterStartLive)
2//!
3//! ```powershell
4//! cd bpi-rs
5//! $env:BPI_ACCOUNT_TOML = "account.toml"
6//! $env:BILI_ROOM_ID = "4354019"
7//! $env:BILI_AREA_ID = "309"
8//! $env:BPI_MUTATING_TEST = "1"
9//! cargo run --example live_web_start --features live,misc
10//! ```
11//!
12//! 若已在直播,加 `--stop-if-live` 会先关播再开播(会短暂断流)。
13//! 只关播并验证状态,使用 `--stop-only`。
14
15#[path = "common/account.rs"]
16mod account;
17
18use bpi_rs::BpiResult;
19
20const DEFAULT_ROOM_ID: i64 = 4354019;
21const DEFAULT_AREA_ID: u64 = 309;
22const MUTATING_ENV: &str = "BPI_MUTATING_TEST";
23
24fn mask(s: &str) -> String {
25    if s.len() <= 8 {
26        return "***".to_string();
27    }
28    format!("{}...{}", &s[..4], &s[s.len() - 4..])
29}
30
31fn mutating_enabled() -> bool {
32    std::env::var(MUTATING_ENV).ok().as_deref() == Some("1")
33}
34
35#[tokio::main]
36async fn main() -> BpiResult<()> {
37    let stop_if_live = std::env::args().any(|a| a == "--stop-if-live");
38    let stop_only = std::env::args().any(|a| a == "--stop-only");
39    let room_id: i64 = std::env::var("BILI_ROOM_ID")
40        .ok()
41        .and_then(|s| s.parse().ok())
42        .unwrap_or(DEFAULT_ROOM_ID);
43    let area_id: u64 = std::env::var("BILI_AREA_ID")
44        .ok()
45        .and_then(|s| s.parse().ok())
46        .unwrap_or(DEFAULT_AREA_ID);
47
48    let bpi = account::authenticated_client()?;
49
50    println!("=== Rust 网页自动开播验证 ===");
51    println!("room_id={room_id} area_v2={area_id}");
52
53    let live = bpi.live();
54    let info = live.room_info(room_id).await?;
55    println!(
56        "当前状态: live_status={} title={} area={}·{}",
57        info.live_status, info.title, info.parent_area_name, info.area_name
58    );
59
60    if !mutating_enabled() {
61        println!("{MUTATING_ENV}=1 未设置,只读取直播间状态,不执行开播、关播或获取推流码。");
62        return Ok(());
63    }
64
65    if stop_only {
66        if info.live_status == 1 {
67            println!("执行关播...");
68            let stop = live.live_stop(room_id as u64, "pc").await?;
69            println!("关播结果: status={}", stop.status);
70            tokio::time::sleep(std::time::Duration::from_secs(3)).await;
71        } else {
72            println!("当前未开播,跳过关播接口。");
73        }
74
75        let after = live.room_info(room_id).await?;
76        println!(
77            "验证: live_status={} ({})",
78            after.live_status,
79            if after.live_status == 0 {
80                "关播成功"
81            } else {
82                "仍在直播中"
83            }
84        );
85        return Ok(());
86    }
87
88    if info.live_status == 1 {
89        if stop_if_live {
90            println!("已在直播,--stop-if-live:先关播...");
91            let stop = live.live_stop(room_id as u64, "pc").await?;
92            println!("关播结果: status={}", stop.status);
93            tokio::time::sleep(std::time::Duration::from_secs(2)).await;
94        } else {
95            println!("已在直播中。若要完整验证开播链路,请加 --stop-if-live 或先手动关播。");
96            println!("仍尝试 FetchWebUpStreamAddr(只读)...");
97            let stream = live.live_fetch_web_up_stream_addr().await?;
98            println!("推流地址: {}{}", stream.addr.addr, mask(&stream.addr.code));
99            return Ok(());
100        }
101    }
102
103    println!("\n[1/2] FetchWebUpStreamAddr...");
104    let stream = live.live_fetch_web_up_stream_addr().await?;
105    println!("  rtmp: {}{}", stream.addr.addr, mask(&stream.addr.code));
106
107    println!("\n[2/2] WebLiveCenterStartLive (WBI)...");
108    let start = live.live_web_center_start(room_id as u64, area_id).await?;
109    println!("  status={} live_key={}", start.status, start.live_key);
110    if let Some(rtmp) = &start.rtmp {
111        println!("  rtmp(响应): {}{}", rtmp.addr, mask(&rtmp.code));
112    } else {
113        println!("  rtmp(响应): null(正常,推流码以 Fetch 为准)");
114    }
115
116    tokio::time::sleep(std::time::Duration::from_secs(2)).await;
117    let after = live.room_info(room_id).await?;
118    println!(
119        "\n验证: live_status={} ({})",
120        after.live_status,
121        if after.live_status == 1 {
122            "开播成功"
123        } else {
124            "未变为直播中(可能需 OBS 推流)"
125        }
126    );
127
128    Ok(())
129}