Whisper-1 API: 첫 오디오 전사
Whisper-1에 녹음을 보내고 작업 ID를 저장한 뒤 텍스트나 자막을 다운로드합니다. Python 예제로 파일 검사, 타임스탬프, 실시간 요금을 확인합니다.
Markdown으로 읽기첫 Whisper-1 API 요청에는 오디오 파일, 명시적인 모델 ID, 출력 형식이 필요합니다. SeedRouter에서는 녹음을 업로드하고 반환된 작업 ID를 저장한 다음, 작업이 완료되면 전사문을 다운로드합니다. 내용을 이미 아는 짧은 녹음으로 시작하면 빠진 단어나 이상한 표기를 알아보기 쉽습니다.
이 가이드는 SeedRouter의 비동기 계약을 따릅니다. OpenAI SDK의 동기 예제를 그대로 대체하는 예제가 아닙니다. Whisper-1 모델 페이지에 Playground와 실시간 가격이 있으며, API 참조 문서에 모든 필드와 남은 호환성 검사가 나옵니다. [1]
녹음 하나 준비
처리할 권한이 있는 음성을 사용합니다. 짧은 WAV나 MP3가 시작하기에 적합합니다. 현재 업로드 제한은 26,214,400바이트이며, 파일에는 읽을 수 있고 길이를 측정할 수 있는 오디오가 있어야 합니다. 텍스트 파일의 확장자를 .mp3로 바꿔도 유효한 오디오가 되지는 않습니다. 참조 문서는 문서에 있는 9가지 입력 형식과 실제 검사를 통과한 형식을 구분합니다. [1]
아래 녹음은 이 튜토리얼을 위해 만든 원본 영어 합성 음성입니다. 표지에는 그 파형이 표시됩니다. 표지의 인용문은 녹음 대본에서 가져온 것이며 정확도 주장이 아닙니다.
10.31초 샘플 다운로드. 대본 원문은 다음과 같습니다. “This is a sample recording for an audio transcription tutorial. Our meeting starts at nine thirty on Monday. Please bring the project notes and review the final checklist before we begin.”
API 키는 서버 측 환경 변수에 보관합니다. 공개 웹페이지, 모바일 앱 번들 또는 공유 스크린샷에 넣지 않습니다. 아래 Python 예제는 requests를 사용하고 환경 변수에서 SEEDROUTER_API_KEY를 읽습니다.
Whisper-1 API 요청은 한 번만 제출
첫 요청에는 json을 선택합니다. 그러면 자막 타임코드를 처리하지 않고도 다운로드한 결과의 text 필드를 읽을 수 있습니다. multipart의 file 파트에는 실제 바이트가 있어야 합니다. 값으로 URL을 제공하는 것은 파일 업로드와 다릅니다. 클라이언트가 multipart 콘텐츠 유형과 boundary를 설정하게 합니다. [1]
이를 transcribe.py로 저장합니다. POST 전에 제출 마커를 쓰고, 접수 후 작업 ID를 저장합니다. 다시 실행하면 기존 작업을 읽습니다. POST의 결과가 불확실하면 마커가 실수로 중복 요청을 만드는 것을 막습니다.
import json
import os
from pathlib import Path
import requests
base = "https://api.seedrouter.ai/v1"
headers = {"Authorization": f"Bearer {os.environ['SEEDROUTER_API_KEY']}"}
state = Path("whisper-task.json")
audio = Path("recording.wav")
if not state.exists():
if not 0 < audio.stat().st_size <= 26_214_400:
raise ValueError("Choose a nonempty recording within the upload limit")
with state.open("x") as marker:
json.dump({"status": "submission_unconfirmed"}, marker)
with audio.open("rb") as recording:
response = requests.post(
f"{base}/audio/transcriptions",
headers=headers,
files={"file": (audio.name, recording, "audio/wav")},
data={"model": "whisper-1", "response_format": "json"},
timeout=180,
allow_redirects=False,
)
response.raise_for_status()
accepted = response.json()
task_id = accepted.get("id")
if not isinstance(task_id, str) or not task_id.startswith("task_"):
raise RuntimeError("Submission could not be confirmed; check task history")
state.write_text(json.dumps({"id": task_id}), encoding="utf-8")
saved = json.loads(state.read_text(encoding="utf-8"))
if "id" not in saved:
raise RuntimeError("Check task history before submitting another recording")
response = requests.get(
f"{base}/tasks/{saved['id']}", headers=headers, timeout=30,
allow_redirects=False,
)
response.raise_for_status()
task = response.json()
print(task["status"])
if task["status"] == "completed":
result = requests.get(task["output"]["url"], timeout=60)
result.raise_for_status()
print(result.json()["text"])
elif task["status"] == "failed":
print(task["error"])python transcribe.py를 실행합니다. processing이 출력되면 몇 초 기다린 후 같은 명령을 다시 실행합니다. 다시 업로드하는 대신 저장된 ID를 읽습니다. 의도적으로 새로운 녹음을 처리할 때는 녹음마다 별도 상태 파일을 저장합니다. 클라이언트 시간 초과만으로 작업 실패를 판단할 수 없습니다.
완료된 전사문 읽기
접수 응답에는 id, model, status, created_at이 있습니다. 완료 시 output.url과 output.format이 추가됩니다. 이 URL은 결과 파일을 가리킵니다. 별도의 유료 요청이 필요한 미디어 생성 작업이 아닙니다. GET으로 결과 파일을 다운로드합니다. [1]
녹음을 들으면서 글을 읽습니다. 자막이나 정확한 인용에 사용하기 전에 이름, 숫자, 문장 경계를 확인합니다. 전사문은 발화의 초안이며, 타임스탬프가 있어도 검토는 필요합니다.
2026년 10월 19일의 로컬 종단 간 검사에서 5가지 전사 형식과 영어 입력 번역을 완료했습니다. 이 검사는 테스트한 녹음의 결과 제공 및 과금 동작을 확인한 것입니다. 정확도 백분율이나 언어 간 번역 품질을 입증하지 않습니다.
텍스트, 타임스탬프 또는 자막 선택
| 다음 작업 | 선택 | 다운로드 파일 읽기 |
|---|---|---|
| 글을 애플리케이션에서 사용 | json | JSON으로 읽고 text부터 확인 |
| 일반 텍스트 전사문 편집 | text | 일반 텍스트 |
| 자막을 편집기에 가져오기 | srt 또는 vtt | 자막 텍스트 |
| 개별 단어나 구간 정렬 | verbose_json | 요청한 타임스탬프가 있는 JSON |
단어 타임스탬프를 쓰려면 response_format=verbose_json과 이름이 timestamp_granularities[], 값이 word인 반복 multipart 필드를 보냅니다. 둘 다 필요하면 값이 segment인 파트를 하나 더 추가합니다. Python requests에서는 반복 필드에 (name, value) 쌍의 목록을 사용합니다. 모든 타임스탬프는 초 단위입니다. [2]
단어 타임스탬프와 화자 라벨은 다른 출력입니다. 구간을 요청하는 것만으로 Whisper-1이 회의를 화자별 전사문으로 만들지는 않습니다. 부분 텍스트도 스트리밍하지 않으며, 이 모델에서는 stream을 무시합니다. 검증된 처리에서는 chunking_strategy를 생략합니다. 명시적으로 선택한 auto는 실제 호환성 검사를 통과하지 못했습니다. [1]
필요할 때 언어와 표기 문맥 추가
선택적 language=en은 전사 요청에 입력이 영어임을 알립니다. 자동 감지를 원하면 생략합니다. 제품명이 잘못 인식되기 쉽다면 오디오와 같은 언어로 올바른 표기를 prompt에 넣습니다. Whisper 프롬프트는 문맥을 제공하며, 특정 형식을 안정적으로 지시하는 채팅 명령처럼 작동하지 않습니다. [3]
클립과 관련된 문맥만 제공합니다. Whisper는 자체 토크나이저의 마지막 224개 토큰만 사용합니다. 긴 문서를 보낸다고 녹음에 무제한 용어집이 생기지는 않으며, 글자 수를 세는 것도 이 토큰 규칙의 정확한 대안이 아닙니다.
영어 번역은 엔드포인트를 /audio/translations로 바꿉니다. 요청 필드 5개는 file, model, prompt, response_format, temperature입니다. 번역은 영어를 출력하며 대상 언어 선택기는 없습니다. 프롬프트를 제공할 경우 영어를 사용합니다. [4]
작업 범위를 넓히기 전 비용 확인
아래 실시간 표는 측정한 오디오 길이를 사용합니다. 같은 녹음에서 전사문이 길어져도 길이 요금이 증가하지 않습니다. 파일별 길이는 정수 초로 올림한 뒤 오디오 계량 단위로 변환합니다. API 참조 문서에 정확한 계산법이 있으며, Playground는 녹음 길이를 읽을 수 있으면 예상 요금을 표시합니다. 실패한 요청에는 요금이 부과되지 않습니다.
| Model | USD per minute | USD per million audio metering units |
|---|---|---|
| whisper-1 | $0.036 | $36 |
For each recording: units = round(ceil(duration in seconds) × 1000 / 60). Multiply these audio units by the live unit rate. These are duration units, not transcript tokens. Both transcription and English translation use this rule. Failed requests are not charged.
많은 파일을 처리하기 전에 대표 녹음 하나를 검증하고 결과를 살펴봅니다. 녹음별 작업 ID를 보관하면 연결 중단 후 기존 상태를 읽어 복구할 수 있습니다. 자막이나 테스트가 적은 형식 조합을 추가하기 전에 전체 매개변수 참조 문서를 확인합니다.
첫 통합에서 자주 묻는 질문
OpenAI Python SDK 예제를 그대로 쓸 수 있나요?
아닙니다. multipart 입력 필드는 익숙하지만 SeedRouter는 비동기 작업 ID를 반환합니다. POST 응답에 text가 있을 것으로 예상하는 동기 클라이언트는 수정이 필요합니다. 이 예제는 제출과 결과 조회를 명확히 구분합니다.
JSON 결과에 단어 타임스탬프가 없는 이유는 무엇인가요?
기본 json 형식은 텍스트 중심입니다. verbose_json과 word 타임스탬프 세부 수준을 함께 요청합니다. 구간 시간 정보만으로 단어별 항목이 생성되지는 않습니다.
시간 초과 후 다른 POST를 보내야 하나요?
저장된 작업 ID나 작업 기록부터 확인합니다. 접수 후 응답만 유실되었을 수 있습니다. 기존 작업을 읽으면 같은 녹음에 다른 요청을 만드는 것을 피할 수 있습니다.
Whisper-1이 종료되나요?
OpenAI는 자체 API의 Whisper를 2027년 2월 26일 종료한다고 발표했습니다. 이 공지는 본 서비스의 종료 날짜를 정하지 않습니다. 새 통합을 만들 때 수명 주기 공지를 유지보수 목록에 포함합니다. [5]
출처
[1] SeedRouter Whisper-1 API 참조 문서 및 검증 상태, 확인 날짜: 2026년 10월 19일.
[2] OpenAI 전사 참조 문서.
[4] OpenAI 번역 참조 문서.



