openai 0.86.0 → 0.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +10 -1
- data/examples/audio/record_and_play.rb +19 -0
- data/examples/responses/websocket_workflows.rb +159 -0
- data/lib/openai/helpers/local_audio/errors.rb +27 -0
- data/lib/openai/helpers/local_audio/process.rb +158 -0
- data/lib/openai/helpers/local_audio.rb +157 -0
- data/lib/openai/helpers/realtime/connection.rb +20 -2
- data/lib/openai/helpers/realtime/errors.rb +18 -0
- data/lib/openai/helpers/realtime/recovery.rb +489 -0
- data/lib/openai/helpers/realtime/resources/realtime_extension.rb +26 -1
- data/lib/openai/helpers/realtime.rb +1 -0
- data/lib/openai/models/beta/beta_response_input_item.rb +84 -1
- data/lib/openai/models/beta/beta_response_item.rb +72 -1
- data/lib/openai/models/beta/beta_response_output_item.rb +84 -1
- data/lib/openai/models/beta/beta_responses_client_event.rb +3 -0
- data/lib/openai/models/beta/beta_tool.rb +69 -37
- data/lib/openai/models/beta/response_create_params.rb +3 -0
- data/lib/openai/models/conversations/conversation_item.rb +82 -1
- data/lib/openai/models/image_edit_completed_event.rb +34 -8
- data/lib/openai/models/image_edit_params.rb +64 -44
- data/lib/openai/models/image_edit_partial_image_event.rb +34 -8
- data/lib/openai/models/image_gen_completed_event.rb +34 -8
- data/lib/openai/models/image_gen_partial_image_event.rb +34 -8
- data/lib/openai/models/image_generate_params.rb +51 -35
- data/lib/openai/models/image_model.rb +4 -0
- data/lib/openai/models/images_response.rb +37 -13
- data/lib/openai/models/responses/response_create_params.rb +3 -0
- data/lib/openai/models/responses/response_input_item.rb +84 -1
- data/lib/openai/models/responses/response_item.rb +72 -1
- data/lib/openai/models/responses/response_output_item.rb +84 -1
- data/lib/openai/models/responses/responses_client_event.rb +3 -0
- data/lib/openai/models/responses/tool.rb +69 -37
- data/lib/openai/models/webhooks/live_call_incoming_webhook_event.rb +3 -3
- data/lib/openai/models/webhooks/realtime_call_incoming_webhook_event.rb +5 -3
- data/lib/openai/resources/images.rb +12 -14
- data/lib/openai/version.rb +1 -1
- data/local-audio.md +146 -0
- data/rbi/openai/helpers/local_audio/interface.rbi +110 -0
- data/rbi/openai/helpers/realtime/connection.rbi +18 -2
- data/rbi/openai/helpers/realtime/extensions.rbi +8 -0
- data/rbi/openai/helpers/realtime/recovery.rbi +27 -0
- data/rbi/openai/models/beta/beta_response_input_item.rbi +86 -1
- data/rbi/openai/models/beta/beta_response_item.rbi +78 -1
- data/rbi/openai/models/beta/beta_response_output_item.rbi +84 -1
- data/rbi/openai/models/beta/beta_responses_client_event.rbi +6 -0
- data/rbi/openai/models/beta/beta_tool.rbi +90 -51
- data/rbi/openai/models/beta/response_create_params.rbi +6 -0
- data/rbi/openai/models/conversations/conversation_item.rbi +88 -1
- data/rbi/openai/models/image_edit_completed_event.rbi +20 -9
- data/rbi/openai/models/image_edit_params.rbi +89 -60
- data/rbi/openai/models/image_edit_partial_image_event.rbi +20 -9
- data/rbi/openai/models/image_gen_completed_event.rbi +20 -9
- data/rbi/openai/models/image_gen_partial_image_event.rbi +20 -9
- data/rbi/openai/models/image_generate_params.rbi +71 -48
- data/rbi/openai/models/image_model.rbi +4 -0
- data/rbi/openai/models/images_response.rbi +27 -16
- data/rbi/openai/models/responses/response_create_params.rbi +6 -0
- data/rbi/openai/models/responses/response_input_item.rbi +88 -1
- data/rbi/openai/models/responses/response_item.rbi +80 -1
- data/rbi/openai/models/responses/response_output_item.rbi +84 -1
- data/rbi/openai/models/responses/responses_client_event.rbi +6 -0
- data/rbi/openai/models/responses/tool.rbi +90 -51
- data/rbi/openai/models/webhooks/live_call_incoming_webhook_event.rbi +4 -4
- data/rbi/openai/models/webhooks/realtime_call_incoming_webhook_event.rbi +8 -4
- data/rbi/openai/resources/beta/responses.rbi +6 -2
- data/rbi/openai/resources/images.rbi +106 -76
- data/rbi/openai/resources/responses.rbi +6 -0
- data/realtime.md +101 -0
- data/responses-websocket.md +182 -0
- data/sig/openai/helpers/local_audio/interface.rbs +62 -0
- data/sig/openai/helpers/realtime/connection.rbs +9 -1
- data/sig/openai/helpers/realtime/extensions.rbs +4 -0
- data/sig/openai/helpers/realtime/recovery.rbs +19 -0
- data/sig/openai/models/beta/beta_response_input_item.rbs +39 -2
- data/sig/openai/models/beta/beta_response_item.rbs +39 -2
- data/sig/openai/models/beta/beta_response_output_item.rbs +39 -2
- data/sig/openai/models/beta/beta_tool.rbs +11 -1
- data/sig/openai/models/conversations/conversation_item.rbs +39 -2
- data/sig/openai/models/image_edit_completed_event.rbs +11 -4
- data/sig/openai/models/image_edit_params.rbs +3 -1
- data/sig/openai/models/image_edit_partial_image_event.rbs +11 -4
- data/sig/openai/models/image_gen_completed_event.rbs +11 -4
- data/sig/openai/models/image_gen_partial_image_event.rbs +11 -4
- data/sig/openai/models/image_generate_params.rbs +4 -1
- data/sig/openai/models/image_model.rbs +8 -0
- data/sig/openai/models/images_response.rbs +10 -4
- data/sig/openai/models/responses/response_input_item.rbs +39 -2
- data/sig/openai/models/responses/response_item.rbs +39 -2
- data/sig/openai/models/responses/response_output_item.rbs +39 -2
- data/sig/openai/models/responses/tool.rbs +11 -1
- metadata +15 -1
|
@@ -55,8 +55,10 @@ module OpenAI
|
|
|
55
55
|
# @see OpenAI::Models::Webhooks::RealtimeCallIncomingWebhookEvent#data
|
|
56
56
|
class Data < OpenAI::Internal::Type::BaseModel
|
|
57
57
|
# @!attribute call_id
|
|
58
|
-
# The Transceiver `rtc_...` ID of the pending SIP session. The
|
|
59
|
-
#
|
|
58
|
+
# The Transceiver `rtc_...` ID of the pending SIP session. The paired
|
|
59
|
+
# `live.call.incoming` event derives its `session_id` by replacing the `rtc_`
|
|
60
|
+
# prefix with `live_`. Use the ID returned by the event with the corresponding
|
|
61
|
+
# Realtime or Live API.
|
|
60
62
|
#
|
|
61
63
|
# @return [String]
|
|
62
64
|
required :call_id, String
|
|
@@ -77,7 +79,7 @@ module OpenAI
|
|
|
77
79
|
#
|
|
78
80
|
# Event data payload.
|
|
79
81
|
#
|
|
80
|
-
# @param call_id [String] The Transceiver `rtc_...` ID of the pending SIP session. The
|
|
82
|
+
# @param call_id [String] The Transceiver `rtc_...` ID of the pending SIP session. The paired
|
|
81
83
|
#
|
|
82
84
|
# @param sip_headers [Array<OpenAI::Models::Webhooks::RealtimeCallIncomingWebhookEvent::Data::SipHeader>] Headers from the SIP Invite.
|
|
83
85
|
|
|
@@ -51,8 +51,7 @@ module OpenAI
|
|
|
51
51
|
# {OpenAI::Models::ImageEditParams} for more details.
|
|
52
52
|
#
|
|
53
53
|
# Creates an edited or extended image given one or more source images and a
|
|
54
|
-
# prompt. This endpoint supports GPT Image models
|
|
55
|
-
# `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`.
|
|
54
|
+
# prompt. This endpoint supports GPT Image models and `dall-e-2`.
|
|
56
55
|
#
|
|
57
56
|
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
58
57
|
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
@@ -64,7 +63,7 @@ module OpenAI
|
|
|
64
63
|
#
|
|
65
64
|
# @param prompt [String] A text description of the desired image(s). The maximum length is 1000 character
|
|
66
65
|
#
|
|
67
|
-
# @param background [Symbol, OpenAI::Models::ImageEditParams::Background, nil] Allows to set transparency for the background of the generated image(s).
|
|
66
|
+
# @param background [Symbol, OpenAI::Models::ImageEditParams::Background, nil] Allows to set transparency for the background of the generated image(s). Must
|
|
68
67
|
#
|
|
69
68
|
# @param input_fidelity [Symbol, OpenAI::Models::ImageEditParams::InputFidelity, nil] Control how much effort the model will exert to match the style and features, es
|
|
70
69
|
#
|
|
@@ -80,11 +79,11 @@ module OpenAI
|
|
|
80
79
|
#
|
|
81
80
|
# @param partial_images [Integer, nil] The number of partial images to generate. This parameter is used for
|
|
82
81
|
#
|
|
83
|
-
# @param quality [Symbol, OpenAI::Models::ImageEditParams::Quality, nil] The quality of the image that will be generated for GPT image models.
|
|
82
|
+
# @param quality [Symbol, OpenAI::Models::ImageEditParams::Quality, nil] The quality of the image that will be generated for GPT image models. The GPT im
|
|
84
83
|
#
|
|
85
84
|
# @param response_format [Symbol, OpenAI::Models::ImageEditParams::ResponseFormat, nil] The format in which the generated images are returned. Must be one of `url` or `
|
|
86
85
|
#
|
|
87
|
-
# @param size [String, Symbol, OpenAI::Models::ImageEditParams::Size, nil] The size of the generated images. For `gpt-image-2
|
|
86
|
+
# @param size [String, Symbol, OpenAI::Models::ImageEditParams::Size, nil] The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `
|
|
88
87
|
#
|
|
89
88
|
# @param user [String] A unique identifier representing your end-user, which can help OpenAI to monitor
|
|
90
89
|
#
|
|
@@ -117,8 +116,7 @@ module OpenAI
|
|
|
117
116
|
# {OpenAI::Models::ImageEditParams} for more details.
|
|
118
117
|
#
|
|
119
118
|
# Creates an edited or extended image given one or more source images and a
|
|
120
|
-
# prompt. This endpoint supports GPT Image models
|
|
121
|
-
# `gpt-image-1-mini`, and `chatgpt-image-latest`) and `dall-e-2`.
|
|
119
|
+
# prompt. This endpoint supports GPT Image models and `dall-e-2`.
|
|
122
120
|
#
|
|
123
121
|
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
124
122
|
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
@@ -130,7 +128,7 @@ module OpenAI
|
|
|
130
128
|
#
|
|
131
129
|
# @param prompt [String] A text description of the desired image(s). The maximum length is 1000 character
|
|
132
130
|
#
|
|
133
|
-
# @param background [Symbol, OpenAI::Models::ImageEditParams::Background, nil] Allows to set transparency for the background of the generated image(s).
|
|
131
|
+
# @param background [Symbol, OpenAI::Models::ImageEditParams::Background, nil] Allows to set transparency for the background of the generated image(s). Must
|
|
134
132
|
#
|
|
135
133
|
# @param input_fidelity [Symbol, OpenAI::Models::ImageEditParams::InputFidelity, nil] Control how much effort the model will exert to match the style and features, es
|
|
136
134
|
#
|
|
@@ -146,11 +144,11 @@ module OpenAI
|
|
|
146
144
|
#
|
|
147
145
|
# @param partial_images [Integer, nil] The number of partial images to generate. This parameter is used for
|
|
148
146
|
#
|
|
149
|
-
# @param quality [Symbol, OpenAI::Models::ImageEditParams::Quality, nil] The quality of the image that will be generated for GPT image models.
|
|
147
|
+
# @param quality [Symbol, OpenAI::Models::ImageEditParams::Quality, nil] The quality of the image that will be generated for GPT image models. The GPT im
|
|
150
148
|
#
|
|
151
149
|
# @param response_format [Symbol, OpenAI::Models::ImageEditParams::ResponseFormat, nil] The format in which the generated images are returned. Must be one of `url` or `
|
|
152
150
|
#
|
|
153
|
-
# @param size [String, Symbol, OpenAI::Models::ImageEditParams::Size, nil] The size of the generated images. For `gpt-image-2
|
|
151
|
+
# @param size [String, Symbol, OpenAI::Models::ImageEditParams::Size, nil] The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `
|
|
154
152
|
#
|
|
155
153
|
# @param user [String] A unique identifier representing your end-user, which can help OpenAI to monitor
|
|
156
154
|
#
|
|
@@ -195,7 +193,7 @@ module OpenAI
|
|
|
195
193
|
#
|
|
196
194
|
# @param prompt [String] A text description of the desired image(s). The maximum length is 32000 characte
|
|
197
195
|
#
|
|
198
|
-
# @param background [Symbol, OpenAI::Models::ImageGenerateParams::Background, nil] Allows to set transparency for the background of the generated image(s).
|
|
196
|
+
# @param background [Symbol, OpenAI::Models::ImageGenerateParams::Background, nil] Allows to set transparency for the background of the generated image(s). Must
|
|
199
197
|
#
|
|
200
198
|
# @param model [String, Symbol, OpenAI::Models::ImageModel, nil] The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT i
|
|
201
199
|
#
|
|
@@ -213,7 +211,7 @@ module OpenAI
|
|
|
213
211
|
#
|
|
214
212
|
# @param response_format [Symbol, OpenAI::Models::ImageGenerateParams::ResponseFormat, nil] The format in which generated images with `dall-e-2` and `dall-e-3` are returned
|
|
215
213
|
#
|
|
216
|
-
# @param size [String, Symbol, OpenAI::Models::ImageGenerateParams::Size, nil] The size of the generated images. For `gpt-image-2
|
|
214
|
+
# @param size [String, Symbol, OpenAI::Models::ImageGenerateParams::Size, nil] The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `
|
|
217
215
|
#
|
|
218
216
|
# @param style [Symbol, OpenAI::Models::ImageGenerateParams::Style, nil] The style of the generated images. This parameter is only supported for `dall-e-
|
|
219
217
|
#
|
|
@@ -253,7 +251,7 @@ module OpenAI
|
|
|
253
251
|
#
|
|
254
252
|
# @param prompt [String] A text description of the desired image(s). The maximum length is 32000 characte
|
|
255
253
|
#
|
|
256
|
-
# @param background [Symbol, OpenAI::Models::ImageGenerateParams::Background, nil] Allows to set transparency for the background of the generated image(s).
|
|
254
|
+
# @param background [Symbol, OpenAI::Models::ImageGenerateParams::Background, nil] Allows to set transparency for the background of the generated image(s). Must
|
|
257
255
|
#
|
|
258
256
|
# @param model [String, Symbol, OpenAI::Models::ImageModel, nil] The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT i
|
|
259
257
|
#
|
|
@@ -271,7 +269,7 @@ module OpenAI
|
|
|
271
269
|
#
|
|
272
270
|
# @param response_format [Symbol, OpenAI::Models::ImageGenerateParams::ResponseFormat, nil] The format in which generated images with `dall-e-2` and `dall-e-3` are returned
|
|
273
271
|
#
|
|
274
|
-
# @param size [String, Symbol, OpenAI::Models::ImageGenerateParams::Size, nil] The size of the generated images. For `gpt-image-2
|
|
272
|
+
# @param size [String, Symbol, OpenAI::Models::ImageGenerateParams::Size, nil] The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `
|
|
275
273
|
#
|
|
276
274
|
# @param style [Symbol, OpenAI::Models::ImageGenerateParams::Style, nil] The style of the generated images. This parameter is only supported for `dall-e-
|
|
277
275
|
#
|
data/lib/openai/version.rb
CHANGED
data/local-audio.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Local recording and playback
|
|
2
|
+
|
|
3
|
+
Use `OpenAI::LocalAudio` to record a finite microphone clip or play generated
|
|
4
|
+
speech. These helpers run separately installed FFmpeg and FFplay executables.
|
|
5
|
+
They do not add native gem dependencies. Loading `openai` or the helper does not
|
|
6
|
+
open a device; calling `record` or `play` starts the corresponding operation.
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
Install FFmpeg and FFplay and make both executables available on `PATH`. Your
|
|
11
|
+
FFmpeg build must include the capture backend for your operating system. Allow
|
|
12
|
+
microphone access in your operating system when recording.
|
|
13
|
+
|
|
14
|
+
With `OPENAI_API_KEY` configured, run:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
bundle exec ruby examples/audio/record_and_play.rb
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The example records five seconds, uploads the clip for transcription, prints the
|
|
21
|
+
transcript, and plays generated speech. Models and voice are constants at the top
|
|
22
|
+
of the example so they are easy to change.
|
|
23
|
+
|
|
24
|
+
## Record a clip
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
require "openai"
|
|
28
|
+
require "openai/helpers/local_audio"
|
|
29
|
+
|
|
30
|
+
client = OpenAI::Client.new
|
|
31
|
+
clip = OpenAI::LocalAudio.record(duration: 5, timeout: 10)
|
|
32
|
+
transcript = client.audio.transcriptions.create(model: "gpt-transcribe", file: clip)
|
|
33
|
+
puts(transcript.text)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`record(duration:, device: nil, timeout: nil)` returns an `OpenAI::FilePart`
|
|
37
|
+
containing a rewound `StringIO`, named `audio.wav` with content type `audio/wav`.
|
|
38
|
+
The audio is mono, 24 kHz, signed 16-bit PCM. The helper buffers the recording in
|
|
39
|
+
memory, so memory use grows with recording duration.
|
|
40
|
+
|
|
41
|
+
`duration` is required and must be positive and finite. `timeout` is an optional
|
|
42
|
+
positive, finite wall-clock deadline in seconds. An expired deadline raises an
|
|
43
|
+
error rather than returning a partial recording.
|
|
44
|
+
|
|
45
|
+
### Choose a microphone
|
|
46
|
+
|
|
47
|
+
On macOS and Linux, omitting `device:` uses the capture backend's default device.
|
|
48
|
+
To select another microphone, pass `device:` directly:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# macOS: AVFoundation audio device index (or its device name).
|
|
52
|
+
clip = OpenAI::LocalAudio.record(duration: 5, device: 0)
|
|
53
|
+
|
|
54
|
+
# Linux: ALSA device name; integer 0 is shorthand for "hw:0".
|
|
55
|
+
clip = OpenAI::LocalAudio.record(duration: 5, device: "hw:0")
|
|
56
|
+
|
|
57
|
+
# Windows: DirectShow requires an explicit audio device name.
|
|
58
|
+
clip = OpenAI::LocalAudio.record(duration: 5, device: "Microphone (USB Audio)")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For Windows, add the appropriate `device:` argument to the example's `record`
|
|
62
|
+
call. There is no device environment variable to configure. Device names and
|
|
63
|
+
indices are local to your machine and may change when hardware is reconnected.
|
|
64
|
+
|
|
65
|
+
List capture devices using your platform's tools:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
# macOS (FFmpeg prints the list and exits without recording)
|
|
69
|
+
ffmpeg -f avfoundation -list_devices true -i ""
|
|
70
|
+
|
|
71
|
+
# Linux
|
|
72
|
+
arecord -L
|
|
73
|
+
|
|
74
|
+
# Windows (FFmpeg prints the list and exits without recording)
|
|
75
|
+
ffmpeg -list_devices true -f dshow -i dummy
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Play speech
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
speech = client.audio.speech.create(
|
|
82
|
+
model: "gpt-4o-mini-tts",
|
|
83
|
+
voice: "marin",
|
|
84
|
+
input: "Recording complete."
|
|
85
|
+
)
|
|
86
|
+
OpenAI::LocalAudio.play(speech, timeout: 30)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`play(source, format: :auto, timeout: nil)` waits for FFplay to finish and returns
|
|
90
|
+
`nil`. It accepts `IO`, `StringIO`, or a `FilePart` containing IO or binary bytes.
|
|
91
|
+
It reads from the source's current position and leaves caller-owned IO open. Bare
|
|
92
|
+
strings are not interpreted as file paths or URLs.
|
|
93
|
+
|
|
94
|
+
The default `format: :auto` supports self-contained WAV, MP3, Ogg, AAC and FLAC
|
|
95
|
+
streams. For headerless mono 24 kHz signed little-endian PCM16, pass
|
|
96
|
+
`format: :pcm`. PCM must end on a complete two-byte sample. Playback uses FFplay's
|
|
97
|
+
configured output device; this helper has no output-device selector.
|
|
98
|
+
|
|
99
|
+
Both methods close their pipes and terminate/reap owned subprocesses on errors
|
|
100
|
+
or interruption. Errors are under `OpenAI::LocalAudio::Error`:
|
|
101
|
+
`DependencyError`, `UnsupportedPlatformError`, `DeviceError`, `PlaybackError`,
|
|
102
|
+
`FormatError`, and `TimeoutError`. Media subprocesses receive a restricted
|
|
103
|
+
environment without the API key, and their diagnostics are not included in
|
|
104
|
+
exceptions. FFplay can exit successfully despite a decoder or device error, so
|
|
105
|
+
the helper drains error-level diagnostics through a pipe, retaining only whether
|
|
106
|
+
an error occurred. Diagnostic contents are discarded and never written to disk.
|
|
107
|
+
|
|
108
|
+
## Model choices
|
|
109
|
+
|
|
110
|
+
Checked against OpenAI documentation on September 8, 2026:
|
|
111
|
+
|
|
112
|
+
- [`gpt-transcribe`](https://developers.openai.com/api/docs/guides/speech-to-text) is the recommended model for general-purpose file transcription.
|
|
113
|
+
- [`gpt-4o-mini-tts`](https://developers.openai.com/api/docs/guides/text-to-speech) is the current recommended speech-generation model; `marin` is one of the recommended voices for quality.
|
|
114
|
+
|
|
115
|
+
## Realtime applications
|
|
116
|
+
|
|
117
|
+
For streaming audio and conversation events, use the existing
|
|
118
|
+
[Realtime API helpers](realtime.md) and [Realtime examples](examples/realtime/README.md).
|
|
119
|
+
The finite helpers here do not manage a continuous microphone stream,
|
|
120
|
+
interruptible voice conversation, echo cancellation, or playback-position tracking.
|
|
121
|
+
|
|
122
|
+
## End-to-end verification
|
|
123
|
+
|
|
124
|
+
Run the actual recording example against the live API without opening physical
|
|
125
|
+
devices:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
bundle exec ruby scripts/test-local-audio-examples.rb
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
To also run the invalid-audio regression against installed FFplay:
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
OPENAI_AUDIO_FFPLAY_TEST=1 bundle exec ruby test/openai/helpers/local_audio_test.rb
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This opt-in test requires `OPENAI_API_KEY`, FFmpeg and FFplay and makes paid API
|
|
138
|
+
calls. It generates synthetic speech, substitutes that file for microphone input,
|
|
139
|
+
runs real FFmpeg capture and transcription, generates speech, and plays it through
|
|
140
|
+
FFplay's dummy output driver. It checks the transcription and successful example
|
|
141
|
+
completion with a 90-second example deadline. Captured API output is not logged;
|
|
142
|
+
temporary synthetic media is removed on normal exit or exceptions.
|
|
143
|
+
|
|
144
|
+
This verifies the software flow, not physical microphone permissions, speaker
|
|
145
|
+
output, or device compatibility. Physical hardware and platform behavior must be
|
|
146
|
+
checked on the intended host.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
module OpenAI
|
|
4
|
+
module LocalAudio
|
|
5
|
+
sig {
|
|
6
|
+
params(duration: Numeric, device: T.nilable(T.any(String, Integer)), timeout: T.nilable(Numeric)).returns(
|
|
7
|
+
OpenAI::FilePart
|
|
8
|
+
)
|
|
9
|
+
}
|
|
10
|
+
def self.record(duration:, device: nil, timeout: nil)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
sig {
|
|
14
|
+
params(source: T.any(IO, StringIO, OpenAI::FilePart), format: Symbol, timeout: T.nilable(Numeric)).returns(
|
|
15
|
+
NilClass
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
def self.play(source, format: :auto, timeout: nil)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @api private
|
|
22
|
+
sig { params(source: T.any(IO, StringIO, OpenAI::FilePart)).returns(T.any(IO, StringIO)) }
|
|
23
|
+
def self.playback_source(source)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @api private
|
|
27
|
+
sig { params(device: T.nilable(T.any(String, Integer)), platform: String).returns([String, String]) }
|
|
28
|
+
def self.capture_device(device, platform: RUBY_PLATFORM)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @api private
|
|
32
|
+
sig { params(bytes: Integer).returns(String) }
|
|
33
|
+
def self.wav_header(bytes)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @api private
|
|
37
|
+
class MediaProcess
|
|
38
|
+
sig { returns(T::Hash[String, String]) }
|
|
39
|
+
def self.environment
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
sig { returns(Float) }
|
|
43
|
+
def self.clock
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
sig { params(value: Numeric, name: T.any(String, Symbol)).returns(Float) }
|
|
47
|
+
def self.duration(value, name:)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
sig {
|
|
51
|
+
params(
|
|
52
|
+
argv: T::Array[String],
|
|
53
|
+
input: T.any(IO, String),
|
|
54
|
+
output: T.any(IO, String),
|
|
55
|
+
timeout: T.nilable(Numeric),
|
|
56
|
+
capture_errors: T::Boolean
|
|
57
|
+
)
|
|
58
|
+
.void
|
|
59
|
+
}
|
|
60
|
+
def initialize(argv, input:, output:, timeout:, capture_errors: false)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
sig { void }
|
|
64
|
+
def check_deadline
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
sig { returns(T::Boolean) }
|
|
68
|
+
def errors?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
sig { params(io: T.any(IO, StringIO), stop_on_exit: T::Boolean).returns(T.nilable(String)) }
|
|
72
|
+
def read(io, stop_on_exit: false)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
sig { params(io: IO, bytes: String).void }
|
|
76
|
+
def write(io, bytes)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
sig { returns(Process::Status) }
|
|
80
|
+
def wait
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
sig { void }
|
|
84
|
+
def close
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class Error < OpenAI::Errors::Error
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class DependencyError < OpenAI::LocalAudio::Error
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class UnsupportedPlatformError < OpenAI::LocalAudio::Error
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class DeviceError < OpenAI::LocalAudio::Error
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class PlaybackError < OpenAI::LocalAudio::Error
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class TimeoutError < OpenAI::LocalAudio::Error
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class FormatError < OpenAI::LocalAudio::Error
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -39,9 +39,9 @@ module OpenAI
|
|
|
39
39
|
|
|
40
40
|
# @api private
|
|
41
41
|
sig do
|
|
42
|
-
params(socket: T.untyped, url: URI::Generic).returns(T.attached_class)
|
|
42
|
+
params(socket: T.untyped, url: URI::Generic, recovery: T.untyped).returns(T.attached_class)
|
|
43
43
|
end
|
|
44
|
-
def self.new(socket:, url:)
|
|
44
|
+
def self.new(socket:, url:, recovery: nil)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
sig do
|
|
@@ -75,6 +75,22 @@ module OpenAI
|
|
|
75
75
|
def send_raw(data)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
sig { returns(T::Boolean) }
|
|
79
|
+
def reconnecting?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
sig { returns(T::Array[String]) }
|
|
83
|
+
def pending_messages
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
sig { returns(T::Array[String]) }
|
|
87
|
+
def take_pending_messages
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
sig { void }
|
|
91
|
+
def flush_pending
|
|
92
|
+
end
|
|
93
|
+
|
|
78
94
|
sig { params(code: Integer, reason: String).void }
|
|
79
95
|
def close(code: 1000, reason: "")
|
|
80
96
|
end
|
|
@@ -98,6 +98,10 @@ module OpenAI
|
|
|
98
98
|
sig do
|
|
99
99
|
params(
|
|
100
100
|
model: String,
|
|
101
|
+
reconnect: T::Boolean,
|
|
102
|
+
max_reconnect_attempts: Integer,
|
|
103
|
+
max_queue_bytes: Integer,
|
|
104
|
+
on_reconnected: T.nilable(T.proc.params(connection: OpenAI::Realtime::Connection).void),
|
|
101
105
|
websocket_base_url: T.nilable(String),
|
|
102
106
|
request_options: T.nilable(OpenAI::RequestOptions::OrHash),
|
|
103
107
|
transport: T.untyped,
|
|
@@ -111,6 +115,10 @@ module OpenAI
|
|
|
111
115
|
end
|
|
112
116
|
def connect(
|
|
113
117
|
model:,
|
|
118
|
+
reconnect: false,
|
|
119
|
+
max_reconnect_attempts: 5,
|
|
120
|
+
max_queue_bytes: 0,
|
|
121
|
+
on_reconnected: nil,
|
|
114
122
|
websocket_base_url: nil,
|
|
115
123
|
request_options: nil,
|
|
116
124
|
transport: nil,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
module OpenAI
|
|
4
|
+
module Errors
|
|
5
|
+
class RealtimeQueueFullError < OpenAI::Errors::Error
|
|
6
|
+
sig { returns(T.attached_class) }
|
|
7
|
+
def self.new
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class RealtimeReconnectError < OpenAI::Errors::Error
|
|
12
|
+
sig { returns(T::Array[String]) }
|
|
13
|
+
attr_reader :unsent_messages
|
|
14
|
+
|
|
15
|
+
sig { returns(T.nilable(String)) }
|
|
16
|
+
attr_reader :uncertain_message
|
|
17
|
+
|
|
18
|
+
# @api private
|
|
19
|
+
sig do
|
|
20
|
+
params(message: String, unsent_messages: T::Array[String], uncertain_message: T.nilable(String))
|
|
21
|
+
.returns(T.attached_class)
|
|
22
|
+
end
|
|
23
|
+
def self.new(message:, unsent_messages: [], uncertain_message: nil)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -2109,6 +2109,17 @@ module OpenAI
|
|
|
2109
2109
|
}
|
|
2110
2110
|
attr_writer :agent
|
|
2111
2111
|
|
|
2112
|
+
# The quality of the image generated by the image generation tool call. One of
|
|
2113
|
+
# `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
|
|
2114
|
+
sig { returns(T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::OrSymbol)) }
|
|
2115
|
+
attr_accessor :quality
|
|
2116
|
+
|
|
2117
|
+
# The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`.
|
|
2118
|
+
sig {
|
|
2119
|
+
returns(T.nilable(T.any(String, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::OrSymbol)))
|
|
2120
|
+
}
|
|
2121
|
+
attr_accessor :size
|
|
2122
|
+
|
|
2112
2123
|
# An image generation request made by the model.
|
|
2113
2124
|
sig do
|
|
2114
2125
|
params(
|
|
@@ -2121,6 +2132,10 @@ module OpenAI
|
|
|
2121
2132
|
|
|
2122
2133
|
agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Agent::OrHash),
|
|
2123
2134
|
|
|
2135
|
+
quality: T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::OrSymbol),
|
|
2136
|
+
|
|
2137
|
+
size: T.nilable(T.any(String, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::OrSymbol)),
|
|
2138
|
+
|
|
2124
2139
|
type: Symbol
|
|
2125
2140
|
)
|
|
2126
2141
|
.returns(T.attached_class)
|
|
@@ -2139,6 +2154,13 @@ module OpenAI
|
|
|
2139
2154
|
# The agent that produced this item.
|
|
2140
2155
|
agent: nil,
|
|
2141
2156
|
|
|
2157
|
+
# The quality of the image generated by the image generation tool call. One of
|
|
2158
|
+
# `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
|
|
2159
|
+
quality: nil,
|
|
2160
|
+
|
|
2161
|
+
# The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`.
|
|
2162
|
+
size: nil,
|
|
2163
|
+
|
|
2142
2164
|
# The type of the image generation call. Always `image_generation_call`.
|
|
2143
2165
|
|
|
2144
2166
|
type: :image_generation_call
|
|
@@ -2152,7 +2174,9 @@ module OpenAI
|
|
|
2152
2174
|
result: T.nilable(String),
|
|
2153
2175
|
status: OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Status::OrSymbol,
|
|
2154
2176
|
type: Symbol,
|
|
2155
|
-
agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Agent)
|
|
2177
|
+
agent: T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Agent),
|
|
2178
|
+
quality: T.nilable(OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::OrSymbol),
|
|
2179
|
+
size: T.nilable(T.any(String, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::OrSymbol))
|
|
2156
2180
|
}
|
|
2157
2181
|
)
|
|
2158
2182
|
end
|
|
@@ -2226,6 +2250,67 @@ module OpenAI
|
|
|
2226
2250
|
end
|
|
2227
2251
|
|
|
2228
2252
|
end
|
|
2253
|
+
|
|
2254
|
+
# The quality of the image generated by the image generation tool call. One of
|
|
2255
|
+
# `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
|
|
2256
|
+
module Quality
|
|
2257
|
+
extend OpenAI::Internal::Type::Enum
|
|
2258
|
+
|
|
2259
|
+
TaggedSymbol = T.type_alias {
|
|
2260
|
+
T.all(Symbol, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality)
|
|
2261
|
+
}
|
|
2262
|
+
OrSymbol = T.type_alias { T.any(Symbol, String) }
|
|
2263
|
+
|
|
2264
|
+
LOW = T.let(:low, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2265
|
+
MEDIUM = T.let(:medium, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2266
|
+
HIGH = T.let(:high, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2267
|
+
XHIGH = T.let(:xhigh, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2268
|
+
MAX = T.let(:max, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2269
|
+
AUTO = T.let(:auto, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol)
|
|
2270
|
+
|
|
2271
|
+
sig {
|
|
2272
|
+
override.returns(
|
|
2273
|
+
T::Array[OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Quality::TaggedSymbol]
|
|
2274
|
+
)
|
|
2275
|
+
}
|
|
2276
|
+
def self.values
|
|
2277
|
+
end
|
|
2278
|
+
end
|
|
2279
|
+
|
|
2280
|
+
# The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`.
|
|
2281
|
+
module Size
|
|
2282
|
+
extend OpenAI::Internal::Type::Union
|
|
2283
|
+
|
|
2284
|
+
Variants = T.type_alias {
|
|
2285
|
+
T.any(String, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::TaggedSymbol)
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
sig {
|
|
2289
|
+
override.returns(T::Array[OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::Variants])
|
|
2290
|
+
}
|
|
2291
|
+
def self.variants
|
|
2292
|
+
end
|
|
2293
|
+
|
|
2294
|
+
TaggedSymbol = T.type_alias do
|
|
2295
|
+
T.all(Symbol, OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size)
|
|
2296
|
+
end
|
|
2297
|
+
|
|
2298
|
+
OrSymbol = T.type_alias { T.any(Symbol, String) }
|
|
2299
|
+
|
|
2300
|
+
SIZE_1024X1024 = T.let(
|
|
2301
|
+
:"1024x1024",
|
|
2302
|
+
OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::TaggedSymbol
|
|
2303
|
+
)
|
|
2304
|
+
SIZE_1024X1536 = T.let(
|
|
2305
|
+
:"1024x1536",
|
|
2306
|
+
OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::TaggedSymbol
|
|
2307
|
+
)
|
|
2308
|
+
SIZE_1536X1024 = T.let(
|
|
2309
|
+
:"1536x1024",
|
|
2310
|
+
OpenAI::Beta::BetaResponseInputItem::ImageGenerationCall::Size::TaggedSymbol
|
|
2311
|
+
)
|
|
2312
|
+
|
|
2313
|
+
end
|
|
2229
2314
|
end
|
|
2230
2315
|
|
|
2231
2316
|
class LocalShellCall < OpenAI::Internal::Type::BaseModel
|