Merge pull request #4147 from pipecat-ai/cb/gemini-transcript-fixes

Fix Gemini Live to handle bundled server_content fields
This commit is contained in:
kompfner
2026-03-27 11:00:10 -04:00
committed by GitHub
2 changed files with 24 additions and 11 deletions

1
changelog/4147.fixed.md Normal file
View File

@@ -0,0 +1 @@
- Fixed Gemini Live message handling to process all `server_content` fields independently. Gemini 3.x can bundle multiple fields (e.g. `model_turn` and `output_transcription`) on the same message, but the previous `elif` chain only processed the first match, silently dropping the rest.

View File

@@ -1371,7 +1371,12 @@ class GeminiLiveLLMService(LLMService):
# Reset failure counter if connection has been stable
self._check_and_reset_failure_counter()
if message.server_content and message.server_content.interrupted:
# server_content fields are NOT mutually exclusive —
# Gemini 3.x can bundle multiple content fields and
# turn_complete on the same message, so process the
# content-bearing fields before closing the turn.
sc = message.server_content
if sc and sc.interrupted:
# NOTE: while the service triggers interruptions in
# the specific case of barge-ins, it does *not*
# emit UserStarted/StoppedSpeakingFrames, as the
@@ -1384,23 +1389,30 @@ class GeminiLiveLLMService(LLMService):
# turn strategies.
logger.debug("Gemini VAD: interrupted signal received")
await self.broadcast_interruption()
elif message.server_content and message.server_content.model_turn:
if sc and sc.model_turn:
await self._handle_msg_model_turn(message)
elif message.server_content and message.server_content.turn_complete:
if sc and sc.input_transcription:
await self._handle_msg_input_transcription(message)
if sc and sc.output_transcription:
await self._handle_msg_output_transcription(message)
if (
sc
and sc.grounding_metadata
and not sc.model_turn
and not sc.output_transcription
):
# model_turn/output_transcription already defer
# bundled grounding metadata to turn_complete.
await self._handle_msg_grounding_metadata(message)
if sc and sc.turn_complete:
if not message.usage_metadata:
logger.warning("Received turn_complete without usage_metadata")
await self._handle_msg_turn_complete(message)
if message.usage_metadata:
await self._handle_msg_usage_metadata(message)
elif message.server_content and message.server_content.input_transcription:
await self._handle_msg_input_transcription(message)
elif message.server_content and message.server_content.output_transcription:
await self._handle_msg_output_transcription(message)
elif message.server_content and message.server_content.grounding_metadata:
await self._handle_msg_grounding_metadata(message)
elif message.tool_call:
if message.tool_call:
await self._handle_msg_tool_call(message)
elif message.session_resumption_update:
if message.session_resumption_update:
self._handle_msg_resumption_update(message)
except Exception as e:
if not self._disconnecting: