문서Node.js SDK
Node.js SDK
@transcript1/sdk로 서버에서 영상 링크와 파일을 변환하세요. 텍스트·자막 다운로드, 진행 상황 확인, 오류 처리까지 예제로 살펴봐요.
TypeScript나 JavaScript 서버에서 @transcript1/sdk로 변환 작업을 시작하세요. 파일 업로드부터 스크립트가 준비될 때까지 기다리는 과정까지 SDK가 처리해요.
YouTube 외 소셜 링크를 쓰려면 SDK 1.1.0 이상이 필요해요. SDK 1.0.1은 YouTube 링크만 지원하며 다른 링크는 서버에 보내기 전에 거부해요. npm i @transcript1/sdk@latest로 업데이트하세요.
1.1.0은 처음 지원한 여섯 플랫폼의 최소 버전이에요. Twitch, Dailymotion, Pinterest, LinkedIn, Snapchat에는 해당 플랫폼 지원이 추가된 릴리스가 필요해요. 구버전에서는 링크를 서버에 보내기 전에 거부할 수 있어요.
SDK 설치하기
npm i @transcript1/sdk아래 예제는 ES 모듈 문법이에요. .mjs로 저장하세요. .js를 쓰려면 package.json에 "type": "module"을 지정하면 돼요. Node 20.19 이상에서는 require('@transcript1/sdk')와 같은 require() 호출도 지원해요.
API 키 설정하기
대시보드의 “API keys” 페이지에서 키를 발급받으세요. 서버의 TRANSCRIPT1_API_KEY 환경 변수에 넣거나, 생성자 옵션인 apiKey로 전달할 수 있어요.
import { Transcript1 } from '@transcript1/sdk';
const t1 = new Transcript1(); // reads TRANSCRIPT1_API_KEY
const other = new Transcript1({ apiKey: 't1_...' });키를 설정하지 않으면 생성 시 Transcript1Error가 발생해요. 오류 코드는 missing_api_key예요.
스크립트가 완성될 때까지 기다리기
transcribe(input, options)를 호출하면 작업을 생성하고 완료될 때까지 기다려요. 성공하면 status: 'completed'인 CompletedTranscription을 반환하며, transcript에 스크립트가 들어 있어요. 작업이 실패하거나 취소되면 Promise가 reject돼요.
const done = await t1.transcribe('https://youtu.be/dQw4w9WgXcQ');
console.log(done.transcript.text);
const file = await t1.transcribe('./interview.m4a', { speakers: true });Buffer 또는 Uint8Array를 전달할 때는 파일 이름도 지정하세요. SDK가 이름으로 미디어 형식을 구분해요.
import { readFile } from 'node:fs/promises';
const buffer = await readFile('./call.mp3');
const call = await t1.transcribe(buffer, { filename: 'call.mp3' });문자열이 http://나 https://로 시작하면 링크로, 그 밖에는 파일 경로로 읽어요. YouTube, X, TikTok, Instagram, Facebook, Bluesky, Twitch, Dailymotion, Pinterest, LinkedIn, Snapchat의 링크와 파일 업로드를 지원해요. 지원하는 공개 녹화 영상과 자막 기능은 지원 링크와 변환 옵션에서 확인하세요. 추가 플랫폼의 링크는 HTTPS여야 해요.
파일 크기는 최대 2,000,000,000바이트예요. 지원 확장자는 mp3, wav, m4a, flac, ogg, opus, mp4, mov, webm, mkv예요.
소셜 게시물은 공개 상태여야 하며, 영상이 여러 개면 첫 번째 영상만 변환해요. 플랫폼은 API가 링크로 알아내요. 단축 링크의 지원 형식과 한도도 지원 링크와 변환 옵션에서 확인할 수 있어요.
Blob, ReadableStream<Uint8Array>, Uint8Array 청크를 내보내는 async iterable도 입력할 수 있어요. Blob에는 filename을 지정하세요. 이름을 가진 File이라면 생략해도 돼요. 스트림과 async iterable에는 filename과 바이트 단위 size를 모두 넣어야 해요.
텍스트와 자막 다운로드하기
download(id, options)로 원하는 형식의 스크립트를 받으세요. 작업 완료를 기다린 뒤 문자열로 반환해요. JSON 형식도 객체로 파싱하지 않고 API의 JSON 원문을 반환해요.
const text = await t1.download(done.id); // text is the default
const withTimes = await t1.download(done.id, { timestamps: true });
const srt = await t1.download(done.id, { format: 'srt' });
const vtt = await t1.download(done.id, { format: 'vtt' });
const json = await t1.download(done.id, { format: 'json' });timestamps: true는 text 형식 전용이에요. 다른 형식과 함께 지정하면 invalid_input으로 Promise가 reject돼요. 작업이 실패하거나 취소돼도 download의 Promise가 reject돼요.
작업만 시작하고 나중에 조회하기
변환 완료를 기다리지 않으려면 transcriptions.create로 작업을 시작하세요. 파일을 입력했다면 업로드까지는 마친 뒤 반환해요.
const job = await t1.transcriptions.create('./long-interview.mp4');
const now = await t1.transcriptions.get(job.id);
const finished = await t1.transcriptions.get(job.id, { wait: true });get은 wait를 지정하지 않으면 현재 상태를 바로 반환해요. wait: true를 넣으면 completed, failed, canceled 중 하나로 끝날 때 Promise가 resolve돼요. 스크립트를 읽기 전에 finished.status를 확인하세요. get은 transcribe와 달리 작업 실패나 취소만으로 Promise를 reject하지 않아요.
작업 목록 조회, 삭제, 계정 확인
for await (const item of t1.transcriptions.list({ status: 'completed', limit: 50 })) {
console.log(item.id, item.created_at);
}
await t1.transcriptions.delete(job.id);
const account = await t1.account();
console.log(account.minutes.remaining);list는 순회할 때 필요한 페이지를 가져와요. status 또는 platform으로 범위를 좁힐 수 있어요. 플랫폼 값은 youtube, x, tiktok, instagram, facebook, bluesky, twitch, dailymotion, pinterest, linkedin, snapchat, upload예요. 페이지당 개수인 limit은 1~100이며 API 기본값은 20이에요.
응답 필드는 API의 snake_case를 그대로 사용해요. media_id의 내부 형식을 해석하지 말고 문자열 전체를 그대로 다루세요.
진행 중인 작업에 delete를 호출하면 취소해요. 이미 끝난 작업이라면 스크립트와 함께 삭제해요. account로는 요금제, 남은 분량, 사용 한도를 조회할 수 있어요.
생성자와 메서드 옵션
생성자 옵션은 apiKey, baseUrl, fetch, maxRetries예요. baseUrl을 생략하면 TRANSCRIPT1_API_URL 값을 사용하고, 이 환경 변수도 없으면 https://api.transcript1.com으로 연결해요. 별도의 fetch 구현이 필요하면 fetch로 전달하세요. maxRetries는 0~10 사이의 정수로 지정하며 기본값은 2예요.
transcribe와 transcriptions.create에서 공통으로 받는 옵션이에요.
| 옵션 | 용도 |
|---|---|
speakers | 화자 분리 사용 여부 |
language | 기본값은 auto예요. ISO 639-1 언어 코드로 직접 지정할 수도 있어요. |
source | 링크는 auto나 stt를 사용해요. YouTube, X, TikTok, Bluesky, Dailymotion, LinkedIn에서 사용할 자막 트랙이 있으면 captions도 가능해요. |
fresh | 같은 링크를 최근 24시간 안에 변환했어도 기존 스크립트를 재사용하지 않아요. |
filename | Buffer, 이름 없는 Blob, 스트림에 필요한 파일 이름이에요. 기존 파일 이름을 바꾸어 보낼 때도 쓸 수 있어요. |
size | 스트림과 async iterable에 필요한 파일 크기. 바이트 단위예요. |
idempotencyKey | 생략하면 호출마다 새 UUID를 만들어요. |
onProgress | 진행 상황을 받을 콜백 |
signal | 호출 취소에 사용할 AbortSignal |
transcriptions.get에는 wait, includeWords, onProgress, signal을 넘길 수 있어요. 단어별 타임스탬프는 includeWords: true로 요청하세요. 대기 중 상태 변화는 onProgress로 받아요.
download의 옵션은 format, timestamps, signal이에요. list에도 signal을 넣을 수 있어요. transcriptions.delete(id, options)나 account(options)를 취소하려면 options 인자로 { signal }을 전달하세요.
진행 상황 확인하기
onProgress 콜백으로 진행 상황을 받으세요. transcribe, transcriptions.create, 완료를 기다리는 transcriptions.get에서 사용할 수 있어요.
await t1.transcribe('./interview.m4a', {
onProgress(event) {
console.log(event);
},
});| 이벤트 종류 | 전달되는 데이터 |
|---|---|
upload | sent는 전송한 바이트 수, total은 전체 바이트 수예요. |
status | status에 현재 작업 상태가 들어가요. |
waiting_slot | retryAfter는 새 작업을 시작할 자리가 있는지 다시 확인하기까지의 대기 시간이에요. 초 단위예요. |
reconnecting | 추가 필드는 없어요. 완료를 기다리다 연결이 끊기면 장애 한 번당 한 번 발생해요. |
호출 중단과 작업 취소
호출을 중단하려면 AbortController에서 만든 AbortSignal을 전달하세요. AbortSignal.timeout으로 제한 시간을 정할 수도 있어요.
await t1.transcribe('https://youtu.be/dQw4w9WgXcQ', {
signal: AbortSignal.timeout(10 * 60_000),
});첫 요청을 보내기 전에 중단하면 작업 ID 없이 Promise가 aborted로 reject돼요. 업로드 중이라면 작업이 아직 awaiting_upload일 때 SDK가 삭제를 시도해요. 이후 작업 ID를 포함한 aborted 오류로 Promise가 reject돼요.
대기만 중단한 경우에는 서버의 변환 작업이 계속 진행돼요. 오류에 있는 transcriptionId를 사용해 transcriptions.get(id, { wait: true })로 다시 기다릴 수 있어요. 서버 작업도 취소하려면 transcriptions.delete(id)를 호출하세요.
작업 완료를 기다릴 때는 네트워크 오류와 HTTP 429, 500, 502, 503, 504 응답을 횟수 제한 없이 재시도해요. 재연결 간격은 2, 4, 8, 16초 순으로 늘어나고 이후에는 30초예요. 다른 요청에는 maxRetries를 적용해요. 새 작업을 생성할 때 동시 작업 한도가 차 있으면 자리가 날 때까지 기다리며 재시도해요. 전체 대기 시간을 제한하려면 signal을 지정하세요.
오류 처리하기
API 호출, 변환 작업, SDK에서 발생한 오류는 Transcript1Error로 잡아 코드를 확인하세요.
import { Transcript1Error } from '@transcript1/sdk';
try {
await t1.transcribe('./call.mp3');
} catch (error) {
if (error instanceof Transcript1Error) {
console.error(error.code, error.message, error.transcriptionId);
}
}| 필드 | 확인할 내용 |
|---|---|
message | 오류 원인을 설명하는 문구 |
code | API·작업 오류 코드, canceled, 또는 SDK 내부 오류 코드 |
status | HTTP 상태 코드. 작업 오류나 SDK 내부 오류에는 없어요. |
details | minutes_needed, action_url 같은 API 오류의 추가 정보. 기본값은 빈 객체예요. |
retryable | 재시도로 해결될 가능성이 있는지 알려 줘요. 기본값은 false예요. |
transcriptionId | 작업 ID를 아는 경우에 포함해요. |
transcription | 마지막으로 받은 작업 객체가 있으면 포함해요. |
SDK 내부 오류 코드는 missing_api_key, invalid_input, aborted, network_error, upload_token_refused예요. 서버의 오류 응답이 JSON이 아니면 http_<status>로 표시해요.
작업이 실패했는데 오류 객체가 없으면 transcription_failed를 사용해요. 완료된 작업을 조회한 뒤에도 스크립트가 없으면 transcribe의 Promise가 internal_error로 reject돼요. API 오류 코드는 오류 처리, 응답 필드는 API 레퍼런스에서 확인하세요.
실행 환경
Node 20.19 이상에서 사용할 수 있어요. Bun과 Deno도 node: 호환 기능으로 동작할 것으로 예상하지만, 자동화 테스트는 Node에서만 진행해요. SDK는 반드시 서버에서 사용하고, API 키를 브라우저에 전달하지 마세요.
최근 업데이트 2026년 10월 16일