openai_api_rs/realtime/
api.rs1use futures_util::stream::{SplitSink, SplitStream};
2use futures_util::StreamExt;
3use tokio::net::TcpStream;
4use tokio_tungstenite::{
5 connect_async,
6 tungstenite::{client::IntoClientRequest, protocol::Message},
7 MaybeTlsStream, WebSocketStream,
8};
9
10const WSS_URL: &str = "wss://api.openai.com/v1/realtime";
11
12pub struct RealtimeClient {
13 pub wss_url: String,
14 pub api_key: String,
15 pub model: String,
16}
17
18impl RealtimeClient {
19 pub fn new(api_key: String, model: String) -> Self {
20 let wss_url = std::env::var("WSS_URL").unwrap_or_else(|_| WSS_URL.to_owned());
21 Self::new_with_endpoint(wss_url, api_key, model)
22 }
23
24 pub fn new_with_endpoint(wss_url: String, api_key: String, model: String) -> Self {
25 Self {
26 wss_url,
27 api_key,
28 model,
29 }
30 }
31
32 pub async fn connect(
33 &self,
34 ) -> Result<
35 (
36 SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>,
37 SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
38 ),
39 Box<dyn std::error::Error>,
40 > {
41 let url = format!("{}?model={}", self.wss_url, self.model);
42 let mut request = url.into_client_request()?;
43 let api_key = self.api_key.clone();
44 request
45 .headers_mut()
46 .insert("Authorization", format!("Bearer {api_key}").parse()?);
47 request
48 .headers_mut()
49 .insert("OpenAI-Beta", "realtime=v1".parse()?);
50 let (ws_stream, _) = connect_async(request).await?;
51 let (write, read) = ws_stream.split();
52 Ok((write, read))
53 }
54}