전송 방식
기본 전송 계층
섹션 제목: “기본 전송 계층”WebRTC를 통한 연결
섹션 제목: “WebRTC를 통한 연결”기본 전송 계층은 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 });}더 낮은 수준의 커스터마이징을 위해 OpenAIRealtimeWebRTC 는 changePeerConnection 도 지원하여, 오퍼가 생성되기 전에 새로 생성된 RTCPeerConnection 을 검사하거나 교체할 수 있습니다.
WebSocket을 통한 연결
섹션 제목: “WebSocket을 통한 연결”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);임의의 녹음/재생 라이브러리를 사용하여 raw PCM16 오디오 바이트를 처리하세요.
고급 통합을 위해 OpenAIRealtimeWebSocket 은 createWebSocket() 을 받아 사용자 정의 소켓 구현을 제공할 수 있으며, 사용자 정의 커넥터가 소켓을 연결된 상태로 전환하는 책임을 질 때는 skipOpenEventListeners 를 사용할 수 있습니다. @openai/agents-extensions 의 Cloudflare 전송은 이러한 훅을 기반으로 구축되었습니다.
SIP를 통한 연결
섹션 제목: “SIP를 통한 연결”OpenAIRealtimeSIP 전송을 사용하여 Twilio 와 같은 공급자의 SIP 전화를 브리지하세요. 이 전송은 통신 공급자가 내보내는 SIP 이벤트와 Realtime 세션을 동기화 상태로 유지합니다.
OpenAIRealtimeSIP.buildInitialConfig()로 초기 세션 구성을 생성하여 수신 전화를 수락합니다. 이렇게 하면 SIP 초대와 Realtime 세션이 동일한 기본값을 공유합니다.OpenAIRealtimeSIP전송을 사용하는RealtimeSession을 연결하고, 공급자 웹후크에서 발급한callId로 연결하세요.- 세션 이벤트를 수신하여 통화 분석, 전사, 에스컬레이션 로직을 구동하세요.
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 에 더 직접 접근하려면 두 가지 옵션이 있습니다.
옵션 1 - 전송 계층에 접근
섹션 제목: “옵션 1 - 전송 계층에 접근”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 responsesession.transport.sendEvent({ type: 'response.create', // ...});옵션 2 — 전송 계층만 사용
섹션 제목: “옵션 2 — 전송 계층만 사용”자동 도구 실행, 가드레일 등 기능이 필요 없다면, 연결 및 인터럽션(중단 처리) 만 관리하는 “슬림” 클라이언트로 전송 계층만 사용할 수도 있습니다.
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', outputModalities: ['text', 'audio'], audio: { input: { format: 'pcm16', }, output: { format: 'pcm16', voice: 'ash', }, }, },});
// optionally for WebSocketsclient.on('audio', (newAudio) => {});
client.sendAudio(audioBuffer);