@@ -125,10 +125,10 @@ public async Task SendAsync(
125125 if ( functionParts . Count > 0 )
126126 {
127127 Dictionary < string , object > toolResponse = new ( ) {
128- { "toolResponse" , new Dictionary < string , object > ( ) {
129- { "functionResponses" , functionParts . Select ( frPart => ( frPart as ModelContent . Part ) . ToJson ( ) [ "functionResponse" ] ) . ToList ( ) }
130- } }
131- } ;
128+ { "toolResponse" , new Dictionary < string , object > ( ) {
129+ { "functionResponses" , functionParts . Select ( frPart => ( frPart as ModelContent . Part ) . ToJson ( ) [ "functionResponse" ] ) . ToList ( ) }
130+ } }
131+ } ;
132132 var toolResponseBytes = Encoding . UTF8 . GetBytes ( Json . Serialize ( toolResponse ) ) ;
133133
134134 await InternalSendBytesAsync ( new ArraySegment < byte > ( toolResponseBytes ) , cancellationToken ) ;
@@ -147,15 +147,15 @@ public async Task SendAsync(
147147
148148 // Prepare the message payload
149149 Dictionary < string , object > contentDict = new ( ) {
150- { "turnComplete" , turnComplete }
151- } ;
150+ { "turnComplete" , turnComplete }
151+ } ;
152152 if ( content . HasValue )
153153 {
154154 contentDict [ "turns" ] = new List < object > ( new [ ] { content ? . ToJson ( ) } ) ;
155155 }
156156 Dictionary < string , object > jsonDict = new ( ) {
157- { "clientContent" , contentDict }
158- } ;
157+ { "clientContent" , contentDict }
158+ } ;
159159 var byteArray = Encoding . UTF8 . GetBytes ( Json . Serialize ( jsonDict ) ) ;
160160
161161 await InternalSendBytesAsync ( new ArraySegment < byte > ( byteArray ) , cancellationToken ) ;
@@ -166,23 +166,84 @@ public async Task SendAsync(
166166 /// </summary>
167167 /// <param name="mediaChunks">A list of media chunks to send.</param>
168168 /// <param name="cancellationToken">A token to cancel the send operation.</param>
169+ /// <remarks>
170+ /// Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead.
171+ /// </remarks>
172+ /// @deprecated Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead.
173+ [ Obsolete ( "Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead." ) ]
169174 public async Task SendMediaChunksAsync (
170175 List < ModelContent . InlineDataPart > mediaChunks ,
171176 CancellationToken cancellationToken = default )
172177 {
173178 if ( mediaChunks == null ) return ;
174179
180+ await InternalSendRealtimeInputAsync ( "mediaChunks" ,
181+ mediaChunks . Select ( mc => ( mc as ModelContent . Part ) . ToJson ( ) [ "inlineData" ] ) . ToList ( ) ,
182+ cancellationToken ) ;
183+ }
184+
185+ /// <summary>
186+ /// Sends text data to the server in realtime.
187+ ///
188+ /// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
189+ /// details about the realtime input usage.
190+ /// </summary>
191+ /// <param name="text">The text data to send.</param>
192+ /// <param name="cancellationToken">A token to cancel the send operation.</param>
193+ public async Task SendTextRealtimeAsync (
194+ string text ,
195+ CancellationToken cancellationToken = default )
196+ {
197+ if ( string . IsNullOrEmpty ( text ) ) return ;
198+
199+ await InternalSendRealtimeInputAsync ( "text" , text , cancellationToken ) ;
200+ }
201+
202+ /// <summary>
203+ /// Sends audio data to the server in realtime.
204+ ///
205+ /// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
206+ /// details about the realtime input usage.
207+ /// </summary>
208+ /// <param name="audio">The audio data to send.</param>
209+ /// <param name="cancellationToken">A token to cancel the send operation.</param>
210+ public async Task SendAudioRealtimeAsync (
211+ ModelContent . InlineDataPart audio ,
212+ CancellationToken cancellationToken = default )
213+ {
214+ await InternalSendRealtimeInputAsync ( "audio" ,
215+ ( audio as ModelContent . Part ) . ToJson ( ) [ "inlineData" ] , cancellationToken ) ;
216+ }
217+
218+ /// <summary>
219+ /// Sends video data to the server in realtime.
220+ ///
221+ /// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
222+ /// details about the realtime input usage.
223+ /// </summary>
224+ /// <param name="video">The video data to send.</param>
225+ /// <param name="cancellationToken">A token to cancel the send operation.</param>
226+ public async Task SendVideoRealtimeAsync (
227+ ModelContent . InlineDataPart video ,
228+ CancellationToken cancellationToken = default )
229+ {
230+ await InternalSendRealtimeInputAsync ( "video" ,
231+ ( video as ModelContent . Part ) . ToJson ( ) [ "inlineData" ] , cancellationToken ) ;
232+ }
233+
234+ private async Task InternalSendRealtimeInputAsync (
235+ string key , object data , CancellationToken cancellationToken )
236+ {
175237 // Prepare the message payload.
176238 Dictionary < string , object > jsonDict = new ( ) {
177- {
178- "realtimeInput" , new Dictionary < string , object > ( ) {
179- {
180- // InlineDataPart inherits from Part, so this conversion should be safe.
181- "mediaChunks" , mediaChunks . Select ( mc => ( mc as ModelContent . Part ) . ToJson ( ) [ "inlineData" ] ) . ToList ( )
239+ {
240+ "realtimeInput" , new Dictionary < string , object > ( ) {
241+ {
242+ key , data
243+ }
182244 }
183245 }
184- }
185- } ;
246+ } ;
186247 var byteArray = Encoding . UTF8 . GetBytes ( Json . Serialize ( jsonDict ) ) ;
187248
188249 await InternalSendBytesAsync ( new ArraySegment < byte > ( byteArray ) , cancellationToken ) ;
@@ -214,7 +275,7 @@ private static byte[] ConvertTo16BitPCM(float[] samples)
214275 public Task SendAudioAsync ( float [ ] audioData , CancellationToken cancellationToken = default )
215276 {
216277 ModelContent . InlineDataPart inlineDataPart = new ( "audio/pcm" , ConvertTo16BitPCM ( audioData ) ) ;
217- return SendMediaChunksAsync ( new List < ModelContent . InlineDataPart > ( new [ ] { inlineDataPart } ) , cancellationToken ) ;
278+ return SendAudioRealtimeAsync ( inlineDataPart , cancellationToken ) ;
218279 }
219280
220281 /// <summary>
0 commit comments