Skip to main content

async_openai/types/realtime/
translation.rs

1use serde::{Deserialize, Serialize};
2
3use crate::types::realtime::{NoiseReductionType, RealtimeServerEventError};
4
5/// Optional source-language transcription configuration for a translation session.
6/// When configured, the server emits `session.input_transcript.delta` events.
7/// Translation itself still runs from the input audio stream.
8#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9pub struct RealtimeTranslationInputTranscription {
10    /// The transcription model used for source transcript deltas.
11    pub model: String,
12}
13
14/// Optional input noise reduction for a translation session.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct RealtimeTranslationNoiseReduction {
17    pub r#type: NoiseReductionType,
18
19    /// Noise suppression strength.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub strength: Option<crate::types::realtime::RealtimeNoiseReductionStrength>,
22}
23
24/// Configuration for translation input audio.
25#[derive(Debug, Default, Clone, Serialize, Deserialize)]
26pub struct RealtimeTranslationInputAudio {
27    // DONT add because it can be 'null': #[serde(skip_serializing_if = "Option::is_none")]
28    /// Optional source-language transcription. Set to `null` to disable.
29    pub transcription: Option<RealtimeTranslationInputTranscription>,
30    // DONT add because it can be 'null': #[serde(skip_serializing_if = "Option::is_none")]
31    /// Optional input noise reduction. Set to `null` to disable.
32    pub noise_reduction: Option<RealtimeTranslationNoiseReduction>,
33}
34
35/// Configuration for translation output audio.
36#[derive(Debug, Default, Clone, Serialize, Deserialize)]
37pub struct RealtimeTranslationOutputAudio {
38    /// Target language for translated output audio and transcript deltas.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub language: Option<String>,
41}
42
43/// Configuration for translation input and output audio.
44#[derive(Debug, Default, Clone, Serialize, Deserialize)]
45pub struct RealtimeTranslationAudio {
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub input: Option<RealtimeTranslationInputAudio>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub output: Option<RealtimeTranslationOutputAudio>,
50}
51
52/// A Realtime translation session. Translation sessions continuously translate input
53/// audio into the configured output language.
54#[derive(Debug, Clone, Serialize, Deserialize, Default)]
55pub struct RealtimeTranslationSession {
56    /// Unique identifier for the session that looks like `sess_1234567890abcdef`.
57    pub id: String,
58    /// The session type. Always `translation` for Realtime translation sessions.
59    pub r#type: String,
60    /// Expiration timestamp for the session, in seconds since epoch.
61    pub expires_at: u64,
62    /// The Realtime translation model used for this session.
63    pub model: String,
64    /// Configuration for translation input and output audio.
65    pub audio: RealtimeTranslationAudio,
66}
67
68/// Realtime translation session configuration. Translation sessions stream
69/// source audio in and translated audio plus transcript deltas out continuously.
70#[derive(Debug, Clone, Serialize, Deserialize, Default)]
71pub struct RealtimeTranslationSessionCreateRequest {
72    /// The Realtime translation model used for this session.
73    pub model: String,
74    /// Configuration for translation input and output audio.
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub audio: Option<RealtimeTranslationAudio>,
77}
78
79/// Realtime translation session fields that can be updated with `session.update`.
80#[derive(Debug, Default, Clone, Serialize, Deserialize)]
81pub struct RealtimeTranslationSessionUpdateRequest {
82    /// Configuration for translation input and output audio.
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub audio: Option<RealtimeTranslationAudio>,
85}
86
87/// The anchor point for the translation client secret expiration.
88#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
89#[serde(rename_all = "snake_case")]
90pub enum RealtimeTranslationClientSecretExpiresAnchor {
91    #[default]
92    CreatedAt,
93}
94
95/// Configuration for the client secret expiration. Expiration refers to
96/// the time after which a client secret will no longer be valid for creating sessions.
97/// The session itself may continue after that time once started. A secret can be used to
98/// create multiple sessions until it expires.
99#[derive(Debug, Default, Clone, Serialize, Deserialize)]
100pub struct RealtimeTranslationClientSecretExpiresAfter {
101    /// The anchor point for the client secret expiration, meaning that
102    /// `seconds` will be added to the `created_at` time of the client
103    /// secret to produce an expiration timestamp. Only `created_at` is currently supported.
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub anchor: Option<RealtimeTranslationClientSecretExpiresAnchor>,
106    /// The number of seconds from the anchor point to the expiration. Select a value between
107    /// `10` and `7200` (2 hours). Defaults to 600 seconds (10 minutes) if not specified.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub seconds: Option<u32>,
110}
111
112/// Create a translation session and client secret for the Realtime API.
113#[derive(Debug, Clone, Serialize, Deserialize, Default)]
114pub struct RealtimeTranslationClientSecretCreateRequest {
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub expires_after: Option<RealtimeTranslationClientSecretExpiresAfter>,
117    pub session: RealtimeTranslationSessionCreateRequest,
118}
119
120/// Response from creating a translation session and client secret for the Realtime API.
121#[derive(Debug, Clone, Serialize, Deserialize, Default)]
122pub struct RealtimeTranslationClientSecretCreateResponse {
123    /// The generated client secret value.
124    pub value: String,
125    /// Expiration timestamp for the client secret, in seconds since epoch.
126    pub expires_at: u64,
127    /// The translation session.
128    pub session: RealtimeTranslationSession,
129}
130
131/// Send this event to update the translation session configuration.
132/// Translation sessions support updates to `audio.output.language`,
133/// `audio.input.transcription`, and `audio.input.noise_reduction`.
134#[derive(Debug, Clone, Serialize, Deserialize, Default)]
135pub struct RealtimeTranslationClientEventSessionUpdate {
136    /// Optional client-generated ID used to identify this event.
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub event_id: Option<String>,
139    /// Translation session fields to update. The session `type` and `model` are set
140    /// at creation and cannot be changed with `session.update`.
141    pub session: RealtimeTranslationSessionUpdateRequest,
142}
143
144/// Send this event to append audio bytes to the translation session input audio buffer.
145///
146/// WebSocket translation sessions accept base64-encoded 24 kHz PCM16 mono
147/// little-endian raw audio bytes. Unsupported websocket audio formats
148/// return a validation error because lower-quality audio materially degrades translation
149/// quality.
150///
151/// Translation consumes 200 ms engine frames. For best realtime behavior,
152/// append audio in 200 ms chunks. If a chunk is shorter, the server buffers it
153/// until it has enough audio for one frame. If a chunk is longer, the server splits
154/// it into 200 ms frames and enqueues them back-to-back.
155///
156/// Keep appending silence while the session is active. If a client stops
157/// sending audio and later resumes, model time treats the resumed audio as
158/// contiguous with the previous audio rather than as a real-world pause.
159#[derive(Debug, Clone, Serialize, Deserialize, Default)]
160pub struct RealtimeTranslationClientEventInputAudioBufferAppend {
161    /// Optional client-generated ID used to identify this event.
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub event_id: Option<String>,
164    /// Base64-encoded 24 kHz PCM16 mono audio bytes.
165    pub audio: String,
166}
167
168/// Gracefully close the realtime translation session. The server flushes pending
169/// input audio and emits any remaining translated output before closing the session.
170#[derive(Debug, Clone, Serialize, Deserialize, Default)]
171pub struct RealtimeTranslationClientEventSessionClose {
172    /// Optional client-generated ID used to identify this event.
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub event_id: Option<String>,
175}
176
177/// A Realtime translation client event.
178#[derive(Debug, Clone, Serialize, Deserialize)]
179#[serde(tag = "type")]
180pub enum RealtimeTranslationClientEvent {
181    #[serde(rename = "session.update")]
182    SessionUpdate(RealtimeTranslationClientEventSessionUpdate),
183    #[serde(rename = "session.input_audio_buffer.append")]
184    InputAudioBufferAppend(RealtimeTranslationClientEventInputAudioBufferAppend),
185    #[serde(rename = "session.close")]
186    SessionClose(RealtimeTranslationClientEventSessionClose),
187}
188
189/// Audio encoding for the translated audio delta.
190#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
191#[serde(rename_all = "lowercase")]
192pub enum RealtimeTranslationAudioFormat {
193    PCM16,
194}
195
196/// Returned when a translation session is created. Emitted automatically when a
197/// new connection is established as the first server event. This event contains
198/// the default translation session configuration.
199#[derive(Debug, Clone, Serialize, Deserialize, Default)]
200pub struct RealtimeTranslationServerEventSessionCreated {
201    /// The unique ID of the server event.
202    pub event_id: String,
203    /// The translation session configuration.
204    pub session: RealtimeTranslationSession,
205}
206
207/// Returned when a translation session is updated with a `session.update` event,
208/// unless there is an error.
209#[derive(Debug, Clone, Serialize, Deserialize, Default)]
210pub struct RealtimeTranslationServerEventSessionUpdated {
211    /// The unique ID of the server event.
212    pub event_id: String,
213    /// The translation session configuration.
214    pub session: RealtimeTranslationSession,
215}
216
217/// Returned when a realtime translation session is closed.
218#[derive(Debug, Clone, Serialize, Deserialize, Default)]
219pub struct RealtimeTranslationServerEventSessionClosed {
220    /// The unique ID of the server event.
221    pub event_id: String,
222}
223
224/// Returned when optional source-language transcript text is available. This event
225/// is emitted only when `audio.input.transcription` is configured.
226///
227/// Transcript deltas are append-only text fragments. Clients should not insert
228/// unconditional spaces between deltas.
229#[derive(Debug, Clone, Serialize, Deserialize, Default)]
230pub struct RealtimeTranslationServerEventSessionInputTranscriptDelta {
231    /// The unique ID of the server event.
232    pub event_id: String,
233    /// Append-only source-language transcript text.
234    pub delta: String,
235    /// Timing metadata for stream alignment, derived from the translation frame
236    /// when available. It advances in 200 ms increments, but multiple transcript
237    /// deltas may share the same `elapsed_ms`. Treat it as alignment metadata,
238    /// not a unique transcript-delta identifier.
239    #[serde(default, skip_serializing_if = "Option::is_none")]
240    pub elapsed_ms: Option<u64>,
241}
242
243/// Returned when translated transcript text is available.
244///
245/// Transcript deltas are append-only text fragments. Clients should not insert
246/// unconditional spaces between deltas.
247#[derive(Debug, Clone, Serialize, Deserialize, Default)]
248pub struct RealtimeTranslationServerEventSessionOutputTranscriptDelta {
249    /// The unique ID of the server event.
250    pub event_id: String,
251    /// Append-only transcript text for the translated output audio.
252    pub delta: String,
253    /// Timing metadata for stream alignment, derived from the translation frame
254    /// when available. It advances in 200 ms increments, but multiple transcript
255    /// deltas may share the same `elapsed_ms`. Treat it as alignment metadata,
256    /// not a unique transcript-delta identifier.
257    #[serde(default, skip_serializing_if = "Option::is_none")]
258    pub elapsed_ms: Option<u64>,
259}
260
261/// Returned when translated output audio is available. Output audio deltas are
262/// 200 ms frames of PCM16 audio.
263#[derive(Debug, Clone, Serialize, Deserialize, Default)]
264pub struct RealtimeTranslationServerEventSessionOutputAudioDelta {
265    /// The unique ID of the server event.
266    pub event_id: String,
267    /// Base64-encoded translated audio data.
268    pub delta: String,
269    /// Sample rate of the audio delta. Defaults to 24000.
270    #[serde(default, skip_serializing_if = "Option::is_none")]
271    pub sample_rate: Option<u32>,
272    /// Number of audio channels. Defaults to 1.
273    #[serde(default, skip_serializing_if = "Option::is_none")]
274    pub channels: Option<u32>,
275    /// Audio encoding for `delta`.
276    #[serde(default, skip_serializing_if = "Option::is_none")]
277    pub format: Option<RealtimeTranslationAudioFormat>,
278    /// Timing metadata for stream alignment, derived from the translation frame
279    /// when available. Treat `elapsed_ms` as alignment metadata, not a unique
280    /// event identifier.
281    #[serde(default, skip_serializing_if = "Option::is_none")]
282    pub elapsed_ms: Option<u64>,
283}
284
285/// A Realtime translation server event.
286#[derive(Debug, Clone, Serialize, Deserialize)]
287#[serde(tag = "type")]
288pub enum RealtimeTranslationServerEvent {
289    #[serde(rename = "error")]
290    Error(RealtimeServerEventError),
291    #[serde(rename = "session.created")]
292    SessionCreated(RealtimeTranslationServerEventSessionCreated),
293    #[serde(rename = "session.updated")]
294    SessionUpdated(RealtimeTranslationServerEventSessionUpdated),
295    #[serde(rename = "session.closed")]
296    SessionClosed(RealtimeTranslationServerEventSessionClosed),
297    #[serde(rename = "session.input_transcript.delta")]
298    SessionInputTranscriptDelta(RealtimeTranslationServerEventSessionInputTranscriptDelta),
299    #[serde(rename = "session.output_transcript.delta")]
300    SessionOutputTranscriptDelta(RealtimeTranslationServerEventSessionOutputTranscriptDelta),
301    #[serde(rename = "session.output_audio.delta")]
302    SessionOutputAudioDelta(RealtimeTranslationServerEventSessionOutputAudioDelta),
303}