package main import ( "bytes" "fmt" "github.com/caarlos0/env/v6" "github.com/gofiber/fiber/v2" "github.com/gofiber/websocket/v2" "l_szr_go/pkg" "os/signal" "syscall" "time" "l_szr_go/entity" "log" "os" "sync" ) var ( config entity.Config activeConnections sync.WaitGroup ) func Server() *fiber.App { app := fiber.New() // 健康检查 app.Get("/health", func(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) }) // WebSocket 路由 app.Use("/ws", func(c *fiber.Ctx) error { if websocket.IsWebSocketUpgrade(c) { c.Locals("allowed", true) return c.Next() } return fiber.ErrUpgradeRequired }) app.Get("/ws", websocket.New(HandleWebSocket)) return app } func HandleWebSocket(c *websocket.Conn) { activeConnections.Add(1) defer activeConnections.Done() var audioBuffer bytes.Buffer fileName := fmt.Sprintf("output_%s.wav", time.Now().Format("20060102_150405.000")) log.Printf("客户端连接: %s", c.RemoteAddr()) defer func() { if audioBuffer.Len() == 0 { log.Println("未接收到音频数据,跳过保存") return } if err := pkg.SaveAsWav(&audioBuffer, fileName, config); err != nil { log.Printf("保存文件失败: %v", err) } else { log.Printf("音频已保存为 %s (%d字节)", fileName, audioBuffer.Len()) } }() for { _, message, err := c.ReadMessage() if err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { log.Printf("客户端异常断开: %v", err) } else { log.Println("客户端主动断开") } break } // 检查缓冲区大小 if audioBuffer.Len()+len(message) > config.MaxBufferSize { log.Println("达到最大缓冲区大小,断开连接") break } // 验证PCM数据 (基本验证) if config.BitDepth == 16 && len(message)%2 != 0 { log.Println("接收到无效的16位PCM数据,长度不是2的倍数") continue } if _, err := audioBuffer.Write(message); err != nil { log.Printf("写入缓冲区失败: %v", err) break } log.Printf("接收到 %d 字节音频数据 (总大小: %d字节)", len(message), audioBuffer.Len()) } } func main() { if err := env.Parse(&config); err != nil { log.Fatalf("加载配置失败: %v", err) } fmt.Print(config.SampleRate) app := Server() // 启动服务器 go func() { log.Printf("服务器启动,监听端口 %s", config.Port) log.Printf("音频配置: %dHz, %d通道, %d位深", config.SampleRate, config.Channels, config.BitDepth) if err := app.Listen(":" + config.Port); err != nil { log.Fatalf("服务器启动失败: %v", err) } }() // 优雅关闭 quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt, syscall.SIGTERM) <-quit log.Println("正在关闭服务器...") // 等待所有连接完成 activeConnections.Wait() log.Println("所有连接已关闭") os.Exit(0) }