Download controller/video_proxy.go from AZILS/new-api: direct link, hf CLI and curl.
- Browser
- Download file 4.77 kB
-
https://huggingface.co/spaces/AZILS/new-api/resolve/main/controller/video_proxy.go
- Command line
-
hf download hf://spaces/AZILS/new-api/controller/video_proxy.go
-
curl -L -o video_proxy.go https://huggingface.co/spaces/AZILS/new-api/resolve/main/controller/video_proxy.go
4.77 kB
| package controller | |
| import ( | |
| "fmt" | |
| "io" | |
| "net/http" | |
| "net/url" | |
| "time" | |
| "github.com/QuantumNous/new-api/constant" | |
| "github.com/QuantumNous/new-api/logger" | |
| "github.com/QuantumNous/new-api/model" | |
| "github.com/gin-gonic/gin" | |
| ) | |
| func VideoProxy(c *gin.Context) { | |
| taskID := c.Param("task_id") | |
| if taskID == "" { | |
| c.JSON(http.StatusBadRequest, gin.H{ | |
| "error": gin.H{ | |
| "message": "task_id is required", | |
| "type": "invalid_request_error", | |
| }, | |
| }) | |
| return | |
| } | |
| task, exists, err := model.GetByOnlyTaskId(taskID) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to query task %s: %s", taskID, err.Error())) | |
| c.JSON(http.StatusInternalServerError, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to query task", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| if !exists || task == nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to get task %s: %v", taskID, err)) | |
| c.JSON(http.StatusNotFound, gin.H{ | |
| "error": gin.H{ | |
| "message": "Task not found", | |
| "type": "invalid_request_error", | |
| }, | |
| }) | |
| return | |
| } | |
| if task.Status != model.TaskStatusSuccess { | |
| c.JSON(http.StatusBadRequest, gin.H{ | |
| "error": gin.H{ | |
| "message": fmt.Sprintf("Task is not completed yet, current status: %s", task.Status), | |
| "type": "invalid_request_error", | |
| }, | |
| }) | |
| return | |
| } | |
| channel, err := model.CacheGetChannel(task.ChannelId) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to get task %s: not found", taskID)) | |
| c.JSON(http.StatusInternalServerError, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to retrieve channel information", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| baseURL := channel.GetBaseURL() | |
| if baseURL == "" { | |
| baseURL = "https://api.openai.com" | |
| } | |
| var videoURL string | |
| client := &http.Client{ | |
| Timeout: 60 * time.Second, | |
| } | |
| req, err := http.NewRequestWithContext(c.Request.Context(), http.MethodGet, "", nil) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to create request: %s", err.Error())) | |
| c.JSON(http.StatusInternalServerError, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to create proxy request", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| switch channel.Type { | |
| case constant.ChannelTypeGemini: | |
| apiKey := task.PrivateData.Key | |
| if apiKey == "" { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Missing stored API key for Gemini task %s", taskID)) | |
| c.JSON(http.StatusInternalServerError, gin.H{ | |
| "error": gin.H{ | |
| "message": "API key not stored for task", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| videoURL, err = getGeminiVideoURL(channel, task, apiKey) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to resolve Gemini video URL for task %s: %s", taskID, err.Error())) | |
| c.JSON(http.StatusBadGateway, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to resolve Gemini video URL", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| req.Header.Set("x-goog-api-key", apiKey) | |
| case constant.ChannelTypeAli: | |
| // Video URL is directly in task.FailReason | |
| videoURL = task.FailReason | |
| default: | |
| // Default (Sora, etc.): Use original logic | |
| videoURL = fmt.Sprintf("%s/v1/videos/%s/content", baseURL, task.TaskID) | |
| req.Header.Set("Authorization", "Bearer "+channel.Key) | |
| } | |
| req.URL, err = url.Parse(videoURL) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to parse URL %s: %s", videoURL, err.Error())) | |
| c.JSON(http.StatusInternalServerError, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to create proxy request", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to fetch video from %s: %s", videoURL, err.Error())) | |
| c.JSON(http.StatusBadGateway, gin.H{ | |
| "error": gin.H{ | |
| "message": "Failed to fetch video content", | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| defer resp.Body.Close() | |
| if resp.StatusCode != http.StatusOK { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Upstream returned status %d for %s", resp.StatusCode, videoURL)) | |
| c.JSON(http.StatusBadGateway, gin.H{ | |
| "error": gin.H{ | |
| "message": fmt.Sprintf("Upstream service returned status %d", resp.StatusCode), | |
| "type": "server_error", | |
| }, | |
| }) | |
| return | |
| } | |
| for key, values := range resp.Header { | |
| for _, value := range values { | |
| c.Writer.Header().Add(key, value) | |
| } | |
| } | |
| c.Writer.Header().Set("Cache-Control", "public, max-age=86400") // Cache for 24 hours | |
| c.Writer.WriteHeader(resp.StatusCode) | |
| _, err = io.Copy(c.Writer, resp.Body) | |
| if err != nil { | |
| logger.LogError(c.Request.Context(), fmt.Sprintf("Failed to stream video content: %s", err.Error())) | |
| } | |
| } | |