ivs-live-translate SDK 문서#
버전 0.1.0
여러분의 Amazon IVS 방송 페이지에 실시간 번역 자막을 붙이는 SDK입니다. 스트리머가 말하면 시청자 화면에 시청자의 언어로 자막이 나타납니다. 스크립트 하나를 올리고 몇 줄만 쓰면 됩니다.
한눈에 보기#
SDK를 붙이면 시청자는 다음을 할 수 있습니다.
| 시청자가 보는 것 | 설명 |
|---|---|
| 자기 언어로 된 자막 | 시청자 브라우저의 언어 설정을 읽어 그 언어로 번역합니다. 따로 고를 필요가 없습니다. |
| 번역 언어 선택 | 영상 오른쪽 위 목록에서 17개 언어 중 고를 수 있습니다. |
| 번역 켜기·끄기 | 영상 오른쪽 위 버튼으로 언제든 끕니다. 영상은 계속 재생됩니다. |
| 목소리 변조 (선택) | 여러분이 켜 두면 스트리머 목소리의 높낮이를 바꿔 들려줍니다. 자막 품질에는 영향이 없습니다. |
여러분은 다음을 할 수 있습니다.
- 자막의 모양·위치·사라지는 시간을 바꾸거나, 자막을 직접 그리기
- 코드로 번역 언어를 정하고, 번역을 시작·중지하기
- 대시보드에서 하루 사용자 수와 사용량 보기
준비물#
| 준비물 | 어디서 받나요 |
|---|---|
| IVS 저지연 방송을 IVS Player로 재생하는 웹 페이지 | 여러분의 서비스 |
| 계정(아이디·비밀번호)과 SDK 키 | 서비스 담당자가 발급합니다 |
| SDK 파일 | 백오피스에서 내려받습니다 |
시작하기#
1. 계정과 SDK 키 받기#
서비스 담당자에게 다음 두 가지를 알려 주세요.
- SDK를 붙일 사이트 주소 (예:
https://www.example.com). 테스트용 주소가 따로 있으면 함께. - IVS 채널이 있는 AWS 계정 번호 (12자리). 재생 주소의
…ap-northeast-2.123456789012.channel.…부분입니다. 등록한 계정의 방송만 번역되므로, 누가 SDK 키를 가져가 다른 방송에 써도 여러분 비용으로 번역되지 않습니다.
담당자가 다음을 전달합니다.
- 백오피스 로그인 아이디와 비밀번호
- SDK 키 (
ilt_로 시작하는 문자열)
SDK 키는 알려 준 사이트 주소에서만 동작합니다. 키 전체는 발급할 때 한 번만 볼 수 있으니 받은 즉시 안전한 곳에 보관하세요.
2. SDK 내려받기#
- 백오피스
https://subsync.de5.net/admin에 받은 아이디로 로그인합니다. - 위쪽 메뉴에서 SDK를 누르고 전체 묶음(zip)을 내려받습니다.
묶음에는 다음 파일이 들어 있습니다.
| 파일 | 용도 |
|---|---|
ivs-live-translate.min.js | <script> 태그로 불러오는 파일. 전역 IVSLiveTranslate가 생깁니다. |
ivs-live-translate.esm.js | import로 불러오는 ES 모듈 (번들러·모듈 스크립트용) |
types/ | TypeScript 타입 선언. types/index.d.ts가 시작점입니다. |
README.md | 이 문서 |
3. 페이지에 붙이기#
내려받은 파일을 여러분의 사이트에 올리고(예: /vendor/ivs-live-translate/), 방송 페이지에서 IVS Player를 만든 뒤 아래처럼 연결합니다. channel은 여러분의 서버가 내려 주는 방송 정보입니다.
<script src="/vendor/ivs-live-translate/ivs-live-translate.min.js"></script>
<script>
const player = IVSPlayer.create();
player.attachHTMLVideoElement(document.querySelector('video'));
player.load(channel.playbackUrl);
player.play();
const translator = new IVSLiveTranslate.LiveTranslator({
video: player, // IVS Player 또는 <video> 요소
proxyUrl: 'https://subsync.de5.net', // 번역 서버 주소 (그대로 쓰세요)
apiKey: 'ilt_…', // 받은 SDK 키
playbackUrl: channel.playbackUrl, // 이 방송의 IVS 재생 주소
enabled: channel.translator_enabled, // 스트리머가 번역을 켰는지
});
translator.start();
</script>
번들러나 모듈 스크립트를 쓴다면:
import { LiveTranslator } from '/vendor/ivs-live-translate/ivs-live-translate.esm.js';
const translator = new LiveTranslator({ video: player, proxyUrl: 'https://subsync.de5.net', apiKey: 'ilt_…', playbackUrl, enabled });
translator.start();
동작은 이렇습니다.
- 스트리머가 번역을 켠 방송(
enabled: true)이면start()하자마자 자막이 나옵니다. 시청자는 따로 누를 필요가 없고, 시청자 브라우저의 언어로 번역됩니다. - 번역을 켜지 않은 방송(
enabled: false)이면start()를 불러도 아무것도 하지 않고 자막 화면도 보이지 않습니다. 방송 중에 스트리머가 켜거나 끄면setEnabled()로 알려 주세요. - 스트리머가 방송을 끝내면 번역도 자동으로 멈추고 자막이 사라집니다.
- 번역 서버가 방송을 직접 받아 한 번만 번역하고 시청자는 자막만 받으므로, 시청자 브라우저는 소리를 보내지 않고 시청자 수가 많아도 가볍습니다.
영상 요소를 감싸는 부모 요소가 있어야 합니다. 자막과 버튼은 영상의 부모 요소 안에, 영상 위에 겹쳐 그려집니다.
4. 동작 확인#
- 번역을 켠 방송을 열면 영상 오른쪽 위에 언어 목록과 "번역 끄기" 버튼이 나타납니다.
- 스트리머가 말하면 영상 아래쪽에 자막이 나옵니다. 말이 시작되고 몇 초 뒤에 따라옵니다.
- 백오피스 대시보드의 "사용 횟수"가 1 늘어납니다.
자막이 나오지 않으면 문제 해결을 보세요.
기능별 사용법#
번역을 켠 방송만 번역하기#
번역을 켤지는 스트리머가 정합니다. 여러분의 서버가 방송마다 가진 값(예: translator_enabled)을 enabled 옵션으로 넘기세요. 방송 중에 값이 바뀌면 setEnabled()를 부르면 됩니다.
// 예: 여러분의 실시간 알림(WebSocket 등)으로 설정이 바뀐 것을 받았을 때
socket.on('translator_enabled', (value) => translator.setEnabled(value));
방송 상태는 broadcast 이벤트로 받습니다.
translator.on('broadcast', ({ status }) => {
// waiting: 아직 방송 소리가 없음 · live: 방송 중 · ended: 방송 종료 (번역도 자동으로 멈춤)
});
방송이 끝난 뒤 같은 페이지에서 다음 방송을 이어 보여 준다면 start()를 다시 부르세요.
번역 언어#
아무것도 정하지 않으면 시청자 브라우저의 언어로 번역합니다. 브라우저 언어가 지원 목록에 없으면 영어로 번역합니다.
// 언어를 고정하고 싶을 때
new LiveTranslator({ video: player, proxyUrl, apiKey, targetLanguage: 'ja' });
// 지원 목록에 없는 브라우저 언어일 때 쓸 언어 바꾸기 (기본 'en')
new LiveTranslator({ video: player, proxyUrl, apiKey, fallbackLanguage: 'ko' });
// 실행 중에 바꾸기. 다음 문장부터 새 언어로 번역됩니다.
translator.setTargetLanguage('zh-CN');
시청자는 영상 오른쪽 위 목록에서 직접 바꿀 수 있습니다. 목록에 나오는 언어는 다음 17개입니다.
ko 한국어 · en English · ja 日本語 · zh-CN 简体中文 · zh-TW 繁體中文 · es Español · fr Français · de Deutsch · pt Português · it Italiano · ru Русский · vi Tiếng Việt · th ไทย · id Bahasa Indonesia · tr Türkçe · ar العربية · hi हिन्दी
목록에 없는 언어 코드도 targetLanguage나 setTargetLanguage()로는 쓸 수 있습니다(예: nl, pl). 스트리머가 이미 시청자의 언어로 말하고 있으면 번역하지 않고 받아 적은 원문을 그대로 자막으로 보여 줍니다.
번역 켜기·끄기#
await translator.start(); // 시작
await translator.stop(); // 멈춤. 영상은 계속 재생됩니다.
await translator.toggle(); // 켜져 있으면 끄고, 꺼져 있으면 켭니다.
translator.getState(); // 'idle'(멈춤) | 'starting'(연결 중) | 'running'(번역 중)
멈춘 동안에는 음성 인식도 번역도 하지 않으므로 사용량이 늘지 않습니다. 시청자는 영상 오른쪽 위 버튼으로 직접 끄고 켤 수 있습니다.
여러분의 버튼 모양을 상태에 맞추려면 statechange 이벤트를 쓰세요.
translator.on('statechange', ({ state }) => {
myButton.textContent = state === 'idle' ? '자막 켜기' : '자막 끄기';
});
자막 모양 바꾸기#
overlay 옵션으로 기본 자막을 조정합니다.
new LiveTranslator({
video: player, proxyUrl, apiKey,
overlay: {
showOriginal: true, // 번역문 위에 원문도 작게 표시
maxLines: 3, // 동시에 보여 줄 줄 수 (기본 2)
controls: false, // 언어 목록과 켜기/끄기 버튼 숨기기 (기본 true)
labels: { start: 'Subtitles on', stop: 'Subtitles off', language: 'Language' },
},
});
글자 크기·색·위치는 CSS로 바꿉니다. 클래스 이름은 .ivslt-root(전체), .ivslt-subs(자막 영역), .ivslt-line(자막 한 줄), .ivslt-orig(원문), .ivslt-controls(버튼 영역)입니다.
.ivslt-line { font-size: 28px; background: rgba(0, 0, 0, .85); }
.ivslt-subs { bottom: 14%; } /* 플레이어 조작 막대와 겹치면 위로 올리기 */
자막을 직접 그리기#
기본 자막을 끄고 이벤트로 받아 여러분의 화면에 그릴 수 있습니다.
const translator = new LiveTranslator({ video: player, proxyUrl, apiKey, overlay: false });
// 말하는 도중의 임시 자막 (계속 갱신됩니다)
translator.on('partial', ({ translation }) => { liveLine.textContent = translation; });
// 문장이 끝나 확정된 자막
translator.on('translation', ({ translation, original }) => {
liveLine.textContent = '';
addSubtitleLine(translation, original);
});
languageSelect.onchange = (e) => translator.setTargetLanguage(e.target.value);
toggleButton.onclick = () => translator.toggle();
자막이 사라지는 시간#
마지막 자막이 나온 뒤 새 자막 없이 이 시간이 지나면 화면의 자막을 지웁니다. 기본은 6초입니다.
new LiveTranslator({ video: player, proxyUrl, apiKey, subtitleDurationMs: 3000 });
translator.setSubtitleDuration(5000); // 실행 중 변경
translator.setSubtitleDuration(0); // 0이면 다음 자막이 나올 때까지 유지
말이 이어지는 동안에는 새 자막이 계속 나오므로 오래된 줄부터 밀려납니다. 이 설정은 말이 멈춘 뒤 마지막 자막이 남아 있는 시간을 정합니다.
자막 속도와 번역 품질#
SDK는 자막을 빨리 보여 주려고 두 가지를 합니다. 둘 다 기본으로 켜져 있습니다.
| 옵션 | 기본 | 하는 일 | 끄거나 늘리면 |
|---|---|---|---|
translatePartials | true | 문장이 끝나기 전에도 말하는 도중의 내용을 번역해 임시 자막으로 보여 줍니다. | false: 문장이 끝난 뒤에만 자막이 나옵니다. 번역 요청 수가 줄어듭니다. |
chunkMs | 2500 | 스트리머가 쉬지 않고 길게 말하면, 이 시간(ms)마다 쉼표나 단어 경계에서 끊어 먼저 확정합니다. | 값을 늘리면(예: 4000) 번역이 더 자연스럽고 자막은 늦어집니다. 0이면 문장이 끝날 때까지 기다립니다. |
끊어서 번역한 자막은 문장 전체를 한 번에 번역할 때보다 어색할 수 있습니다. 특히 영어와 한국어처럼 어순이 크게 다른 언어 사이에서 그렇습니다. 빠른 자막이 중요하면 기본값을, 매끄러운 번역이 중요하면 chunkMs를 늘려 쓰세요.
스트리머의 언어 지정#
기본은 자동 감지입니다. 스트리머가 쓰는 언어를 알고 있다면 지정하는 편이 더 빠르고 정확합니다.
new LiveTranslator({ video: player, proxyUrl, apiKey, sourceLanguage: 'en-US' });
값은 en-US, ko-KR, ja-JP처럼 언어와 지역을 함께 쓰는 코드입니다. 지원하는 언어는 서비스 설정에 따라 다르니 담당자에게 확인하세요.
목소리 변조#
시청자가 듣는 스트리머 목소리의 높낮이를 바꿉니다. 자막을 만드는 데는 변조하지 않은 원래 목소리를 쓰므로 자막 품질은 그대로입니다.
const translator = new LiveTranslator({
video: player, proxyUrl, apiKey,
voiceChanger: { enabled: true, pitch: 3 }, // enabled가 true일 때만 동작합니다
});
await translator.setVoiceChanger({ pitch: -2 }); // 실행 중 높낮이 변경
await translator.setVoiceChanger({ enabled: false }); // 끄기
translator.getVoiceChanger(); // { enabled: false, pitch: -2 }
- 켰을 때만 동작합니다.
voiceChanger를 쓰지 않거나 한 번도 켜지 않으면 SDK는 영상의 소리를 전혀 건드리지 않습니다. pitch는 반음 단위입니다. 양수면 높게, 음수면 낮게, 범위는 -12~12(한 옥타브)이고 기본은 3입니다.- 권장 범위는 +2~+4입니다. 이 범위에서는 목소리가 분명히 달라지면서 말이 또렷하게 남습니다. 낮추는 쪽은 같은 폭에서도 알아듣기가 더 어려워지고, 폭이 클수록 부자연스러워집니다.
- 번역을
stop()해도 변조는 유지됩니다.destroy()하면 원래 목소리로 돌아갑니다. - 처음 켤 때는
start()처럼 시청자의 클릭 안에서 호출하세요.
알아 둘 점:
- 높낮이와 함께 음색도 같이 바뀝니다(크게 올리면 가늘게, 크게 내리면 굵게 들립니다).
- 소리가 영상보다 약 0.03초 늦어집니다. 입 모양과 어긋나 보일 정도는 아닙니다.
- 변조를 켠 상태에서 영상을 음소거하면 자막도 나오지 않습니다.
마이크처럼 영상이 아닌 소리에 같은 변조를 걸려면 createPitchShifter()를 씁니다.
import { createPitchShifter } from '/vendor/ivs-live-translate/ivs-live-translate.esm.js';
const ctx = new AudioContext();
const shifter = await createPitchShifter(ctx, 3);
ctx.createMediaStreamSource(micStream).connect(shifter);
shifter.connect(ctx.destination);
shifter.parameters.get('semitones').value = -2; // 높낮이 변경
로그인한 사용자 기준으로 사용자 수 세기#
대시보드의 "고유 사용자"는 기본적으로 브라우저 단위로 셉니다. 같은 사람이 휴대폰과 PC로 보면 두 명이 됩니다. 여러분의 서비스에 로그인이 있다면 사용자 ID를 넘겨 사람 단위로 셀 수 있습니다.
new LiveTranslator({ video: player, proxyUrl, apiKey, userId: currentUser.id });
넘긴 ID는 브라우저 안에서 알아볼 수 없는 값(해시)으로 바뀐 뒤 전송됩니다. 원래 ID는 여러분의 사이트 밖으로 나가지 않습니다.
사용자 식별 자체를 원하지 않으면 usageTracking: false를 주세요. 이때 고유 사용자 수는 대략적인 값이 됩니다.
플레이어를 없앨 때#
시청자가 방송을 나가거나 플레이어를 없앨 때 함께 정리하세요. 자막과 버튼이 지워지고 연결이 끊깁니다.
await translator.destroy();
player.delete();
destroy()한 뒤에는 다시 쓸 수 없습니다. 다시 필요하면 새로 만드세요.
API 레퍼런스#
new LiveTranslator(options)#
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
video | IVSPlayer | HTMLMediaElement | 필수 | 방송을 재생하는 IVS Player 또는 <video> 요소 |
playbackUrl | string | 없음 | 방송의 IVS 재생 주소. 주면 번역 서버가 이 방송을 직접 받아 번역합니다(권장). 시작하기 참고 |
enabled | boolean | true | 스트리머가 번역을 켰는지. false면 start()가 아무것도 하지 않습니다 |
proxyUrl | string | 필수 | 번역 서버 주소. https://subsync.de5.net |
apiKey | string | 필수 | 발급받은 SDK 키 |
targetLanguage | string | 브라우저 언어 | 번역할 언어. 예: "ko", "ja", "zh-CN" |
fallbackLanguage | string | "en" | 브라우저 언어가 지원 목록에 없을 때 쓸 언어 |
sourceLanguage | string | "auto" | 스트리머가 말하는 언어. 예: "en-US" |
subtitleDurationMs | number | 6000 | 자막이 사라지는 시간(ms). 0이면 유지 |
audioStream | MediaStream | 없음 | 영상 대신 이 소리를 받아 적습니다 (예: getUserMedia로 연 마이크). 주면 영상의 소리는 쓰지 않고, 영상 요소는 자막 자리로만 씁니다. 스트림은 직접 관리합니다(멈춰도 끄지 않음) |
voiceChanger | { enabled: boolean, pitch?: number } | 없음 | 목소리 변조. enabled: true일 때만 동작 |
overlay | boolean | object | true | 기본 자막 화면. false면 끄고 이벤트만 받습니다. 객체는 아래 표 참고 |
translatePartials | boolean | true | 말하는 도중에도 임시 자막을 보여 줌 |
chunkMs | number | 2500 | 긴 말을 이 시간마다 끊어 먼저 확정. 0이면 끊지 않음 |
partialIntervalMs | number | 700 | 임시 자막을 갱신하는 최소 간격(ms) |
contextSize | number | 2 | 번역할 때 문맥으로 함께 참고하는 직전 문장 수 |
userId | string | 없음 | 여러분 서비스의 사용자 ID. 고유 사용자를 사람 단위로 셉니다 |
usageTracking | boolean | true | false면 사용자 식별 값을 만들거나 보내지 않음 |
getAuthToken | () => string | Promise<string> | 없음 | 서비스 담당자가 추가 인증을 안내한 경우에만 씁니다 |
overlay에 넘기는 객체:
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
container | HTMLElement | 영상의 부모 요소 | 자막을 붙일 요소 |
controls | boolean | true | 언어 목록과 켜기/끄기 버튼 표시 |
showOriginal | boolean | false | 번역문 위에 원문도 작게 표시 |
maxLines | number | 2 | 동시에 보여 줄 최대 줄 수 |
languages | { code, nativeName, englishName }[] | 17개 언어 | 언어 목록에 보여 줄 언어 |
labels | { start?, stop?, language? } | 한국어 문구 | 버튼 문구와 언어 목록의 접근성 이름 |
잘못된 옵션(video 누락, 올바르지 않은 언어 코드 등)은 TypeError를 던집니다.
메서드#
| 메서드 | 설명 |
|---|---|
start(): Promise<void> | 번역을 시작합니다. 준비되면 완료됩니다. 실패하면 이유와 함께 실패하고 error 이벤트가 발생합니다. 이미 실행 중이면 아무 일도 하지 않습니다. |
stop(): Promise<void> | 번역을 멈추고 화면의 자막을 지웁니다. 영상 재생에는 영향이 없습니다. start()로 다시 시작할 수 있습니다. |
toggle(): Promise<void> | 멈춰 있으면 시작하고, 그렇지 않으면 멈춥니다. |
destroy(): Promise<void> | 멈추고 자막 화면과 이벤트 연결을 모두 정리합니다. 이후에는 다시 쓸 수 없습니다. |
getState() | "idle" | "starting" | "running" |
isRunning | 번역 중이면 true (속성) |
setTargetLanguage(code) | 번역 언어를 바꿉니다. 형식이 틀리면 TypeError |
getTargetLanguage() | 현재 번역 언어 |
setSubtitleDuration(ms) | 자막이 사라지는 시간을 바꿉니다. 음수나 숫자가 아니면 TypeError |
getSubtitleDuration() | 현재 값(ms) |
setVoiceChanger({ enabled?, pitch? }): Promise<void> | 목소리 변조를 켜거나 끄고 높낮이를 바꿉니다. 바꿀 값만 넘깁니다. pitch가 -12~12를 벗어나면 실패합니다. |
getVoiceChanger() | 현재 설정 { enabled, pitch } |
setEnabled(enabled): Promise<void> | 스트리머의 번역 설정이 바뀌었을 때 호출합니다. true면 시작하고, false면 멈추고 자막 화면을 숨깁니다. |
isEnabled() | 지금 enabled 값 |
on(event, listener) | 이벤트를 받습니다. 돌려받은 함수를 호출하면 해제됩니다. |
off(event, listener) | 이벤트 받기를 해제합니다. |
이벤트#
| 이벤트 | 받는 값 | 언제 |
|---|---|---|
translation | TranslationResult | 문장(또는 끊어 낸 구) 하나의 번역이 확정됐을 때. 항상 말한 순서대로 옵니다. |
partial | { id, original, translation, targetLanguage } | 말하는 도중의 임시 자막이 갱신될 때. 같은 id의 translation이 오면 그것으로 바꿉니다. |
transcript | { id, text, isFinal, language? } | 받아 적은 원문이 올 때마다 (도중 결과 포함) |
statechange | { state, previous } | 상태가 바뀔 때 |
languagechange | { targetLanguage, previous } | 번역 언어가 바뀔 때 (시청자가 목록에서 고른 경우 포함) |
broadcast | { status, reason? } | 방송 상태: waiting(소리 없음) · live · ended(방송 종료, 번역도 멈춤) |
error | Error | 시작 실패, 번역 실패, 연결 끊김. message에 이유가 들어 있습니다. |
문장 하나의 번역이 실패하면 그 문장만 건너뛰고 계속합니다. 연결이 끊기면 자동으로 다시 연결을 시도하고, 끝내 실패하면 error 이벤트 뒤에 스스로 멈춥니다.
interface TranslationResult {
id: string; // 문장 ID. 긴 말을 끊어 확정하면 둘째 조각부터 "id#1", "id#2"…
seq: number; // 0부터 늘어나는 순번
original: string; // 받아 적은 원문
translation: string; // 번역문
sourceLanguage?: string; // 감지된 원문 언어 (예: "en-US")
targetLanguage: string;
skipped: boolean; // 원문과 번역 언어가 같아 번역하지 않았으면 true
timing: { // 걸린 시간(ms). 자막이 느릴 때 어디가 느린지 볼 수 있습니다
recognitionMs: number; // 말이 인식된 뒤 확정될 때까지
firstTextMs: number; // 확정된 뒤 번역문 첫 글자까지
translationMs: number; // 확정된 뒤 번역 완료까지
};
}
언어 도구와 상수#
| 이름 | 설명 |
|---|---|
detectBrowserLanguage(fallback = "en") | 시청자 브라우저의 언어 설정에서 번역 언어를 고릅니다. 선호 순서대로 살펴 처음으로 지원 목록과 맞는 언어를 돌려줍니다. |
SUPPORTED_LANGUAGES | 언어 목록에 나오는 17개 언어. 각 항목은 { code, nativeName, englishName } |
getLanguageName(code) | 언어 코드의 표시 이름 (예: "ja" → "日本語") |
isValidLanguageTag(code) | 언어 코드 형식이 맞는지 |
DEFAULT_VOICE_PITCH | 목소리 변조의 기본 높낮이 (3) |
VOICE_PITCH_MIN / VOICE_PITCH_MAX | 높낮이 범위 (-12 / 12) |
createPitchShifter(ctx, semitones?) | 영상이 아닌 소리에 쓰는 변조 노드. 목소리 변조 참고 |
브라우저 언어가 어떻게 번역 언어가 되는지:
| 브라우저 언어 | 번역 언어 |
|---|---|
ko-KR | ko |
en-GB | en |
zh-TW, zh-HK | zh-TW |
zh, zh-CN, zh-SG | zh-CN |
| 스웨덴어 다음으로 일본어를 선호 | ja (스웨덴어는 목록에 없어 다음 선호 언어를 씁니다) |
사용량 확인하기#
백오피스 https://subsync.de5.net/admin에 로그인하면 대시보드에서 여러분 회사의 사용량을 볼 수 있습니다. 다른 회사의 데이터는 보이지 않습니다. 오늘 값과 최근 7·30·90일의 일별 추이, 번역 언어 비율이 나옵니다.
| 항목 | 뜻 |
|---|---|
| 고유 사용자 | SDK를 쓴 시청자를 중복 없이 센 수. 기간의 값은 일별 값을 더한 것이 아니라 기간 전체에서 중복을 뺀 값입니다. |
| 사용 횟수 | 번역을 시작한 횟수 (start() 한 번이 1회). 연결이 끊겨 다시 붙은 것은 따로 세지 않습니다. |
| 음성 인식 | 음성 인식에 쓰인 방송 소리의 길이 |
| 번역 요청 | 번역한 횟수. 말하는 도중의 임시 자막 번역도 포함합니다. 글자 수와 토큰 수도 함께 나옵니다. |
고유 사용자는 기본적으로 브라우저 단위로 셉니다. 같은 사람이 다른 브라우저나 기기를 쓰면 따로 세고, 브라우저 저장소를 지우면 새 사용자로 셉니다. 사람 단위로 세려면 userId를 넘기세요.
사용량을 줄이려면 translatePartials: false로 임시 자막을 끄는 것이 가장 효과가 큽니다. 번역 요청이 문장당 한 번으로 줄어듭니다.
SDK 키 관리#
- SDK 키는 비밀번호가 아닙니다. 웹 페이지에 들어가는 값이라 페이지 소스를 보면 누구나 볼 수 있습니다. 그래서 키는 등록된 사이트 주소(허용 출처)에서만 동작하게 되어 있습니다.
- 사이트 주소가 바뀌거나 늘어나면 담당자에게 알려 주세요. 등록되지 않은 주소에서는 "이 SDK 키는 이 사이트에서 쓸 수 없습니다" 오류가 납니다. 주소는
https://www.example.com처럼 프로토콜과 도메인(포트가 있으면 포트까지)이 정확히 맞아야 합니다.www가 있는 주소와 없는 주소는 서로 다른 주소입니다. - 운영용과 테스트용 키를 따로 받을 수 있습니다.
- 키를 잃어버렸거나 다른 곳에서 쓰이는 것 같다면 담당자에게 폐기와 재발급을 요청하세요. 폐기는 즉시 적용됩니다.
- 사용 중인 키의 앞부분과 등록된 사이트 주소는 백오피스 연동 정보에서 볼 수 있습니다. 로그인 비밀번호도 그 화면에서 바꿉니다.
시청자 데이터와 개인정보#
SDK가 시청자의 브라우저에서 무엇을 내보내는지입니다. 여러분의 개인정보 처리방침이나 시청자 안내에 반영해야 하는지는 직접 판단하세요.
| 무엇을 | 왜 | 저장되나요 |
|---|---|---|
| 재생 중인 방송의 소리 | 스트리머의 말을 받아 적기 위해 | 번역 서버는 저장하지 않습니다. 음성 인식과 번역을 위해 외부 엔진으로 전달됩니다. 어떤 엔진을 쓰는지는 담당자에게 확인하세요. |
| 익명 식별 값 | 고유 사용자 수를 세기 위해 | 알아볼 수 없게 바꾼 값(해시)만 저장됩니다 |
| 번역 언어, 사용 시간 | 사용량 집계 | 합계만 저장됩니다. 자막 내용은 저장하지 않습니다. |
- 시청자의 마이크나 카메라는 쓰지 않습니다.
playbackUrl을 쓰면(권장) 시청자 브라우저는 소리를 전혀 보내지 않고, 번역 서버가 방송을 직접 받습니다.playbackUrl없이 쓰면 재생 중인 방송의 소리를 보냅니다. (여러분이audioStream옵션으로 마이크를 직접 넘긴 경우에만 그 소리를 보냅니다.) - 익명 식별 값은 브라우저 저장소(
localStorage의ivslt-client-id)에 둡니다.userId를 넘기면 그 값을 알아볼 수 없게 바꿔서 대신 씁니다.usageTracking: false면 둘 다 쓰지 않습니다. - 번역을 멈추면(
stop()) 소리 전송도 멈춥니다.
브라우저 지원과 제약#
| 환경 | 지원 | 비고 |
|---|---|---|
| Chrome / Edge (PC, Android) | ✅ | |
| Firefox | ✅ | |
| Safari (macOS) | ⚠️ | 동작할 것으로 예상하지만 실제 방송으로 확인이 필요합니다 |
| Safari (iPhone / iPad) | ❌ | 이 환경에서는 브라우저가 방송 소리를 꺼내 쓰는 것을 허용하지 않습니다 |
위 표는 각 브라우저가 필요한 기능을 지원하는지를 기준으로 한 것이며, 자동 테스트는 Chrome 계열에서만 수행했습니다. 지원하지 않는 환경에서는 자막 버튼을 숨기는 것을 권합니다.
- IVS 저지연 방송용입니다. IVS 실시간(WebRTC) 방송은 지원하지 않습니다.
- 자막은 말보다 1~3초 늦습니다. 받아 적고 번역하는 데 걸리는 시간입니다.
- 고유명사, 게임 용어, 빠른 말, 배경 음악이 큰 방송에서는 받아 적기가 틀릴 수 있고, 그러면 번역도 틀립니다.
- HTTPS 페이지에서 쓰세요. 브라우저의 소리 관련 기능은 HTTPS(또는
localhost)에서만 동작합니다. - 페이지에 콘텐츠 보안 정책(CSP)을 쓰고 있다면
connect-src에 번역 서버 주소(https://subsync.de5.net와 그wss://주소)를,script-src에blob:을 허용해야 합니다.
문제 해결#
start()가 실패하거나 error 이벤트가 오면 message에 이유가 들어 있습니다. 개발 중에는 이렇게 확인하세요.
translator.on('error', (err) => console.error('자막 오류:', err.message));
translator.start().catch(() => {});
| 증상 또는 메시지 | 확인할 것 |
|---|---|
| "SDK 키가 필요합니다" | apiKey 옵션을 넣었는지 확인하세요. |
| "유효하지 않은 SDK 키입니다" | 키를 끝까지 정확히 복사했는지, 폐기된 키가 아닌지 확인하세요. |
| "이 SDK 키는 이 사이트에서 쓸 수 없습니다" | 지금 페이지의 주소가 등록되어 있지 않습니다. 메시지에 나온 주소를 담당자에게 알려 등록을 요청하세요. |
| "사용이 중지된 고객사의 SDK 키입니다" | 담당자에게 문의하세요. |
| "이 SDK 키로는 이 방송을 번역할 수 없습니다" | playbackUrl이 등록한 AWS 계정의 IVS 방송이 아닙니다. 재생 주소의 12자리 계정 번호를 담당자에게 알려 등록을 요청하세요. |
| "방송 모드에 쓸 AWS 계정이 등록되어 있지 않습니다" | IVS 채널의 AWS 계정 번호를 담당자에게 알려 등록을 요청하세요. |
| "허용되지 않은 방송 주소입니다" | playbackUrl에 IVS 재생 주소(https://….live-video.net/….m3u8)를 넣었는지 확인하세요. |
start()를 했는데 아무것도 안 나옴 (오류 없음) | enabled가 false인지 확인하세요. 스트리머가 번역을 켜지 않은 방송이면 아무것도 하지 않습니다. |
broadcast 이벤트가 waiting에서 바뀌지 않음 | 방송이 아직 시작되지 않았거나 재생 주소가 틀렸습니다. 영상이 나오는지 확인하세요. |
| "STT 서버에 연결할 수 없습니다" | proxyUrl이 https://subsync.de5.net인지, 네트워크나 방화벽이 WebSocket 연결을 막지 않는지 확인하세요. |
| "음성 인식을 준비하는 중입니다" | 서버가 준비 중입니다. 잠시 뒤 다시 시작하세요. 계속되면 담당자에게 알려 주세요. |
| 오류는 없는데 자막이 안 나옴 | 스트리머가 말하고 있는지 확인하세요. playbackUrl 없이 쓰는 경우 영상이 재생 중이고 소리가 나는지, start()를 클릭 안에서 호출했는지 확인하세요. transcript 이벤트가 오는지 보면 받아 적기까지 되는지 알 수 있습니다. |
| 원문은 오는데 번역이 안 나옴 | error 이벤트의 메시지를 확인하세요. "번역 요청 실패"가 반복되면 담당자에게 알려 주세요. |
| 번역이 안 되고 원문이 그대로 나옴 | 스트리머의 언어와 번역 언어가 같으면 번역하지 않습니다. translation 이벤트의 skipped가 true입니다. |
| 엉뚱한 언어로 받아 적음 | sourceLanguage로 스트리머의 언어를 지정하세요. |
| 자막이 너무 늦게 나옴 | translation 이벤트의 timing을 보세요. recognitionMs가 크면 chunkMs를 줄이고, translationMs가 크면 담당자에게 알려 주세요. |
| 자막이 플레이어 조작 막대와 겹침 | .ivslt-subs { bottom: … }을 조정하거나 overlay.container를 지정하세요. |
| 자막이 영상 밖에 나오거나 안 보임 | 영상의 부모 요소가 영상과 같은 크기인지 확인하세요. 자막은 부모 요소를 기준으로 놓입니다. |
| 목소리 변조를 켰더니 자막이 안 나옴 | 영상이 음소거 상태인지 확인하세요. |
| 대시보드의 사용자 수가 예상보다 많음 | 브라우저 단위로 세기 때문입니다. userId를 넘기면 사람 단위로 셉니다. |
담당자에게 문의할 때는 오류 메시지, 페이지 주소, 브라우저 종류와 버전, 발생 시각을 함께 알려 주시면 빨리 확인할 수 있습니다.
업데이트와 문의#
- 새 버전이 나오면 백오피스의 SDK에서 다시 내려받아 사이트의 파일을 바꿔 올립니다. 지금 쓰는 버전은 이 문서 맨 위와 SDK 화면에서 볼 수 있습니다.
- 이 문서의 최신판은
https://subsync.de5.net/docs에 있습니다. - 키 발급·폐기, 사이트 주소 등록, 계정 문의는 서비스 담당자에게 하세요.