diff --git a/relay/channel/task/doubao/adaptor.go b/relay/channel/task/doubao/adaptor.go index fcb0608..b44f5a2 100644 --- a/relay/channel/task/doubao/adaptor.go +++ b/relay/channel/task/doubao/adaptor.go @@ -71,24 +71,24 @@ type responseTask struct { Model string `json:"model"` Status string `json:"status"` Content struct { - VideoURL string `json:"video_url"` + VideoURL string `json:"videoUrl"` } `json:"content"` Seed int `json:"seed"` Resolution string `json:"resolution"` Duration int `json:"duration"` Ratio string `json:"ratio"` - FramesPerSecond int `json:"framespersecond"` - ServiceTier string `json:"service_tier"` + FramesPerSecond int `json:"framesPerSecond"` + ServiceTier string `json:"serviceTier"` Usage struct { - CompletionTokens int `json:"completion_tokens"` - TotalTokens int `json:"total_tokens"` + CompletionTokens int `json:"completionTokens"` + TotalTokens int `json:"totalTokens"` } `json:"usage"` Error struct { Code string `json:"code"` Message string `json:"message"` } `json:"error"` - CreatedAt int64 `json:"created_at"` - UpdatedAt int64 `json:"updated_at"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` } // ============================ diff --git a/relay/channel/task/doubao/adaptor_test.go b/relay/channel/task/doubao/adaptor_test.go index 9353818..8a7938e 100644 --- a/relay/channel/task/doubao/adaptor_test.go +++ b/relay/channel/task/doubao/adaptor_test.go @@ -13,8 +13,8 @@ func TestParseTaskResult_SuccessWithUsage(t *testing.T) { adaptor := &TaskAdaptor{} taskInfo, err := adaptor.ParseTaskResult([]byte(`{ "status":"succeeded", - "content":{"video_url":"https://example.test/video.mp4"}, - "usage":{"completion_tokens":12,"total_tokens":3456} + "content":{"videoUrl":"https://example.test/video.mp4"}, + "usage":{"completionTokens":12,"totalTokens":3456} }`)) require.NoError(t, err) @@ -28,7 +28,7 @@ func TestParseTaskResult_SuccessWithoutUsage(t *testing.T) { adaptor := &TaskAdaptor{} taskInfo, err := adaptor.ParseTaskResult([]byte(`{ "status":"succeeded", - "content":{"video_url":"https://example.test/video.mp4"} + "content":{"videoUrl":"https://example.test/video.mp4"} }`)) require.NoError(t, err) @@ -241,6 +241,38 @@ func TestConvertToOpenAIVideo_FailedUsesUpstreamError(t *testing.T) { require.Contains(t, string(data), `"code":"InvalidParameter"`) } +// Parses the exact Volcengine response shape observed in production: +// camelCase videoUrl / usage tokens, not snake_case. +func TestParseTaskResult_RealVolcengineResponse(t *testing.T) { + adaptor := &TaskAdaptor{} + taskInfo, err := adaptor.ParseTaskResult([]byte(`{ + "id":"cgt-20260819170015-glgnd", + "seed":46303, + "draft":false, + "model":"doubao-seedance-2-0-260128", + "ratio":"16:9", + "usage":{"totalTokens":216900,"completionTokens":216900}, + "status":"succeeded", + "content":{"videoUrl":"https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/output.mp4"}, + "duration":10, + "priority":0, + "createdAt":1787130015, + "updatedAt":1787130344, + "resolution":"720p", + "serviceTier":"default", + "outputFormat":"mp4", + "generateAudio":false, + "framesPerSecond":24, + "executionExpiresAfter":172800 + }`)) + + require.NoError(t, err) + require.Equal(t, string(model.TaskStatusSuccess), taskInfo.Status) + require.Equal(t, "https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/output.mp4", taskInfo.Url) + require.Equal(t, 216900, taskInfo.CompletionTokens) + require.Equal(t, 216900, taskInfo.TotalTokens) +} + func TestGetModelList_IncludesSeedance20Models(t *testing.T) { adaptor := &TaskAdaptor{} models := adaptor.GetModelList()