<br />

| **Preview** : Using theFirebase AI LogicSDKs with theGemini Live APIis 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.

<br />

TheGemini Live APIenables low-latency bidirectional text and voice interactions withGemini. Using theLive API, you can provide end users with the experience of natural, human-like voice conversations, with the 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 can provide text and audio output.

You can prototype with prompts and theLive APIin[Google AI Studio](https://aistudio.google.com)or[Vertex AI Studio](https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstarts/quickstart).

TheLive APIis a stateful API that creates a WebSocket connection to establish a***session*** between the client and theGeminiserver. For details, see theLive APIreference documentation ([Gemini Developer API](https://ai.google.dev/api/live)\|[Vertex AIGemini API](https://cloud.google.com//vertex-ai/generative-ai/docs/model-reference/multimodal-live#messages)).
| **Important:** If you're not looking for*live bidirectional* streaming, but rather basic streaming of text responses (using`generateContentStream`or`sendMessageStream`), then check out the documentation to stream responses when[generating text](https://firebase.google.com/docs/ai-logic/generate-text#streaming),[analyzing images](https://firebase.google.com/docs/ai-logic/analyze-images#streaming),[analyzing video](https://firebase.google.com/docs/ai-logic/analyze-video#streaming),[analyzing audio](https://firebase.google.com/docs/ai-logic/analyze-audio#streaming),[analyzing documents (like PDFs)](https://firebase.google.com/docs/ai-logic/analyze-documents#streaming), or in a[chat experience](https://firebase.google.com/docs/ai-logic/chat#streaming).

## Before you begin

<br />

|----------------------------------------------------------------------------------------------------------------------------------|
| *Click yourGemini APIprovider to view provider-specific content and code on this page.* Gemini Developer APIVertex AI Gemini API |

<br />

If you haven't already, complete the[getting started guide](https://firebase.google.com/docs/ai-logic/get-started), which describes how to set up your Firebase project, connect your app to Firebase, add the SDK, initialize the backend service for your chosenGemini APIprovider, and create a`LiveModel`instance.

<br />

| **Always use the latest versions of theFirebase AI LogicSDKs.** If you're still using the "Vertex AI in Firebase" SDKs, see the[migration guide](https://firebase.google.com/docs/ai-logic/migrate-to-latest-sdk).

<br />

#### Models that support this capability

The models that support theLive APIdepend on your chosenGemini APIprovider.
| **Important:** Regardless of the API provider, the`gemini-2.0-flash`and`gemini-2.5-flash`models do***not*** support theLive API.  
| Also,Firebase AI Logicdoes***not*** yet support the native audio models (like`gemini-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 AIGemini API**

  - `gemini-live-2.5-flash`(private GA^**\***^)
  - `gemini-2.0-flash-live-preview-04-09`(only available to access in`us-central1`)

Take note that for the 2.5 model names for theLive API, the`live`segment immediately follows the`gemini`segment.

^**\*** *Reach out to yourGoogle Cloudaccount 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:

- [Send text and receive text](https://firebase.google.com/docs/ai-logic/live-api#text-in-text-out)
- [Send audio and receive audio](https://firebase.google.com/docs/ai-logic/live-api#audio-in-audio-out)
- [Send audio and receive text](https://firebase.google.com/docs/ai-logic/live-api#audio-in-text-out)
- [Send text and receive audio](https://firebase.google.com/docs/ai-logic/live-api#text-in-audio-out)

| **Note:** To improve consistency when using theLive API, consider configuring the[temperature in the model configuration](https://firebase.google.com/docs/ai-logic/model-parameters), setting[system instructions](https://firebase.google.com/docs/ai-logic/system-instructions), and using[prompting techniques](https://firebase.google.com/docs/ai-logic/prompt-design).

### Generate streamed text from streamed text input

<br />

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| *Before trying this sample, complete the[Before you begin](https://firebase.google.com/docs/ai-logic/live-api#before-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 APIprovider so that you see provider-specific content on this page**.* |

<br />

You can send streamed text input and receive streamed text output. Make sure to create a`liveModel`instance and set the[response modality](https://firebase.google.com/docs/ai-logic/model-parameters#config-gemini-live-api)to`Text`.  

### Swift


    import FirebaseAILogic

    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    let model = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with text
      generationConfig: LiveGenerationConfig(
        responseModalities: [.text]
      )
    )

    do {
      let session = try await model.connect()

      // Provide a text prompt
      let text = "tell a short story"

      await session.sendTextRealtime(text)

      var outputText = ""
      for try await message in session.responses {
        if case let .content(content) = message.payload {
          content.modelTurn?.parts.forEach { part in
            if let part = part as? TextPart {
              outputText += part.text
            }
          }
          // Optional: if you don't require to send more requests.
          if content.isTurnComplete {
            await session.close()
          }
        }
      }

      // Output received from the server.
      print(outputText)
    } catch {
      fatalError(error.localizedDescription)
    }

### Kotlin


    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
        modelName = "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        generationConfig = liveGenerationConfig {
            responseModality = ResponseModality.TEXT 
       }
    )

    val session = model.connect()

    // Provide a text prompt
    val text = "tell a short story"

    session.send(text)

    var outputText = ""
    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


    ExecutorService executor = 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)
    LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
            "gemini-2.0-flash-live-preview-04-09",
            // Configure the model to respond with text
            new LiveGenerationConfig.Builder()
                    .setResponseModalities(ResponseModality.TEXT)
                    .build()
    );
    LiveModelFutures model = LiveModelFutures.from(lm);
    ListenableFuture<LiveSession> sessionFuture =  model.connect();
    class LiveContentResponseSubscriber implements Subscriber<LiveContentResponse> {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(Long.MAX_VALUE); // Request an unlimited number of items
        }
        @Override
        public void onNext(LiveContentResponse liveContentResponse) {
           // Handle the response from the server.
    	System.out.println(liveContentResponse.getText());
        }
        @Override
        public void onError(Throwable t) {
            System.err.println("Error: " + t.getMessage());
        }
        @Override
        public void onComplete() {
            System.out.println("Done receiving messages!");
        }
    }
    Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
        @Override
        public void onSuccess(LiveSession ses) {
    	  LiveSessionFutures session = LiveSessionFutures.from(ses);
            // Provide a text prompt
            String text = "tell me a short story?";
            session.send(text);
            Publisher<LiveContentResponse> publisher = session.receive();
            publisher.subscribe(new LiveContentResponseSubscriber());
        }
        @Override
        public void onFailure(Throwable t) {
            // Handle exceptions
        }
    }, executor);

### Web


    // Initialize the Gemini Developer API backend service
    const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

    // Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)
    const model = getLiveGenerativeModel(ai, {
      model: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with text
      generationConfig: {
        responseModalities: [ResponseModality.TEXT],
      },
    });

    const session = await model.connect();

    // Provide a text prompt
    const prompt = "tell a short story";
    session.send(prompt);

    // Collect text from model's turn
    let text = "";
    const messages = session.receive();
    for await (const message of messages) {
      switch (message.type) {
        case "serverContent":
          if (message.turnComplete) {
            console.log(text);
          } else {
            const parts = message.modelTurn?.parts;
            if (parts) {
              text += parts.map((part) => part.text).join("");
            }
          }
          break;
        case "toolCall":
          // Ignore
        case "toolCallCancellation":
          // Ignore
      }
    }

### Dart


    import 'package:firebase_ai/firebase_ai.dart';
    import 'package:firebase_core/firebase_core.dart';
    import 'firebase_options.dart';

    late LiveModelSession _session;

    await Firebase.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)
    final model = FirebaseAI.googleAI().liveGenerativeModel(
      model: 'gemini-2.0-flash-live-preview-04-09',
      // Configure the model to respond with text
      liveGenerationConfig: LiveGenerationConfig(responseModalities: [ResponseModalities.text]),
    );

    _session = await model.connect();

    // Provide a text prompt
    final prompt = Content.text('tell a short story');
    await _session.send(input: prompt, turnComplete: true);

    // In a separate thread, receive the response
    await for (final message in _session.receive()) {
       // Process the received message
    }

### Unity


    using Firebase;
    using Firebase.AI;

    async Task SendTextReceiveText() {
      // Initialize the Gemini Developer API backend service
      // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
      var model = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
        modelName: "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        liveGenerationConfig: new LiveGenerationConfig(
            responseModalities: new[] { ResponseModality.Text })
      );

      LiveSession session = await model.ConnectAsync();

      // Provide a text prompt
      var prompt = ModelContent.Text("tell a short story");
      await session.SendAsync(content: prompt, turnComplete: true);

      // Receive the response
      await foreach (var message in session.ReceiveAsync()) {
        // Process the received message
        if (!string.IsNullOrEmpty(message.Text)) {
          UnityEngine.Debug.Log("Received message: " + message.Text);
        }
      }
    }

### Generate streamed audio from streamed audio input

<br />

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| *Before trying this sample, complete the[Before you begin](https://firebase.google.com/docs/ai-logic/live-api#before-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 APIprovider so that you see provider-specific content on this page**.* |

<br />

You can send streamed audio input and receive streamed audio output. Make sure to create a`LiveModel`instance and set the[response modality](https://firebase.google.com/docs/ai-logic/model-parameters#config-gemini-live-api)to`Audio`.

Learn how to configure and customize the[response voice](https://firebase.google.com/docs/ai-logic/live-api#change-voice-and-language)(later on this page).  

### Swift


    import FirebaseAILogic

    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    let model = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with audio
      generationConfig: LiveGenerationConfig(
        responseModalities: [.audio]
      )
    )

    do {
      let session = try await model.connect()

      // Load the audio file, or tap a microphone
      guard let audioFile = NSDataAsset(name: "audio.pcm") else {
        fatalError("Failed to load audio file")
      }

      // Provide the audio data
      await session.sendAudioRealtime(audioFile.data)

      var outputText = ""
      for try await message in session.responses {
        if case let .content(content) = message.payload {
          content.modelTurn?.parts.forEach { part in
            if let part = part as? InlineDataPart, part.mimeType.starts(with: "audio/pcm") {
              // Handle 16bit pcm audio data at 24khz
              playAudio(part.data)
            }
          }
          // Optional: if you don't require to send more requests.
          if content.isTurnComplete {
            await session.close()
          }
        }
      }
    } catch {
      fatalError(error.localizedDescription)
    }

### Kotlin


    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
        modelName = "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with audio
        generationConfig = liveGenerationConfig {
            responseModality = ResponseModality.AUDIO 
       }
    )

    val session = model.connect()

    // This is the recommended way.
    // However, you can create your own recorder and handle the stream.
    session.startAudioConversation()

### Java


    ExecutorService executor = 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)
    LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
            "gemini-2.0-flash-live-preview-04-09",
            // Configure the model to respond with audio
            new LiveGenerationConfig.Builder()
                    .setResponseModalities(ResponseModality.AUDIO)
                    .build()
    );
    LiveModelFutures model = LiveModelFutures.from(lm);
    ListenableFuture<LiveSession> sessionFuture =  model.connect();

    Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
        @Override
        public void onSuccess(LiveSession ses) {
    	 LiveSessionFutures session = LiveSessionFutures.from(ses);
            session.startAudioConversation();
        }
        @Override
        public void onFailure(Throwable t) {
            // Handle exceptions
        }
    }, executor);

### Web


    // Initialize the Gemini Developer API backend service
    const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

    // Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)
    const model = getLiveGenerativeModel(ai, {
      model: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with audio
      generationConfig: {
        responseModalities: [ResponseModality.AUDIO],
      },
    });

    const session = await model.connect();

    // Start the audio conversation
    const audioConversationController = await startAudioConversation(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';

    late LiveModelSession _session;
    final _audioRecorder = YourAudioRecorder();

    await Firebase.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)
    final model = FirebaseAI.googleAI().liveGenerativeModel(
      model: 'gemini-2.0-flash-live-preview-04-09',
       // Configure the model to respond with audio
       liveGenerationConfig: LiveGenerationConfig(responseModalities: [ResponseModalities.audio]),
    );

    _session = await model.connect();

    final audioRecordStream = _audioRecorder.startRecordingStream();
    // Map the Uint8List stream to InlineDataPart stream
    final mediaChunkStream = audioRecordStream.map((data) {
      return InlineDataPart('audio/pcm', data);
    });
    await _session.startMediaStream(mediaChunkStream);

    // In a separate thread, receive the audio response from the model
    await for (final message in _session.receive()) {
       // Process the received message
    }

### Unity


    using Firebase;
    using Firebase.AI;

    async Task SendTextReceiveAudio() {
      // Initialize the Gemini Developer API backend service
      // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
      var model = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
        modelName: "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with audio
        liveGenerationConfig: new LiveGenerationConfig(
            responseModalities: new[] { ResponseModality.Audio })
      );

      LiveSession session = await model.ConnectAsync();

      // Start a coroutine to send audio from the Microphone
      var recordingCoroutine = StartCoroutine(SendAudio(session));

      // Start receiving the response
      await ReceiveAudio(session);
    }

    IEnumerator SendAudio(LiveSession liveSession) {
      string microphoneDeviceName = null;
      int recordingFrequency = 16000;
      int recordingBufferSeconds = 2;

      var recordingClip = Microphone.Start(microphoneDeviceName, true,
                                           recordingBufferSeconds, recordingFrequency);

      int lastSamplePosition = 0;
      while (true) {
        if (!Microphone.IsRecording(microphoneDeviceName)) {
          yield break;
        }

        int currentSamplePosition = 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.
          int sampleCount;
          if (currentSamplePosition > lastSamplePosition) {
            sampleCount = currentSamplePosition - lastSamplePosition;
          } else {
            sampleCount = recordingClip.samples - lastSamplePosition + currentSamplePosition;
          }

          if (sampleCount > 0) {
            // Get the audio chunk
            float[] samples = new float[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 Microphone
        const float MicrophoneReadDelay = 0.5f;
        yield return new WaitForSeconds(MicrophoneReadDelay);
      }
    }

    Queue audioBuffer = new();

    async Task ReceiveAudio(LiveSession liveSession) {
      int sampleRate = 24000;
      int channelCount = 1;

      // Create a looping AudioClip to fill with the received audio data
      int bufferSamples = (int)(sampleRate * channelCount);
      AudioClip clip = AudioClip.Create("StreamingPCM", bufferSamples, channelCount,
                                        sampleRate, true, OnAudioRead);

      // Attach the clip to an AudioSource and start playing it
      AudioSource audioSource = GetComponent();
      audioSource.clip = clip;
      audioSource.loop = true;
      audioSource.Play();

      // Start receiving the response
      await foreach (var message in liveSession.ReceiveAsync()) {
        // Process the received message
        foreach (float[] pcmData in message.AudioAsFloat) {
          lock (audioBuffer) {
            foreach (float sample in pcmData) {
              audioBuffer.Enqueue(sample);
            }
          }
        }
      }
    }

    // This method is called by the AudioClip to load audio data.
    private void OnAudioRead(float[] data) {
      int samplesToProvide = data.Length;
      int samplesProvided = 0;

      lock(audioBuffer) {
        while (samplesProvided < samplesToProvide && audioBuffer.Count > 0) {
          data[samplesProvided] = audioBuffer.Dequeue();
          samplesProvided++;
        }
      }

      while (samplesProvided < samplesToProvide) {
        data[samplesProvided] = 0.0f;
        samplesProvided++;
      }
    }

<br />

### Generate streamed text from streamed audio input

<br />

<br />

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| *Before trying this sample, complete the[Before you begin](https://firebase.google.com/docs/ai-logic/live-api#before-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 APIprovider so that you see provider-specific content on this page**.* |

<br />

You can send streamed audio input and receive streamed text output. Make sure to create a`LiveModel`instance and set the[response modality](https://firebase.google.com/docs/ai-logic/model-parameters#config-gemini-live-api)to`Text`.  

### Swift


    import FirebaseAILogic

    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    let model = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with text
      generationConfig: LiveGenerationConfig(
        responseModalities: [.text]
      )
    )

    do {
      let session = try await model.connect()

      // Load the audio file, or tap a microphone
      guard let audioFile = NSDataAsset(name: "audio.pcm") else {
        fatalError("Failed to load audio file")
      }

      // Provide the audio data
      await session.sendAudioRealtime(audioFile.data)

      var outputText = ""
      for try await message in session.responses {
        if case let .content(content) = message.payload {
          content.modelTurn?.parts.forEach { part in
            if let part = part as? TextPart {
              outputText += part.text
            }
          }
          // Optional: if you don't require to send more requests.
          if content.isTurnComplete {
            await session.close()
          }
        }
      }

      // Output received from the server.
      print(outputText)
    } catch {
      fatalError(error.localizedDescription)
    }

### Kotlin


    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
        modelName = "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        generationConfig = liveGenerationConfig {
            responseModality = ResponseModality.TEXT
       }
    )

    val session = model.connect()

    // Provide a text prompt
    val audioContent = content("user") { audioData }

    session.send(audioContent)

    var outputText = ""
    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


    ExecutorService executor = 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)
    LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
            "gemini-2.0-flash-live-preview-04-09",
            // Configure the model to respond with text
            new LiveGenerationConfig.Builder()
                    .setResponseModalities(ResponseModality.TEXT)
                    .build()
    );
    LiveModelFutures model = LiveModelFutures.from(lm);
    ListenableFuture<LiveSession> sessionFuture =  model.connect();
    class LiveContentResponseSubscriber implements Subscriber<LiveContentResponse> {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(Long.MAX_VALUE); // Request an unlimited number of items
        }
        @Override
        public void onNext(LiveContentResponse liveContentResponse) {
            // Handle the response from the server.
    	System.out.println(liveContentResponse.getText());
        }
        @Override
        public void onError(Throwable t) {
            System.err.println("Error: " + t.getMessage());
        }
        @Override
        public void onComplete() {
            System.out.println("Done receiving messages!");
        }
    }
    Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
        @Override
        public void onSuccess(LiveSession ses) {
    	 LiveSessionFutures session = LiveSessionFutures.from(ses);
            // Send Audio data
    	 session.send(new Content.Builder().addInlineData(audioData, "audio/pcm").build());

            session.send(text);
            Publisher<LiveContentResponse> publisher = session.receive();
            publisher.subscribe(new LiveContentResponseSubscriber());
        }
        @Override
        public void onFailure(Throwable t) {
            // Handle exceptions
        }
    }, executor);

### Web


    // Initialize the Gemini Developer API backend service
    const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

    // Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)
    const model = getLiveGenerativeModel(ai, {
      model: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with text
      generationConfig: {
        responseModalities: [ResponseModality.TEXT],
      },
    });

    const session = await model.connect();

    // TODO(developer): Collect audio data (16-bit 16kHz PCM)
    // const audioData = ...

    // Send audio
    const audioPart = {
      inlineData: { data: audioData, mimeType: "audio/pcm" },
    };
    session.send([audioPart]);

    // Collect text from model's turn
    let text = "";
    const messages = session.receive();
    for await (const message of messages) {
      switch (message.type) {
        case "serverContent":
          if (message.turnComplete) {
            console.log(text);
          } else {
            const parts = message.modelTurn?.parts;
            if (parts) {
              text += parts.map((part) => part.text).join("");
            }
          }
          break;
        case "toolCall":
          // Ignore
        case "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';

    late LiveModelSession _session;
    final _audioRecorder = YourAudioRecorder();

    await Firebase.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)
    final model = FirebaseAI.googleAI().liveGenerativeModel(
      model: 'gemini-2.0-flash-live-preview-04-09',
      // Configure the model to respond with text
      liveGenerationConfig: LiveGenerationConfig(responseModalities: ResponseModalities.text),
    );

    _session = await model.connect();

    final audioRecordStream = _audioRecorder.startRecordingStream();
    final mediaChunkStream = audioRecordStream.map((data) {
      return InlineDataPart('audio/pcm', data);
    });

    await _session.startMediaStream(mediaChunkStream);

    final responseStream = _session.receive();

    return responseStream.asyncMap((response) async {
      if (response.parts.isNotEmpty && response.parts.first.text != null) {
        return response.parts.first.text!;
      } else {
        throw Exception('Text response not found.');
      }
    });

    Future main() async {
      try {
        final textStream = await audioToText();

        await for (final text in textStream) {
          print('Received text: $text');
          // Handle the text response
        }
      } catch (e) {
        print('Error: $e');
      }
    }

### Unity


    using Firebase;
    using Firebase.AI;

    async Task SendAudioReceiveText() {
      // Initialize the Gemini Developer API backend service
      // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
      var model = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
        modelName: "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with text
        liveGenerationConfig: new LiveGenerationConfig(
            responseModalities: new[] { ResponseModality.Text })
      );

      LiveSession session = await model.ConnectAsync();

      // Start a coroutine to send audio from the Microphone
      var recordingCoroutine = StartCoroutine(SendAudio(session));

      // Receive the response
      await foreach (var message in session.ReceiveAsync()) {
        // Process the received message
        if (!string.IsNullOrEmpty(message.Text)) {
          UnityEngine.Debug.Log("Received message: " + message.Text);
        }
      }

      StopCoroutine(recordingCoroutine);
    }

    IEnumerator SendAudio(LiveSession liveSession) {
      string microphoneDeviceName = null;
      int recordingFrequency = 16000;
      int recordingBufferSeconds = 2;

      var recordingClip = Microphone.Start(microphoneDeviceName, true,
                                           recordingBufferSeconds, recordingFrequency);

      int lastSamplePosition = 0;
      while (true) {
        if (!Microphone.IsRecording(microphoneDeviceName)) {
          yield break;
        }

        int currentSamplePosition = 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.
          int sampleCount;
          if (currentSamplePosition > lastSamplePosition) {
            sampleCount = currentSamplePosition - lastSamplePosition;
          } else {
            sampleCount = recordingClip.samples - lastSamplePosition + currentSamplePosition;
          }

          if (sampleCount > 0) {
            // Get the audio chunk
            float[] samples = new float[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 Microphone
        const float MicrophoneReadDelay = 0.5f;
        yield return new WaitForSeconds(MicrophoneReadDelay);
      }
    }

<br />

<br />

<br />

### Generate streamed audio from streamed text input

<br />

<br />

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| *Before trying this sample, complete the[Before you begin](https://firebase.google.com/docs/ai-logic/live-api#before-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 APIprovider so that you see provider-specific content on this page**.* |

<br />

You can send streamed text input and receive streamed audio output. Make sure to create a`LiveModel`instance and set the[response modality](https://firebase.google.com/docs/ai-logic/model-parameters#config-gemini-live-api)to`Audio`.

Learn how to configure and customize the[response voice](https://firebase.google.com/docs/ai-logic/live-api#change-voice-and-language)(later on this page).  

### Swift


    import FirebaseAILogic

    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    let model = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with audio
      generationConfig: LiveGenerationConfig(
        responseModalities: [.audio]
      )
    )

    do {
      let session = try await model.connect()

      // Provide a text prompt
      let text = "tell a short story"

      await session.sendTextRealtime(text)

      var outputText = ""
      for try await message in session.responses {
        if case let .content(content) = message.payload {
          content.modelTurn?.parts.forEach { part in
            if let part = part as? InlineDataPart, part.mimeType.starts(with: "audio/pcm") {
              // Handle 16bit pcm audio data at 24khz
              playAudio(part.data)
            }
          }
          // Optional: if you don't require to send more requests.
          if content.isTurnComplete {
            await session.close()
          }
        }
      }
    } catch {
      fatalError(error.localizedDescription)
    }

### Kotlin


    // Initialize the Gemini Developer API backend service
    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    val model = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
        modelName = "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with audio
        generationConfig = liveGenerationConfig {
            responseModality = ResponseModality.AUDIO
       }
    )

    val session = model.connect()

    // Provide a text prompt
    val text = "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 24khz
        playAudio(it.data)
    }

### Java


    ExecutorService executor = 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)
    LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
            "gemini-2.0-flash-live-preview-04-09",
            // Configure the model to respond with text
            new LiveGenerationConfig.Builder()
                    .setResponseModalities(ResponseModality.AUDIO)
                    .build()
    );
    LiveModelFutures model = LiveModelFutures.from(lm);
    ListenableFuture<LiveSession> sessionFuture =  model.connect();
    class LiveContentResponseSubscriber implements Subscriber<LiveContentResponse> {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(Long.MAX_VALUE); // Request an unlimited number of items
        }
        @Override
        public void onNext(LiveContentResponse liveContentResponse) {
            // Handle 16bit pcm audio data at 24khz
    	liveContentResponse.getData();
        }
        @Override
        public void onError(Throwable t) {
            System.err.println("Error: " + t.getMessage());
        }
        @Override
        public void onComplete() {
            System.out.println("Done receiving messages!");
        }
    }
    Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
        @Override
        public void onSuccess(LiveSession ses) {
    	 LiveSessionFutures session = LiveSessionFutures.from(ses);
            // Provide a text prompt
            String text = "tell me a short story?";
            session.send(text);
            Publisher<LiveContentResponse> publisher = session.receive();
            publisher.subscribe(new LiveContentResponseSubscriber());
        }
        @Override
        public void onFailure(Throwable t) {
            // Handle exceptions
        }
    }, executor);

### Web


    // Initialize the Gemini Developer API backend service
    const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

    // Create a `LiveGenerativeModel` instance with the flash-live model (only model that supports the Live API)
    const model = getLiveGenerativeModel(ai, {
      model: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to respond with audio
      generationConfig: {
        responseModalities: [ResponseModality.AUDIO],
      },
    });

    const session = await model.connect();

    // Provide a text prompt
    const prompt = "tell a short story";
    session.send(prompt);

    // Handle the model's audio output
    const messages = session.receive();
    for await (const message of messages) {
      switch (message.type) {
        case "serverContent":
          if (message.turnComplete) {
            // TODO(developer): Handle turn completion
          } else if (message.interrupted) {
            // TODO(developer): Handle the interruption
            break;
          } else if (message.modelTurn) {
            const parts = message.modelTurn?.parts;
            parts?.forEach((part) => {
              if (part.inlineData) {
                // TODO(developer): Play the audio chunk
              }
            });
          }
          break;
        case "toolCall":
          // Ignore
        case "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';

    late LiveModelSession _session;

    Future<Stream<Uint8List>> textToAudio(String textPrompt) async {
      WidgetsFlutterBinding.ensureInitialized();

      await Firebase.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)
      final model = FirebaseAI.googleAI().liveGenerativeModel(
        model: 'gemini-2.0-flash-live-preview-04-09',
        // Configure the model to respond with audio
        liveGenerationConfig: LiveGenerationConfig(responseModalities: ResponseModalities.audio),
      );

      _session = await model.connect();

      final prompt = Content.text(textPrompt);

      await _session.send(input: prompt);

      return _session.receive().asyncMap((response) async {
        if (response is LiveServerContent && response.modelTurn?.parts != null) {
           for (final part in response.modelTurn!.parts) {
             if (part is InlineDataPart) {
               return part.bytes;
             }
           }
        }
        throw Exception('Audio data not found');
      });
    }

    Future<void> main() async {
      try {
        final audioStream = await textToAudio('Convert this text to audio.');

        await for (final audioData in audioStream) {
          // 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


    using Firebase;
    using Firebase.AI;

    async Task SendTextReceiveAudio() {
      // Initialize the Gemini Developer API backend service
      // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
      var model = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
        modelName: "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to respond with audio
        liveGenerationConfig: new LiveGenerationConfig(
            responseModalities: new[] { ResponseModality.Audio })
      );

      LiveSession session = await model.ConnectAsync();

      // Provide a text prompt
      var prompt = ModelContent.Text("Convert this text to audio.");
      await session.SendAsync(content: prompt, turnComplete: true);

      // Start receiving the response
      await ReceiveAudio(session);
    }

    Queue<float> audioBuffer = new();

    async Task ReceiveAudio(LiveSession session) {
      int sampleRate = 24000;
      int channelCount = 1;

      // Create a looping AudioClip to fill with the received audio data
      int bufferSamples = (int)(sampleRate * channelCount);
      AudioClip clip = AudioClip.Create("StreamingPCM", bufferSamples, channelCount,
                                        sampleRate, true, OnAudioRead);

      // Attach the clip to an AudioSource and start playing it
      AudioSource audioSource = GetComponent<AudioSource>();
      audioSource.clip = clip;
      audioSource.loop = true;
      audioSource.Play();

      // Start receiving the response
      await foreach (var message in session.ReceiveAsync()) {
        // Process the received message
        foreach (float[] pcmData in message.AudioAsFloat) {
          lock (audioBuffer) {
            foreach (float sample in pcmData) {
              audioBuffer.Enqueue(sample);
            }
          }
        }
      }
    }

    // This method is called by the AudioClip to load audio data.
    private void OnAudioRead(float[] data) {
      int samplesToProvide = data.Length;
      int samplesProvided = 0;

      lock(audioBuffer) {
        while (samplesProvided < samplesToProvide && audioBuffer.Count > 0) {
          data[samplesProvided] = audioBuffer.Dequeue();
          samplesProvided++;
        }
      }

      while (samplesProvided < samplesToProvide) {
        data[samplesProvided] = 0.0f;
        samplesProvided++;
      }
    }

<br />

<br />

<br />

*** ** * ** ***

## Create more engaging and interactive experiences

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

### Change the response voice

TheLive APIuses Chirp 3 to support synthesized speech responses. When usingFirebase AI Logic, you can send audio in a variety of HD voices languages. For a full list and demos of what each voice sounds like, see[Chirp 3: HD voices](https://cloud.google.com/text-to-speech/docs/chirp3-hd).
| **Important:** Firebase AI Logicdoes*not* yet support setting a response language. We only support setting the response*voice*.

To specify a voice, set the voice name within the`speechConfig`object as part of the[model configuration](https://firebase.google.com/docs/ai-logic/model-parameters#config-gemini-live-api). If you don't specify a voice, the default is`Puck`.

<br />

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| *Before trying this sample, complete the[Before you begin](https://firebase.google.com/docs/ai-logic/live-api#before-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 APIprovider so that you see provider-specific content on this page**.* |

<br />

### Swift


    import FirebaseAILogic

    // ...

    let model = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to use a specific voice for its audio response
      generationConfig: LiveGenerationConfig(
        responseModalities: [.audio],
        speech: SpeechConfig(voiceName: "<var translate="no">VOICE_NAME</var>")
      )
    )

    // ...

### Kotlin


    // ...

    val model = 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 response
        generationConfig = liveGenerationConfig {
            responseModality = ResponseModality.AUDIO
            speechConfig = SpeechConfig(voice = Voice("<var translate="no">VOICE_NAME</var>"))
        }
    )

    // ...

### Java


    // ...

    LiveModel model = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
        "gemini-2.0-flash-live-preview-04-09",
        // Configure the model to use a specific voice for its audio response
        new LiveGenerationConfig.Builder()
            .setResponseModalities(ResponseModality.AUDIO)
            .setSpeechConfig(new SpeechConfig(new Voice("<var translate="no">VOICE_NAME</var>")))
            .build()
    );

    // ...

### Web


    // Initialize the Gemini Developer API backend service
    const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

    // Create a `LiveModel` instance with the flash-live model (only model that supports the Live API)
    const model = getLiveGenerativeModel(ai, {
      model: "gemini-2.0-flash-live-preview-04-09",
      // Configure the model to use a specific voice for its audio response
      generationConfig: {
        responseModalities: [ResponseModality.AUDIO],
        speechConfig: {
          voiceConfig: {
            prebuiltVoiceConfig: { voiceName: "<var translate="no">VOICE_NAME</var>" },
          },
        },
      },
    });

### Dart


    // ...

    final model = FirebaseAI.googleAI().liveGenerativeModel(
      model: 'gemini-2.0-flash-live-preview-04-09',
      // Configure the model to use a specific voice for its audio response
      liveGenerationConfig: LiveGenerationConfig(
        responseModalities: ResponseModalities.audio,
        speechConfig: SpeechConfig(voiceName: '<var translate="no">VOICE_NAME</var>'),
      ),
    );

    // ...

### Unity


    var model = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
      modelName: "gemini-2.0-flash-live-preview-04-09",
      liveGenerationConfig: new LiveGenerationConfig(
        responseModalities: new[] { ResponseModality.Audio },
        speechConfig: SpeechConfig.UsePrebuiltVoice("<var translate="no">VOICE_NAME</var>"))
    );

For the best results when prompting and requiring the model to respond in a non-English language, include the following as part of your[system instructions](https://firebase.google.com/docs/ai-logic/system-instructions):  

    RESPOND IN <var translate="no">LANGUAGE</var>. YOU MUST RESPOND UNMISTAKABLY IN <var translate="no">LANGUAGE</var>.

| **Note:** Firebase AI Logicdoes*not*support updating system instructions mid-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 interactions to represent the exact sequence of events . For longer contexts, we recommend providing a single message summary to free up the context window for subsequent interactions.

### Handle interruptions

Firebase AI Logicdoes*not*yet support handling interruptions. Check back soon!

### Use function calling (tools)

You can define tools, like available functions, to use with the Live API just like you can with the standard content generation methods. This section describes some nuances when using the Live API with function calling. For a complete description and examples for function calling, see the[function calling guide](https://firebase.google.com/docs/ai-logic/function-calling).
| **Important:** Audio inputs and audio outputs can negatively impact the model's ability to use function calling.

From a single prompt, the model can generate multiple function calls and the code necessary to chain their outputs. This code executes in a sandbox environment, generating subsequent[`BidiGenerateContentToolCall`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/multimodal-live#bidigeneratecontenttoolcall)messages. The execution pauses until the results of each function call are available, which ensures sequential processing.

Additionally, using the Live API with function calling is particularly powerful because 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 parameter value to a function it wants to call, then the model can ask the user to provide more or clarifying information.

The client should respond with[`BidiGenerateContentToolResponse`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/multimodal-live#bidigeneratecontenttoolresponse).

<br />

*** ** * ** ***

## Limitations and requirements

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

### Transcription

Firebase AI Logicdoes*not*yet support transcriptions. Check back soon!

### Languages

- **Input languages:** See the full list of[supported input languages forGeminimodels](https://firebase.google.com/docs/ai-logic/models#languages)
- **Output languages:** See the full list of available output languages in[Chirp 3: HD voices](https://cloud.google.com/text-to-speech/docs/chirp3-hd)

### Audio formats

TheLive APIsupports 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 APIhas rate limits for both concurrent sessions per Firebase project as well as tokens per minute (TPM).

- **Gemini Developer API**:

  - Limits vary based on your project'sGemini Developer API"usage tier" (see their[rate limits documentation](https://ai.google.dev/gemini-api/docs/rate-limits))
- **Vertex AIGemini 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 duration exceeds the limit, the connection is terminated.

The model is also limited by the context size. Sending large chunks of input may result in earlier session termination.
| **Note:** Firebase AI Logicdoes*not*yet support extending the session length.

### Voice activity detection (VAD)

The model automatically performs voice activity detection (VAD) on a continuous audio input stream. VAD is enabled by default.
| **Note:** Firebase AI Logicdoes*not*yet support disabling VAD or configuring VAD parameters.

### Token counting

You cannot use the`CountTokens`API with theLive API.

<br />

[Give feedback about your experience withFirebase AI Logic](https://firebase.google.com/docs/ai-logic/feedback)

<br />