HiAPI
블로그

튜토리얼

HeyGen Avatar V API는 어떻게 사용하나요? 아바타 선택부터 완성 영상 다운로드까지

대사와 오디오 두 가지 경로, 아바타·음성 값 조회, cURL, 응답 구조, 제한된 폴링, 영상/SRT 다운로드 포함.

Oct 13, 2026
HeyGen Avatar V API는 어떻게 사용하나요? 아바타 선택부터 완성 영상 다운로드까지

HeyGen Avatar V는 프리셋 디지털 휴먼을 하나 선택하고 대사나 오디오를 입력하면 입모양이 동기화된 영상을 생성합니다. HiAPI는 출력 길이 기준으로 초당 $0.15, 10초 영상은 $1.50를 청구합니다.

HeyGen Avatar V는 HiAPI에 출시되었습니다. 모델 페이지 열기에서 먼저 아바타와 음성을 선택한 뒤 API를 연동하세요. 아래 비즈니스 설명 영상은 이미 완성된 결과물입니다:

Brandon Office Sitting Front, Dexter - Professional; 16:9, 완성 영상 1280×720, 약 8초. 원래 요청은 1080p이며, 이 페이지는 720p 웹 버전입니다.

Hi, I'm Daniel. Send me your quarterly numbers, and I'll walk your team through what changed and what to do next.

이 프롬프트로 생성하기 → 대사는 이미 입력되어 있습니다. 위에서 아바타, 음성, 1080p, 16:9를 직접 선택하고 출력은 MP4를 선택하세요.

온라인에서 어떻게 시험하나요?

  1. 미리 채워진 링크를 열고 이 짧은 대사를 유지합니다.
  2. 아바타와 음성을 선택하세요. 이 매개변수는 직접 선택해야 하며, 링크는 대사만 불러옵니다.
  3. 화면 비율, 해상도, 형식을 설정하세요. 첫 시도에는 위 조합을 사용하면 됩니다.
  4. 생성 후 더빙을 들어보고 입모양을 확인한 뒤 완성 영상을 다운로드하고, 자신의 문구로 바꾸세요.

이번 시험에서 사용한 아바타, 음성, 화면 비율을 기록해 두고 일괄 생성 시 그대로 유지하면서 대사만 바꾸면 출연자와 음성을 일관되게 유지할 수 있습니다.

V는 프리셋 아바타 중에서 출연자를 선택합니다. 자신의 사진을 출연시키려면 Avatar IV를 선택하세요.

모든 해상도는 실제 출력 초 단위로 청구되며, 실패 시 전액 환불됩니다. 전체 비용은 가격 및 예산표를 참고하세요.

API에 무엇을 준비해야 하나요?

콘솔에서 API key를 생성하세요. 요청에 model, 필수인 input.avatar를 명시하고, prompt와 audio_url 중 하나를 선택하세요. 아바타와 음성은 문서 카드의 영문 요청값을 사용하며, 중국어 이름은 식별용으로만 사용합니다.

대사는 그대로 읽히므로 카메라 지시문을 prompt에 넣지 마세요. 오디오 구동 시 접근 가능한 HTTP(S) 주소를 전달하고 prompt와 voice를 제거하세요. duration은 전달할 필요가 없으며, 길이는 대사 낭독이나 오디오에 따라 결정됩니다.

가진 것 전달할 구동 필드
읽어야 할 대사 avatar + prompt; voice 선택 사항
이미 녹음한 음성 avatar + audio_url; prompt와 voice 생략

아바타 값 조회: 매개변수 문서 → 디지털 휴먼 아바타에서 전체를 펼친 뒤 검색하여 영문 'Request value'를 복사하세요. 음성도 마찬가지로 프리셋 음성에서 찾으세요. 영문 페이지에서는 Request value에 해당하며, 중국어 표시 이름을 요청에 넣지 마세요.

**오디오 구동 최소 전체 요청:** 자리 표시자 주소를 자신의 공개 접근 가능한 오디오 URL로 바꾸세요. 생략한 화면 비율, 해상도, 형식은 문서 기본값을 사용합니다. 오디오는 최대 600초, 최대 32 MiB입니다.

{
  "model": "heygen-avatar-v",
  "input": {
    "avatar": "Brandon Office Sitting Front",
    "audio_url": "https://example.com/your-recording.mp3"
  }
}

cURL로 작업 생성 및 조회하기

Key 자리 표시자를 자신의 값으로 바꾸세요. 이 요청은 비즈니스 사례 매개변수를 그대로 사용합니다:

export HIAPI_API_KEY="sk-YOUR_KEY"
curl --fail-with-body --connect-timeout 10 --max-time 60 \
  -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "heygen-avatar-v",
    "input": {
      "avatar": "Brandon Office Sitting Front",
      "prompt": "Hi, I\u0027m Daniel. Send me your quarterly numbers, and I\u0027ll walk your team through what changed and what to do next.",
      "voice": "Dexter - Professional",
      "aspect_ratio": "16:9",
      "resolution": "1080p",
      "caption": false,
      "output_format": "mp4"
    }
  }'

HTTP 상태와 JSON의 code를 확인하고, 성공적으로 생성되면 data.taskId를 저장하세요. 이후에는 동일한 작업만 조회합니다:

TASK_ID="REPLACE_WITH_data.taskId"
curl --fail-with-body --connect-timeout 10 --max-time 60 \
  "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"

queued, handling, archiving은 처리 중을 의미하며, 종료 상태는 success 또는 fail입니다. 성공 후 data.output[].type을 기준으로 video를 찾고, 자막을 활성화한 경우 caption도 찾으세요. 산출물의 url을 읽고 expireAt에 맞춰 제때 다운로드하세요.

**응답 구조 예시:** 첫 번째는 생성 성공, 두 번째는 자막 활성화 후 성공 조회입니다. 작업 ID, URL, 만료 시간은 모두 예시 값이며, expireAt은 숫자로 Unix 초 단위입니다. POST가 타임아웃되거나 응답이 유실된 경우 먼저 작업 기록을 조회하고, 무작정 다시 POST하지 마세요. ID가 있으면 GET을 계속하세요.

{
  "code": 200,
  "data": {"taskId": "TASK_ID_FROM_CREATE"}
}
{
  "code": 200,
  "data": {
    "taskId": "TASK_ID_FROM_CREATE",
    "status": "success",
    "output": [
      {"type": "video", "url": "https://example.com/result.mp4", "expireAt": 4070908800},
      {"type": "caption", "url": "https://example.com/result.srt", "expireAt": 4070908800}
    ]
  }
}

Python: 생성, 제한된 폴링, 다운로드

먼저 requests를 설치하고 환경 변수 HIAPI_API_KEY에 Key를 설정하세요. 코드는 한 번만 제출하며, 폴링은 최대 30분입니다. 타임아웃 시 작업 ID를 보관하고 조회를 계속하세요.

import os
import time
from pathlib import Path
import requests

API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}
payload = {
    "model": "heygen-avatar-v",
    "input": {
        "avatar": "Brandon Office Sitting Front",
        "prompt": "Hi, I'm Daniel. Send me your quarterly numbers, and I'll walk your team through what changed and what to do next.",
        "voice": "Dexter - Professional",
        "aspect_ratio": "16:9",
        "resolution": "1080p",
        "caption": False,
        "output_format": "mp4",
    },
}

def api_request(method, url, **kwargs):
    advice = (
        "Submission state may be unknown; check task history before another POST."
        if method == "POST"
        else f"Continue GET with the saved task ID: {url.rsplit('/', 1)[-1]}."
    )
    try:
        response = requests.request(
            method, url, headers=HEADERS, timeout=(10, 30), **kwargs
        )
    except requests.RequestException:
        raise RuntimeError(f"Network error. {advice}") from None
    if not response.ok:
        raise RuntimeError(f"HTTP {response.status_code}. {advice}")
    try:
        body = response.json()
    except ValueError:
        raise RuntimeError(f"Response is not JSON. {advice}") from None
    if not isinstance(body, dict):
        raise RuntimeError(f"Unexpected response shape. {advice}")
    if body.get("code") != 200 or not isinstance(body.get("data"), dict):
        raise RuntimeError(f"API error: code={body.get('code')}. {advice}")
    return body["data"]

# Submit once. No automatic POST retries.
created = api_request("POST", API, json=payload)
task_id = created.get("taskId")
if not isinstance(task_id, str) or not task_id:
    raise RuntimeError("Missing taskId; check task history before resubmitting.")
print("taskId:", task_id)  # Keep this ID to resume GET queries.
deadline = time.monotonic() + 1800
while time.monotonic() < deadline:
    data = api_request("GET", f"{API}/{task_id}")
    status = data.get("status")
    if status == "fail":
        raise RuntimeError(f"Task failed: {task_id}; inspect its task record.")
    if status == "success":
        break
    if status not in ("queued", "handling", "archiving"):
        raise RuntimeError(f"Unexpected task status: {status}")
    time.sleep(8)
else:
    raise TimeoutError(f"Polling timed out; continue GET for taskId={task_id}.")

raw_outputs = data.get("output")
if not isinstance(raw_outputs, list):
    raise RuntimeError(f"Missing output list; inspect taskId={task_id}.")
outputs = {
    item["type"]: item
    for item in raw_outputs
    if isinstance(item, dict) and item.get("type") in ("video", "caption")
}
if "video" not in outputs:
    raise RuntimeError("Successful task has no video artifact.")
for kind, artifact in outputs.items():
    if not isinstance(artifact.get("url"), str) or not artifact["url"]:
        raise RuntimeError(f"Missing {kind} URL; inspect taskId={task_id}.")
    suffix = payload["input"]["output_format"] if kind == "video" else "srt"
    target = Path(f"avatar-v.{suffix}")
    # Artifact downloads do not need the API Authorization header.
    with requests.get(artifact["url"], stream=True, timeout=(10, 120)) as response:
        response.raise_for_status()
        with target.open("wb") as file:
            for chunk in response.iter_content(chunk_size=1024 * 1024):
                if chunk:
                    file.write(chunk)
    print("saved:", target)

어떤 매개변수를 명시적으로 설정해야 하나요?

필드 규칙 및 기본값
avatar 필수, 영문 아바타 요청값
prompt / audio_url 둘 중 하나; 대사 최대 5,000자, 오디오 최대 600초, 최대 32 MiB
voice 대사 경로에서 선택 사항, 기본값 Warm Pro Narrator
resolution 기본값 720p, 선택 가능 1080p, 소문자 4k
aspect_ratio 기본값 16:9; 그 외 9:16, 4:5, 5:4, 1:1, auto
fit 기본값 cover, 선택 가능 contain
caption 기본값 false; true이면 별도 SRT 반환
output_format 기본값 mp4, 선택 가능 webm
remove_background 기본값 false; 투명 용도에는 true와 webm을 함께 사용하고, 먼저 짧은 영상으로 선택한 아바타를 확인하세요
background 객체; type은 color 또는 image, value에는 16진수 색상 또는 HTTP(S) 이미지 URL 입력

해상도와 화면 비율은 별개의 매개변수입니다. 가로형 설명에는 16:9, 세로형 구두 방송에는 9:16을 사용하며, 모두 요청에 명시하세요. 다운로드 후 파일의 실제 크기를 한번 확인하세요. 투명 WebM은 선택한 아바타의 배경 제거 효과를 먼저 확인한 뒤 편집 소프트웨어로 가져오세요.

자막은 영상에 직접 새겨지지 않으며, 플레이어나 편집 소프트웨어에서 오버레이해야 합니다. 아래 세로형 사례는 caption=true로 설정하여 별도 SRT를 반환합니다. 영상은 1080×1920, 6.52초이며, 요청은 1080p, 9:16입니다. 별도 SRT 자막은 편집 시 가져올 수 있습니다.

New drop just landed: our travel mug keeps coffee hot for twelve hours. Swipe up and grab yours today!

이 프롬프트로 생성하기 → 대사는 이미 입력되어 있습니다. Riley Casual Front, Charming Charles - Friendly, 9:16, 1080p를 직접 선택하고 자막을 켜고 출력은 MP4를 선택하세요.

출시 전에 무엇을 점검해야 하나요?

  1. 입력 검증: 아바타, 구동 방식, 영문 요청값, 길이 제한을 확인하세요.
  2. 작업 ID 저장: 조회 실패나 타임아웃 시 같은 ID로 GET을 계속하세요.
  3. 산출물 모두 찾기: 성공 후 type을 기준으로 video를 찾고, 자막을 켠 경우 caption도 찾으세요.
  4. 다운로드 점검: 실제 크기, 소리, 자막 파일을 확인한 뒤 전달하세요.

일반적인 문제는 어떻게 처리하나요?

  • **입력 검증 문제:** avatar, 둘 중 하나의 구동 필드, 영문 요청값, 대사와 오디오 상한을 확인하세요. 해상도는 4k로 쓰고, duration은 삭제하세요.
  • **POST 타임아웃:** 먼저 작업 기록을 조회하세요. 이미 taskId가 있으면 GET을 계속하세요. 매번 POST할 때마다 새 작업이 생성됩니다.
  • **작업 fail:** 작업 기록에서 오류 원인을 확인하고, 해당 입력을 수정한 뒤 다시 제출하세요.
  • **다운로드 링크 만료:** 성공 후 산출물을 제때 저장하세요. 자막은 type=caption에서 읽으세요.

서버 측에서는 input과 같은 레벨에 "callback": {"url": "https://yourapp.com/webhook", "when": "final"}를 추가하여 종료 상태 작업 객체를 받고, GET으로 보완 조회할 수 있습니다.

가격 세부 사항은 초당 단가 및 예산표를, 아바타 교체는 두 가지 사례를, 전체 값은 API 매개변수 문서를 참고하세요.

이 프롬프트로 생성하기 → 대사는 이미 입력되어 있습니다. 비즈니스 아바타와 음성, 1080p, 16:9, MP4를 직접 선택하고 먼저 한 문장을 생성한 뒤 전체 스크립트를 연동하세요.

영구 AI 아티팩트로 빌드 시작하기

API 키를 받아 태스크 기반의 하나의 API로 이미지, 비디오, 오디오 모델을 호출하세요.

API 문서 보기