탐색으로 건너뛰기

비동기 텍스트 음성 변환

이 가이드에서는 전사 작업이 완료될 때 비동기 알림을 받기 위해 웹훅을 사용하는 방법을 안내합니다.

사용 가이드 · 텍스트 음성 변환 퀵스타트를 완료했다고 가정합니다.

개요

웹훅을 사용하면 텍스트 음성 변환 전사 작업이 완료될 때 자동 알림을 받을 수 있어, 상태 업데이트를 위해 API를 지속적으로 폴링할 필요가 없습니다. 특히 장시간 실행되는 전사 작업이나 대량의 오디오 파일을 처리할 때 유용합니다.

전사가 완료되면 ElevenLabs는 전사 텍스트, 언어 감지 및 메타데이터를 포함한 전사 결과를 지정한 웹훅 URL로 POST 요청으로 전송합니다.

웹훅 사용하기

이 가이드는 API 키와 SDK를 설정했다고 가정합니다. 아직 완료하지 않았다면 먼저 퀵스타트를 완료하세요.

1

웹훅 만들기 또는 수정하기

ElevenLabs 대시보드에서 개발자 > 웹훅으로 이동합니다. 웹훅 만들기를 클릭하거나 기존 웹훅을 수정합니다.

Transcription completed가 선택된 웹훅 만들기 대화 상자
웹훅을 만들거나 수정할 때 Transcription completed를 선택합니다

다음과 같이 웹훅을 구성합니다.

  • 이름: 웹훅을 설명하는 이름
  • 콜백 URL: 공개적으로 접근 가능한 HTTPS 엔드포인트
  • 웹훅 인증 방식: HMAC 또는 OAuth 중 하나입니다. 검증 메커니즘은 클라이언트에서 구현해야 합니다. ElevenLabs는 검증에 사용할 수 있는 헤더를 전송하지만 이를 강제하지는 않습니다.
  • 이벤트: Transcription completed를 선택합니다.
2

웹훅 매개변수를 활성화하여 API 호출하기

텍스트 음성 변환 API 호출 시 webhook 매개변수를 true로 설정하면 해당 요청에 대한 웹훅 알림이 활성화됩니다.

from dotenv import load_dotenv
from elevenlabs.client import ElevenLabs
load_dotenv()
elevenlabs = ElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
def transcribe_with_webhook(audio_file):
try:
result = elevenlabs.speech_to_text.convert(
file=audio_file,
model_id="scribe_v2",
webhook=True,
)
print(f"Transcription started: {result.request_id}")
return result
except Exception as e:
print(f"Error starting transcription: {e}")
raise e

웹훅 페이로드

전사가 완료되면 웹훅 엔드포인트는 전사 및 웹훅 데이터가 포함된 POST 요청을 받습니다.

{
type: 'speech_to_text_transcription',
data: {
request_id: 'some-request-id-123',
webhook_metadata: { ... }, // if provided in the convert request
transcription: {
"language_code": "en",
"language_probability": 0.98,
"text": "Hello world!",
"words": [
{
"text": "Hello",
"start": 0.0,
"end": 0.5,
"type": "word",
"speaker_id": "speaker_1"
},
{
"text": " ",
"start": 0.5,
"end": 0.5,
"type": "spacing",
"speaker_id": "speaker_1"
},
{
"text": "world!",
"start": 0.5,
"end": 1.2,
"type": "word",
"speaker_id": "speaker_1"
}
]
}
}
}

응답 구조에 관한 자세한 내용은 텍스트 음성 변환 API 레퍼런스를 참고하세요.

요청에 transcript_edit 지침이 포함된 경우, transcription 객체에는 편집된 텍스트가 담긴 edited_transcript 필드도 포함됩니다.

전사에 실패하면 엔드포인트는 대신 webhook_error 이벤트를 받습니다. 이 이벤트에는 data 객체가 없습니다. 최상위 수준의 request_id(요청이 수락되었을 때 반환된 동일한 ID), error_message, 요청의 webhook_metadata를 포함합니다.

웹훅 엔드포인트 구현하기

수신 알림을 처리하는 웹훅 엔드포인트 구현 예시는 다음과 같습니다.

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import "dotenv/config";
import express from "express";
const elevenlabs = new ElevenLabsClient();
const app = express();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
// The raw body is required: verification runs over the exact bytes sent.
app.post("/webhook/speech-to-text", express.raw({ type: "application/json" }), async (req, res) => {
const signature = req.headers["elevenlabs-signature"];
let event;
try {
event = await elevenlabs.webhooks.constructEvent(
req.body.toString(),
signature,
WEBHOOK_SECRET
);
} catch (error) {
return res.status(401).json({ error: "Invalid signature" });
}
if (event.type === "speech_to_text_transcription") {
const { request_id, transcription } = event.data;
console.log(`Transcription ${request_id} completed`);
console.log(`Language: ${transcription.language_code}`);
console.log(`Text: ${transcription.text}`);
processTranscription(request_id, transcription);
} else if (event.type === "webhook_error") {
console.error(`Transcription ${event.request_id} failed: ${event.error_message}`);
handleTranscriptionError(event.request_id, event.webhook_metadata, event.error_message);
}
res.status(200).json({ received: true });
});
async function processTranscription(requestId, transcription) {
console.log("Processing completed transcription...");
}
async function handleTranscriptionError(requestId, webhookMetadata, errorMessage) {
console.log("Handling transcription error...");
}
app.listen(3000, () => {
console.log("Webhook server listening on port 3000");
});

보안 고려 사항

서명 검증

요청이 ElevenLabs에서 온 것인지 확인하기 위해 항상 웹훅 서명을 검증하세요.

HTTPS 요구 사항

전사 데이터를 안전하게 전송하려면 웹훅 URL에 HTTPS를 사용해야 합니다.

속도 제한

악용을 방지하기 위해 웹훅 엔드포인트에 속도 제한을 구현하세요.

import rateLimit from "express-rate-limit";
const webhookLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many webhook requests from this IP",
});
app.use("/webhook", webhookLimiter);

실패 응답

웹훅을 확인했음을 알리려면 2xx 상태 코드를 반환하세요.

기본적으로 텍스트 음성 변환 전사 웹훅은 한 번만 전송됩니다. 2xx가 아닌 모든 응답은 전송 실패로 처리되며, 반복적으로 실패하면 웹훅이 자동 비활성화됩니다.

웹훅에 재시도를 켜면 실패한 전송(5xx, 408, 429 또는 연결 오류)은 이전 시도 후 약 30초, 2분, 8분, 30분, 30분 간격으로 최대 5회 더 재시도됩니다. 그 외 4xx 응답은 재시도되지 않습니다. 동일 이벤트에 대한 모든 시도에는 동일한 ElevenLabs-Webhook-Delivery-Id 헤더가 포함되므로, 핸들러에서 중복을 무시할 수 있습니다.

재시도가 켜진 경우 enable_logging을 false로 설정한 요청(보존 기간 0 모드)은 이전 시도 후 5초와 30초에 최대 2회의 빠른 재시도를 수행합니다. 전사본은 저장되지 않습니다.

전송이 계속 실패하면 요청이 수락되었을 때 반환된 transcription_id를 사용하여 전사본 가져오기로 결과를 가져오세요. enable_logging을 false로 설정한 요청의 전사본은 저장되지 않습니다.

웹훅 테스트하기

로컬 개발

로컬에서 테스트하려면 ngrok과 같은 도구를 사용해 로컬 서버를 외부에 노출하세요.

ngrok http 3000

개발 중에는 제공된 HTTPS URL을 웹훅 엔드포인트로 사용하세요.

웹훅 테스트

전사 요청을 보내고 엔드포인트를 모니터링하여 웹훅 구현을 테스트할 수 있습니다.

async function testWebhook() {
const audioFile = new File([audioBuffer], "test.mp3", { type: "audio/mp3" });
const result = await elevenlabs.speechToText.convert({
file: audioFile,
modelId: "scribe_v2",
webhook: true,
});
console.log("Test transcription started:", result.requestId);
}

다음 단계