@@ -258,25 +258,37 @@ <h3>Realtime Audio<a class="headerlink" href="#realtime-audio" title="Link to th
258258< p > If input and/or output is encoded (compressed) like mp4/aac then you must have ffmpeg installed.</ p >
259259< p > Due to the overhead of the router (API call) - realtime only supports a single agent setup.</ p >
260260< p > Realtime uses MongoDB for memory so Zep is not needed.</ p >
261+ < p > This example will work using expo-audio on Android and iOS.</ p >
261262< div class ="highlight-python notranslate "> < div class ="highlight "> < pre > < span > </ span > < span class ="kn "> from</ span > < span class ="w "> </ span > < span class ="nn "> solana_agent</ span > < span class ="w "> </ span > < span class ="kn "> import</ span > < span class ="n "> SolanaAgent</ span >
262263
263264< span class ="n "> solana_agent</ span > < span class ="o "> =</ span > < span class ="n "> SolanaAgent</ span > < span class ="p "> (</ span > < span class ="n "> config</ span > < span class ="o "> =</ span > < span class ="n "> config</ span > < span class ="p "> )</ span >
264265
265- < span class ="c1 "> # Example: mobile sends MP4/AAC; server encodes output to AAC</ span >
266- < span class ="n "> audio_content</ span > < span class ="o "> =</ span > < span class ="k "> await</ span > < span class ="n "> audio_file</ span > < span class ="o "> .</ span > < span class ="n "> read</ span > < span class ="p "> ()</ span > < span class ="c1 "> # bytes</ span >
267- < span class ="k "> async</ span > < span class ="k "> for</ span > < span class ="n "> audio_chunk</ span > < span class ="ow "> in</ span > < span class ="n "> solana_agent</ span > < span class ="o "> .</ span > < span class ="n "> process</ span > < span class ="p "> (</ span >
268- < span class ="s2 "> "user123"</ span > < span class ="p "> ,</ span > < span class ="c1 "> # required</ span >
269- < span class ="n "> audio_content</ span > < span class ="p "> ,</ span > < span class ="c1 "> # required</ span >
270- < span class ="n "> realtime</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span > < span class ="c1 "> # optional (default False)</ span >
271- < span class ="n "> output_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "audio"</ span > < span class ="p "> ,</ span > < span class ="c1 "> # required</ span >
272- < span class ="n "> vad</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span > < span class ="c1 "> # enable VAD (optional)</ span >
273- < span class ="n "> rt_encode_input</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span > < span class ="c1 "> # accept compressed input (optional)</ span >
274- < span class ="n "> rt_encode_output</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span > < span class ="c1 "> # encode output for client (optional)</ span >
275- < span class ="n "> rt_voice</ span > < span class ="o "> =</ span > < span class ="s2 "> "marin"</ span > < span class ="c1 "> # the voice to use for interactions (optional)</ span >
276- < span class ="n "> audio_input_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "mp4"</ span > < span class ="p "> ,</ span > < span class ="c1 "> # client transport (optional)</ span >
277- < span class ="n "> audio_output_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "aac"</ span > < span class ="c1 "> # client transport (optional)</ span >
278- < span class ="p "> ):</ span >
279- < span class ="n "> handle_audio</ span > < span class ="p "> (</ span > < span class ="n "> audio_chunk</ span > < span class ="p "> )</ span >
266+ < span class ="n "> audio_content</ span > < span class ="o "> =</ span > < span class ="k "> await</ span > < span class ="n "> audio_file</ span > < span class ="o "> .</ span > < span class ="n "> read</ span > < span class ="p "> ()</ span >
267+
268+ < span class ="k "> async</ span > < span class ="k "> def</ span > < span class ="w "> </ span > < span class ="nf "> generate</ span > < span class ="p "> ():</ span >
269+ < span class ="k "> async</ span > < span class ="k "> for</ span > < span class ="n "> chunk</ span > < span class ="ow "> in</ span > < span class ="n "> solana_agent</ span > < span class ="o "> .</ span > < span class ="n "> process</ span > < span class ="p "> (</ span >
270+ < span class ="n "> user_id</ span > < span class ="o "> =</ span > < span class ="n "> user_id</ span > < span class ="p "> ,</ span >
271+ < span class ="n "> message</ span > < span class ="o "> =</ span > < span class ="n "> audio_content</ span > < span class ="p "> ,</ span >
272+ < span class ="n "> realtime</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span >
273+ < span class ="n "> rt_encode_input</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span >
274+ < span class ="n "> rt_encode_output</ span > < span class ="o "> =</ span > < span class ="kc "> True</ span > < span class ="p "> ,</ span >
275+ < span class ="n "> rt_voice</ span > < span class ="o "> =</ span > < span class ="s2 "> "marin"</ span > < span class ="p "> ,</ span >
276+ < span class ="n "> output_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "audio"</ span > < span class ="p "> ,</ span >
277+ < span class ="n "> audio_output_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "m4a"</ span > < span class ="p "> ,</ span >
278+ < span class ="n "> audio_input_format</ span > < span class ="o "> =</ span > < span class ="s2 "> "mp4"</ span > < span class ="p "> ,</ span >
279+ < span class ="p "> ):</ span >
280+ < span class ="k "> yield</ span > < span class ="n "> chunk</ span >
281+
282+ < span class ="k "> return</ span > < span class ="n "> StreamingResponse</ span > < span class ="p "> (</ span >
283+ < span class ="n "> content</ span > < span class ="o "> =</ span > < span class ="n "> generate</ span > < span class ="p "> (),</ span >
284+ < span class ="n "> media_type</ span > < span class ="o "> =</ span > < span class ="s2 "> "audio/mp4"</ span > < span class ="p "> ,</ span >
285+ < span class ="n "> headers</ span > < span class ="o "> =</ span > < span class ="p "> {</ span >
286+ < span class ="s2 "> "Cache-Control"</ span > < span class ="p "> :</ span > < span class ="s2 "> "no-store"</ span > < span class ="p "> ,</ span >
287+ < span class ="s2 "> "Pragma"</ span > < span class ="p "> :</ span > < span class ="s2 "> "no-cache"</ span > < span class ="p "> ,</ span >
288+ < span class ="s2 "> "Content-Disposition"</ span > < span class ="p "> :</ span > < span class ="s2 "> "inline; filename=stream.m4a"</ span > < span class ="p "> ,</ span >
289+ < span class ="s2 "> "X-Accel-Buffering"</ span > < span class ="p "> :</ span > < span class ="s2 "> "no"</ span > < span class ="p "> ,</ span >
290+ < span class ="p "> },</ span >
291+ < span class ="p "> )</ span >
280292</ pre > </ div >
281293</ div >
282294</ section >
0 commit comments