|
2 | 2 | // Licensed under the MIT License.
|
3 | 3 |
|
4 | 4 | /*
|
5 |
| -# VoiceLive SDK Streaming Updates Usage Examples |
| 5 | +# VoiceLive SDK Server Events Usage Examples |
6 | 6 |
|
7 |
| -This file demonstrates how to use the VoiceLive SDK's streaming update functionality. |
| 7 | +This file demonstrates how to use the VoiceLive SDK's server event streaming functionality. |
8 | 8 |
|
9 |
| -## Basic Update Streaming |
| 9 | +## Basic Server Event Streaming |
10 | 10 |
|
11 | 11 | ```csharp
|
12 | 12 | using Azure.AI.VoiceLive;
|
13 | 13 |
|
14 | 14 | // Create and connect to a VoiceLive session
|
15 | 15 | var client = new VoiceLiveClient(endpoint, credential);
|
16 |
| -var session = await client.CreateSessionAsync(sessionOptions); |
| 16 | +var session = await client.StartSessionAsync(sessionOptions); |
17 | 17 |
|
18 |
| -// Get all updates as they arrive |
19 |
| -await foreach (VoiceLiveUpdate update in session.GetUpdatesAsync()) |
| 18 | +// Get all server events as they arrive |
| 19 | +await foreach (VoiceLiveServerEvent serverEvent in session.GetUpdatesAsync()) |
20 | 20 | {
|
21 |
| - Console.WriteLine($"Received update: {update.Kind}"); |
| 21 | + Console.WriteLine($"Received event: {serverEvent.Type}"); |
22 | 22 |
|
23 |
| - // Handle specific update types |
24 |
| - switch (update) |
| 23 | + // Handle specific event types |
| 24 | + switch (serverEvent) |
25 | 25 | {
|
26 |
| - case SessionStartedUpdate sessionStarted: |
27 |
| - Console.WriteLine($"Session started: {sessionStarted.SessionId}"); |
| 26 | + case VoiceLiveServerEventSessionCreated sessionCreated: |
| 27 | + Console.WriteLine($"Session created: {sessionCreated.Session?.Id}"); |
28 | 28 | break;
|
29 | 29 |
|
30 |
| - case OutputDeltaUpdate deltaUpdate: |
31 |
| - if (deltaUpdate.IsTextDelta) |
32 |
| - { |
33 |
| - Console.Write(deltaUpdate.TextDelta); // Stream text as it arrives |
34 |
| - } |
35 |
| - else if (deltaUpdate.IsAudioDelta) |
36 |
| - { |
37 |
| - ProcessAudioData(deltaUpdate.AudioDelta); // Process audio chunks |
38 |
| - } |
| 30 | + case VoiceLiveServerEventResponseTextDelta textDelta: |
| 31 | + Console.Write(textDelta.Delta); // Stream text as it arrives |
39 | 32 | break;
|
40 | 33 |
|
41 |
| - case InputAudioUpdate inputUpdate: |
42 |
| - if (inputUpdate.IsSpeechStarted) |
43 |
| - { |
44 |
| - Console.WriteLine("User started speaking"); |
45 |
| - } |
46 |
| - else if (inputUpdate.IsTranscriptionDelta) |
47 |
| - { |
48 |
| - Console.WriteLine($"Transcription delta: {inputUpdate.TranscriptionDelta}"); |
49 |
| - } |
| 34 | + case VoiceLiveServerEventResponseAudioDelta audioDelta: |
| 35 | + ProcessAudioData(audioDelta.Delta); // Process audio chunks |
50 | 36 | break;
|
51 | 37 |
|
52 |
| - case ErrorUpdate errorUpdate: |
53 |
| - Console.WriteLine($"Error: {errorUpdate.ErrorMessage}"); |
| 38 | + case VoiceLiveServerEventInputAudioBufferSpeechStarted speechStarted: |
| 39 | + Console.WriteLine("User started speaking"); |
| 40 | + break; |
| 41 | +
|
| 42 | + case VoiceLiveServerEventConversationItemInputAudioTranscriptionDelta transcriptionDelta: |
| 43 | + Console.WriteLine($"Transcription delta: {transcriptionDelta.Delta}"); |
| 44 | + break; |
| 45 | +
|
| 46 | + case VoiceLiveServerEventError errorEvent: |
| 47 | + Console.WriteLine($"Error: {errorEvent.Error?.Message}"); |
54 | 48 | break;
|
55 | 49 | }
|
56 | 50 | }
|
57 | 51 | ```
|
58 | 52 |
|
59 |
| -## Filtered Update Streaming |
| 53 | +## Filtered Server Event Streaming |
60 | 54 |
|
61 | 55 | ```csharp
|
62 |
| -// Get only specific types of updates |
63 |
| -await foreach (OutputDeltaUpdate delta in session.GetUpdatesAsync<OutputDeltaUpdate>()) |
| 56 | +// Get only specific types of server events |
| 57 | +await foreach (VoiceLiveServerEventResponseTextDelta textDelta in session.GetUpdatesAsync<VoiceLiveServerEventResponseTextDelta>()) |
64 | 58 | {
|
65 |
| - if (delta.IsTextDelta) |
66 |
| - { |
67 |
| - Console.Write(delta.TextDelta); |
68 |
| - } |
| 59 | + Console.Write(textDelta.Delta); |
69 | 60 | }
|
70 | 61 |
|
71 |
| -// Get updates of specific kinds |
72 |
| -await foreach (VoiceLiveUpdate update in session.GetUpdatesAsync( |
73 |
| - cancellationToken, |
74 |
| - VoiceLiveUpdateKind.ResponseTextDelta, |
75 |
| - VoiceLiveUpdateKind.ResponseAudioDelta)) |
| 62 | +// Get only audio delta events |
| 63 | +await foreach (VoiceLiveServerEventResponseAudioDelta audioDelta in session.GetUpdatesAsync<VoiceLiveServerEventResponseAudioDelta>()) |
76 | 64 | {
|
77 |
| - // Process only text and audio deltas |
| 65 | + ProcessAudioData(audioDelta.Delta); |
78 | 66 | }
|
79 | 67 | ```
|
80 | 68 |
|
81 | 69 | ## Synchronous Usage
|
82 | 70 |
|
83 | 71 | ```csharp
|
84 | 72 | // For scenarios where you need synchronous processing
|
85 |
| -foreach (VoiceLiveUpdate update in session.GetUpdates()) |
| 73 | +foreach (VoiceLiveServerEvent serverEvent in session.GetUpdates()) |
86 | 74 | {
|
87 |
| - ProcessUpdate(update); |
| 75 | + ProcessServerEvent(serverEvent); |
88 | 76 | }
|
89 | 77 | ```
|
90 | 78 |
|
91 | 79 | ## Convenience Methods
|
92 | 80 |
|
93 | 81 | ```csharp
|
94 |
| -// Wait for a specific update type |
95 |
| -SessionStartedUpdate sessionStarted = await session.WaitForUpdateAsync<SessionStartedUpdate>(); |
96 |
| -Console.WriteLine($"Session {sessionStarted.SessionId} is ready"); |
| 82 | +// Wait for a specific server event type |
| 83 | +VoiceLiveServerEventSessionCreated sessionCreated = await session.WaitForUpdateAsync<VoiceLiveServerEventSessionCreated>(); |
| 84 | +Console.WriteLine($"Session {sessionCreated.Session?.Id} is ready"); |
97 | 85 |
|
98 |
| -// Wait for a specific update kind |
99 |
| -VoiceLiveUpdate errorUpdate = await session.WaitForUpdateAsync(VoiceLiveUpdateKind.Error); |
| 86 | +// Wait for any error event |
| 87 | +VoiceLiveServerEventError errorEvent = await session.WaitForUpdateAsync<VoiceLiveServerEventError>(); |
| 88 | +Console.WriteLine($"Error: {errorEvent.Error?.Message}"); |
| 89 | +``` |
100 | 90 |
|
101 |
| -// Get only delta updates (streaming content) |
102 |
| -await foreach (OutputDeltaUpdate delta in session.GetDeltaUpdatesAsync()) |
103 |
| -{ |
104 |
| - ProcessDelta(delta); |
105 |
| -} |
| 91 | +## Avatar and Animation Events |
106 | 92 |
|
107 |
| -// Get only streaming updates (completion events) |
108 |
| -await foreach (OutputStreamingUpdate streaming in session.GetStreamingUpdatesAsync()) |
| 93 | +```csharp |
| 94 | +// Handle avatar-specific events |
| 95 | +await foreach (VoiceLiveServerEvent serverEvent in session.GetUpdatesAsync()) |
109 | 96 | {
|
110 |
| - ProcessStreamingUpdate(streaming); |
111 |
| -} |
| 97 | + switch (serverEvent) |
| 98 | + { |
| 99 | + case VoiceLiveServerEventSessionAvatarConnecting avatarConnecting: |
| 100 | + Console.WriteLine("Avatar connection in progress"); |
| 101 | + break; |
112 | 102 |
|
113 |
| -// Get only input audio updates |
114 |
| -await foreach (InputAudioUpdate inputAudio in session.GetInputAudioUpdatesAsync()) |
115 |
| -{ |
116 |
| - ProcessInputAudio(inputAudio); |
117 |
| -} |
| 103 | + case ResponseAnimationBlendshapeDeltaEvent blendshapeDelta: |
| 104 | + ProcessBlendshapeData(blendshapeDelta.Frames); |
| 105 | + break; |
118 | 106 |
|
119 |
| -// Get only error updates |
120 |
| -await foreach (ErrorUpdate error in session.GetErrorUpdatesAsync()) |
121 |
| -{ |
122 |
| - HandleError(error); |
| 107 | + case ResponseAnimationVisemeDeltaEvent visemeDelta: |
| 108 | + ProcessVisemeData(visemeDelta.VisemeIds); |
| 109 | + break; |
| 110 | +
|
| 111 | + case ResponseEmotionHypothesis emotionHypothesis: |
| 112 | + Console.WriteLine($"Detected emotion: {emotionHypothesis.Emotion} (confidence: {emotionHypothesis.Candidates?.FirstOrDefault()?.Confidence})"); |
| 113 | + break; |
| 114 | + } |
123 | 115 | }
|
124 | 116 | ```
|
125 | 117 |
|
126 |
| -## WebSocket Message Handling |
127 |
| -
|
128 |
| -The SDK automatically handles: |
129 |
| -- WebSocket message fragmentation and reassembly |
130 |
| -- JSON deserialization of server events |
131 |
| -- Conversion from server events to typed update objects |
132 |
| -- Connection lifecycle management |
133 |
| -- Thread-safe message processing |
| 118 | +## Response Lifecycle Tracking |
134 | 119 |
|
135 |
| -## Update Types |
| 120 | +```csharp |
| 121 | +await foreach (VoiceLiveServerEvent serverEvent in session.GetUpdatesAsync()) |
| 122 | +{ |
| 123 | + switch (serverEvent) |
| 124 | + { |
| 125 | + case VoiceLiveServerEventResponseCreated responseCreated: |
| 126 | + Console.WriteLine($"Response started: {responseCreated.Response?.Id}"); |
| 127 | + break; |
136 | 128 |
|
137 |
| -### VoiceLiveUpdateKind Enumeration |
| 129 | + case VoiceLiveServerEventResponseOutputItemAdded itemAdded: |
| 130 | + Console.WriteLine($"Output item added: {itemAdded.Item?.Id}"); |
| 131 | + break; |
138 | 132 |
|
139 |
| -- **Session Events**: SessionStarted, SessionUpdated, SessionAvatarConnecting |
140 |
| -- **Input Audio Events**: InputAudioBufferCommitted, InputAudioBufferCleared, InputAudioSpeechStarted, InputAudioSpeechStopped |
141 |
| -- **Input Transcription Events**: InputAudioTranscriptionCompleted, InputAudioTranscriptionDelta, InputAudioTranscriptionFailed |
142 |
| -- **Response Events**: ResponseStarted, ResponseCompleted |
143 |
| -- **Response Streaming Events**: ResponseOutputItemAdded, ResponseOutputItemDone, ResponseContentPartAdded, ResponseContentPartDone |
144 |
| -- **Response Delta Events**: ResponseTextDelta, ResponseAudioDelta, ResponseAudioTranscriptDelta |
145 |
| -- **Animation Events**: ResponseAnimationBlendshapesDelta, ResponseAnimationVisemeDelta, ResponseAudioTimestampDelta |
146 |
| -- **Error Events**: Error |
| 133 | + case VoiceLiveServerEventResponseOutputItemDone itemDone: |
| 134 | + Console.WriteLine($"Output item completed: {itemDone.Item?.Id}"); |
| 135 | + break; |
147 | 136 |
|
148 |
| -### Update Classes |
| 137 | + case VoiceLiveServerEventResponseDone responseDone: |
| 138 | + Console.WriteLine($"Response completed: {responseDone.Response?.Id} (status: {responseDone.Response?.Status})"); |
| 139 | + break; |
| 140 | + } |
| 141 | +} |
| 142 | +``` |
149 | 143 |
|
150 |
| -- **VoiceLiveUpdate**: Base class for all updates |
151 |
| -- **SessionStartedUpdate**: Session initialization complete |
152 |
| -- **InputAudioUpdate**: Input audio processing events (speech detection, transcription) |
153 |
| -- **OutputDeltaUpdate**: Streaming content updates (text, audio, animations) |
154 |
| -- **OutputStreamingUpdate**: Completion events and response lifecycle |
155 |
| -- **ErrorUpdate**: Error conditions and failures |
| 144 | +## Event Type Categories |
| 145 | +
|
| 146 | +The VoiceLive service generates several categories of server events: |
| 147 | +
|
| 148 | +### Session Events |
| 149 | +- **VoiceLiveServerEventSessionCreated**: Session initialization complete |
| 150 | +- **VoiceLiveServerEventSessionUpdated**: Session configuration updated |
| 151 | +- **VoiceLiveServerEventSessionAvatarConnecting**: Avatar connection in progress |
| 152 | +
|
| 153 | +### Input Audio Events |
| 154 | +- **VoiceLiveServerEventInputAudioBufferSpeechStarted**: Voice activity detected |
| 155 | +- **VoiceLiveServerEventInputAudioBufferSpeechStopped**: Voice activity ended |
| 156 | +- **VoiceLiveServerEventInputAudioBufferCommitted**: Audio buffer committed |
| 157 | +- **VoiceLiveServerEventInputAudioBufferCleared**: Audio buffer cleared |
| 158 | +
|
| 159 | +### Response Events |
| 160 | +- **VoiceLiveServerEventResponseCreated**: Response generation started |
| 161 | +- **VoiceLiveServerEventResponseDone**: Response generation completed |
| 162 | +- **VoiceLiveServerEventResponseOutputItemAdded**: New output item created |
| 163 | +- **VoiceLiveServerEventResponseOutputItemDone**: Output item completed |
| 164 | +
|
| 165 | +### Content Streaming Events |
| 166 | +- **VoiceLiveServerEventResponseTextDelta**: Text content streaming |
| 167 | +- **VoiceLiveServerEventResponseTextDone**: Text content completed |
| 168 | +- **VoiceLiveServerEventResponseAudioDelta**: Audio content streaming |
| 169 | +- **VoiceLiveServerEventResponseAudioDone**: Audio content completed |
| 170 | +- **VoiceLiveServerEventResponseAudioTranscriptDelta**: Audio transcript streaming |
| 171 | +- **VoiceLiveServerEventResponseAudioTranscriptDone**: Audio transcript completed |
| 172 | +
|
| 173 | +### Animation Events (VoiceLive-specific) |
| 174 | +- **ResponseAnimationBlendshapeDeltaEvent**: Blendshape animation data streaming |
| 175 | +- **ResponseAnimationBlendshapeDoneEvent**: Blendshape animation completed |
| 176 | +- **ResponseAnimationVisemeDeltaEvent**: Viseme animation data streaming |
| 177 | +- **ResponseAnimationVisemeDoneEvent**: Viseme animation completed |
| 178 | +- **ResponseEmotionHypothesis**: Emotion detection results |
| 179 | +
|
| 180 | +### Conversation Events |
| 181 | +- **VoiceLiveServerEventConversationItemCreated**: New conversation item |
| 182 | +- **VoiceLiveServerEventConversationItemDeleted**: Conversation item removed |
| 183 | +- **VoiceLiveServerEventConversationItemInputAudioTranscriptionDelta**: Input transcription streaming |
| 184 | +- **VoiceLiveServerEventConversationItemInputAudioTranscriptionCompleted**: Input transcription completed |
| 185 | +
|
| 186 | +### Error Events |
| 187 | +- **VoiceLiveServerEventError**: Error conditions and failures |
156 | 188 |
|
157 | 189 | ## Error Handling
|
158 | 190 |
|
159 | 191 | ```csharp
|
160 |
| -try |
| 192 | +await foreach (VoiceLiveServerEvent serverEvent in session.GetUpdatesAsync()) |
161 | 193 | {
|
162 |
| - await foreach (VoiceLiveUpdate update in session.GetUpdatesAsync()) |
| 194 | + if (serverEvent is VoiceLiveServerEventError errorEvent) |
163 | 195 | {
|
164 |
| - if (update is ErrorUpdate errorUpdate) |
| 196 | + Console.WriteLine($"Error occurred: {errorEvent.Error?.Message}"); |
| 197 | + Console.WriteLine($"Error type: {errorEvent.Error?.Type}"); |
| 198 | + Console.WriteLine($"Error code: {errorEvent.Error?.Code}"); |
| 199 | +
|
| 200 | + // Handle specific error conditions |
| 201 | + switch (errorEvent.Error?.Type) |
165 | 202 | {
|
166 |
| - Console.WriteLine($"Service error: {errorUpdate.ErrorMessage}"); |
167 |
| - // Handle the error appropriately |
168 |
| - break; |
| 203 | + case "connection_error": |
| 204 | + // Handle connection issues |
| 205 | + break; |
| 206 | + case "invalid_request_error": |
| 207 | + // Handle request validation errors |
| 208 | + break; |
| 209 | + default: |
| 210 | + // Handle other errors |
| 211 | + break; |
169 | 212 | }
|
170 |
| - // Process other updates |
171 | 213 | }
|
172 | 214 | }
|
173 |
| -catch (OperationCanceledException) |
174 |
| -{ |
175 |
| - Console.WriteLine("Update streaming was cancelled"); |
176 |
| -} |
177 |
| -catch (Exception ex) |
178 |
| -{ |
179 |
| - Console.WriteLine($"Unexpected error: {ex.Message}"); |
180 |
| -} |
181 | 215 | ```
|
182 | 216 |
|
183 |
| -## Best Practices |
184 |
| -
|
185 |
| -1. **Use appropriate update filtering** to reduce processing overhead |
186 |
| -2. **Handle cancellation** properly with CancellationToken |
187 |
| -3. **Process delta updates quickly** to avoid buffer overrun |
188 |
| -4. **Monitor for error updates** to handle service issues |
189 |
| -5. **Use async enumeration** for better resource utilization |
190 |
| -6. **Implement proper cleanup** when done with the session |
191 |
| -
|
192 | 217 | */
|
0 commit comments