Skip to content

feat: add openai video remix endpoint - #2372

Closed
creamlike1024 wants to merge 3 commits into
mainfrom
sora-remix
Closed

feat: add openai video remix endpoint#2372
creamlike1024 wants to merge 3 commits into
mainfrom
sora-remix

Conversation

@creamlike1024

@creamlike1024 creamlike1024 commented Dec 5, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Submit video remix requests with a prompt via a new remix endpoint.
    • Remix submissions inherit original video settings and channel context to preserve output consistency.
    • UI now labels remix tasks in logs for easy identification.
  • Bug Fixes

    • Remix requests are validated to ensure non-empty prompts and correct origin references.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a video "remix" flow: new route and middleware detection, relay task origin-task lookup and channel synchronization, remix-specific request validation and remix endpoint URL construction in the Sora adaptor.

Changes

Cohort / File(s) Summary
Routing & Middleware
router/video-router.go, middleware/distributor.go
Adds POST /videos/:video_id/remix route and middleware branch that detects remix paths, sets relay_mode to VideoSubmit, and disables automatic channel selection.
Relay task origin handling
relay/relay_task.go
Detects remix action from request path, extracts OriginTaskID, loads origin task, propagates origin model info, and when needed loads and syncs origin channel (base URL, auth header, ChannelId, platform) and applies origin parameters (seconds/size) to price/ratios.
Sora adaptor validation & URL handling
relay/channel/task/sora/adaptor.go
Adds validateRemixRequest to enforce JSON body with a non-empty trimmed prompt; ValidateRequestAndSetAction short-circuits for remix; BuildRequestURL returns remix-specific endpoint /v1/videos/{OriginTaskID}/remix.
Constants & UI
constant/task.go, web/src/constants/common.constant.js, web/src/components/table/task-logs/TaskLogsColumnDefs.jsx
Adds TaskActionRemix / TASK_ACTION_REMIX_GENERATE constants and updates task log rendering to treat remix action as a video task with a UI tag.
Module manifest
go.mod
Module file present in diff (no exported API changes).

Sequence Diagram

sequenceDiagram
    autonumber
    participant Client
    participant Router
    participant Middleware
    participant RelayTask
    participant DB
    participant Adaptor
    participant SoraAPI

    Client->>Router: POST /v1/videos/:video_id/remix
    Router->>Middleware: route to RelayTask handler
    Middleware->>Middleware: detect "/remix" path\nset relay_mode=VideoSubmit\nshouldSelectChannel=false
    Middleware->>RelayTask: forward request (marked remix)

    RelayTask->>RelayTask: extract video_id -> OriginTaskID
    RelayTask->>DB: fetch origin task by userId + OriginTaskID
    DB-->>RelayTask: origin task (or error)
    alt origin channel != current channel
        RelayTask->>DB: fetch origin channel
        DB-->>RelayTask: origin channel
        RelayTask->>RelayTask: update ChannelBaseUrl, auth header, ChannelId, platform
    end
    RelayTask->>RelayTask: propagate OriginModelName / parameters
    RelayTask->>Adaptor: ValidateRequestAndSetAction(action=remix)
    Adaptor->>Adaptor: validateRemixRequest (JSON, non-empty prompt)
    Adaptor->>Adaptor: BuildRequestURL -> /v1/videos/{OriginTaskID}/remix
    Adaptor-->>RelayTask: prepared request
    RelayTask->>SoraAPI: POST /v1/videos/{OriginTaskID}/remix
    SoraAPI-->>RelayTask: response
    RelayTask-->>Client: return result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review points:
    • relay/relay_task.go: origin task loading, channel sync, and parameter propagation logic.
    • middleware/distributor.go: correctness of relay_mode and shouldSelectChannel flags.
    • relay/channel/task/sora/adaptor.go: JSON validation edge cases and integration with existing multipart flow.

Possibly related PRs

Suggested reviewers

  • seefs001

Poem

🐇 I hopped a remix through the gate,
origin echoes guide the fate,
channels hum and Sora sings,
prompts now dance on feathered wings,
a rabbit's patchwork, swift and great.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a new endpoint for OpenAI video remix functionality across backend routing, middleware, and frontend components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sora-remix

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d732cdd and 80ad006.

📒 Files selected for processing (5)
  • constant/task.go (1 hunks)
  • relay/channel/task/sora/adaptor.go (2 hunks)
  • relay/relay_task.go (1 hunks)
  • web/src/components/table/task-logs/TaskLogsColumnDefs.jsx (3 hunks)
  • web/src/constants/common.constant.js (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-26T09:59:00.337Z
Learnt from: Sh1n3zZ
Repo: QuantumNous/new-api PR: 1659
File: relay/relay_task.go:285-305
Timestamp: 2025-08-26T09:59:00.337Z
Learning: In controller/task_video.go, data: URLs (containing base64 encoded video data) are prevented from being stored in task.FailReason by checking if the URL starts with "data:" before assignment. This same pattern should be applied consistently across the codebase.

Applied to files:

  • relay/channel/task/sora/adaptor.go
🧬 Code graph analysis (3)
web/src/components/table/task-logs/TaskLogsColumnDefs.jsx (1)
web/src/constants/common.constant.js (4)
  • TASK_ACTION_REMIX_GENERATE (45-45)
  • TASK_ACTION_REMIX_GENERATE (45-45)
  • TASK_ACTION_REFERENCE_GENERATE (44-44)
  • TASK_ACTION_REFERENCE_GENERATE (44-44)
relay/relay_task.go (6)
constant/task.go (1)
  • TaskActionRemix (18-18)
service/error.go (2)
  • TaskErrorWrapperLocal (134-138)
  • TaskErrorWrapper (140-157)
model/task.go (1)
  • GetByTaskId (264-277)
model/channel.go (1)
  • GetChannelById (338-353)
common/constants.go (1)
  • ChannelStatusEnabled (198-198)
types/price_data.go (1)
  • PriceData (11-27)
relay/channel/task/sora/adaptor.go (4)
common/gin.go (1)
  • UnmarshalBodyReusable (35-60)
service/error.go (1)
  • TaskErrorWrapperLocal (134-138)
constant/task.go (1)
  • TaskActionRemix (18-18)
relay/common/relay_utils.go (1)
  • ValidateMultipartDirect (121-188)
🔇 Additional comments (11)
constant/task.go (1)

18-18: LGTM!

The new constant is correctly named and follows the existing pattern. The value matches the frontend constant TASK_ACTION_REMIX_GENERATE.

web/src/constants/common.constant.js (1)

45-45: LGTM!

The constant is properly exported and its value matches the backend constant TaskActionRemix.

web/src/components/table/task-logs/TaskLogsColumnDefs.jsx (3)

42-42: LGTM!

The import is correctly added and used in the subsequent code.


129-134: LGTM!

The case handling is consistent with other video generation actions, using the same blue color and Sparkles icon.


369-370: LGTM!

Correctly includes remix generation tasks in the video task check, ensuring remix tasks can display video previews when successful.

relay/channel/task/sora/adaptor.go (2)

72-83: LGTM!

The validation function correctly parses the request body, trims whitespace, and validates that the prompt field is required. Error handling is appropriate.


86-89: LGTM!

The conditional routing to remix-specific validation is clean and maintains the existing validation flow for non-remix requests.

relay/relay_task.go (4)

52-75: LGTM!

The origin task retrieval logic correctly validates task existence, enforces user access control, and extracts the model name from multiple fallback sources with appropriate error handling.


76-93: LGTM!

The channel synchronization logic correctly loads the origin channel, validates it's enabled, and consistently updates both the gin context and RelayInfo with the origin channel details. The security check for disabled channels is appropriate.


96-113: LGTM!

The remix parameters are correctly extracted from the origin task data with safe defaults. The size multiplier logic is consistent with the pricing logic in relay/common/relay_utils.go.


35-114: Well-integrated remix flow.

The remix detection and origin task handling is correctly positioned early in the flow, before adaptor initialization. The second InitChannelMeta call at Line 119 appropriately re-initializes after potential channel synchronization from the origin task.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
relay/relay_task.go (3)

35-47: Path detection logic is duplicated with distributor.go.

The remix path detection (strings.Contains(path, "/v1/videos/") && strings.HasSuffix(path, "/remix")) is duplicated here and in middleware/distributor.go (lines 184-187). Consider extracting this to a shared helper to avoid divergence.

+// In a shared location, e.g., relay/common/path_utils.go
+func IsRemixPath(path string) bool {
+    return strings.Contains(path, "/v1/videos/") && strings.HasSuffix(path, "/remix")
+}

68-74: Silent error from json.Unmarshal may hide data issues.

If originTask.Data is malformed, the error is discarded and the model lookup silently fails. Consider logging the error for debugging purposes.

 			} else {
 				var taskData map[string]interface{}
-				_ = json.Unmarshal(originTask.Data, &taskData)
+				if err := json.Unmarshal(originTask.Data, &taskData); err != nil {
+					common.SysLog(fmt.Sprintf("failed to unmarshal origin task data: %v", err))
+				}
 				if m, ok := taskData["model"].(string); ok && m != "" {

76-93: Variable channel shadows the imported package name.

The variable channel at line 77 shadows the imported github.com/QuantumNous/new-api/relay/channel package, which could cause confusion and potential bugs if the package is needed later in this scope.

 		if originTask.ChannelId != info.ChannelId {
-			channel, err := model.GetChannelById(originTask.ChannelId, true)
+			originChannel, err := model.GetChannelById(originTask.ChannelId, true)
 			if err != nil {
 				taskErr = service.TaskErrorWrapperLocal(err, "channel_not_found", http.StatusBadRequest)
 				return
 			}
-			if channel.Status != common.ChannelStatusEnabled {
+			if originChannel.Status != common.ChannelStatusEnabled {
 				taskErr = service.TaskErrorWrapperLocal(errors.New("the channel of the origin task is disabled"), "task_channel_disable", http.StatusBadRequest)
 				return
 			}
-			c.Set("base_url", channel.GetBaseURL())
+			c.Set("base_url", originChannel.GetBaseURL())
 			c.Set("channel_id", originTask.ChannelId)
-			c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", channel.Key))
+			c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", originChannel.Key))
 
-			info.ChannelBaseUrl = channel.GetBaseURL()
+			info.ChannelBaseUrl = originChannel.GetBaseURL()
 			info.ChannelId = originTask.ChannelId
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b9f6a5 and d732cdd.

📒 Files selected for processing (4)
  • middleware/distributor.go (1 hunks)
  • relay/channel/task/sora/adaptor.go (2 hunks)
  • relay/relay_task.go (1 hunks)
  • router/video-router.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-26T09:59:00.337Z
Learnt from: Sh1n3zZ
Repo: QuantumNous/new-api PR: 1659
File: relay/relay_task.go:285-305
Timestamp: 2025-08-26T09:59:00.337Z
Learning: In controller/task_video.go, the redactVideoResponseBody function sanitizes video task responses by removing bytesBase64Encoded fields and truncating base64 strings to 256 characters to prevent large binary data from being stored in task.Data.

Applied to files:

  • router/video-router.go
🧬 Code graph analysis (3)
router/video-router.go (1)
controller/relay.go (1)
  • RelayTask (392-435)
middleware/distributor.go (1)
relay/constant/relay_mode.go (1)
  • RelayModeVideoSubmit (44-44)
relay/channel/task/sora/adaptor.go (4)
common/gin.go (1)
  • UnmarshalBodyReusable (35-60)
service/error.go (1)
  • TaskErrorWrapperLocal (134-138)
relay/channel/adapter.go (1)
  • TaskAdaptor (34-53)
relay/common/relay_utils.go (1)
  • ValidateMultipartDirect (121-188)
🔇 Additional comments (5)
relay/channel/task/sora/adaptor.go (2)

71-82: LGTM! Clean validation for remix requests.

The validation correctly handles JSON parsing errors and enforces non-empty prompts with whitespace trimming.


84-89: Approve the action-based dispatch pattern.

Clean short-circuit to remix validation when action is "remix", falling back to existing multipart validation for other actions.

relay/relay_task.go (1)

51-61: Good authorization check: origin task is scoped to current user.

The lookup model.GetByTaskId(info.UserId, info.OriginTaskID) correctly ensures users can only remix their own tasks, preventing unauthorized access to other users' video tasks.

router/video-router.go (1)

17-17: LGTM! Route correctly added for remix endpoint.

The route follows the existing pattern and is properly placed within the authenticated video router group with the appropriate middleware chain.

middleware/distributor.go (1)

184-187: LGTM! Remix path correctly handled before general video path.

The remix-specific branch is correctly placed before the general /v1/videos handler, and shouldSelectChannel = false correctly delegates channel selection to the origin task lookup in relay_task.go.

Comment on lines 91 to 96
func (a *TaskAdaptor) BuildRequestURL(info *relaycommon.RelayInfo) (string, error) {
if info.Action == "remix" {
return fmt.Sprintf("%s/v1/videos/%s/remix", a.baseURL, info.OriginTaskID), nil
}
return fmt.Sprintf("%s/v1/videos", a.baseURL), nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for OriginTaskID usage and validation
rg -n 'OriginTaskID' relay/ -A 3 -B 3

Repository: QuantumNous/new-api

Length of output: 2193


🏁 Script executed:

#!/bin/bash
# Search for BuildRequestURL usage and downstream URL handling
rg -n 'BuildRequestURL' relay/ -A 5 -B 2

# Also check the full adaptor file for URL encoding
cat relay/channel/task/sora/adaptor.go | head -150

Repository: QuantumNous/new-api

Length of output: 12753


🏁 Script executed:

#!/bin/bash
# Check the complete flow from api_request.go to understand URL handling
sed -n '300,320p' relay/channel/api_request.go

# Search for any URL validation or sanitization middleware
rg -n 'net/url|url\.Parse|path.*valid|sanitize' relay/ -i

Repository: QuantumNous/new-api

Length of output: 1026


Add validation for OriginTaskID to reject path traversal characters.

The OriginTaskID is interpolated directly into the URL path without format validation. Currently, relay_task.go only checks if videoID is empty; characters like ../, /, ?, and # can pass through and manipulate the upstream request path. Validate that video_id contains only allowed characters (e.g., alphanumeric, hyphens, underscores) before assigning it to OriginTaskID.

🤖 Prompt for AI Agents
In relay/channel/task/sora/adaptor.go around lines 91 to 96, BuildRequestURL
interpolates info.OriginTaskID into the URL path without validation; add
validation to reject path-traversal or unsafe characters by ensuring
OriginTaskID matches a strict whitelist (e.g., ^[A-Za-z0-9_-]+$) and return an
error if it fails; sanitize or refuse values containing ../, /, ?, #, spaces or
other disallowed chars, and update the function to perform this check before
constructing the URL so only safe IDs are used in the path.

@seefs001

Copy link
Copy Markdown
Collaborator

已合并在另一个PR

@seefs001 seefs001 closed this Dec 14, 2025
@Calcium-Ion
Calcium-Ion deleted the sora-remix branch April 1, 2026 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants