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}