diff --git a/src/google/adk/agents/live_request_queue.py b/src/google/adk/agents/live_request_queue.py index 9b698c81d6..95ded79bd8 100644 --- a/src/google/adk/agents/live_request_queue.py +++ b/src/google/adk/agents/live_request_queue.py @@ -70,6 +70,8 @@ def send_content(self, content: types.Content): self._queue.put_nowait(LiveRequest(content=content)) def send_realtime(self, blob: types.Blob): + if not blob.mime_type: + blob.mime_type = "audio/pcm;rate=16000" self._queue.put_nowait(LiveRequest(blob=blob)) def send_activity_start(self): diff --git a/tests/unittests/agents/test_live_request_queue_issue5584.py b/tests/unittests/agents/test_live_request_queue_issue5584.py new file mode 100644 index 0000000000..927f0875eb --- /dev/null +++ b/tests/unittests/agents/test_live_request_queue_issue5584.py @@ -0,0 +1,52 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import asyncio +import unittest +from unittest.mock import MagicMock + +from google.adk.agents.live_request_queue import LiveRequest +from google.adk.agents.live_request_queue import LiveRequestQueue +from google.genai import types + + +class TestLiveRequestQueueIssue5584(unittest.IsolatedAsyncioTestCase): + + async def test_send_realtime_default_mime_type(self): + queue = LiveRequestQueue() + test_data = b"test_audio_data" + blob = types.Blob(data=test_data) + + queue.send_realtime(blob) + retrieved_request = await queue.get() + + self.assertIsNotNone(retrieved_request.blob) + self.assertEqual(retrieved_request.blob.data, test_data) + self.assertEqual(retrieved_request.blob.mime_type, "audio/pcm;rate=16000") + + async def test_send_realtime_explicit_mime_type(self): + queue = LiveRequestQueue() + test_data = b"test_audio_data_opus" + explicit_mime_type = "audio/opus" + blob = types.Blob(data=test_data, mime_type=explicit_mime_type) + + queue.send_realtime(blob) + retrieved_request = await queue.get() + + self.assertIsNotNone(retrieved_request.blob) + self.assertEqual(retrieved_request.blob.data, test_data) + self.assertEqual(retrieved_request.blob.mime_type, explicit_mime_type) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/unittests/agents/test_live_request_queue_mime_type.py b/tests/unittests/agents/test_live_request_queue_mime_type.py new file mode 100644 index 0000000000..13df856b1c --- /dev/null +++ b/tests/unittests/agents/test_live_request_queue_mime_type.py @@ -0,0 +1,79 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import asyncio +from unittest.mock import MagicMock, patch + +from google.adk.agents.live_request_queue import LiveRequestQueue, LiveRequest +from google.genai import types + + +class TestLiveRequestQueueMimeType(unittest.IsolatedAsyncioTestCase): + + def setUp(self): + self.live_request_queue = LiveRequestQueue() + + async def test_send_realtime_default_mime_type(self): + """ + Tests that send_realtime sets the default MIME type for audio blobs + when no mime_type is explicitly provided. + """ + audio_data = b"some_audio_data" + blob = types.Blob(data=audio_data, mime_type=None) + + self.live_request_queue.send_realtime(blob) + + # Retrieve the request from the queue + request = await self.live_request_queue.get() + + # Assert that mime_type was set to the default + self.assertEqual(request.blob.mime_type, "audio/pcm;rate=16000") + self.assertEqual(request.blob.data, audio_data) + + async def test_send_realtime_preserves_explicit_mime_type(self): + """ + Tests that send_realtime preserves an explicitly provided MIME type + for audio blobs. + """ + audio_data = b"some_other_audio_data" + explicit_mime_type = "audio/opus" + blob = types.Blob(data=audio_data, mime_type=explicit_mime_type) + + self.live_request_queue.send_realtime(blob) + + # Retrieve the request from the queue + request = await self.live_request_queue.get() + + # Assert that the explicit mime_type was preserved + self.assertEqual(request.blob.mime_type, explicit_mime_type) + self.assertEqual(request.blob.data, audio_data) + + # Removed test_send_realtime_non_blob_data as send_realtime expects types.Blob + + async def test_send_realtime_blob_with_non_none_mime_type(self): + """ + Tests that send_realtime does not alter mime_type if it's already set to non-None. + """ + audio_data = b"more_audio_data" + existing_mime_type = "audio/wav" + blob = types.Blob(data=audio_data, mime_type=existing_mime_type) + + self.live_request_queue.send_realtime(blob) + + # Retrieve the request from the queue + request = await self.live_request_queue.get() + + self.assertEqual(request.blob.mime_type, existing_mime_type) + self.assertEqual(request.blob.data, audio_data)