For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
기본 탐색 메뉴
Theme

실시간 번역

실시간 음성을 번역하고 오디오와 텍스트를 스트리밍으로 받으세요.

Realtime 번역을 사용하면 원본 오디오를 전용 번역 세션으로 스트리밍하고, 화자가 말하는 도중에도 번역된 오디오와 새로 생성된 텍스트를 받을 수 있습니다. 실시간 통역, 다국어 통화, 방송, 회의, 수업, 화상 대화방 등에 활용하세요.

사람이 하는 말을 번역하는 앱에는 gpt-realtime-translate 모델을 사용하세요. 질문에 답하고 도구를 호출하며 대화를 이끄는 어시스턴트가 필요하다면 표준 Realtime 세션에서 gpt-realtime-2.1 모델을 사용하세요.

번역 세션의 차이점

Realtime 번역 세션과 음성 에이전트 세션은 동작 방식이 다릅니다.

음성 에이전트 세션 번역 세션
/v1/realtime에 연결합니다. /v1/realtime/translations에 연결합니다.
모델이 어시스턴트 역할을 합니다. 모델이 통역사 역할을 합니다.
대화와 응답의 수명 주기에 따라 동작합니다. 들어오는 오디오를 바탕으로 출력을 계속 스트리밍합니다.
도구를 호출하고 어시스턴트 차례에 응답을 생성할 수 있습니다. 번역된 오디오와 텍스트를 생성되는 대로 출력합니다.
response.create를 호출할 수 있습니다. response.create를 호출하지 않습니다.

오디오 스트림이 들어오면 번역이 시작됩니다. 구절 사이의 무음까지 포함해 오디오를 계속 추가하고, 출력 이벤트가 도착할 때마다 처리하세요.

전송 방식 선택

브라우저에서 오디오를 캡처하거나 재생할 때는 WebRTC를 사용하세요. WebRTC는 원본 오디오를 미디어 트랙으로 보내고 번역된 음성을 원격 오디오 트랙으로 받습니다. 따라서 PCM 청크를 직접 리샘플링하거나 재생할 필요가 없습니다.

서버가 Twilio Media Streams, SIP 미디어, 방송 입력 스트림, 미디어 워커 등에서 이미 원시 오디오를 받고 있다면 WebSocket을 사용하세요. WebSocket에서는 base64로 인코딩한 24 kHz PCM16 오디오를 보내고 반환되는 오디오 조각을 직접 재생하세요.

브라우저에서 WebRTC 세션 만들기

브라우저 앱의 경우 서버에서 유효 기간이 짧은 클라이언트 시크릿을 생성하세요. 일반 API 키를 브라우저에 노출하지 마세요.

번역용 클라이언트 시크릿 생성
app.post("/session", async (req, res) => {
  const language = req.body.targetLanguage ?? "es";

  const response = await fetch(
    "https://api.openai.com/v1/realtime/translations/client_secrets",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        "Content-Type": "application/json",
        "OpenAI-Safety-Identifier": "hashed-user-id",
      },
      body: JSON.stringify({
        session: {
          model: "gpt-realtime-translate",
          audio: {
            output: { language },
          },
        },
      }),
    }
  );

  res.status(response.status).json(await response.json());
});

브라우저에서 오디오를 캡처하고 피어 연결을 만든 다음, SDP 오퍼를 번역 통화 엔드포인트에 POST 요청으로 보내세요.

브라우저에서 번역 통화 연결
const { value: clientSecret } = await fetch("/session", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ targetLanguage: "es" }),
}).then((response) => response.json());

const sourceStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
});

const pc = new RTCPeerConnection();
pc.addTrack(sourceStream.getAudioTracks()[0], sourceStream);

const translatedAudio = new Audio();
translatedAudio.autoplay = true;
pc.ontrack = ({ streams }) => {
  translatedAudio.srcObject = streams[0];
};

const events = pc.createDataChannel("oai-events");
events.onmessage = ({ data }) => {
  const event = JSON.parse(data);
  if (event.type === "session.output_transcript.delta") {
    subtitles.textContent += event.delta;
  }
};

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const sdpResponse = await fetch(
  "https://api.openai.com/v1/realtime/translations/calls",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${clientSecret}`,
      "Content-Type": "application/sdp",
    },
    body: offer.sdp,
  }
);

if (!sdpResponse.ok) {
  throw new Error(await sdpResponse.text());
}

await pc.setRemoteDescription({
  type: "answer",
  sdp: await sdpResponse.text(),
});

WebSocket 세션 만들기

번역 전용 엔드포인트에 연결할 때 URL에서 모델을 지정하세요.

예제를 실행하기 전에 Node.js에서는 ws를, Python에서는 websocket-client와 sounddevice를, Ruby에서는 async-websocket을 설치하세요(gem install async-websocket). Java에서는 Maven 종속성 com.openai:openai-java:4.75.1을 추가하세요.

Java 예제는 연결 설정, 언어 설정, 오디오 입력을 각각 따로 다룹니다. Java SDK는 이벤트 수신과 세션 종료도 지원하지만, 이 가이드의 Java 예제에는 해당 단계가 포함되어 있지 않습니다. 아래의 전체 번역 워크플로우를 따라 하려면 Node.js 또는 Python 예제를 사용하세요.

번역 세션에 연결
import WebSocket from "ws";

const ws = new WebSocket(
  "wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate",
  {
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
      "OpenAI-Safety-Identifier": "hashed-user-id",
    },
  }
);

Ruby에서는 아래의 언어 설정 및 오디오 추가 코드를 Async::WebSocket::Client.connect 블록 안에 넣으세요. 세션 생성 여부를 확인하는 코드 뒤, 블록이 끝나기 전에 넣으면 됩니다. 오디오를 보내고 번역 이벤트를 받는 동안 연결을 유지하세요.

Java 연결 예제에서는 try 블록이 끝나면 소켓이 닫힙니다. Java 언어 설정 및 오디오 입력 예제를 실행하려면 TranslationConnection이 열려 있어야 합니다. 오디오를 보내고 출력을 받는 동안 연결을 유지하세요. 블록을 벗어나기 전에 세션을 종료하고 session.closed까지 남은 이벤트를 모두 읽으세요. 자세한 절차는 WebSocket 세션 닫기를 참고하세요.

소켓이 열리면 대상 언어를 설정하세요.

대상 언어 설정
ws.on("open", () => {
  ws.send(
    JSON.stringify({
      type: "session.update",
      session: {
        audio: {
          output: {
            language: "es",
          },
        },
      },
    })
  );
});

그런 다음 오디오를 계속 추가하세요.

원본 오디오 추가
ws.send(
  JSON.stringify({
    type: "session.input_audio_buffer.append",
    audio: base64Pcm16,
  })
);

번역된 오디오와 텍스트를 수신하세요.

번역된 오디오와 텍스트 수신
ws.on("message", (data) => {
  const event = JSON.parse(data.toString());

  if (event.type === "session.output_audio.delta") {
    playPcm16(event.delta);
  }

  if (event.type === "session.output_transcript.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "session.input_transcript.delta") {
    updateSourceTranscript(event.delta);
  }
});

Go에서는 오디오를 보내는 동안 listen을 동시에 실행하세요. 이 함수는 session.closed를 받으면 연결을 닫습니다.

WebSocket 세션 닫기

원본 스트림이 끝나면 WebSocket을 닫기 전에 session.close 이벤트를 보내세요. 이 이벤트를 받으면 서비스는 대기 중인 입력 오디오를 모두 처리하고, 남은 번역 오디오와 텍스트를 출력한 다음 session.closed 이벤트를 보냅니다. session.close 이벤트는 번역 세션에서만 지원됩니다.

session.close를 보낸 후에는 오디오 추가를 중단하고, 기존 수신 루프에서 session.closed를 받을 때까지 이벤트를 계속 읽으세요. 소켓을 바로 닫으면 세션에서 아직 전송 중인 번역 결과가 누락될 수 있습니다.

번역 세션 닫기
let translationSessionClosing = false;
let gotTranslationClosed = false;
let drainDeadline;

ws.on("close", () => {
  clearTimeout(drainDeadline);
  if (!gotTranslationClosed) {
    console.error("Translation disconnected before final session.closed");
    process.exitCode = 1;
  }
});

function closeTranslationSession() {
  if (translationSessionClosing) {
    return;
  }

  translationSessionClosing = true;
  // Adjust this deadline for your application's finalization requirements.
  drainDeadline = setTimeout(() => {
    console.error("Translation finalization timed out");
    process.exitCode = 1;
    ws.close();
  }, 15_000);
  ws.send(JSON.stringify({ type: "session.close" }));
}

// Use this in place of the earlier output handler, so audio plays only once.
ws.on("message", (data) => {
  const event = JSON.parse(data.toString());

  if (event.type === "session.output_audio.delta") {
    playPcm16(event.delta);
  }

  if (event.type === "session.output_transcript.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "session.input_transcript.delta") {
    updateSourceTranscript(event.delta);
  }

  if (event.type === "error") {
    clearTimeout(drainDeadline);
    console.error("Translation error", event.error?.code);
    process.exitCode = 1;
    ws.close();
  }

  if (event.type === "session.closed") {
    clearTimeout(drainDeadline);
    gotTranslationClosed = true;
    ws.close();
  }
});

// Call this when the source stream ends.
closeTranslationSession();

청중을 위한 실시간 통역 구현

한 사람의 발언이나 하나의 스트림을 번역해 청중에게 들려줄 때 이 방식을 사용하세요. 라이브 스트리밍, 콘퍼런스 발표, 웨비나, 실적 발표 컨퍼런스콜, 강의, 동영상 등이 대표적인 예입니다.

일반적인 구조는 다음과 같습니다.

source audio -> translation session -> translated audio + subtitles

대상 언어마다 번역 세션을 하나씩 만드세요. 같은 영어 원본을 스페인어와 프랑스어로 출력해야 한다면 영어를 스페인어로 번역하는 세션과 영어를 프랑스어로 번역하는 세션을 각각 만드세요.

브라우저에서 통역을 들려주는 앱에서는 getDisplayMedia()로 탭 오디오를 캡처해 WebRTC로 보내고, 번역된 원격 오디오 트랙을 재생하세요. 실제 방송 환경에서는 서버의 미디어 워커에서 번역을 실행하고 번역된 오디오 트랙이나 자막을 청중에게 송출하세요.

대화 통역 구현

두 명 이상의 참가자가 서로 다른 언어로 대화할 때는 대화 통역을 사용하세요. 고객 지원 통화, 영업 통화, 개인 지도, 화상 대화방 등에 활용할 수 있습니다.

참가자별 오디오 트랙을 분리하세요. 여러 화자의 음성을 하나의 스트림으로 합치면 화자를 구분하고 화자별 자막을 표시하거나 겹치는 발화를 처리하기가 어려워집니다.

두 사람이 통화할 때는 번역 방향별로 세션을 하나씩 만드세요.

Caller A audio -> translate into Caller B language -> play to Caller B
Caller B audio -> translate into Caller A language -> play to Caller A

그룹 대화방에서 필요한 세션 수는 현재 발언 중인 화자 수와 대상 언어 수에 따라 달라집니다.

translation sessions ~= active source speaker tracks x distinct target languages

소규모 대화방에서는 각 청취자가 통역을 원하는 원격 화자별로 브라우저에 번역 사이드카를 만들 수 있습니다. 대규모 대화방에서는 서버 측 참가자나 미디어 워커를 사용하세요. 이 참가자나 워커가 각 화자의 원본 트랙을 한 번씩 구독하고, 대상 언어마다 번역 세션을 하나씩 만든 뒤 번역된 트랙을 다시 배포합니다.

품질과 지연 시간 테스트

실제 오디오로 번역을 테스트하고 두 언어에 능통한 검토자에게 결과를 확인받으세요. 자동 평가 지표도 도움이 되지만, 사용자가 알아차리는 오류를 모두 찾아내지는 못합니다.

다음 항목을 테스트하세요.

  • 언어 쌍별 번역 품질
  • 이름, 숫자, 날짜, 통화, 전화번호의 번역 정확도
  • 전문 분야의 용어
  • 발화 중 언어 전환과 여러 언어가 섞인 대화
  • 다양한 억양, 빠른 말, 겹치는 발화
  • 첫 번역 오디오가 출력될 때까지의 지연 시간
  • 발화 종료 시점의 지연 시간
  • 자막 표시 타이밍
  • 음성의 일관성
  • 재연결 시 동작

이름이나 전문 용어를 정확하게 번역해야 한다면 출시 전에 정답이 있는 평가 데이터 세트를 만들고 실패 사례를 직접 검토하세요.

프로덕션 체크리스트

  • 브라우저 미디어에는 WebRTC를, 서버 미디어에는 WebSocket을 사용하세요.
  • 번역 전용 /v1/realtime/translations 엔드포인트를 사용하세요.
  • 구절 사이의 무음까지 포함해 오디오를 끊김 없이 스트리밍하세요.
  • WebSocket 세션을 닫기 전에 session.close를 보내고 session.closed가 도착할 때까지 기다리세요.
  • 대화 통역에서는 화자별 트랙을 분리하세요.
  • 출력 언어마다 세션을 하나씩 사용하세요.
  • 필요에 따라 원문과 번역문을 함께 표시하세요.
  • 사용자가 원본 오디오, 번역 오디오, 자막, 음소거, 음량을 제어할 수 있도록 하세요.
  • 재연결 중, 지연, 이용 불가 상태를 사용자에게 표시하세요.
  • 번역 품질과 별도로 지연 시간을 추적하세요.

관련 가이드

Realtime 및 오디오 개요

음성 에이전트, 번역, 음성 전사 세션을 비교하세요.

WebRTC 연결

브라우저 미디어를 Realtime 세션에 연결하세요.

WebSocket 연결

서버 측 미디어 파이프라인으로 원시 오디오를 스트리밍하세요.

실시간 음성 전사

실시간 오디오를 텍스트로 변환하고 새로 생성된 텍스트를 스트리밍하세요.