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

WARP를 사용한 WebRTC 연결

WARP로 GPT-Live와 Realtime API의 연결 지연 시간을 줄이세요.

WebRTC Abridged Roundtrip Protocol(WARP)을 사용하면 GPT-Live 또는 Realtime API에서 음성 세션을 시작하는 데 걸리는 시간을 줄일 수 있습니다. WARP는 세 가지 전송 최적화 기능(DTLS 1.3, SPED, SNAP)을 사전 협상된 데이터 채널과 함께 사용해 연결에 필요한 네트워크 왕복 횟수를 줄입니다.

각 최적화 기능은 개별적으로도 사용할 수 있습니다. WARP 기능 중 일부만 사용할 수 있는 경우에도 클라이언트에서 지원하는 기능을 활성화하면 연결 지연 시간을 줄일 수 있습니다. 모든 기능을 함께 사용하면 전체 WARP 핸드셰이크가 수행됩니다.

WARP, SPED, SNAP은 IETF 인터넷 초안이므로 명세와 클라이언트의 지원 여부가 달라질 수 있습니다.

GPT-Live와 Realtime API는 동일한 WebRTC 최적화 기능을 사용합니다. 애플리케이션 서버에서 사용하는 언어와 관계없이 브라우저나 네이티브 클라이언트에서 이 기능들을 설정하세요. 세션을 만들 때 협상된 데이터 채널 ID를 보내는 방법은 API마다 다릅니다.

네이티브 클라이언트에서 WARP 활성화하기

WARP 기능을 모두 사용하려면 필드 트라이얼로 전송 최적화 기능을 활성화하고 데이터 채널을 사전 협상하세요. 두 단계 중 하나만 적용할 수도 있습니다.

필드 트라이얼 활성화하기

현재 libwebrtc 버전에는 WARP 최적화 기능이 포함되어 있습니다. 네이티브 클라이언트가 호환되는 libwebrtc 빌드를 사용한다면 다음 필드 트라이얼을 활성화하세요.

WebRTC-ForceDtls13/Enabled/
WebRTC-Sctp-Snap/Enabled/
WebRTC-IceHandshakeDtls/Enabled/

각 필드 트라이얼은 순서대로 DTLS 1.3, SNAP, SPED를 활성화합니다. 활성화하려는 기능에 해당하는 필드 트라이얼만 포함하세요.

통합 환경에 따라 필드 트라이얼을 하나의 문자열로 합쳐야 합니다.

WebRTC-ForceDtls13/Enabled/WebRTC-Sctp-Snap/Enabled/WebRTC-IceHandshakeDtls/Enabled/

피어 연결 팩토리를 만들기 전에 필드 트라이얼을 초기화하세요. 래퍼에 따라 설정할 수 있는 옵션이 제한될 수 있습니다. 예를 들어 webrtc-sys 0.3.51에서는 SPED를 피어 연결 팩토리에서 활성화하고 SNAP을 연결 설정에서 활성화합니다.

use webrtc_sys::peer_connection::ffi::{
    ContinualGatheringPolicy, IceTransportsType, RtcConfiguration,
};
use webrtc_sys::peer_connection_factory::ffi::create_peer_connection_factory_with_options;

// The wrapper enables SPED on the factory; SNAP is an immutable connection option.
let factory = create_peer_connection_factory_with_options(false, true);
let configuration = RtcConfiguration {
    ice_servers: vec![],
    continual_gathering_policy: ContinualGatheringPolicy::GatherOnce,
    ice_transport_type: IceTransportsType::All,
    enable_sctp_snap: true,
};

네이티브 LiveKit SDK처럼 libwebrtc를 래핑하는 SDK를 사용한다면 SDK의 WebRTC 설정이나 초기화 옵션에 같은 필드 트라이얼 문자열을 전달하세요. SDK가 필드 트라이얼 설정을 제공하지 않는다면 SDK가 피어 연결 팩토리를 만들기 전에 내부 libwebrtc 인스턴스를 초기화하거나, 이 설정을 제공하는 래퍼로 업데이트하세요.

데이터 채널 사전 협상하기

클라이언트와 시그널링 요청에서 같은 채널 ID를 사용하세요. 다음 단계는 네이티브 클라이언트와 브라우저 모두에 적용되며, 세 가지 전송 최적화 기능을 모두 활성화할 필요는 없습니다.

  1. SDP 오퍼를 만들기 전에 데이터 채널을 만드세요. negotiated는 true로 설정하고 id에는 4처럼 사용 가능한 채널 ID를 지정하세요. 채널 레이블에는 어떤 문자열이든 사용할 수 있습니다.
  2. SDP 오퍼와 채널 ID를 애플리케이션 서버로 보낸 다음, 아래에서 사용하는 API에 해당하는 단계를 따르세요.

GPT-Live에 연결하기

먼저 GPT-Live WebRTC 빠른 시작을 따르세요. 서버에서 채널 ID를 transport.dcid 값으로 지정해 POST /v1/live/sessions 요청의 JSON 본문에 포함하세요. transport.type 값은 webrtc로 유지하고 transport.sdp에는 클라이언트의 SDP 오퍼를 그대로 사용하세요.

id: 4로 만든 채널이라면 다음 JSON 본문을 POST /v1/live/sessions로 보내세요. <SDP offer>를 클라이언트에서 생성한 실제 SDP 오퍼로 바꾸세요.

{
  "session": {
    "model": "gpt-live-1"
  },
  "transport": {
    "type": "webrtc",
    "sdp": "<SDP offer>",
    "dcid": 4
  }
}

transport.dcid 필드는 사전 협상된 채널을 활성화합니다. 표준 데이터 채널을 사용할 때는 이 필드를 생략하세요. dcid를 URL 쿼리 매개변수로 보내지 마세요. 아래의 Realtime API 연결 플로우와 달리 GPT-Live는 쿼리 매개변수가 포함된 요청을 거부합니다.

응답으로 받은 transport.sdp를 원격 SDP 응답으로 적용하고 session.started 이벤트를 받은 뒤에 애플리케이션 명령어를 보내세요. HTTP 요청으로 세션이 시작되므로 데이터 채널에서 session.start를 보내지 마세요.

SDK에서 transport.dcid를 설정할 수 없다면 GPT-Live 빠른 시작의 표준 데이터 채널 설정을 그대로 사용하세요. 이 경우에도 클라이언트가 지원하는 전송 최적화 기능은 개별적으로 활성화할 수 있습니다.

Realtime API에 연결하기

통합 WebRTC 연결 플로우를 사용하세요. 서버에서 dcid 쿼리 매개변수에 채널 ID를 넣어 /v1/realtime/calls를 호출하세요. id: 4로 만든 채널이라면 POST /v1/realtime/calls?dcid=4를 사용하고 멀티파트 요청 본문의 SDP와 세션 설정은 그대로 유지하세요.

반환된 SDP를 원격 SDP 응답으로 적용하세요. 표준 데이터 채널을 사용할 때는 dcid를 생략하세요. 아래의 전체 예제에서 두 설정을 모두 확인할 수 있습니다.

브라우저에서 WARP 활성화하기

Chrome, Edge 등 Chromium 기반 브라우저에는 libwebrtc가 포함되어 있지만 웹 페이지에서는 필드 트라이얼을 설정할 수 없습니다. 브라우저에서 사용할 수 있는 전송 기능을 활성화한 다음, 네이티브 클라이언트와 동일한 API별 시그널링 방식으로 데이터 채널을 사전 협상하세요.

사용 가능한 기능과 오리진 트라이얼 활성화하기

오리진 트라이얼을 통해 등록된 웹사이트에서 브라우저의 실험적 기능을 활성화할 수 있습니다. 각 WARP 기능의 지원 여부를 확인하세요.

  • DTLS 1.3: Chrome은 오리진 트라이얼 없이 DTLS 1.3을 지원합니다.
  • SNAP: Chrome 151~156에서는 오리진 트라이얼을 통해 SNAP을 지원합니다. Edge에서는 사용 중인 버전에서 SNAP 오리진 트라이얼을 사용할 수 있는지 확인한 다음, 트라이얼에 등록해 Edge에서 발급하는 토큰을 받으세요.
  • SPED: 현재 SPED를 위한 브라우저 오리진 트라이얼은 없습니다. 나중에 SPED 지원 여부를 다시 확인하세요. WARP 기능을 모두 사용하려면 브라우저에서 SPED를 기본으로 활성화하거나, 브라우저 시작 플래그를 제어할 수 있는 개발자가 필요한 필드 트라이얼을 직접 활성화해야 합니다.

SNAP 오리진 트라이얼을 활성화해도 SPED나 전체 WARP 기능이 활성화되지는 않습니다. 브라우저에서 SPED를 활성화할 수 없는 경우에도 DTLS 1.3과 SNAP 오리진 트라이얼을 사용하면 각 기능의 최적화 효과를 얻을 수 있습니다.

사용 중인 브라우저의 오리진 트라이얼을 확인하세요.

SNAP 오리진 트라이얼을 활성화하려면 다음 단계를 따르세요.

  1. 브라우저의 오리진 트라이얼 페이지를 열고 WebRTC Data Channel: SCTP Negotiation Acceleration Protocol (SNAP) 항목을 찾으세요.

  2. Register를 선택하고 https://example.com과 같이 애플리케이션의 오리진을 입력하세요.

  3. 페이지의 <head>에 발급받은 토큰을 추가하세요. 토큰은 RTCPeerConnection을 생성하는 스크립트보다 앞에 와야 합니다.

    <meta http-equiv="origin-trial" content="YOUR_ORIGIN_TRIAL_TOKEN" />
  4. 페이지를 새로고침하세요. Chrome에서 개발자 도구를 열고 애플리케이션을 선택한 다음, WebRtcSctpSnap이 오리진 트라이얼 아래에 표시되는지 확인하세요.

토큰을 HTTP 응답 헤더로 제공할 수도 있습니다.

Origin-Trial: YOUR_ORIGIN_TRIAL_TOKEN

오리진 트라이얼 토큰은 토큰에 명시된 기능, 토큰을 발급한 브라우저, 등록된 오리진에서만 유효합니다. SNAP 토큰으로는 SPED를 활성화할 수 없으며 Chrome 토큰으로는 Edge에서 트라이얼을 활성화할 수 없습니다. Firefox, Safari, iOS 브라우저, 이전 Chromium 빌드는 전체 WARP 기능을 지원하지 않아도 표준 WebRTC를 지원할 수 있습니다.

브라우저 데이터 채널 사전 협상하기

위의 데이터 채널 설정 단계를 따른 다음, GPT-Live 또는 Realtime API 연결 방법에 따라 같은 채널 ID를 보내세요. 채널 사전 협상에는 오리진 트라이얼이 필요하지 않으며, WARP 기능 중 일부만 사용할 수 있는 경우에도 서버 이벤트를 받기까지의 대기 시간을 줄일 수 있습니다.

통합 인터페이스로 연결하기

통합 WebRTC 연결 플로우를 사용하면 Realtime API에 더 빠르게 연결할 수 있습니다. 브라우저는 SDP 오퍼와 협상된 데이터 채널 ID를 애플리케이션 서버로 보냅니다. 서버는 같은 ID를 dcid 쿼리 매개변수에 넣어 /v1/realtime/calls를 호출합니다.

애플리케이션 서버 설정하기

다음 애플리케이션 서버는 표준 WebRTC와 WARP를 모두 지원합니다. WARP only 주석은 WARP 연결에 필요한 dcid 전달 코드를 표시합니다.

import express from "express";

const app = express();

// Parse raw SDP payloads posted from the browser
app.use(express.text({ type: ["application/sdp", "text/plain"] }));

const sessionConfig = JSON.stringify({
  type: "realtime",
  model: "gpt-realtime-2.1",
  audio: { output: { voice: "marin" } },
});

// An endpoint which creates a Realtime API session.
app.post("/session", async (req, res) => {
  const fd = new FormData();
  fd.set("sdp", req.body);
  fd.set("session", sessionConfig);

  const endpoint = new URL("https://api.openai.com/v1/realtime/calls");

  // WARP only: forward the negotiated data-channel ID to the Realtime API.
  if (typeof req.query.dcid === "string") {
    endpoint.searchParams.set("dcid", req.query.dcid);
  }

  try {
    const r = await fetch(endpoint, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        "OpenAI-Safety-Identifier": "hashed-user-id",
      },
      body: fd,
    });
    // Send back the SDP we received from the OpenAI REST API
    const sdp = await r.text();
    res.set(
      "Content-Type",
      r.ok ? "application/sdp" : (r.headers.get("Content-Type") ?? "text/plain")
    );
    const location = r.headers.get("Location");
    if (location) res.set("Location", location);
    res.status(r.status).send(sdp);
  } catch (error) {
    console.error("Session creation error:", error);
    res.status(500).json({ error: "Failed to create session" });
  }
});

app.listen(3000);

브라우저에서 연결하기

브라우저에서 사용할 수 있는 최적화 기능을 활성화한 다음 useWarp를 true로 설정하세요. 사용 가능한 데이터 채널 ID를 하나 선택해 같은 ID를 서버에 전달하세요. WARP only 주석은 표준 WebRTC에서는 필요하지 않은 설정과 시그널링 코드를 표시합니다.

// WARP only: set to true after enabling the supported WARP optimizations.
const useWarp = false;

// WARP only: choose any available data-channel ID.
const dataChannelId = 4;

// Create a peer connection
const pc = new RTCPeerConnection();

// Set up to play remote audio from the model
audioElement.current = document.createElement("audio");
audioElement.current.autoplay = true;
pc.ontrack = (e) => (audioElement.current.srcObject = e.streams[0]);

// Add local audio track for microphone input in the browser
const ms = await navigator.mediaDevices.getUserMedia({
  audio: true,
});
pc.addTrack(ms.getTracks()[0]);

// Set up the event channel using any channel label.
// WARP only: pre-negotiate the channel using the selected data-channel ID.
const dc = pc.createDataChannel(
  "events",
  useWarp ? { negotiated: true, id: dataChannelId } : undefined,
);

// Start the session using the Session Description Protocol (SDP)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const endpoint = new URL("/session", window.location.origin);

// WARP only: include the matching data-channel ID in the session request.
if (useWarp) {
  endpoint.searchParams.set("dcid", String(dataChannelId));
}

const sdpResponse = await fetch(endpoint, {
  method: "POST",
  body: offer.sdp,
  headers: {
    "Content-Type": "application/sdp",
  },
});

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

WARP를 지원하지 않는 클라이언트 사용하기

WebRTC 클라이언트가 libwebrtc를 사용하지 않는다면 WebRTC 스택에 WARP 호환 전송 최적화 기능을 추가하거나 해당 스택에서 지원하는 다른 방법을 사용하세요. 관련 명세는 WARP, SPED, SNAP, DTLS 1.3, 데이터 채널 설정입니다.

이러한 최적화 기능을 사용할 수 없다면 표준 GPT-Live WebRTC 플로우 또는 Realtime API 통합 인터페이스를 사용하세요.