syntax = "proto3"; package synclive.v1; option go_package = "sync-live/gen"; // SyncLive 是直播 SFU 分流服务的控制面契约(protobuf / gRPC)。 // // 媒体面(WebRTC SDP 交换)不在此契约内:浏览器与 Cloudflare Realtime / SRS // 直连,经本服务反向代理转发(服务端注入 AppSecret / stream token)。 // 本契约只负责房间、后端、发布/订阅拓扑的协调与扇出状态广播。 service SyncLive { rpc GetConfig(GetConfigRequest) returns (GetConfigResponse); rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse); rpc Publish(PublishRequest) returns (PublishResponse); rpc Subscribe(SubscribeRequest) returns (SubscribeResponse); rpc StopStream(StopStreamRequest) returns (StopStreamResponse); rpc WatchRoom(WatchRoomRequest) returns (stream RoomEvent); // ---- Auth & Casbin ---- rpc Login(LoginRequest) returns (LoginResponse); rpc Register(RegisterRequest) returns (RegisterResponse); rpc GetMe(GetMeRequest) returns (GetMeResponse); rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); rpc UpdateUserRole(UpdateUserRoleRequest) returns (UpdateUserRoleResponse); } enum BackendKind { BACKEND_KIND_UNSPECIFIED = 0; BACKEND_KIND_CLOUDFLARE = 1; // Cloudflare Realtime(主 SFU) BACKEND_KIND_SRS = 2; // SRS(次级 / 本地对照) } enum DistributionKind { DISTRIBUTION_KIND_UNSPECIFIED = 0; DISTRIBUTION_KIND_SRS_HLS = 1; // SRS HLS 直推(主干 remux 原地出) DISTRIBUTION_KIND_CF_SFU = 2; // Cloudflare SFU 分发(中继) DISTRIBUTION_KIND_CDN = 3; // 第三方直播 CDN 分发(RTMP/SRT Forward) } message IceServer { repeated string urls = 1; string username = 2; string credential = 3; } message GetConfigRequest {} message BackendInfo { BackendKind kind = 1; string name = 2; bool configured = 3; bool primary = 4; } message DistributorInfo { DistributionKind kind = 1; string name = 2; bool configured = 3; bool enabled = 4; } message DistributionTarget { DistributionKind kind = 1; string url = 2; string status = 3; // forwarding | ready | error int64 updated_at = 4; } message GetConfigResponse { repeated BackendInfo backends = 1; string candidate = 2; bool token_required = 3; BackendInfo trunk = 4; repeated DistributorInfo distributors = 5; } message StreamTarget { BackendKind backend = 1; string session_id = 2; string stream = 3; string publish_token = 4; string url = 5; int64 published_at = 6; } message Room { string name = 1; repeated StreamTarget targets = 2; repeated DistributionTarget distributions = 3; } message ListRoomsRequest {} message ListRoomsResponse { repeated Room rooms = 1; } message PublishRequest { string room = 1; BackendKind backend = 2; string identity = 3; } message PublishResponse { string session_id = 1; string stream = 2; string publish_token = 3; repeated IceServer ice_servers = 4; StreamTarget target = 5; } message SubscribeRequest { string room = 1; BackendKind backend = 2; string identity = 3; } message SubscribeResponse { string session_id = 1; string stream = 2; string publisher_session_id = 3; repeated IceServer ice_servers = 4; } message StopStreamRequest { string room = 1; BackendKind backend = 2; } message StopStreamResponse { bool ok = 1; } message WatchRoomRequest { string room = 1; } message RoomEvent { string room = 1; repeated StreamTarget targets = 2; repeated DistributionTarget distributions = 3; } // ===== Auth & RBAC (Casbin) ===== message UserInfo { string username = 1; string role = 2; int64 created_at = 3; } message LoginRequest { string username = 1; string password = 2; } message LoginResponse { string token = 1; UserInfo user = 2; int64 expires_at = 3; } message RegisterRequest { string username = 1; string password = 2; string role = 3; } message RegisterResponse { string token = 1; UserInfo user = 2; int64 expires_at = 3; } message GetMeRequest {} message GetMeResponse { UserInfo user = 1; int64 expires_at = 2; int64 issued_at = 3; } message ListUsersRequest {} message ListUsersResponse { repeated UserInfo users = 1; } message UpdateUserRoleRequest { string username = 1; string role = 2; } message UpdateUserRoleResponse { bool ok = 1; UserInfo user = 2; }