문서

SoulDub 동영상 번역 Agent API 레퍼런스

SoulDub 동영상 번역을 자동화하는 Agent, 백엔드 서비스, 스크립트를 위한 실행 API 레퍼런스입니다.

대상 독자: SoulDub 동영상 번역을 자동화하는 Agent, 백엔드 서비스 및 스크립트입니다.

이 문서는 Skill의 실행 시점 API 레퍼런스이며 scripts/video_translation.py를 대체하지 않습니다. 일반 번역은 먼저 스크립트를 사용하고, API 호출, 인증, 멱등성, 속도 제한, 결과 다운로드 또는 오류 코드를 디버깅할 때 이 문서를 확인하세요.

1. Agent 빠른 참고

  • 현재 API 기본 URL: https://xxx.com/api/v1
  • 외부 API 경로는 /api/v1/... 아래에 있습니다.
  • 모든 /api/v1/... 엔드포인트에는 Agent API key가 필요합니다. Authorization: Bearer ${AGENT_API_KEY} 사용을 권장합니다.
  • 바이너리 동영상 업로드는 저장소의 presigned URL에 PUT {presignedUrl}으로 직접 전송하며 API key를 포함하지 않습니다.
  • 미디어 게이트웨이 URL은 API key 없이 직접 다운로드합니다.
  • 자막 다운로드 엔드포인트는 Agent API이므로 API key가 필요합니다.
  • 작업 생성과 재번역에는 안정적인 Idempotency-Key가 필요합니다.
  • API key, 업로드 presigned URL, 임시 미디어 다운로드 URL 또는 서명 파라미터를 로그, 상태 파일, 테스트 보고서 또는 프롬프트에 기록하지 마세요.
  • 429 응답은 Retry-After에 따라 기다립니다. 동시 실행 제한에도 기다려야 하며 공격적으로 재시도하지 마세요.
  • 임시 URL이 만료되면 결과 엔드포인트에서 새 URL을 요청하세요.

2. 호출 흐름

순서단계엔드포인트
1업로드 시작POST /video-uploads/initiate
2파트 URL 서명POST /video-uploads/presign-part
3동영상 바이트 업로드PUT {presignedUrl}
4업로드 완료POST /video-uploads/complete
5번역 작업 생성POST /video-translations
6작업 상태 조회GET /video-translations/{taskId}
7결과 목록 조회GET /video-translations/{taskId}/results
8미디어 URL 하나 가져오기GET /video-translations/{taskId}/results/files/{variant}
9자막 다운로드GET /video-translations/{taskId}/results/subtitles/{variant}

선택적 재번역:

POST /video-translations/{existingTaskId}/retranslate

3. 인증 및 공통 규칙

Agent API는 두 가지 인증 헤더를 지원합니다. 첫 번째 헤더를 권장합니다.

Authorization: Bearer ${AGENT_API_KEY}
X-API-Key: ${AGENT_API_KEY}

일반적인 JSON 요청 헤더:

Content-Type: application/json
Accept: application/json
Authorization: Bearer ${AGENT_API_KEY}
X-Request-Id: agent-run-20260704-0001

X-Request-Id는 선택 사항입니다. 지정하는 경우 길이는 8..64자이고 A-Z a-z 0-9 _ . : -만 사용할 수 있습니다. 서버는 응답 헤더에 최종 request id를 반환합니다.

성공 응답은 다음 JSON envelope을 사용합니다.

{
  "code": 0,
  "message": "ok",
  "data": {}
}

오류 응답도 JSON envelope을 사용합니다.

{
  "code": -1,
  "message": "INVALID_REQUEST",
  "data": null,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Validation failed.",
    "requestId": "req_abc123",
    "details": {}
  }
}

디버깅할 때는 다음 순서로 확인하세요.

  1. HTTP 상태 코드
  2. error.code
  3. error.details
  4. 응답 헤더의 X-Request-Id

모든 Agent API 응답에는 다음 속도 제한 헤더가 포함될 수 있습니다.

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1782300000

속도 제한 응답:

HTTP/1.1 429 Too Many Requests
Retry-After: 17

RATE_LIMITED가 반환되면 Retry-After만큼 기다린 후 다시 시도하세요.

4. 동영상 업로드

4.1 업로드 시작

POST /video-uploads/initiate

요청:

{
  "filename": "demo.mp4",
  "contentType": "video/mp4",
  "fileSizeBytes": 342556
}
필드필수설명
filename예.mp4 파일 이름이어야 합니다.
contentType예정확히 video/mp4여야 합니다.
fileSizeBytes예0보다 크고 계정 파일 크기 제한 이하여야 합니다.

응답에서 fileId, uploadId, key, bucket을 저장하세요. 업로드 완료와 작업 생성 호출에 필요합니다.

4.2 파트 presigned URL 생성

POST /video-uploads/presign-part

요청:

{
  "uploadId": "opaque-r2-upload-id",
  "key": "storage-key-from-initiate",
  "partNumber": 1,
  "expiresInSeconds": 900
}
필드필수설명
uploadId예업로드 시작 응답에서 반환됩니다.
key예업로드 시작 응답에서 반환됩니다.
partNumber예1..10000 범위입니다.
expiresInSeconds아니요URL TTL이며 서버가 60..86400초로 제한합니다.

반환된 presignedUrl은 현재 업로드에만 사용하세요. 로그나 상태 파일에 저장하지 마세요.

4.3 동영상 바이트 업로드

PUT {presignedUrl}
Content-Type: video/mp4

요청 본문은 동영상 바이트입니다. 이 요청은 Agent API 요청이 아닙니다.

  • Authorization을 포함하지 마세요.
  • X-API-Key를 포함하지 마세요.
  • presignedUrl을 로그에 남기지 마세요.
  • URL이 만료되면 presign-part를 다시 호출하세요.
  • 성공적인 PUT은 보통 200을 반환하며, 클라이언트가 ETag를 Agent API로 보낼 필요는 없습니다.

4.4 업로드 완료

POST /video-uploads/complete

요청:

{
  "uploadId": "opaque-r2-upload-id",
  "key": "storage-key-from-initiate"
}

data.success == true, data.status == "completed"인지 확인하고 data.fileId가 업로드 시작 응답의 fileId와 같은지 확인하세요.

5. 번역 작업 생성

POST /video-translations
Idempotency-Key: ${UNIQUE_IDEMPOTENCY_KEY}

요청:

{
  "fileId": "uploaded-file-id",
  "videoDurationSeconds": 6,
  "checksumSha256": "optional-file-sha256",
  "sourceLanguage": "auto",
  "targetLanguage": "en",
  "speakerCount": 1,
  "allowDynamicDuration": true
}
필드필수설명
fileId예완료된 업로드의 fileId입니다.
videoDurationSeconds예1..3600초입니다.
checksumSha256아니요추적 및 검증을 위한 원본 파일 SHA-256입니다.
sourceLanguage예원본 언어이며 auto를 사용할 수 있습니다.
targetLanguage예대상 언어이며 auto는 사용할 수 없습니다.
speakerCount아니요0..15; 기본값 0은 자동 감지입니다.
allowDynamicDuration아니요true이면 동적 길이 동기화를 허용합니다.

지원 언어는 references/languages.json과 서버 측 검증으로 정의됩니다.

taskId, fileId, creditsConsumed 및 요청에 사용한 Idempotency-Key를 저장하세요.

크레딧은 분 단위로 올림 계산합니다.

durationInMinutes = max(1, ceil(videoDurationSeconds / 60))
creditsConsumed = durationInMinutes * credit.points_per_minute

현재 기본값은 credit.points_per_minute=3이며 실제 값은 서버 설정에 따라 달라집니다.

상황결과
처음 성공한 요청작업을 만들고 크레딧을 차감한 뒤 taskId를 반환합니다.
같은 Key + 같은 본문같은 응답을 반환하며 다시 차감하지 않습니다.
같은 Key + 다른 본문409 IDEMPOTENCY_KEY_REUSED
같은 멱등 요청이 처리 중409 IDEMPOTENCY_REQUEST_IN_PROGRESS

네트워크 시간 초과로 서버가 요청을 받았는지 확실하지 않다면 동일한 본문과 동일한 Idempotency-Key로 재시도하세요.

6. 작업 진행률 조회

GET /video-translations/{taskId}
필드설명
taskId작업 ID
statuspending, processing, completed, failed, cancelled
progress일반적으로 0..100인 작업 진행률
errorMessage실패 이유. 성공 또는 처리 중에는 보통 비어 있습니다.
status종료 상태처리
pending아니요계속 조회합니다.
processing아니요계속 조회합니다.
completed예결과를 가져옵니다.
failed예조회를 중지하고 errorMessage를 보고합니다.
cancelled예조회를 중지합니다.

권장 조회 전략:

  1. 작업 생성 2초 후 처음 조회합니다.
  2. 완료되지 않았다면 2s -> 5s -> 10s -> 20s -> 30s로 간격을 늘립니다.
  3. 권장 최대 간격은 30초입니다.
  4. HTTP 429는 Retry-After에 따라 기다립니다.
  5. HTTP 5xx는 전체 시간 제한과 지수 백오프를 사용합니다.

API가 completed, failed 또는 cancelled를 반환할 때만 조회를 중지하세요.

7. 결과 가져오기

7.1 결과 목록 조회

GET /video-translations/{taskId}/results?expiresIn=600

작업은 completed 상태여야 합니다. expiresIn은 선택 사항이며 미디어 다운로드 URL TTL은 서버에서 60..3600초로 제한되고 기본값은 3600초입니다.

typevariant설명
videovideo최종 합성 MP4 동영상
audiovocal분리된 음성 WAV
audiobackground분리된 배경음 WAV
audiofull합성된 전체 음성 WAV
subtitlesource원본 언어 SRT 자막
subtitletranslated대상 언어 SRT 자막
subtitlebilingual이중 언어 SRT 자막

처리 규칙:

  • access=media_gateway URL은 API key 없이 직접 다운로드합니다.
  • access=api이고 requiresAuthorization=true인 자막 URL은 API key가 필요합니다.
  • 미디어 URL이 만료되면 이 엔드포인트 또는 단일 파일 엔드포인트를 다시 호출하여 새 URL을 받으세요.

7.2 미디어 파일 URL 하나 가져오기

GET /video-translations/{taskId}/results/files/{variant}?expiresIn=600
variant내용
video최종 합성 MP4 동영상
vocal음성 WAV
background배경음 WAV
full합성된 전체 음성 WAV

응답의 url은 임시 미디어 게이트웨이 URL입니다.

  • API key를 포함하지 마세요.
  • 장기간 저장하지 마세요.
  • expiresAt에 가까워 다운로드가 실패하면 이 엔드포인트를 다시 호출하여 URL을 갱신하세요.
  • 미디어 게이트웨이는 Range GET을 지원하므로 대용량 파일을 이어받을 수 있습니다.

7.3 자막 다운로드

GET /video-translations/{taskId}/results/subtitles/{variant}
variant내용
source원본 언어 자막
translated대상 언어 자막
bilingual이중 언어 자막

응답은 JSON이 아닌 일반 SRT 텍스트입니다.

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

?download=1을 추가하면 첨부 파일 형태로 다운로드할 수 있습니다. 자막 엔드포인트도 Agent API이므로 API key가 필요합니다.

8. 재번역

POST /video-translations/{existingTaskId}/retranslate
Idempotency-Key: ${UNIQUE_IDEMPOTENCY_KEY}

허용되는 기존 작업 상태:

  • completed
  • failed
  • cancelled

요청 본문은 비워도 됩니다. 본문을 보내는 경우 현재 다음 옵션만 지원합니다.

{
  "allowDynamicDuration": true
}

재번역은 새 작업을 만들고 크레딧을 차감하며 동시 실행 제한을 적용받습니다. 반드시 Idempotency-Key를 사용하세요.

9. 복구 가능한 상태 머신

최소한 다음 상태를 저장하세요.

{
  "apiBase": "https://xxx.com/api/v1",
  "fileId": "string",
  "uploadId": "string",
  "key": "string",
  "taskId": "string",
  "idempotencyKey": "string",
  "sourceLanguage": "auto",
  "targetLanguage": "en",
  "status": "pending|processing|completed|failed|cancelled"
}

다음 값은 저장하지 마세요.

  • 평문 Agent API key
  • 업로드 presigned URL
  • 임시 미디어 다운로드 URL
  • 임시 서명 쿼리 파라미터, 서명 또는 인증 정보

권장 상태 머신:

NEW
  -> UPLOAD_INITIATED
  -> PART_PRESIGNED
  -> PART_UPLOADED
  -> UPLOAD_COMPLETED
  -> TASK_CREATED
  -> TASK_PROCESSING
  -> TASK_COMPLETED
  -> RESULT_DOWNLOADED

복구 규칙:

  • uploadId와 key가 있으면 완료되지 않은 파트의 URL을 다시 생성합니다.
  • 작업 생성 요청이 서버에 도달했을 수 있으면 동일한 본문과 Idempotency-Key로 다시 전송합니다.
  • taskId가 있으면 GET /video-translations/{taskId}부터 다시 시작합니다.
  • 다운로드 URL이 만료되면 results/files/{variant} 또는 results를 다시 요청합니다.

10. 오류 코드 빠른 참고

error.codeHTTP의미자동 재시도
UNAUTHORIZED401API key가 없습니다.아니요
API_KEY_INVALID401API key가 올바르지 않습니다.아니요
API_KEY_EXPIRED401API key가 만료되었습니다.아니요
API_KEY_REVOKED401API key가 폐기되었습니다.아니요
RATE_LIMITED429요청이 제한되었습니다.예, Retry-After만큼 대기
CONCURRENCY_LIMIT_REACHED429계정의 동시 실행 제한에 도달했습니다.예, 작업 완료까지 대기
INSUFFICIENT_CREDITS402크레딧이 부족합니다.아니요
INVALID_REQUEST400요청 본문, 필드 또는 variant가 올바르지 않습니다.아니요
MISSING_IDEMPOTENCY_KEY400멱등성 키가 없거나 올바르지 않습니다.아니요
INVALID_FILE_SIZE400파일 크기가 0 이하입니다.아니요
FILE_TOO_LARGE400파일이 너무 큽니다.아니요
INVALID_CONTENT_TYPE400MP4 파일이 아닙니다.아니요
INVALID_LANGUAGE400지원하지 않는 언어입니다.아니요
INVALID_SPEAKER_COUNT400화자 수가 올바르지 않습니다.아니요
INVALID_DURATION400동영상 길이가 올바르지 않습니다.아니요
IDEMPOTENCY_KEY_REUSED409다른 본문으로 같은 키를 재사용했습니다.아니요
IDEMPOTENCY_REQUEST_IN_PROGRESS409같은 멱등 요청이 처리 중입니다.예, 같은 본문과 키로 나중에 재시도
UPLOAD_NOT_FOUND404 / 409업로드 세션이 없거나 만료되었거나 허용되지 않는 상태입니다.상황에 따라 다름
UPLOAD_NOT_COMPLETED409파일 업로드가 완료되지 않았습니다.아니요, 먼저 업로드 완료
TASK_NOT_FOUND404작업이 없거나 권한이 없습니다.아니요
TASK_NOT_COMPLETED409작업이 아직 완료되지 않았습니다.예, 계속 조회
LANGUAGE_PAIR_TASK_EXISTS409같은 파일과 언어 조합의 작업이 이미 있습니다.아니요, details.existingTaskId 확인
FINAL_VIDEO_EXPIRED409최종 동영상 결과가 만료되었습니다.아니요, 다시 처리하거나 복구
FINAL_AUDIO_EXPIRED409최종 오디오 결과가 만료되었습니다.아니요, 다시 처리하거나 복구
RESULT_NOT_READY404결과 파일이 아직 준비되지 않았습니다.예, 잠시 기다린 후 재시도
SUBTITLE_NOT_FOUND404자막이 없거나 비어 있습니다.아니요, 완료 직후의 짧은 재시도 제외
모든 5xx500 / 503서비스가 일시적으로 사용할 수 없습니다.예, 상한이 있는 지수 백오프

11. 외부 호출 참고

  • 호출자는 이 문서에 적힌 Base URL, Agent API key 및 엔드포인트 경로만 있으면 됩니다.
  • 업로드 presigned URL이나 임시 미디어 다운로드 URL을 캐시하거나 저장하지 마세요.
  • API key, 업로드 URL 또는 미디어 다운로드 URL을 로그나 대화 컨텍스트에 기록하지 마세요.
  • 다운로드 URL이 만료되면 결과 엔드포인트를 다시 호출하여 새 URL을 받으세요.