package main import ( "flag" "fmt" "net/http" "os" "time" "hightube/internal/api" "hightube/internal/chat" "hightube/internal/db" "hightube/internal/monitor" "hightube/internal/stream" ) type serverConfig struct { apiPort int rtmpPort int } func main() { cfg := parseFlags() monitor.Init(2000) monitor.Infof("Starting Hightube Server v1.0.1") // Initialize Database and run auto-migrations db.InitDB() // Initialize Chat WebSocket Hub chat.InitChat() srv := stream.NewRTMPServer(fmt.Sprintf("%d", cfg.rtmpPort)) // Start the API server in a goroutine so it doesn't block the RTMP server go func() { apiAddr := fmt.Sprintf(":%d", cfg.apiPort) r := api.SetupRouter(srv) httpServer := &http.Server{ Addr: apiAddr, Handler: r, ReadHeaderTimeout: 5 * time.Second, IdleTimeout: 60 * time.Second, MaxHeaderBytes: 1 << 20, } monitor.Infof("API server listening on %s", apiAddr) monitor.Infof("Web console listening on %s/admin", apiAddr) if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { monitor.Errorf("Failed to start API server: %v", err) } }() // Setup and start the RTMP server rtmpAddr := fmt.Sprintf(":%d", cfg.rtmpPort) monitor.Infof("Ready to receive RTMP streams from OBS") if err := srv.Start(rtmpAddr); err != nil { monitor.Errorf("Failed to start RTMP server: %v", err) } } func parseFlags() serverConfig { cfg := serverConfig{} flag.IntVar(&cfg.apiPort, "api-port", 8080, "API/Web console listen port") flag.IntVar(&cfg.rtmpPort, "rtmp-port", 1935, "RTMP listen port") flag.Parse() if !validPort(cfg.apiPort) { fmt.Fprintf(os.Stderr, "invalid --api-port %d: port must be between 1 and 65535\n", cfg.apiPort) os.Exit(2) } if !validPort(cfg.rtmpPort) { fmt.Fprintf(os.Stderr, "invalid --rtmp-port %d: port must be between 1 and 65535\n", cfg.rtmpPort) os.Exit(2) } return cfg } func validPort(port int) bool { return port >= 1 && port <= 65535 }