콘텐츠로 이동

전송 방식

기본 전송 레이어는 WebRTC를 사용합니다. 오디오는 마이크에서 녹음되고 자동으로 재생됩니다.

자체 미디어 스트림이나 오디오 요소를 사용하려면 세션을 생성할 때 OpenAIRealtimeWebRTC 인스턴스를 제공하세요.

import { RealtimeAgent, RealtimeSession, OpenAIRealtimeWebRTC } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
async function main() {
const transport = new OpenAIRealtimeWebRTC({
mediaStream: await navigator.mediaDevices.getUserMedia({ audio: true }),
audioElement: document.createElement('audio'),
});
const customSession = new RealtimeSession(agent, { transport });
}

WebRTC 대신 WebSocket 연결을 사용하려면 세션을 생성할 때 transport: 'websocket' 또는 OpenAIRealtimeWebSocket 인스턴스를 전달하세요. 이는 예를 들어 Twilio로 전화 에이전트를 구축하는 등 서버 측 사용 사례에 적합합니다.

import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
const myRecordedArrayBuffer = new ArrayBuffer(0);
const wsSession = new RealtimeSession(agent, {
transport: 'websocket',
model: 'gpt-realtime',
});
await wsSession.connect({ apiKey: process.env.OPENAI_API_KEY! });
wsSession.on('audio', (event) => {
// event.data is a chunk of PCM16 audio
});
wsSession.sendAudio(myRecordedArrayBuffer);

원문 PCM16 오디오 바이트를 처리하려면 임의의 녹음/재생 라이브러리를 사용하세요.

OpenAIRealtimeSIP 전송을 사용하여 Twilio와 같은 공급자의 SIP 전화를 브리지하세요. 이 전송은 통신 공급자가 내보내는 SIP 이벤트와 Realtime 세션의 동기화를 유지합니다.

  1. OpenAIRealtimeSIP.buildInitialConfig()로 초기 세션 구성을 생성하여 걸려오는 전화를 수락합니다. 이를 통해 SIP 초대와 Realtime 세션이 동일한 기본값을 공유하도록 보장합니다
  2. OpenAIRealtimeSIP 전송을 사용하는 RealtimeSession을 연결하고, 공급자 웹훅에서 발급한 callId로 접속합니다
  3. 세션 이벤트를 수신하여 통화 분석, 전사, 에스컬레이션 로직을 구동합니다
import OpenAI from 'openai';
import {
OpenAIRealtimeSIP,
RealtimeAgent,
RealtimeSession,
type RealtimeSessionOptions,
} from '@openai/agents/realtime';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY!,
webhookSecret: process.env.OPENAI_WEBHOOK_SECRET!,
});
const agent = new RealtimeAgent({
name: 'Receptionist',
instructions:
'Welcome the caller, answer scheduling questions, and hand off if the caller requests a human.',
});
const sessionOptions: Partial<RealtimeSessionOptions> = {
model: 'gpt-realtime',
config: {
audio: {
input: {
turnDetection: { type: 'semantic_vad', interruptResponse: true },
},
},
},
};
export async function acceptIncomingCall(callId: string): Promise<void> {
const initialConfig = await OpenAIRealtimeSIP.buildInitialConfig(
agent,
sessionOptions,
);
await openai.realtime.calls.accept(callId, initialConfig);
}
export async function attachRealtimeSession(
callId: string,
): Promise<RealtimeSession> {
const session = new RealtimeSession(agent, {
transport: new OpenAIRealtimeSIP(),
...sessionOptions,
});
session.on('history_added', (item) => {
console.log('Realtime update:', item.type);
});
await session.connect({
apiKey: process.env.OPENAI_API_KEY!,
callId,
});
return session;
}

Cloudflare Workers (workerd) 참고 사항

섹션 제목: “Cloudflare Workers (workerd) 참고 사항”

Cloudflare Workers 및 기타 workerd 런타임은 전역 WebSocket 생성자를 사용해 아웃바운드 WebSocket을 열 수 없습니다. 확장 패키지의 Cloudflare 전송을 사용하세요. 내부적으로 fetch() 기반 업그레이드를 수행합니다.

import { CloudflareRealtimeTransportLayer } from '@openai/agents-extensions';
import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'My Agent',
});
// Create a transport that connects to OpenAI Realtime via Cloudflare/workerd's fetch-based upgrade.
const cfTransport = new CloudflareRealtimeTransportLayer({
url: 'wss://api.openai.com/v1/realtime?model=gpt-realtime',
});
const session = new RealtimeSession(agent, {
// Set your own transport.
transport: cfTransport,
});

사용자 지정 전송 메커니즘 구축

섹션 제목: “사용자 지정 전송 메커니즘 구축”

다른 음성-대-음성 API를 사용하거나 자체 전송 메커니즘이 필요한 경우 RealtimeTransportLayer 인터페이스를 구현하고 RealtimeTransportEventTypes 이벤트를 발생시켜 직접 만들 수 있습니다.

Realtime API와의 더 직접적인 상호작용

섹션 제목: “Realtime API와의 더 직접적인 상호작용”

OpenAI Realtime API를 사용하면서 Realtime API에 더 직접적으로 접근하려면 두 가지 옵션이 있습니다.

RealtimeSession의 모든 기능을 그대로 활용하고 싶다면 session.transport를 통해 전송 레이어에 접근할 수 있습니다.

전송 레이어는 수신하는 모든 이벤트를 * 이벤트로 내보내며, sendEvent() 메서드를 사용해 원문 이벤트를 전송할 수 있습니다.

import { RealtimeAgent, RealtimeSession } from '@openai/agents/realtime';
const agent = new RealtimeAgent({
name: 'Greeter',
instructions: 'Greet the user with cheer and answer questions.',
});
const session = new RealtimeSession(agent, {
model: 'gpt-realtime',
});
session.transport.on('*', (event) => {
// JSON parsed version of the event received on the connection
});
// Send any valid event as JSON. For example triggering a new response
session.transport.sendEvent({
type: 'response.create',
// ...
});

자동 도구 실행, 가드레일 등은 필요 없고 연결과 인터럽션(중단 처리)만 관리하는 “얇은” 클라이언트가 필요하다면 전송 레이어만 사용할 수도 있습니다.

import { OpenAIRealtimeWebRTC } from '@openai/agents/realtime';
const client = new OpenAIRealtimeWebRTC();
const audioBuffer = new ArrayBuffer(0);
await client.connect({
apiKey: '<api key>',
model: 'gpt-4o-mini-realtime-preview',
initialSessionConfig: {
instructions: 'Speak like a pirate',
voice: 'ash',
modalities: ['text', 'audio'],
inputAudioFormat: 'pcm16',
outputAudioFormat: 'pcm16',
},
});
// optionally for WebSockets
client.on('audio', (newAudio) => {});
client.sendAudio(audioBuffer);