# 门铃自研会议室 API(给 App / 前端对接) Date: 2026-10-27(Asia/Shanghai) > **媒体层自研**:SRS 5 WHIP 推流 + WHEP/HTTP-FLV/HLS 拉流。 > **不接** 融云 RTC / 腾讯 TRTC / Agora 等第三方会议云。 > 旧 Java `api.menling.com/meeting/*`(融云 RTC)**暂保留**,新 App 请切到本文档 Base URL。 --- ## 1. Base URL | 项 | 值 | |----|-----| | **API Base(自研站)** | `https://meeting.menling.com/api/meeting/` | | **API Base(开放平台入口)** | `https://open.menkou.com/api/meeting/` | | 开放平台文档 | `https://open.menkou.com/docs/meeting.html` | | 官网首页 | `https://meeting.menling.com/` | | 会议室 | `https://meeting.menling.com/room?id={room_id}` | | 烟测页 | `https://meeting.menling.com/smoke` | | 本文档 | `https://meeting.menling.com/MEETING-API.md` | | 千人架构 | `https://meeting.menling.com/WEBINAR-1K.md` · 源 `/home/meeting/docs/WEBINAR-1K.md` | | WHIP 推流域 | `https://live.menling.com`(同直播推流边缘) | | WHEP / FLV / HLS 播域 | `https://zhibo.menling.com`(同直播看播边缘) | | 业务库 | `daomenkoumenling.meeting` / `meeting_users` / `meeting_block` | 响应统一: ```json { "code": 200, "msg": "ok", "data": { } } ``` `code !== 200` 为失败(401 未登录、403 无权限/密码错、404 不存在、410 已结束)。 --- ## 2. 鉴权(门铃号 = uid) App 登录门铃号后,调用会议室 API 时带上其一: ### 推荐:Authorization Bearer ``` Authorization: Bearer {uid}.{token} ``` `token = md5(uid + "|" + authSecret)`。可用 `POST /api/meeting/login` 用门铃号+密码换取;或技术联调时用 `POST /api/meeting/token`。 ### 联调:Header 门铃号 + 共享密钥 ``` X-Doorbell-Uid: 995298414 X-Meeting-Secret: meeting-menling-selfhost-20261027 ``` ### Cookie(H5 / 同源) - `meeting_door={uid}.{token}`(本站登录后下发,域 `.menling.com`) - 或已有直播站 `zhibo_door`(同样接受) ### 登录换 Token `POST /api/meeting/login` ```json { "doorbell": "10001", "password": "你的密码" } ``` 成功 `data`: ```json { "uid": 10001, "doorbell": "10001", "nickname": "…", "token": "32位md5", "authorization": "Bearer 10001.32位md5" } ``` ### 技术签发(仅联调) `POST /api/meeting/token` Header: `X-Meeting-Secret: meeting-menling-selfhost-20261027` Body: `{ "uid": 10001 }` --- ## 3. 媒体模型(必读) 默认小房间 = **多路独立推流**(mesh)。千人请用 `mode=webinar`(见 §10): 会议室 mesh: - 每人推一条流:`meet/{stream}`,`stream = meet_{roomId}_{uid}` - App:**自己 WHIP 推**,**其他人 WHEP(或 FLV)拉** - v1 信令:**轮询** `userList`(建议 2–3s),无需融云 RTC 房间 | 用途 | URL 形态 | |------|----------| | 自己推流 WHIP | `https://live.menling.com/rtc/v1/whip/?app=meet&stream=meet_{roomId}_{uid}` | | 拉别人 WHEP | `https://zhibo.menling.com/rtc/v1/whep/?app=meet&stream=meet_{roomId}_{对方uid}` | | 备选 HTTP-FLV | `https://zhibo.menling.com/meet/meet_{roomId}_{uid}.flv` | | 备选 HLS | `https://zhibo.menling.com/meet/meet_{roomId}_{uid}.m3u8` | WebRTC 用法(浏览器 / WebView): 1. `getUserMedia` → `RTCPeerConnection` 2. `POST` WHIP URL,`Content-Type: application/sdp`,body = local SDP offer;响应 = answer SDP 3. 拉流同理 POST WHEP 4. 可参考直播站 SDK:`https://zhibo.menling.com/assets/srs/srs.sdk.js` 原生 App:用系统 WebRTC 或 SRS 官方示例对接 WHIP/WHEP 即可。 --- ## 4. 接口一览 | Method | Path | 说明 | |--------|------|------| | GET/POST | `/api/meeting/health` | 健康检查 | | POST | `/api/meeting/login` | 门铃号登录换 token | | POST | `/api/meeting/token` | 联调签发 token | | GET/POST | `/api/meeting/me` | 当前用户 | | POST | `/api/meeting/create` | 创建会议室(主持人) | | POST | `/api/meeting/join` | 加入 | | GET/POST | `/api/meeting/list` | 我的会议室列表 | | GET/POST | `/api/meeting/userList` | 房内成员 + 各路播流 URL | | GET/POST | `/api/meeting/info` | 房间摘要(可不登录) | | POST | `/api/meeting/exit` | 离开 | | POST | `/api/meeting/end` | 主持人结束 | | POST | `/api/meeting/kick` | 主持人踢人 | | POST | `/api/meeting/block` | 主持人封禁 | | POST | `/api/meeting/raiseHand` | 研讨会:观众举手 / 取消 | | POST | `/api/meeting/approveSpeak` | 研讨会:批准/取消连麦(升嘉宾) | | POST | `/api/meeting/muteAll` | 主持人/联席:全员静音 | | POST | `/api/meeting/setRole` | 设置角色 host/guest/audience/cohost | 角色:`role=0` 主持人,`role=1` 嘉宾/参会者,`role=2` 观众(仅 webinar),`role=3` 联席主持。 `create` 可选 `mode=meeting|webinar`(默认 meeting,**兼容旧客户端**)。千人研讨会见下文 §10 与 [WEBINAR-1K.md](./WEBINAR-1K.md)。 --- ## 5. 请求 / 响应示例 ### 5.1 create ```http POST /api/meeting/create Authorization: Bearer 10001.xxxxx Content-Type: application/json { "meeting_theme": "周会", "password": "", "mode": "meeting" } ``` 可选:`password` 非空则 `is_password=1`。 可选:`mode`=`meeting`(默认,mesh 小房间)| `webinar`(千人研讨会)。 webinar 还可传 `audience_mode`=`hls_flv`(默认)|`hls`|`flv`,`max_guests`(默认 16)。 成功摘要: ```json { "code": 200, "msg": "ok", "data": { "room_id": 8000041, "meeting_theme": "周会", "is_password": 0, "share_code": "A1B2C3D4", "platform": "SELF", "media_mode": "SRS_MESH", "role": 0, "host_uid": 10001, "self": { "uid": 10001, "nickname": "…", "role": 0, "publish": { "whip": "https://live.menling.com/rtc/v1/whip/?app=meet&stream=meet_8000041_10001", "rtmp": "rtmp://live.menling.com:1935/meet/meet_8000041_10001", "app": "meet", "stream": "meet_8000041_10001" }, "play": { "whep": "https://zhibo.menling.com/rtc/v1/whep/?app=meet&stream=meet_8000041_10001", "http_flv": "https://zhibo.menling.com/meet/meet_8000041_10001.flv", "hls": "https://zhibo.menling.com/meet/meet_8000041_10001.m3u8" } }, "signaling": { "mode": "poll", "userList": "/api/meeting/userList", "interval_ms": 3000 } } } ``` ### 5.2 join ```json { "room_id": 8000041, "password": "" } ``` 也可用 `{ "share_code": "A1B2C3D4" }`(有 share_code 列时)。 成功 `data` 含: - `role`、`self.publish` / `self.play` - `participants[]`:每位成员的 `play`(WHEP/FLV/HLS);自己额外带 `publish` ### 5.3 userList ```json { "room_id": 8000041 } ``` ```json { "code": 200, "data": { "room_id": 8000041, "is_end": 0, "host_uid": 10001, "count": 2, "participants": [ { "user_id": 10001, "nickname": "…", "role": 0, "is_self": 1, "stream": "meet_8000041_10001", "publish": { "whip": "…" }, "play": { "whep": "…", "http_flv": "…", "hls": "…" } }, { "user_id": 1, "nickname": "…", "role": 1, "is_self": 0, "stream": "meet_8000041_1", "play": { "whep": "…", "http_flv": "…", "hls": "…" } } ] } } ``` **App 逻辑**:对 `is_self=0` 的成员建立 WHEP 拉流;自己保持 WHIP 推流。成员增减以 `userList` 为准。 ### 5.4 list ```json { "active": 1, "limit": 20 } ``` 返回我主持或曾加入、且(默认)未结束的房间列表。 ### 5.5 exit / end / kick / block ```json // exit { "room_id": 8000041 } // end(仅主持人) { "room_id": 8000041 } // kick(仅主持人) { "room_id": 8000041, "user_id": 1 } // block(仅主持人;time=分钟,0=永久) { "room_id": 8000041, "user_id": 1, "time": 60 } ``` --- ## 6. App 接入步骤(建议) 1. 用户门铃登录 → 拿 `Authorization: Bearer …`(或沿用你们现有会话后换成本站 token) 2. `create` 或 `join` → 拿到 `self.publish.whip` 与 `participants[].play.whep` 3. 本地 WHIP 推音视频 4. 每 2–3 秒 `userList`:新成员开 WHEP,离开的关 PeerConnection;`is_end=1` 则退出 UI 5. 离开调 `exit`;主持人散会调 `end` 6. IM 邀请仍可用现有融云/自有 IM 发 `room_id` / `share_code`(**只替换媒体房间**) --- --- ## 10. 千人研讨会(mode=webinar) 产品:**主讲在讲、大家听**;观众端与直播看播相同(HLS/HTTP-FLV)。自建 SRS,不接腾讯云。 架构详见:[WEBINAR-1K.md](./WEBINAR-1K.md) · 开放站 https://open.menkou.com/docs/meeting.html(千人章节) ### 10.1 角色与媒体 | role | 名称 | 推流 | 拉流 | |------|------|------|------| | 0 | host | WHIP 个人流 + **节目流** `webinar_{roomId}` | WHEP 嘉宾 | | 1 | guest | WHIP 个人流 | WHEP 主持/嘉宾 | | 2 | audience | 无 | **仅** `program` 的 HLS/FLV | | 3 | cohost | 同嘉宾 | 同嘉宾 + 可审批 | 节目流(观众,形态同直播): ``` https://zhibo.menling.com/meet/webinar_{roomId}.flv https://zhibo.menling.com/meet/webinar_{roomId}.m3u8 ``` 主持推节目流: ``` https://live.menling.com/rtc/v1/whip/?app=meet&stream=webinar_{roomId} ``` ### 10.2 create webinar ```http POST https://open.menkou.com/api/meeting/create Authorization: Bearer 10001.xxxxx Content-Type: application/json { "meeting_theme": "千人分享会", "mode": "webinar", "audience_mode": "hls_flv", "max_guests": 16, "password": "" } ``` 成功要点:`mode=webinar`,`media_mode=SRS_WEBINAR`,`self.publish` + `self.publish_program`,`program.http_flv` / `program.hls`。 ### 10.3 join(默认观众) ```json { "room_id": 8000100 } ``` 观众:`role=2`,`can_publish=0`,`publish=null`,`play`/`program` 为 HLS/FLV。 已被批准的嘉宾重进会保留 `role=1` 并带回 WHIP/WHEP。 ### 10.4 raiseHand / approveSpeak / muteAll / setRole ```json // 观众举手 POST /api/meeting/raiseHand { "room_id": 8000100, "raise": 1 } // 主持批准连麦 → 升为嘉宾(返回 media.publish / play) POST /api/meeting/approveSpeak { "room_id": 8000100, "user_id": 10002, "approve": 1 } // 全员静音(主持除外) POST /api/meeting/muteAll { "room_id": 8000100, "mute": 1 } // 设联席主持 POST /api/meeting/setRole { "room_id": 8000100, "user_id": 10003, "role": "cohost" } ``` `userList` 在 webinar 下额外返回 `program`、`hand_raises[]`、`mute_all`;观众行不附带每人 play URL(防千人包体膨胀)。 ### 10.5 App 建议(webinar) 1. 主持:`create mode=webinar` → WHIP 推 `publish_program.whip`(主画面) 2. 观众:`join` → 只播 `program.http_flv` 或 `program.hls`(同直播播放器) 3. 观众举手 → 主持 `approveSpeak` → 客户端改走 WHIP/WHEP 4. 轮询 `userList` 建议 5s --- ## 7. 错误码 | code | 含义 | |------|------| | 200 | 成功 | | 400 | 参数错误 | | 401 | 未登录 / token 无效 | | 403 | 密码错 / 非主持人 / 被封禁 / Secret 错 | | 404 | 房间或接口不存在 | | 410 | 会议已结束 | | 500 | 服务端错误 | --- ## 8. 与旧接口关系 | | 旧(融云 RTC) | 新(自研) | |--|----------------|------------| | 主机 | `https://api.menling.com/meeting/*` | `https://meeting.menling.com/api/meeting/*` | | 媒体 | RongCloud `/v2/rtc/rooms/` | SRS WHIP/WHEP | | 身份 | SealTalk cookie | Bearer / X-Doorbell-Uid / meeting_door | | 表 | 同库 `meeting*` | 同表;自研房 `platform=SELF` | 旧接口**先不要删**,App 发版切换后再下线融云 RTC。 --- ## 9. 运维备忘 - 代码根:`/home/meeting` - 备份与状态:`/home/backup/cleanup/meeting-selfhost-20261027/` - SRS:本机 `5.0.225`,HTTP-API `1985`,RTC candidate `14.18.194.196` - Apache:`meeting.menling.com` → php82 `meeting-yii3`;`/rtc/` 代理到 SRS(与 live/zhibo 一致)