Streaming bidirecional usando a API Gemini Live


O Gemini Live API permite interações de texto e voz bidirecionais de baixa latência com o Gemini. Com o Live API, você pode oferecer aos usuários finais a experiência de conversas por voz naturais e humanas, com a capacidade de interromper as respostas do modelo usando comandos de texto ou de voz. O modelo pode processar entradas de texto e áudio (o vídeo será lançado em breve) e fornecer saídas de texto e áudio.

É possível criar protótipos com comandos e o Live API em Vertex AI Studio.

O Live API é uma API stateful que cria uma conexão WebSocket para estabelecer uma sessão entre o cliente e o servidor Gemini. Para mais detalhes, consulte a documentação de referência do Live API.

Antes de começar

Disponível apenas ao usar o Vertex AI Gemini API como seu provedor de API.

Se ainda não tiver feito isso, conclua o guia de início, que descreve como configurar seu projeto do Firebase, conectar seu app ao Firebase, adicionar o SDK, inicializar o serviço de back-end para o Vertex AI Gemini API e criar uma instância de LiveModel.

Modelos compatíveis com esse recurso

O Live API tem suporte apenas para gemini-2.0-flash-live-preview-04-09, não para gemini-2.0-flash.

Usar os recursos padrão do Live API

Esta seção descreve como usar os recursos padrão do Live API, especificamente para transmitir vários tipos de entradas e saídas:

Gerar texto transmitido por streaming com base na entrada de texto transmitida

Antes de testar este exemplo, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, você também clicará em um botão do provedor Gemini API escolhido para acessar o conteúdo específico do provedor nessa página.

É possível enviar entradas de texto em streaming e receber saídas de texto em streaming. Crie uma instância liveModel e defina a modalidade de resposta como Text.

Swift

O Live API ainda não é compatível com apps da plataforma Apple, mas volte em breve.

Kotlin

// Initialize the Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
val model = Firebase.vertexAI.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.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 Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.vertexAI()).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

O Live API ainda não é compatível com apps da Web, mas volte em breve.

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 Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
final model = FirebaseAI.vertexAI().liveModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
  // Configure the model to respond with text
  config: LiveGenerationConfig(responseModalities: [ResponseModality.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 Vertex AI Gemini API backend service
  // Create a `LiveModel` instance with the model that supports the Live API
  var model = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI()).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);
    }
  }
}

Saiba como escolher um modelo adequado para seu caso de uso e app.

Gerar áudio transmitido por streaming da entrada de áudio transmitido por streaming

Antes de testar este exemplo, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, você também clicará em um botão do provedor Gemini API escolhido para acessar o conteúdo específico do provedor nessa página.

É possível enviar entrada de áudio por streaming e receber saída de áudio por streaming. Crie uma instância LiveModel e defina a modalidade de resposta como Audio.

Saiba como configurar e personalizar a voz de resposta (mais adiante nesta página).

Swift

O Live API ainda não é compatível com apps da plataforma Apple, mas volte em breve.

Kotlin

// Initialize the Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
val model = Firebase.vertexAI.liveModel(
    modelName = "gemini-2.0-flash-live-preview-04-09",
    // Configure the model to respond with text
    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 Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.vertexAI()).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();

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

O Live API ainda não é compatível com apps da Web, mas volte em breve.

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 Vertex AI Gemini API backend service
// Create a `LiveModel` instance with the model that supports the Live API
final model = FirebaseAI.vertexAI().liveModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
   // Configure the model to respond with audio
   config: LiveGenerationConfig(responseModalities: [ResponseModality.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 Vertex AI Gemini API backend service
  // Create a `LiveModel` instance with the model that supports the Live API
  var model = FirebaseAI.GetInstance(FirebaseAI.Backend.VertexAI()).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++;
  }
}

Saiba como escolher um modelo adequado para seu caso de uso e app.



Crie experiências mais envolventes e interativas

Esta seção descreve como criar e gerenciar recursos mais envolventes ou interativos do Live API.

Mudar a voz da resposta

O Live API usa o Chirp 3 para oferecer suporte a respostas de fala sintetizadas. Ao usar Firebase AI Logic, é possível enviar áudio em cinco vozes em HD e 31 idiomas.

Se você não especificar uma voz, o padrão será Puck. Também é possível configurar o modelo para responder em qualquer um dos seguintes idiomas:

Aoede (feminino)
Charon (masculino)
Fenrir (masculino)
Kore (feminino)
Puck (masculino)

Para conferir demonstrações de como essas vozes soam e a lista completa de idiomas disponíveis, consulte Chirp 3: vozes em alta definição.

Para especificar uma voz, defina o nome da voz no objeto speechConfig como parte da configuração do modelo:

Swift

O Live API ainda não é compatível com apps da plataforma Apple, mas volte em breve.

Kotlin

// ...

val model = Firebase.vertexAI.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 = Voices.FENRIR)
    }
)

// ...

Java

// ...

LiveModel model = Firebase.getVertexAI().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(Voices.FENRIR))
        .build()
);

// ...

Web

O Live API ainda não é compatível com apps da Web, mas volte em breve.

Dart

// ...

final model = FirebaseVertexAI.instance.liveModel(
  model: 'gemini-2.0-flash-live-preview-04-09',
  // Configure the model to use a specific voice for its audio response
  config: LiveGenerationConfig(
    responseModality: ResponseModality.audio,
    speechConfig: SpeechConfig(voice: Voice.fenrir),
  ),
);

// ...

Unity

Snippets coming soon!

Para melhores resultados ao solicitar e exigir que o modelo responda em um idioma diferente do inglês, inclua o seguinte como parte das instruções do sistema:

RESPOND IN LANGUAGE. YOU MUST RESPOND UNMISTAKABLY IN LANGUAGE.

Manter o contexto em sessões e solicitações

Você pode usar uma estrutura de chat para manter o contexto em todas as sessões e solicitações. Isso só funciona para entrada e saída de texto.

Essa abordagem é melhor para contextos curtos. Você pode enviar interações passo a passo para representar a sequência exata de eventos. Para contextos mais longos, recomendamos fornecer um único resumo de mensagem para liberar a janela de contexto para interações subsequentes.

Processar interrupções

Firebase AI Logic ainda não oferece suporte ao processamento de interrupções. Verifique novamente mais tarde.

Usar chamada de função (ferramentas)

É possível definir ferramentas, como funções disponíveis, para usar com a API Live, assim como nos métodos padrão de geração de conteúdo. Esta seção descreve algumas nuances ao usar a API Live com chamadas de função. Para uma descrição completa e exemplos de chamadas de função, consulte o guia de chamadas de função.

Com um único comando, o modelo pode gerar várias chamadas de função e o código necessário para encadear as saídas. Esse código é executado em um ambiente de sandbox, gerando mensagens BidiGenerateContentToolCall posteriores. A execução é pausada até que os resultados de cada chamada de função estejam disponíveis, o que garante o processamento sequencial.

Além disso, o uso da API Live com a chamada de função é particularmente poderoso, porque o modelo pode solicitar informações de acompanhamento ou esclarecimentos do usuário. Por exemplo, se o modelo não tiver informações suficientes para fornecer um valor de parâmetro a uma função que ele quer chamar, o modelo poderá pedir ao usuário que forneça mais informações ou informações mais claras.

O cliente precisa responder com BidiGenerateContentToolResponse.



Limitações e requisitos

Considere as seguintes limitações e requisitos do Live API.

Transcrição

O Firebase AI Logic ainda não oferece suporte a transcrições. Verifique novamente mais tarde.

Idiomas

Formatos de áudio

O Live API oferece suporte aos seguintes formatos de áudio:

  • Formato de áudio de entrada:áudio PCM bruto de 16 bits a 16 kHz little-endian
  • Formato de áudio de saída:áudio PCM bruto de 16 bits em 24 kHz little-endian

Limites de taxas

Os seguintes limites de taxa são aplicáveis:

  • 10 sessões simultâneas por projeto do Firebase
  • 4 milhões de tokens por minuto

Duração da sessão

A duração padrão de uma sessão é de 30 minutos. Quando a duração da sessão ultrapassa o limite, a conexão é encerrada.

O modelo também é limitado pelo tamanho do contexto. O envio de grandes quantidades de entrada pode resultar no encerramento antecipado da sessão.

Detecção de atividade de voz (VAD)

O modelo realiza automaticamente a detecção de atividade de voz (VAD, na sigla em inglês) em um fluxo de entrada de áudio contínuo. O VAD está ativado por padrão.

Contagem de tokens

Não é possível usar a API CountTokens com o Live API.


Enviar feedback sobre sua experiência com o Firebase AI Logic