Bidirectional streaming using the Gemini Live API

Preview: Using theFirebase AI Logic SDKs with theGemini Live API is a feature that's in Preview, which means that it isn't subject to any SLA or deprecation policy and could change in backwards-incompatible ways.

This feature issupported for Android, Flutter, Web, and Unity apps. Support for Apple platform apps is coming soon!


TheGemini Live API enables low-latency bidirectional text and voiceinteractions withGemini. Using theLive API, you can provideend users with the experience of natural, human-like voice conversations, withthe ability to interrupt the model's responses using text or voice commands.The model can process text and audio input (video coming soon!), and it canprovide text and audio output.

You can prototype with prompts and theLive API inGoogle AI Studio orVertex AI Studio.

TheLive API is a stateful API that creates a WebSocket connection toestablish asession between the client and theGemini server.For details, see theLive API reference documentation(Gemini Developer API |Vertex AI Gemini API).

Important: If you're not looking forlive bidirectional streaming, but ratherbasic streaming of text responses(usinggenerateContentStream orsendMessageStream),then check out the documentation to stream responses whengenerating text,analyzing images,analyzing video,analyzing audio,analyzing documents (like PDFs),or in achat experience.

Before you begin

Click yourGemini API provider to view provider-specific content and code on this page.

If you haven't already, complete thegetting started guide,which describes how to set up your Firebase project,connect your app to Firebase, add the SDK,initialize the backend service for your chosenGemini API provider, andcreate aLiveModel instance.

This guide assumes you're using the latestFirebase AI Logic SDKs. If you're still using the "Vertex AI in Firebase" SDKs, see themigration guide.

Models that support this capability

The models that support theLive API depend on your chosenGemini API provider.

Important: Regardless of the API provider, thegemini-2.0-flash andgemini-2.5-flash models donot support theLive API.
Also,Firebase AI Logic doesnot yet support the native audiomodels (likegemini-2.5-flash-native-audio-preview-09-2025).
  • Gemini Developer API

    • gemini-live-2.5-flash(private GA*)
    • gemini-live-2.5-flash-preview
    • gemini-2.0-flash-live-001
    • gemini-2.0-flash-live-preview-04-09
  • Vertex AI Gemini API

    • gemini-live-2.5-flash(private GA*)
    • gemini-2.0-flash-live-preview-04-09(only available to access inus-central1)

Take note that for the 2.5 model names for theLive API,thelive segment immediately follows thegemini segment.

*Reach out to yourGoogle Cloud account team representative to request access.

Use the standard features of theLive API

This section describes how to use the standard features of theLive API, specifically to stream various types of inputs and outputs:

Note: To improve consistency when using theLive API, considerconfiguring thetemperature in the model configuration,settingsystem instructions, andusingprompting techniques.

Generate streamed text from streamed text input

Before trying this sample, complete theBefore you begin section of this guide to set up your project and app.
In that section, you'll also click a button for your chosenGemini API provider so that you see provider-specific content on this page.

You can send streamed text input and receive streamed text output. Make sure tocreate aliveModel instance and set theresponse modalitytoText.

Swift

TheLive API is not yet supported for Apple platform apps, but check back soon!

Kotlin

// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(modelName="gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textgenerationConfig=liveGenerationConfig{responseModality=ResponseModality.TEXT})valsession=model.connect()// Provide a text promptvaltext="tell a short story"session.send(text)varoutputText=""session.receive().collect{if(it.turnComplete){// Optional: if you don't require to send more requests.session.stopReceiving();}outputText=outputText+it.text}// Output received from the server.println(outputText)

Java

ExecutorServiceexecutor=Executors.newFixedThreadPool(1);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)LiveGenerativeModellm=FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel("gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textnewLiveGenerationConfig.Builder().setResponseModalities(ResponseModality.TEXT).build());LiveModelFuturesmodel=LiveModelFutures.from(lm);ListenableFuture<LiveSession>sessionFuture=model.connect();classLiveContentResponseSubscriberimplementsSubscriber<LiveContentResponse>{@OverridepublicvoidonSubscribe(Subscriptions){s.request(Long.MAX_VALUE);// Request an unlimited number of items}@OverridepublicvoidonNext(LiveContentResponseliveContentResponse){// Handle the response from the server.System.out.println(liveContentResponse.getText());}@OverridepublicvoidonError(Throwablet){System.err.println("Error: "+t.getMessage());}@OverridepublicvoidonComplete(){System.out.println("Done receiving messages!");}}Futures.addCallback(sessionFuture,newFutureCallback<LiveSession>(){@OverridepublicvoidonSuccess(LiveSessionses){LiveSessionFuturessession=LiveSessionFutures.from(ses);// Provide a text promptStringtext="tell me a short story?";session.send(text);Publisher<LiveContentResponse>publisher=session.receive();publisher.subscribe(newLiveContentResponseSubscriber());}@OverridepublicvoidonFailure(Throwablet){// Handle exceptions}},executor);

Web

// Initialize the Gemini Developer API backend serviceconstai=getAI(firebaseApp,{backend:newGoogleAIBackend()});// Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)constmodel=getLiveGenerativeModel(ai,{model:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textgenerationConfig:{responseModalities:[ResponseModality.TEXT],},});constsession=awaitmodel.connect();// Provide a text promptconstprompt="tell a short story";session.send(prompt);// Collect text from model's turnlettext="";constmessages=session.receive();forawait(constmessageofmessages){switch(message.type){case"serverContent":if(message.turnComplete){console.log(text);}else{constparts=message.modelTurn?.parts;if(parts){text+=parts.map((part)=>part.text).join("");}}break;case"toolCall":// Ignorecase"toolCallCancellation":// Ignore}}

Dart

import'package:firebase_ai/firebase_ai.dart';import'package:firebase_core/firebase_core.dart';import'firebase_options.dart';lateLiveModelSession_session;awaitFirebase.initializeApp(options:DefaultFirebaseOptions.currentPlatform,);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)finalmodel=FirebaseAI.googleAI().liveGenerativeModel(model:'gemini-2.0-flash-live-preview-04-09',// Configure the model to respond with textliveGenerationConfig:LiveGenerationConfig(responseModalities:[ResponseModalities.text]),);_session=awaitmodel.connect();// Provide a text promptfinalprompt=Content.text('tell a short story');await_session.send(input:prompt,turnComplete:true);// In a separate thread, receive the responseawaitfor(finalmessagein_session.receive()){// Process the received message}

Unity

usingFirebase;usingFirebase.AI;asyncTaskSendTextReceiveText(){// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)varmodel=FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(modelName:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textliveGenerationConfig:newLiveGenerationConfig(responseModalities:new[]{ResponseModality.Text}));LiveSessionsession=awaitmodel.ConnectAsync();// Provide a text promptvarprompt=ModelContent.Text("tell a short story");awaitsession.SendAsync(content:prompt,turnComplete:true);// Receive the responseawaitforeach(varmessageinsession.ReceiveAsync()){// Process the received messageif(!string.IsNullOrEmpty(message.Text)){UnityEngine.Debug.Log("Received message: "+message.Text);}}}

Generate streamed audio from streamed audio input

Before trying this sample, complete theBefore you begin section of this guide to set up your project and app.
In that section, you'll also click a button for your chosenGemini API provider so that you see provider-specific content on this page.

You can send streamed audio input and receive streamed audio output. Make sureto create aLiveModel instance and set theresponse modalitytoAudio.

Learn how to configure and customize theresponse voice (later on this page).

Swift

TheLive API is not yet supported for Apple platform apps, but check back soon!

Kotlin

// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(modelName="gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textgenerationConfig=liveGenerationConfig{responseModality=ResponseModality.AUDIO})valsession=model.connect()// This is the recommended way.// However, you can create your own recorder and handle the stream.session.startAudioConversation()

Java

ExecutorServiceexecutor=Executors.newFixedThreadPool(1);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)LiveGenerativeModellm=FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel("gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textnewLiveGenerationConfig.Builder().setResponseModalities(ResponseModality.TEXT).build());LiveModelFuturesmodel=LiveModelFutures.from(lm);ListenableFuture<LiveSession>sessionFuture=model.connect();Futures.addCallback(sessionFuture,newFutureCallback<LiveSession>(){@OverridepublicvoidonSuccess(LiveSessionses){LiveSessionFuturessession=LiveSessionFutures.from(ses);session.startAudioConversation();}@OverridepublicvoidonFailure(Throwablet){// Handle exceptions}},executor);

Web

// Initialize the Gemini Developer API backend serviceconstai=getAI(firebaseApp,{backend:newGoogleAIBackend()});// Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)constmodel=getLiveGenerativeModel(ai,{model:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with audiogenerationConfig:{responseModalities:[ResponseModality.AUDIO],},});constsession=awaitmodel.connect();// Start the audio conversationconstaudioConversationController=awaitstartAudioConversation(session);// ... Later, to stop the audio conversation// await audioConversationController.stop()

Dart

import'package:firebase_ai/firebase_ai.dart';import'package:firebase_core/firebase_core.dart';import'firebase_options.dart';import'package:your_audio_recorder_package/your_audio_recorder_package.dart';lateLiveModelSession_session;final_audioRecorder=YourAudioRecorder();awaitFirebase.initializeApp(options:DefaultFirebaseOptions.currentPlatform,);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)finalmodel=FirebaseAI.googleAI().liveGenerativeModel(model:'gemini-2.0-flash-live-preview-04-09',// Configure the model to respond with audioliveGenerationConfig:LiveGenerationConfig(responseModalities:[ResponseModalities.audio]),);_session=awaitmodel.connect();finalaudioRecordStream=_audioRecorder.startRecordingStream();// Map the Uint8List stream to InlineDataPart streamfinalmediaChunkStream=audioRecordStream.map((data){returnInlineDataPart('audio/pcm',data);});await_session.startMediaStream(mediaChunkStream);// In a separate thread, receive the audio response from the modelawaitfor(finalmessagein_session.receive()){// Process the received message}

Unity

usingFirebase;usingFirebase.AI;asyncTaskSendTextReceiveAudio(){// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)varmodel=FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(modelName:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with audioliveGenerationConfig:newLiveGenerationConfig(responseModalities:new[]{ResponseModality.Audio}));LiveSessionsession=awaitmodel.ConnectAsync();// Start a coroutine to send audio from the MicrophonevarrecordingCoroutine=StartCoroutine(SendAudio(session));// Start receiving the responseawaitReceiveAudio(session);}IEnumeratorSendAudio(LiveSessionliveSession){stringmicrophoneDeviceName=null;intrecordingFrequency=16000;intrecordingBufferSeconds=2;varrecordingClip=Microphone.Start(microphoneDeviceName,true,recordingBufferSeconds,recordingFrequency);intlastSamplePosition=0;while(true){if(!Microphone.IsRecording(microphoneDeviceName)){yieldbreak;}intcurrentSamplePosition=Microphone.GetPosition(microphoneDeviceName);if(currentSamplePosition!=lastSamplePosition){// The Microphone uses a circular buffer, so we need to check if the// current position wrapped around to the beginning, and handle it// accordingly.intsampleCount;if(currentSamplePosition>lastSamplePosition){sampleCount=currentSamplePosition-lastSamplePosition;}else{sampleCount=recordingClip.samples-lastSamplePosition+currentSamplePosition;}if(sampleCount>0){// Get the audio chunkfloat[]samples=newfloat[sampleCount];recordingClip.GetData(samples,lastSamplePosition);// Send the data, discarding the resulting Task to avoid the warning_=liveSession.SendAudioAsync(samples);lastSamplePosition=currentSamplePosition;}}// Wait for a short delay before reading the next sample from the MicrophoneconstfloatMicrophoneReadDelay=0.5f;yieldreturnnewWaitForSeconds(MicrophoneReadDelay);}}QueueaudioBuffer=new();asyncTaskReceiveAudio(LiveSessionliveSession){intsampleRate=24000;intchannelCount=1;// Create a looping AudioClip to fill with the received audio dataintbufferSamples=(int)(sampleRate*channelCount);AudioClipclip=AudioClip.Create("StreamingPCM",bufferSamples,channelCount,sampleRate,true,OnAudioRead);// Attach the clip to an AudioSource and start playing itAudioSourceaudioSource=GetComponent();audioSource.clip=clip;audioSource.loop=true;audioSource.Play();// Start receiving the responseawaitforeach(varmessageinliveSession.ReceiveAsync()){// Process the received messageforeach(float[]pcmDatainmessage.AudioAsFloat){lock(audioBuffer){foreach(floatsampleinpcmData){audioBuffer.Enqueue(sample);}}}}}// This method is called by the AudioClip to load audio data.privatevoidOnAudioRead(float[]data){intsamplesToProvide=data.Length;intsamplesProvided=0;lock(audioBuffer){while(samplesProvided<samplesToProvide&&audioBuffer.Count>0){data[samplesProvided]=audioBuffer.Dequeue();samplesProvided++;}}while(samplesProvided<samplesToProvide){data[samplesProvided]=0.0f;samplesProvided++;}}

Generate streamed text from streamed audio input

Before trying this sample, complete theBefore you begin section of this guide to set up your project and app.
In that section, you'll also click a button for your chosenGemini API provider so that you see provider-specific content on this page.

You can send streamed audio input and receive streamed text output. Make sure tocreate aLiveModel instance and set theresponse modalitytoText.

Swift

TheLive API is not yet supported for Apple platforms apps, but check back soon!

Kotlin

// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(modelName="gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textgenerationConfig=liveGenerationConfig{responseModality=ResponseModality.TEXT})valsession=model.connect()// Provide a text promptvalaudioContent=content("user"){audioData}session.send(audioContent)varoutputText=""session.receive().collect{if(it.status==Status.TURN_COMPLETE){// Optional: if you don't require to send more requests.session.stopReceiving();}outputText=outputText+it.text}// Output received from the server.println(outputText)

Java

ExecutorServiceexecutor=Executors.newFixedThreadPool(1);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)LiveGenerativeModellm=FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel("gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textnewLiveGenerationConfig.Builder().setResponseModalities(ResponseModality.TEXT).build());LiveModelFuturesmodel=LiveModelFutures.from(lm);ListenableFuture<LiveSession>sessionFuture=model.connect();classLiveContentResponseSubscriberimplementsSubscriber<LiveContentResponse>{@OverridepublicvoidonSubscribe(Subscriptions){s.request(Long.MAX_VALUE);// Request an unlimited number of items}@OverridepublicvoidonNext(LiveContentResponseliveContentResponse){// Handle the response from the server.System.out.println(liveContentResponse.getText());}@OverridepublicvoidonError(Throwablet){System.err.println("Error: "+t.getMessage());}@OverridepublicvoidonComplete(){System.out.println("Done receiving messages!");}}Futures.addCallback(sessionFuture,newFutureCallback<LiveSession>(){@OverridepublicvoidonSuccess(LiveSessionses){LiveSessionFuturessession=LiveSessionFutures.from(ses);// Send Audio datasession.send(newContent.Builder().addInlineData(audioData,"audio/pcm").build());session.send(text);Publisher<LiveContentResponse>publisher=session.receive();publisher.subscribe(newLiveContentResponseSubscriber());}@OverridepublicvoidonFailure(Throwablet){// Handle exceptions}},executor);

Web

// Initialize the Gemini Developer API backend serviceconstai=getAI(firebaseApp,{backend:newGoogleAIBackend()});// Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)constmodel=getLiveGenerativeModel(ai,{model:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textgenerationConfig:{responseModalities:[ResponseModality.TEXT],},});constsession=awaitmodel.connect();// TODO(developer): Collect audio data (16-bit 16kHz PCM)// const audioData = ...// Send audioconstaudioPart={inlineData:{data:audioData,mimeType:"audio/pcm"},};session.send([audioPart]);// Collect text from model's turnlettext="";constmessages=session.receive();forawait(constmessageofmessages){switch(message.type){case"serverContent":if(message.turnComplete){console.log(text);}else{constparts=message.modelTurn?.parts;if(parts){text+=parts.map((part)=>part.text).join("");}}break;case"toolCall":// Ignorecase"toolCallCancellation":// Ignore}}

Dart

import'package:firebase_ai/firebase_ai.dart';import'package:firebase_core/firebase_core.dart';import'firebase_options.dart';import'package:your_audio_recorder_package/your_audio_recorder_package.dart';import'dart:async';lateLiveModelSession_session;final_audioRecorder=YourAudioRecorder();awaitFirebase.initializeApp(options:DefaultFirebaseOptions.currentPlatform,);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)finalmodel=FirebaseAI.googleAI().liveGenerativeModel(model:'gemini-2.0-flash-live-preview-04-09',// Configure the model to respond with textliveGenerationConfig:LiveGenerationConfig(responseModalities:ResponseModalities.text),);_session=awaitmodel.connect();finalaudioRecordStream=_audioRecorder.startRecordingStream();finalmediaChunkStream=audioRecordStream.map((data){returnInlineDataPart('audio/pcm',data);});await_session.startMediaStream(mediaChunkStream);finalresponseStream=_session.receive();returnresponseStream.asyncMap((response)async{if(response.parts.isNotEmpty&&response.parts.first.text!=null){returnresponse.parts.first.text!;}else{throwException('Text response not found.');}});Futuremain()async{try{finaltextStream=awaitaudioToText();awaitfor(finaltextintextStream){print('Received text:$text');// Handle the text response}}catch(e){print('Error:$e');}}

Unity

usingFirebase;usingFirebase.AI;asyncTaskSendAudioReceiveText(){// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)varmodel=FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(modelName:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textliveGenerationConfig:newLiveGenerationConfig(responseModalities:new[]{ResponseModality.Text}));LiveSessionsession=awaitmodel.ConnectAsync();// Start a coroutine to send audio from the MicrophonevarrecordingCoroutine=StartCoroutine(SendAudio(session));// Receive the responseawaitforeach(varmessageinsession.ReceiveAsync()){// Process the received messageif(!string.IsNullOrEmpty(message.Text)){UnityEngine.Debug.Log("Received message: "+message.Text);}}StopCoroutine(recordingCoroutine);}IEnumeratorSendAudio(LiveSessionliveSession){stringmicrophoneDeviceName=null;intrecordingFrequency=16000;intrecordingBufferSeconds=2;varrecordingClip=Microphone.Start(microphoneDeviceName,true,recordingBufferSeconds,recordingFrequency);intlastSamplePosition=0;while(true){if(!Microphone.IsRecording(microphoneDeviceName)){yieldbreak;}intcurrentSamplePosition=Microphone.GetPosition(microphoneDeviceName);if(currentSamplePosition!=lastSamplePosition){// The Microphone uses a circular buffer, so we need to check if the// current position wrapped around to the beginning, and handle it// accordingly.intsampleCount;if(currentSamplePosition>lastSamplePosition){sampleCount=currentSamplePosition-lastSamplePosition;}else{sampleCount=recordingClip.samples-lastSamplePosition+currentSamplePosition;}if(sampleCount>0){// Get the audio chunkfloat[]samples=newfloat[sampleCount];recordingClip.GetData(samples,lastSamplePosition);// Send the data, discarding the resulting Task to avoid the warning_=liveSession.SendAudioAsync(samples);lastSamplePosition=currentSamplePosition;}}// Wait for a short delay before reading the next sample from the MicrophoneconstfloatMicrophoneReadDelay=0.5f;yieldreturnnewWaitForSeconds(MicrophoneReadDelay);}}

Generate streamed audio from streamed text input

Before trying this sample, complete theBefore you begin section of this guide to set up your project and app.
In that section, you'll also click a button for your chosenGemini API provider so that you see provider-specific content on this page.

You can send streamed text input and receive streamed audio output. Make sure tocreate aLiveModel instance and set theresponse modalitytoAudio.

Learn how to configure and customize theresponse voice (later on this page).

Swift

TheLive API is not yet supported for Apple platform apps, but check back soon!

Kotlin

// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(modelName="gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with audiogenerationConfig=liveGenerationConfig{responseModality=ResponseModality.AUDIO})valsession=model.connect()// Provide a text promptvaltext="tell a short story"session.send(text)session.receive().collect{if(it.turnComplete){// Optional: if you don't require to send more requests.session.stopReceiving();}// Handle 16bit pcm audio data at 24khzplayAudio(it.data)}

Java

ExecutorServiceexecutor=Executors.newFixedThreadPool(1);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)LiveGenerativeModellm=FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel("gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with textnewLiveGenerationConfig.Builder().setResponseModalities(ResponseModality.AUDIO).build());LiveModelFuturesmodel=LiveModelFutures.from(lm);ListenableFuture<LiveSession>sessionFuture=model.connect();classLiveContentResponseSubscriberimplementsSubscriber<LiveContentResponse>{@OverridepublicvoidonSubscribe(Subscriptions){s.request(Long.MAX_VALUE);// Request an unlimited number of items}@OverridepublicvoidonNext(LiveContentResponseliveContentResponse){// Handle 16bit pcm audio data at 24khzliveContentResponse.getData();}@OverridepublicvoidonError(Throwablet){System.err.println("Error: "+t.getMessage());}@OverridepublicvoidonComplete(){System.out.println("Done receiving messages!");}}Futures.addCallback(sessionFuture,newFutureCallback<LiveSession>(){@OverridepublicvoidonSuccess(LiveSessionses){LiveSessionFuturessession=LiveSessionFutures.from(ses);// Provide a text promptStringtext="tell me a short story?";session.send(text);Publisher<LiveContentResponse>publisher=session.receive();publisher.subscribe(newLiveContentResponseSubscriber());}@OverridepublicvoidonFailure(Throwablet){// Handle exceptions}},executor);

Web

// Initialize the Gemini Developer API backend serviceconstai=getAI(firebaseApp,{backend:newGoogleAIBackend()});// Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)constmodel=getLiveGenerativeModel(ai,{model:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with audiogenerationConfig:{responseModalities:[ResponseModality.AUDIO],},});constsession=awaitmodel.connect();// Provide a text promptconstprompt="tell a short story";session.send(prompt);// Handle the model's audio outputconstmessages=session.receive();forawait(constmessageofmessages){switch(message.type){case"serverContent":if(message.turnComplete){// TODO(developer): Handle turn completion}elseif(message.interrupted){// TODO(developer): Handle the interruptionbreak;}elseif(message.modelTurn){constparts=message.modelTurn?.parts;parts?.forEach((part)=>{if(part.inlineData){// TODO(developer): Play the audio chunk}});}break;case"toolCall":// Ignorecase"toolCallCancellation":// Ignore}}

Dart

import'package:firebase_ai/firebase_ai.dart';import'package:firebase_core/firebase_core.dart';import'firebase_options.dart';import'dart:async';import'dart:typed_data';lateLiveModelSession_session;Future<Stream<Uint8List>>textToAudio(StringtextPrompt)async{WidgetsFlutterBinding.ensureInitialized();awaitFirebase.initializeApp(options:DefaultFirebaseOptions.currentPlatform,);// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)finalmodel=FirebaseAI.googleAI().liveGenerativeModel(model:'gemini-2.0-flash-live-preview-04-09',// Configure the model to respond with audioliveGenerationConfig:LiveGenerationConfig(responseModalities:ResponseModalities.audio),);_session=awaitmodel.connect();finalprompt=Content.text(textPrompt);await_session.send(input:prompt);return_session.receive().asyncMap((response)async{if(responseisLiveServerContent &&response.modelTurn?.parts!=null){for(finalpartinresponse.modelTurn!.parts){if(partisInlineDataPart){returnpart.bytes;}}}throwException('Audio data not found');});}Future<void>main()async{try{finalaudioStream=awaittextToAudio('Convert this text to audio.');awaitfor(finalaudioDatainaudioStream){// Process the audio data (e.g., play it using an audio player package)print('Received audio data:${audioData.length} bytes');// Example using flutter_sound (replace with your chosen package):// await _flutterSoundPlayer.startPlayer(fromDataBuffer: audioData);}}catch(e){print('Error:$e');}}

Unity

usingFirebase;usingFirebase.AI;asyncTaskSendTextReceiveAudio(){// Initialize the Gemini Developer API backend service// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)varmodel=FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(modelName:"gemini-2.0-flash-live-preview-04-09",// Configure the model to respond with audioliveGenerationConfig:newLiveGenerationConfig(responseModalities:new[]{ResponseModality.Audio}));LiveSessionsession=awaitmodel.ConnectAsync();// Provide a text promptvarprompt=ModelContent.Text("Convert this text to audio.");awaitsession.SendAsync(content:prompt,turnComplete:true);// Start receiving the responseawaitReceiveAudio(session);}Queue<float>audioBuffer=new();asyncTaskReceiveAudio(LiveSessionsession){intsampleRate=24000;intchannelCount=1;// Create a looping AudioClip to fill with the received audio dataintbufferSamples=(int)(sampleRate*channelCount);AudioClipclip=AudioClip.Create("StreamingPCM",bufferSamples,channelCount,sampleRate,true,OnAudioRead);// Attach the clip to an AudioSource and start playing itAudioSourceaudioSource=GetComponent<AudioSource>();audioSource.clip=clip;audioSource.loop=true;audioSource.Play();// Start receiving the responseawaitforeach(varmessageinsession.ReceiveAsync()){// Process the received messageforeach(float[]pcmDatainmessage.AudioAsFloat){lock(audioBuffer){foreach(floatsampleinpcmData){audioBuffer.Enqueue(sample);}}}}}// This method is called by the AudioClip to load audio data.privatevoidOnAudioRead(float[]data){intsamplesToProvide=data.Length;intsamplesProvided=0;lock(audioBuffer){while(samplesProvided <samplesToProvide &&audioBuffer.Count >0){data[samplesProvided]=audioBuffer.Dequeue();samplesProvided++;}}while(samplesProvided <samplesToProvide){data[samplesProvided]=0.0f;samplesProvided++;}}



Create more engaging and interactive experiences

This section describes how to create and manage more engaging or interactivefeatures of theLive API.

Change the response voice

TheLive API uses Chirp 3 to support synthesized speech responses.When usingFirebase AI Logic, you can send audio in a variety of HD voiceslanguages. For a full list and demos of what each voice sounds like, seeChirp 3: HD voices.

Important:Firebase AI Logic doesnot yet support setting a responselanguage. We only support setting the responsevoice.

To specify a voice, set the voice name within thespeechConfig object as partof themodel configuration.If you don't specify a voice, the default isPuck.

Before trying this sample, complete theBefore you begin section of this guide to set up your project and app.
In that section, you'll also click a button for your chosenGemini API provider so that you see provider-specific content on this page.

Swift

TheLive API is not yet supported for Apple platform apps, but check back soon!

Kotlin

// ...valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(modelName="gemini-2.0-flash-live-preview-04-09",// Configure the model to use a specific voice for its audio responsegenerationConfig=liveGenerationConfig{responseModality=ResponseModality.AUDIOspeechConfig=SpeechConfig(voice=Voice("VOICE_NAME"))})// ...

Java

// ...LiveModelmodel=FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel("gemini-2.0-flash-live-preview-04-09",// Configure the model to use a specific voice for its audio responsenewLiveGenerationConfig.Builder().setResponseModalities(ResponseModality.AUDIO).setSpeechConfig(newSpeechConfig(newVoice("VOICE_NAME"))).build());// ...

Web

// Initialize the Gemini Developer API backend serviceconstai=getAI(firebaseApp,{backend:newGoogleAIBackend()});// Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)constmodel=getLiveGenerativeModel(ai,{model:"gemini-2.0-flash-live-preview-04-09",// Configure the model to use a specific voice for its audio responsegenerationConfig:{responseModalities:[ResponseModality.AUDIO],speechConfig:{voiceConfig:{prebuiltVoiceConfig:{voiceName:"VOICE_NAME"},},},},});

Dart

// ...finalmodel=FirebaseAI.googleAI().liveGenerativeModel(model:'gemini-2.0-flash-live-preview-04-09',// Configure the model to use a specific voice for its audio responseliveGenerationConfig:LiveGenerationConfig(responseModalities:ResponseModalities.audio,speechConfig:SpeechConfig(voiceName:'VOICE_NAME'),),);// ...

Unity

varmodel=FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(modelName:"gemini-2.0-flash-live-preview-04-09",liveGenerationConfig:newLiveGenerationConfig(responseModalities:new[]{ResponseModality.Audio},speechConfig:SpeechConfig.UsePrebuiltVoice("VOICE_NAME")));

For the best results when prompting and requiring the model to respond in anon-English language, include the following as part of yoursystem instructions:

RESPOND INLANGUAGE. YOU MUST RESPOND UNMISTAKABLY INLANGUAGE.
Note:Firebase AI Logic doesnot support updating system instructionsmid-session or mid-response.

Maintain context across sessions and requests

You can use a chat structure to maintain context across sessions and requests.Note that this only works for text input and text output.

This approach is best for short contexts; you can send turn-by-turn interactionsto represent the exact sequence of events .For longer contexts, we recommend providing a single message summary to free upthe context window for subsequent interactions.

Handle interruptions

Firebase AI Logic doesnot yet support handling interruptions.Check back soon!

Use function calling (tools)

You can define tools, like available functions, to use with the Live API justlike you can with the standard content generation methods. This sectiondescribes some nuances when using the Live API with function calling. For acomplete description and examples for function calling, see thefunction calling guide.

Important: Audio inputs and audio outputs can negatively impact the model'sability to use function calling.

From a single prompt, the model can generate multiple function calls and thecode necessary to chain their outputs. This code executes in a sandboxenvironment, generating subsequentBidiGenerateContentToolCall messages. The execution pauses until the results of each function call areavailable, which ensures sequential processing.

Additionally, using the Live API with function calling is particularly powerfulbecause the model can request follow-up or clarifying information from the user.For example, if the model doesn't have enough information to provide a parametervalue to a function it wants to call, then the model can ask the user to providemore or clarifying information.

The client should respond withBidiGenerateContentToolResponse.



Limitations and requirements

Keep in mind the following limitations and requirements of theLive API.

Transcription

Firebase AI Logic doesnot yet support transcriptions. Check back soon!

Languages

Audio formats

TheLive API supports the following audio formats:

  • Input audio format: Raw 16 bit PCM audio at 16kHz little-endian
  • Output audio format: Raw 16 bit PCM audio at 24kHz little-endian

Rate limits

TheLive API has rate limits for both concurrent sessions perFirebase project as well as tokens per minute (TPM).

  • Gemini Developer API:

  • Vertex AI Gemini API:

    • 5,000 concurrent sessions per Firebase project
    • 4M tokens per minute

Session length

The default length for a session is 10 minutes. When the session durationexceeds the limit, the connection is terminated.

The model is also limited by the context size. Sending large chunks of input mayresult in earlier session termination.

Note:Firebase AI Logic doesnot yet support extending the session length.

Voice activity detection (VAD)

The model automatically performs voice activity detection (VAD) on a continuousaudio input stream. VAD is enabled by default.

Note:Firebase AI Logic doesnot yet support disabling VAD or configuringVAD parameters.

Token counting

You cannot use theCountTokens API with theLive API.


Give feedback about your experience withFirebase AI Logic


Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-10-04 UTC.