feat: sync group call livestream support

This commit is contained in:
A 2026-07-06 14:31:19 +08:00
parent 56d995474c
commit f1a27996d3
37 changed files with 2219 additions and 83 deletions

View file

@ -530,6 +530,9 @@ const (
// ChannelActionGroupCall 映射 messageActionGroupCall:started(CallDuration=0)
// 与 ended(CallDuration>0)共用同一构造器,官方语义即如此。
ChannelActionGroupCall ChannelMessageActionType = "group_call"
// ChannelActionGroupCallScheduled 映射 messageActionGroupCallScheduled:
// 定时通话创建的服务消息("scheduled a video chat for ..."),ScheduleDate 必填。
ChannelActionGroupCallScheduled ChannelMessageActionType = "group_call_scheduled"
// ChannelActionInviteToGroupCall 映射 messageActionInviteToGroupCall(被邀请
// 者通过频道消息收到可点击的入会卡片,UserIDs 为受邀人)。
ChannelActionInviteToGroupCall ChannelMessageActionType = "invite_to_group_call"
@ -561,6 +564,8 @@ type ChannelMessageAction struct {
CallID int64
CallAccessHash int64
CallDuration int
// CallScheduleDate 仅 group_call_scheduled 使用(开播时间)。
CallScheduleDate int
// Boosts 仅 boost_apply 服务消息使用。
Boosts int
// BroadcastMessagesAllowed/Stars 仅 paid_messages_price 服务消息使用。

View file

@ -55,6 +55,15 @@ type GroupCall struct {
State GroupCallState
Title string
JoinMuted bool
// RtmpStream=true 表示这是 RTMP 直播房间(推流走外部 RTMP ingest,观众经
// broadcast 拉流),join 不建 SFU 连接、connection params 返回 stream JSON。
RtmpStream bool
// ScheduleDate>0 表示定时通话尚未开始(客户端显示倒计时面板、不入会);
// startScheduledGroupCall 清零后客户端自动 initialJoin。持久列。
ScheduleDate int
// ScheduleStartSubscribed 是 per-viewer 投影字段(非持久列):当前 viewer 是否
// 订阅了开播提醒。RPC/推送出站前按 viewer 回填(与 Creator flag 同类语义)。
ScheduleStartSubscribed bool
// Version 是参与者协议版本:所有参与者变更事务内 +1,单调且持久。
Version int
ParticipantsCount int
@ -87,6 +96,10 @@ func (c GroupCall) Conference() bool {
type GroupCallParticipant struct {
CallID int64
UserID int64
// JoinAsChannelID 非零表示以该频道/群身份入会(匿名管理员语义),TL 输出
// participant.peer=PeerChannel;0=以本人用户身份。身份唯一键仍是 UserID,
// 换身份 rejoin 是替换。
JoinAsChannelID int64
// SSRC 是客户端在 join JSON 里自报的 audio ssrc(uint32 值域,存 int64 防符号坑)。
SSRC int64
JoinDate int
@ -124,13 +137,15 @@ type CreateGroupCallRequest struct {
// JoinGroupCallRequest 加入/重进群通话(rejoin 同主键换新 ssrc)。
type JoinGroupCallRequest struct {
CallID int64
UserID int64
SSRC int64
Muted bool
IsAdmin bool
PublicKey []byte
JoinBlock []byte
CallID int64
UserID int64
// JoinAsChannelID 非零=以频道身份入会(调用方已完成权限校验)。
JoinAsChannelID int64
SSRC int64
Muted bool
IsAdmin bool
PublicKey []byte
JoinBlock []byte
// VideoJSON 是本次 join 铸造的视频内部状态(endpoint+源组+active);rejoin
// 整体替换并**清空旧 PresentationJSON**(客户端主连接 rejoin 后会重发
// joinGroupCallPresentation,旧屏幕登记必须作废)。

View file

@ -0,0 +1,20 @@
package domain
import "errors"
// LiveStreamChannel 是直播时间轴上一个可拉流通道的快照(RTMP unified 模式恒为
// channel=1 / scale=0;last_timestamp_ms 是最新可取 segment 的起始时间戳)。
type LiveStreamChannel struct {
Channel int
Scale int
LastTimestampMs int64
}
// 直播拉流业务错误;rpc 层映射见 upload.getFile(inputGroupCallStream):
// - PartNotReady → TIME_TOO_BIG(客户端 100ms 后原样重试)
// - PartExpired / NoStream → 普通 400(客户端重新对时 resync)
var (
ErrLiveStreamPartNotReady = errors.New("live stream part not ready")
ErrLiveStreamPartExpired = errors.New("live stream part expired")
ErrLiveStreamNoStream = errors.New("live stream not active")
)