/** * package api * * 媒体服务监控 API 处理器 * 功能: * 1. 查看媒体服务器状态 * 2. 查看活跃房间和流 * 3. 管理桥接器 */ package api import ( "xk-websocket-v2/internal/mediaserver" "xk-websocket-v2/internal/utils" "github.com/gin-gonic/gin" ) // MediaServerStatusResponse 媒体服务器状态响应 type MediaServerStatusResponse struct { Enabled bool `json:"enabled"` Config map[string]interface{} `json:"config"` RoomCount int `json:"room_count"` SFUTrackCount int `json:"sfu_track_count"` RTMPStreamCount int `json:"rtmp_stream_count"` } // GetMediaServerStatusHandler 获取媒体服务器状态 // GET /api/media/status func GetMediaServerStatusHandler(c *gin.Context) { ms := mediaserver.GetServer() config := ms.GetConfig() if config == nil { utils.Error(c, 503, "媒体服务未配置") return } response := MediaServerStatusResponse{ Enabled: config.Enabled, RoomCount: ms.GetRoomCount(), Config: map[string]interface{}{ "public_ip": config.PublicIP, "webrtc_port": config.WebRTCPort, "rtmp_port": config.RTMPPort, "http_flv_port": config.HTTPFLVPort, "max_room_size": config.MaxRoomSize, }, } // 获取 SFU 轨道数 if sfu := ms.GetSFU(); sfu != nil { response.SFUTrackCount = sfu.GetTrackCount() } // 获取 RTMP 流数 if rtmp := ms.GetRTMP(); rtmp != nil { response.RTMPStreamCount = rtmp.GetStreamCount() } utils.SuccessWithData(c, response, "获取成功") } // GetAllRoomsHandler 获取所有房间 // GET /api/media/rooms func GetAllRoomsHandler(c *gin.Context) { ms := mediaserver.GetServer() rooms := ms.GetAllRooms() utils.SuccessWithData(c, gin.H{ "count": len(rooms), "rooms": rooms, }, "获取成功") } // GetRoomDetailHandler 获取房间详情 // GET /api/media/rooms/:room_id func GetRoomDetailHandler(c *gin.Context) { roomID := c.Param("room_id") if roomID == "" { utils.BadRequest(c, "房间ID不能为空") return } ms := mediaserver.GetServer() room := ms.GetRoom(roomID) if room == nil { utils.NotFound(c, "房间不存在") return } info := room.GetInfo() // 获取桥接信息 bm := mediaserver.GetBridgeManager() bridge := bm.GetBridge(roomID) var bridgeInfo map[string]interface{} if bridge != nil && bridge.IsRunning() { w2r, r2w := bridge.GetAllConverters() w2rCount, r2wCount := bridge.GetConverterCount() bridgeInfo = map[string]interface{}{ "running": true, "webrtc_to_rtmp": w2rCount, "rtmp_to_webrtc": r2wCount, "w2r_converters": w2r, "r2w_converters": r2w, } } utils.SuccessWithData(c, gin.H{ "room": info, "bridge": bridgeInfo, }, "获取成功") } // GetRTMPStreamsHandler 获取 RTMP 流列表 // GET /api/media/rtmp/streams func GetRTMPStreamsHandler(c *gin.Context) { ms := mediaserver.GetServer() rtmp := ms.GetRTMP() if rtmp == nil { utils.Error(c, 503, "RTMP服务未启用") return } roomID := c.Query("room_id") var streams []*mediaserver.RTMPStream if roomID != "" { streams = rtmp.GetStreamsByRoom(roomID) } else { // 获取所有流(简化实现:只返回数量) utils.SuccessWithData(c, gin.H{ "count": rtmp.GetStreamCount(), }, "获取成功") return } utils.SuccessWithData(c, gin.H{ "count": len(streams), "streams": streams, }, "获取成功") } // CloseRoomHandler 关闭房间 // POST /api/media/rooms/:room_id/close func CloseRoomHandler(c *gin.Context) { roomID := c.Param("room_id") if roomID == "" { utils.BadRequest(c, "房间ID不能为空") return } ms := mediaserver.GetServer() room := ms.GetRoom(roomID) if room == nil { utils.NotFound(c, "房间不存在") return } // 移除桥接 bm := mediaserver.GetBridgeManager() bm.RemoveBridge(roomID) // 移除房间 ms.RemoveRoom(roomID) utils.Success(c, "房间已关闭") } // RegisterMediaRoutes 注册媒体相关路由 func RegisterMediaRoutes(router *gin.RouterGroup) { mediaGroup := router.Group("/media") { mediaGroup.GET("/status", GetMediaServerStatusHandler) mediaGroup.GET("/rooms", GetAllRoomsHandler) mediaGroup.GET("/rooms/:room_id", GetRoomDetailHandler) mediaGroup.POST("/rooms/:room_id/close", CloseRoomHandler) mediaGroup.GET("/rtmp/streams", GetRTMPStreamsHandler) } }