n8n 텍스트 음성 변환(TTS): 텍스트를 오디오 파일로
n8n에서 HTTP Request 노드로 텍스트를 음성으로 변환하세요. 노드 하나가 텍스트를 제출하고, Wait 루프가 Job을 확인하고, 다른 노드 하나가 오디오를 바이너리 파일로 내려받습니다.

n8n에서 텍스트를 음성으로 변환하려면 HTTP Request 노드에서 텍스트 음성 변환(TTS) API로 텍스트를 보내고, Job이 끝날 때까지 기다린 뒤, 파일을 반환하도록 설정한 두 번째 HTTP Request 노드로 오디오를 내려받으세요. 이후 노드는 이 파일을 바이너리 데이터로 쓸 수 있습니다. Sume에서는 첫 번째 노드가 텍스트와 음성을 https://api.sume.com/v1/tts-1.0/generate로 POST하고, Wait 노드와 상태 확인으로 된 루프가 Job이 끝날 때까지 돌며, 결과의 audio_url이 가져올 파일입니다.
Sume 전용 n8n 노드는 없으며, 일반 HTTPS 호출로 직접 호출합니다. 노드 설정은 n8n의 HTTP Request 노드와 Wait 노드 문서를 따르고, Sume 필드는 Sume API 레퍼런스의 TTS 스키마와 Job과 결과 (영문) 문서를 따릅니다. Sume API 레퍼런스는 API 레퍼런스 문서의 바탕이 되는 OpenAPI 문서입니다. 모두 2026-09-28에 확인했습니다. 폴링 루프는 이 워크플로의 음성 인식(STT) 버전에서 노드별로 만든 것과 같습니다.
n8n에서 TTS 요청은 어떻게 설정하나요?
HTTP Request 노드 하나가 Job을 제출합니다. 음성 인식 워크플로와 마찬가지로 Sume API 키를 담은 generic Bearer auth 자격 증명과, 항목 자체의 id로 만든 Idempotency-Key 헤더를 설정하세요. 음성 합성에서 달라지는 것은 본문입니다. 들어오는 항목의 텍스트는 {{ $json.text }} 같은 표현식(expression)으로 매핑하세요.
- Using Fields Below를 쓰면 JSON이 자동으로 만들어집니다. JSON 본문을 직접 쓰는 경우 텍스트 안의 큰따옴표나 줄바꿈을 이스케이프해야 하며, 그렇지 않으면 본문이 올바른 JSON이 아니게 됩니다.
avatar_handle은 단순한 name/value 쌍에 들어가는 음성 선택 필드입니다. 다른 하나인voice.id(음성 UUID 또는voi_라이브러리 ID)는voice객체 안에 있으므로 Using JSON 본문으로 보내세요.
| 설정 | 값 | 이유 |
|---|---|---|
| Method, URL | POST, https://api.sume.com/v1/tts-1.0/generate | Sume의 TTS 1.0 경로. |
| Send Body | JSON, Using Fields Below | name/value 쌍을 JSON 본문으로 보냄. |
transcript | {{ $json.text }} | 1–20,000자. 공백과 문장 부호도 포함. |
avatar_handle | 음성이 ready인 아바타 | 음성을 선택. API는 음성 목록을 공개하지 않음. |
language | ja, ko 또는 다른 코드 | 영어가 아닌 텍스트에 필요. 생략하면 영어가 기본값. |
워크플로는 오디오를 어떻게 기다리나요?
제출 요청은 오디오가 생기기 전에 data.status_url을 담아 바로 응답합니다. 음성 인식과 같은 루프로 이 URL을 폴링하세요. 짧은 Wait 노드, 상태 URL에 대한 인증된 GET, 그리고 terminal이 true가 될 때까지 false 출력을 다시 Wait 노드로 연결하는 If 노드로 구성하며, n8n에서 루프를 만드는 방식 그대로입니다. 느린 Job은 실패한 Job이 아니므로 다시 제출하지 마세요.
폴링을 건너뛰려면 Wait 노드를 On Webhook Call로 설정하고, 그 노드의 $execution.resumeUrl을 Job의 webhook_url로 보내세요. 이 패턴과, 실행마다 달라지는 URL이 Idempotency-Key와 어떻게 맞물리는지는 n8n AI 영상 워크플로에서 다룹니다. Sume는 완료, 실패, 취소 같은 종료 이벤트에서만 콜백을 보냅니다.
오디오 파일은 n8n으로 어떻게 가져오나요?
terminal이 true가 되면 {{ $json.data.sume_status }}가 completed인지 확인하세요. 실패하거나 취소된 Job에는 결과가 없어서 result_url이 409 job_not_completed로 응답하며, HTTP Request 노드는 기본적으로 2xx 응답에만 성공을 반환합니다. 그다음 제출할 때처럼 인증해서 {{ $json.data.result_url }}을 GET하세요. 결과는 data.result 아래에 있으며, 현재 코드에서는 data.result.audio_url이 음성 파일로, media.sume.com에 있는 공개 아티팩트입니다. 두 번째 HTTP Request 노드가 이 파일을 내려받습니다.
- Method는
GET, URL은{{ $json.data.result.audio_url }}입니다. - Add Option → Response를 추가하고 Response Format을 File로 설정한 뒤, Put Output in Field에
data같은 필드 이름을 넣으세요. - 이후 노드는 그 필드에서 파일을 읽습니다. 예를 들어 다른 HTTP Request 노드가 n8n Binary File 본문 유형을 쓰고 Input Data Field Name에 그 필드 이름을 넣어 파일을 전달할 수 있습니다.
- 요청에서
output_format을 설정하지 않으면 파일은 44,100 Hz, 128 kbps MP3입니다.
n8n에서 쓸 수 있는 무료 TTS API가 있나요?
Sume의 TTS는 무료가 아닙니다. 텍스트 음성 변환 요금은 1,000자당 $0.0475이며 기본적으로 5.5% 에이전트 수수료가 더해지고, 항목마다 공백과 문장 부호를 포함한 대본 글자 수로 계산됩니다. 그래서 새 행마다 음성을 만드는 워크플로는 행마다 과금됩니다. 요청 하나는 최대 20,000자를 받으며, 음성이 1,200초를 넘으면 tts_duration_exceeded로 실패하고 크레딧은 확정되지 않습니다. 요율은 API 요금에 나와 있습니다.
n8n TTS 요청이 왜 거부되었나요?
음성과 관련된 거부는 두 가지이며, 둘 다 Job이 생기기 전인 제출 시점에 옵니다.
invalid_voice_id와 함께 오는400:voice.id가 음성 UUID도voi_라이브러리 ID도 아닙니다. ID를 그대로 복사하거나, 대신avatar_handle을 보내세요.409 tts_voice_language_mismatch(현재 코드): 라이브러리 음성에 기록된 언어가 요청의 언어와 다릅니다. 아직 Job도 요금도 생기지 않았습니다. 그 음성을 계속 쓰려면 같은 본문과Idempotency-Key에confirm_language_mismatch: true를 더해 다시 보내세요.
출처
관련 글
연동 카테고리의 다른 글
- PowerShell Invoke-RestMethod로 JSON POST 요청하기
해시테이블을 ConvertTo-Json -Depth로 바꾼 뒤 Bearer 헤더를 넣어 Invoke-RestMethod -Method Post -ContentType 'application/json'으로 보내세요.
- Python requests 재시도: 백오프·Retry-After·POST
Requests는 기본적으로 재시도하지 않습니다. urllib3 Retry(백오프, status_forcelist)를 Session에 마운트하고, POST는 Idempotency-Key가 있을 때만 재시도하세요.
- Rails 웹훅: 컨트롤러에서 HMAC 서명 검증하기
request.raw_post를 읽고 그 액션만 CSRF를 건너뛴 뒤, OpenSSL::HMAC.hexdigest를 각 sume-v1 항목과 secure_compare로 비교하고 head 204로 응답하세요.
- Rust HMAC-SHA256: axum에서 웹훅 서명 검증하기
Rust에서는 hmac·sha2 크레이트로 HMAC-SHA256을 계산합니다. axum에서는 Bytes로 받아 timestamp.body에 MAC을 적용하고 각 항목을 verify_slice로 확인하세요.
작성자 Sume