use crate::audio::AudioFormat;
use crate::config::RealtimeConfig;
use crate::error::Result;
use crate::model::RealtimeModel;
use crate::session::BoxedSession;
use async_trait::async_trait;
use super::session::OpenAIRealtimeSession;
use super::{DEFAULT_MODEL, OPENAI_REALTIME_URL, OPENAI_VOICES, OpenAITransport};
#[derive(Debug, Clone)]
pub struct OpenAIRealtimeModel {
api_key: String,
model_id: String,
base_url: Option<String>,
transport: OpenAITransport,
}
impl OpenAIRealtimeModel {
pub fn new(api_key: impl Into<String>, model_id: impl Into<String>) -> Self {
Self {
api_key: api_key.into(),
model_id: model_id.into(),
base_url: None,
transport: OpenAITransport::default(),
}
}
pub fn with_default_model(api_key: impl Into<String>) -> Self {
Self::new(api_key, DEFAULT_MODEL)
}
pub fn with_base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = Some(url.into());
self
}
pub fn with_transport(mut self, transport: OpenAITransport) -> Self {
self.transport = transport;
self
}
pub fn websocket_url(&self) -> String {
let base = self.base_url.as_deref().unwrap_or(OPENAI_REALTIME_URL);
format!("{}?model={}", base, self.model_id)
}
pub fn api_key(&self) -> &str {
&self.api_key
}
}
#[async_trait]
impl RealtimeModel for OpenAIRealtimeModel {
fn provider(&self) -> &str {
"openai"
}
fn model_id(&self) -> &str {
&self.model_id
}
fn supported_input_formats(&self) -> Vec<AudioFormat> {
vec![AudioFormat::pcm16_24khz(), AudioFormat::g711_ulaw(), AudioFormat::g711_alaw()]
}
fn supported_output_formats(&self) -> Vec<AudioFormat> {
vec![AudioFormat::pcm16_24khz(), AudioFormat::g711_ulaw(), AudioFormat::g711_alaw()]
}
fn available_voices(&self) -> Vec<&str> {
OPENAI_VOICES.to_vec()
}
async fn connect(&self, config: RealtimeConfig) -> Result<BoxedSession> {
match self.transport {
OpenAITransport::WebSocket => {
let session =
OpenAIRealtimeSession::connect(&self.websocket_url(), &self.api_key, config)
.await?;
let handler = crate::openai::protocol::OpenAIProtocolHandler::new(session);
Ok(Box::new(handler))
}
#[cfg(feature = "openai-webrtc")]
OpenAITransport::WebRTC => {
let session = super::webrtc::OpenAIWebRTCSession::connect(
&self.api_key,
&self.model_id,
config,
)
.await?;
let handler = crate::openai::protocol::OpenAIProtocolHandler::new(session);
Ok(Box::new(handler))
}
}
}
}
impl Default for OpenAIRealtimeModel {
fn default() -> Self {
Self {
api_key: String::new(),
model_id: DEFAULT_MODEL.to_string(),
base_url: None,
transport: OpenAITransport::default(),
}
}
}