Skip to main content

gproxy_protocol/protocol/openai/audio/
mod.rs

1mod enums;
2mod requests;
3mod responses;
4mod stream;
5
6pub use enums::*;
7pub use requests::*;
8pub use responses::*;
9pub use stream::*;
10
11use super::common::OpenAiWireModel;
12
13/// Speech responses are raw audio bytes unless `stream_format=sse` is used.
14pub type SpeechWireModel = OpenAiWireModel<SpeechRequest, Vec<u8>>;
15pub type TranscriptionWireModel = OpenAiWireModel<TranscriptionRequest, TranscriptionResponse>;
16pub type TranscriptionStreamWireModel =
17    OpenAiWireModel<TranscriptionRequest, TranscriptionStreamEvent>;
18pub type TranslationWireModel = OpenAiWireModel<TranslationRequest, TranslationResponse>;
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23
24    #[test]
25    fn transcription_request_accepts_normalized_multipart_fields() {
26        let request: TranscriptionRequest = serde_json::from_value(serde_json::json!({
27            "file": "data:audio/wav;base64,UklGRg==",
28            "model": "gpt-4o-transcribe-diarize",
29            "chunking_strategy": {"type": "server_vad", "threshold": 0.5},
30            "known_speaker_names": ["agent"],
31            "response_format": "diarized_json",
32            "stream": true
33        }))
34        .unwrap();
35        assert!(request.stream.is_some_and(|stream| stream));
36        assert!(matches!(
37            request.chunking_strategy,
38            Some(AudioChunkingStrategy::ServerVad(_))
39        ));
40    }
41
42    #[test]
43    fn transcription_response_selects_verbose_shape() {
44        let response: TranscriptionResponse = serde_json::from_value(serde_json::json!({
45            "task": "transcribe",
46            "language": "english",
47            "duration": 1.5,
48            "text": "hello",
49            "segments": []
50        }))
51        .unwrap();
52        assert!(matches!(response, TranscriptionResponse::Verbose(_)));
53    }
54
55    #[test]
56    fn changed_known_stream_event_falls_back_losslessly() {
57        let event: TranscriptionStreamEvent = serde_json::from_value(serde_json::json!({
58            "type": "transcript.text.delta",
59            "delta": {"future": true}
60        }))
61        .unwrap();
62        assert!(matches!(event, TranscriptionStreamEvent::Unknown(_)));
63    }
64
65    #[test]
66    fn stream_done_accepts_official_usage_without_type_discriminator() {
67        let event: TranscriptionStreamEvent = serde_json::from_value(serde_json::json!({
68            "type": "transcript.text.done",
69            "text": "hello",
70            "usage": {"input_tokens": 7, "output_tokens": 3, "total_tokens": 10}
71        }))
72        .unwrap();
73        assert!(matches!(event, TranscriptionStreamEvent::Known(_)));
74    }
75}