Files
nl-im-service/internal/mediaserver/server.go

238 lines
5.3 KiB
Go
Raw Normal View History

2025-12-15 09:04:14 +08:00
/**
* package mediaserver
*
* 媒体服务器主入口
* 功能
* 1. 集成 WebRTC SFU支持 H5/App 端音视频通话
* 2. 集成 RTMP 服务支持微信小程序 live-pusher/live-player
* 3. 实现 WebRTC RTMP 媒体桥接跨平台互通
*/
package mediaserver
import (
"log"
"sync"
"github.com/spf13/viper"
)
// MediaServer 媒体服务器主结构
type MediaServer struct {
2025-12-15 21:57:21 +08:00
sfu *SFUServer // WebRTC SFU 服务
rtmp *RTMPServer // RTMP 服务
wsProxy *WebMToRTMPProxy // WebSocket to RTMP 代理
rooms map[string]*Room // 通话房间管理
mu sync.RWMutex // 房间锁
config *MediaServerConfig // 配置
2025-12-15 09:04:14 +08:00
}
// MediaServerConfig 媒体服务器配置
type MediaServerConfig struct {
Enabled bool `mapstructure:"enabled"`
PublicIP string `mapstructure:"public_ip"`
WebRTCPort int `mapstructure:"webrtc_port"`
RTMPPort int `mapstructure:"rtmp_port"`
HTTPFLVPort int `mapstructure:"http_flv_port"`
// SFU 配置
MaxRoomSize int `mapstructure:"max_room_size"` // 单房间最大人数
// 编解码配置
VideoCodec string `mapstructure:"video_codec"` // 视频编解码h264
AudioCodec string `mapstructure:"audio_codec"` // 音频编解码opus/aac
}
// 全局媒体服务器实例
var (
server *MediaServer
once sync.Once
)
// GetServer 获取媒体服务器单例
func GetServer() *MediaServer {
once.Do(func() {
server = newMediaServer()
})
return server
}
// newMediaServer 创建媒体服务器实例
func newMediaServer() *MediaServer {
config := loadConfig()
ms := &MediaServer{
rooms: make(map[string]*Room),
config: config,
}
if config.Enabled {
ms.sfu = NewSFUServer(config)
ms.rtmp = NewRTMPServer(config)
2025-12-15 21:57:21 +08:00
// 创建 WebSocket to RTMP 代理
ms.wsProxy = NewWebMToRTMPProxy(ms.rtmp)
2025-12-15 09:04:14 +08:00
}
return ms
}
// loadConfig 从 viper 加载配置
func loadConfig() *MediaServerConfig {
config := &MediaServerConfig{
Enabled: viper.GetBool("media.enabled"),
PublicIP: viper.GetString("media.public_ip"),
WebRTCPort: viper.GetInt("media.webrtc_port"),
RTMPPort: viper.GetInt("media.rtmp_port"),
HTTPFLVPort: viper.GetInt("media.http_flv_port"),
MaxRoomSize: viper.GetInt("media.max_room_size"),
VideoCodec: viper.GetString("media.video_codec"),
AudioCodec: viper.GetString("media.audio_codec"),
}
// 设置默认值
if config.PublicIP == "" {
config.PublicIP = viper.GetString("turn.public_ip") // 复用 TURN 的公网IP
}
if config.WebRTCPort == 0 {
config.WebRTCPort = 8080
}
if config.RTMPPort == 0 {
config.RTMPPort = 1935
}
if config.HTTPFLVPort == 0 {
config.HTTPFLVPort = 7001
}
if config.MaxRoomSize == 0 {
config.MaxRoomSize = 9 // 默认最多9人
}
if config.VideoCodec == "" {
config.VideoCodec = "h264"
}
if config.AudioCodec == "" {
config.AudioCodec = "opus"
}
return config
}
// Start 启动媒体服务器
func Start() {
ms := GetServer()
if !ms.config.Enabled {
log.Println(" [MediaServer] 服务已禁用")
return
}
log.Println("🎥 [MediaServer] 正在启动...")
// 启动 WebRTC SFU
if ms.sfu != nil {
go ms.sfu.Start()
}
// 启动 RTMP 服务
if ms.rtmp != nil {
go ms.rtmp.Start()
}
log.Printf("🎥 [MediaServer] 已启动 | WebRTC: %d | RTMP: %d | HTTP-FLV: %d",
ms.config.WebRTCPort, ms.config.RTMPPort, ms.config.HTTPFLVPort)
}
// Stop 停止媒体服务器
func (ms *MediaServer) Stop() {
log.Println("🛑 [MediaServer] 正在停止...")
// 关闭所有房间
ms.mu.Lock()
for _, room := range ms.rooms {
room.Close()
}
ms.rooms = make(map[string]*Room)
ms.mu.Unlock()
// 停止 SFU
if ms.sfu != nil {
ms.sfu.Stop()
}
// 停止 RTMP
if ms.rtmp != nil {
ms.rtmp.Stop()
}
log.Println("🛑 [MediaServer] 已停止")
}
// GetOrCreateRoom 获取或创建房间
func (ms *MediaServer) GetOrCreateRoom(roomID string) *Room {
ms.mu.Lock()
defer ms.mu.Unlock()
if room, exists := ms.rooms[roomID]; exists {
return room
}
room := NewRoom(roomID, ms.config.MaxRoomSize)
ms.rooms[roomID] = room
log.Printf("🎥 [MediaServer] 创建房间: %s", roomID)
return room
}
// GetRoom 获取房间
func (ms *MediaServer) GetRoom(roomID string) *Room {
ms.mu.RLock()
defer ms.mu.RUnlock()
return ms.rooms[roomID]
}
// RemoveRoom 移除房间
func (ms *MediaServer) RemoveRoom(roomID string) {
ms.mu.Lock()
defer ms.mu.Unlock()
if room, exists := ms.rooms[roomID]; exists {
room.Close()
delete(ms.rooms, roomID)
log.Printf("🎥 [MediaServer] 移除房间: %s", roomID)
}
}
// GetConfig 获取配置
func (ms *MediaServer) GetConfig() *MediaServerConfig {
return ms.config
}
// GetSFU 获取 SFU 服务
func (ms *MediaServer) GetSFU() *SFUServer {
return ms.sfu
}
// GetRTMP 获取 RTMP 服务
func (ms *MediaServer) GetRTMP() *RTMPServer {
return ms.rtmp
}
2025-12-15 21:57:21 +08:00
// GetWSProxy 获取 WebSocket to RTMP 代理
func (ms *MediaServer) GetWSProxy() *WebMToRTMPProxy {
return ms.wsProxy
}
2025-12-15 09:04:14 +08:00
// GetRoomCount 获取房间数量
func (ms *MediaServer) GetRoomCount() int {
ms.mu.RLock()
defer ms.mu.RUnlock()
return len(ms.rooms)
}
// GetAllRooms 获取所有房间信息(用于调试/监控)
func (ms *MediaServer) GetAllRooms() []*RoomInfo {
ms.mu.RLock()
defer ms.mu.RUnlock()
infos := make([]*RoomInfo, 0, len(ms.rooms))
for _, room := range ms.rooms {
infos = append(infos, room.GetInfo())
}
return infos
}