| 1 | import type { |
| 2 | AsyncVCreativeTaskRequest, |
| 3 | AsyncVCreativeTaskResponse, |
| 4 | GetVCreativeTaskResultRequest, |
| 5 | GetVCreativeTaskResultResponse, |
| 6 | } from '../volcengine.interface' |
| 7 | import { Injectable } from '@nestjs/common' |
| 8 | import { getErrorDetail } from '@yikart/common' |
| 9 | import { isAxiosError } from 'axios' |
| 10 | import { VolcengineConfig } from '../volcengine.config' |
| 11 | import { BaseService } from './base.service' |
| 12 | |
| 13 | /** |
| 14 | * Volcengine VCreative 服务 |
| 15 | * 负责 AI 漫剧转绘任务 |
| 16 | */ |
| 17 | @Injectable() |
| 18 | export class VCreativeService extends BaseService { |
| 19 | constructor(config: VolcengineConfig) { |
| 20 | super(config) |
| 21 | } |
| 22 | |
| 23 | /** |
| 24 | * 提交 AI 漫剧转绘任务 |
| 25 | * 文档:https://www.volcengine.com/docs/4/1924630 |
| 26 | * POST https://vod.volcengineapi.com?Action=AsyncVCreativeTask&Version=2018-01-01 |
| 27 | */ |
| 28 | async asyncVCreativeTask( |
| 29 | request: AsyncVCreativeTaskRequest, |
| 30 | ): Promise<AsyncVCreativeTaskResponse> { |
| 31 | try { |
| 32 | const api = this.vodService.createAPI< |
| 33 | Record<string, unknown>, |
| 34 | AsyncVCreativeTaskResponse |
| 35 | >('AsyncVCreativeTask', { |
| 36 | Version: '2018-01-01', |
| 37 | method: 'POST', |
| 38 | contentType: 'json', |
| 39 | }) |
| 40 | |
| 41 | // ParamObj 应该是对象,API 会自动序列化 |
| 42 | const requestData: Record<string, unknown> = { |
| 43 | Scene: request.Scene, |
| 44 | Uploader: request.Uploader, |
| 45 | ParamObj: typeof request.ParamObj === 'string' ? JSON.parse(request.ParamObj) : request.ParamObj, |
| 46 | } |
| 47 | |
| 48 | this.logger.debug({ |
| 49 | scene: requestData['Scene'], |
| 50 | uploader: requestData['Uploader'], |
| 51 | paramObj: requestData['ParamObj'], |
| 52 | }, '[AsyncVCreativeTask] 提交任务') |
| 53 | |
| 54 | const response = await api(requestData) |
| 55 | |
| 56 | this.logger.debug({ |
| 57 | vCreativeId: response.Result?.VCreativeId, |
| 58 | responseMetadata: response.ResponseMetadata, |
| 59 | }, '[AsyncVCreativeTask] 任务提交成功') |
| 60 | |
| 61 | // 检查响应中的错误 |
| 62 | this.checkApiResponseError(response, 'Submit AsyncVCreativeTask', requestData) |
| 63 | |
| 64 | return response.Result |
| 65 | } |
| 66 | catch (error) { |
| 67 | // 详细记录错误 |
| 68 | const errorDetails = isAxiosError(error) |
| 69 | ? { |
| 70 | message: error.message, |
| 71 | stack: error.stack, |
| 72 | response: error.response?.data, |
| 73 | status: error.response?.status, |
| 74 | headers: error.response?.headers, |
| 75 | request: { |
| 76 | url: error.config?.url, |
| 77 | method: error.config?.method, |
| 78 | baseURL: error.config?.baseURL, |
| 79 | data: error.config?.data, |
| 80 | }, |
| 81 | } |
| 82 | : getErrorDetail(error) |
| 83 | |
| 84 | this.logger.error(errorDetails, 'AsyncVCreativeTask请求失败') |
| 85 | throw error |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | /** |
| 90 | * 获取 AI 漫剧转绘任务结果 |
| 91 | * 文档:https://www.volcengine.com/docs/4/1924630 |
| 92 | * GET https://vod.volcengineapi.com?Action=GetVCreativeTaskResult&Version=2018-01-01&VCreativeId=xxx |
| 93 | */ |
| 94 | async getVCreativeTaskResult( |
| 95 | request: GetVCreativeTaskResultRequest, |
| 96 | ): Promise<GetVCreativeTaskResultResponse> { |
| 97 | try { |
| 98 | this.logger.debug({ |
| 99 | vCreativeId: request.VCreativeId, |
| 100 | }, '[getVCreativeTaskResult] 查询任务') |
| 101 | |
| 102 | const api = this.vodService.createAPI< |
| 103 | Record<string, unknown>, |
| 104 | GetVCreativeTaskResultResponse |
| 105 | >('GetVCreativeTaskResult', { |
| 106 | Version: '2018-01-01', |
| 107 | method: 'GET', |
| 108 | contentType: 'json', |
| 109 | }) |
| 110 | |
| 111 | const requestData: Record<string, unknown> = { |
| 112 | VCreativeId: request.VCreativeId, |
| 113 | } |
| 114 | |
| 115 | const response = await api(requestData) |
| 116 | |
| 117 | this.logger.debug({ |
| 118 | vCreativeId: request.VCreativeId, |
| 119 | status: response.Result?.Status, |
| 120 | uploader: response.Result?.['Uploader'], |
| 121 | workflowId: response.Result?.['WorkflowId'], |
| 122 | hasOutputJson: !!response.Result?.OutputJson, |
| 123 | outputJsonPreview: response.Result?.OutputJson |
| 124 | ? (response.Result.OutputJson.length > 200 |
| 125 | ? `${response.Result.OutputJson.substring(0, 200)}...` |
| 126 | : response.Result.OutputJson) |
| 127 | : undefined, |
| 128 | }, '[getVCreativeTaskResult] 收到响应') |
| 129 | |
| 130 | // 检查响应中的错误 |
| 131 | this.checkApiResponseError(response, 'Get VCreativeTask result', requestData) |
| 132 | |
| 133 | return response.Result |
| 134 | } |
| 135 | catch (error) { |
| 136 | const errorDetails = isAxiosError(error) |
| 137 | ? { |
| 138 | message: error.message, |
| 139 | stack: error.stack, |
| 140 | response: error.response?.data, |
| 141 | status: error.response?.status, |
| 142 | } |
| 143 | : getErrorDetail(error) |
| 144 | |
| 145 | this.logger.error(errorDetails, '[getVCreativeTaskResult] 请求失败') |
| 146 | throw error |
| 147 | } |
| 148 | } |
| 149 | } |
| 150 |