Update default voice ID, fix MARS naming, and clean up example

This commit is contained in:
Neil Ruaro
2026-01-09 21:22:33 +09:00
parent 56da2caeed
commit 78fa2ab65e
3 changed files with 19 additions and 26 deletions

View File

@@ -4,10 +4,10 @@
# SPDX-License-Identifier: BSD 2-Clause License # SPDX-License-Identifier: BSD 2-Clause License
# #
"""Camb.ai MARS-8 TTS example with local audio (microphone/speakers). """Camb.ai MARS TTS example with local audio (microphone/speakers).
This example demonstrates: This example demonstrates:
- Basic TTS synthesis with Camb.ai MARS-8 - Basic TTS synthesis with Camb.ai MARS
- Local audio input/output (no WebRTC or Daily needed) - Local audio input/output (no WebRTC or Daily needed)
- Handling interruptions - Handling interruptions
@@ -83,7 +83,7 @@ async def main(voice_id: int):
messages = [ messages = [
{ {
"role": "system", "role": "system",
"content": """You are a helpful voice assistant powered by Camb.ai's MARS-8 "content": """You are a helpful voice assistant powered by Camb.ai's MARS
text-to-speech technology. Keep your responses concise and conversational since text-to-speech technology. Keep your responses concise and conversational since
they will be spoken aloud. Avoid special characters, emojis, or bullet points.""", they will be spoken aloud. Avoid special characters, emojis, or bullet points.""",
}, },
@@ -117,14 +117,9 @@ they will be spoken aloud. Avoid special characters, emojis, or bullet points.""
), ),
) )
# Run the pipeline # Start the conversation when the pipeline is ready
runner = PipelineRunner() @task.event_handler("on_pipeline_started")
logger.info("Starting Camb.ai TTS bot with local audio...") async def on_pipeline_started(task, frame):
logger.info("Speak into your microphone to interact with the bot.")
# Start the conversation with a greeting after a short delay
async def start_greeting():
await asyncio.sleep(1) # Wait for pipeline to start
messages.append( messages.append(
{ {
"role": "system", "role": "system",
@@ -133,11 +128,11 @@ they will be spoken aloud. Avoid special characters, emojis, or bullet points.""
) )
await task.queue_frames([LLMRunFrame()]) await task.queue_frames([LLMRunFrame()])
# Run greeting and pipeline concurrently # Run the pipeline
await asyncio.gather( runner = PipelineRunner()
runner.run(task), logger.info("Starting Camb.ai TTS bot with local audio...")
start_greeting(), logger.info("Speak into your microphone to interact with the bot.")
) await runner.run(task)
if __name__ == "__main__": if __name__ == "__main__":
@@ -145,8 +140,8 @@ if __name__ == "__main__":
parser.add_argument( parser.add_argument(
"--voice-id", "--voice-id",
type=int, type=int,
default=2681, default=147320,
help="Camb.ai voice ID to use (default: 2681 - Attic voice)", help="Camb.ai voice ID to use (default: 147320)",
) )
args = parser.parse_args() args = parser.parse_args()
asyncio.run(main(args.voice_id)) asyncio.run(main(args.voice_id))

View File

@@ -38,7 +38,7 @@ from pipecat.utils.tracing.service_decorators import traced_tts
# Default configuration # Default configuration
DEFAULT_VOICE_ID = 2681 # Attic voice (publicly available) DEFAULT_VOICE_ID = 147320
DEFAULT_LANGUAGE = "en-us" DEFAULT_LANGUAGE = "en-us"
DEFAULT_MODEL = "mars-flash" # Faster inference DEFAULT_MODEL = "mars-flash" # Faster inference
DEFAULT_BASE_URL = "https://client.camb.ai/apis" DEFAULT_BASE_URL = "https://client.camb.ai/apis"
@@ -135,7 +135,7 @@ class CambTTSService(TTSService):
tts = CambTTSService( tts = CambTTSService(
api_key="your-api-key", api_key="your-api-key",
voice_id=2681, voice_id=147320,
model="mars-flash", model="mars-flash",
aiohttp_session=session, aiohttp_session=session,
params=CambTTSService.InputParams( params=CambTTSService.InputParams(
@@ -146,7 +146,7 @@ class CambTTSService(TTSService):
# For mars-instruct with custom instructions: # For mars-instruct with custom instructions:
tts_instruct = CambTTSService( tts_instruct = CambTTSService(
api_key="your-api-key", api_key="your-api-key",
voice_id=2681, voice_id=147320,
model="mars-instruct", model="mars-instruct",
aiohttp_session=session, aiohttp_session=session,
params=CambTTSService.InputParams( params=CambTTSService.InputParams(
@@ -190,7 +190,7 @@ class CambTTSService(TTSService):
Args: Args:
api_key: Camb.ai API key for authentication. api_key: Camb.ai API key for authentication.
aiohttp_session: Shared aiohttp session for making HTTP requests. aiohttp_session: Shared aiohttp session for making HTTP requests.
voice_id: Voice ID to use (e.g., 2681 for Attic). Defaults to 2681. voice_id: Voice ID to use. Defaults to 147320.
model: TTS model to use. Options: "mars-flash", "mars-pro", "mars-instruct". model: TTS model to use. Options: "mars-flash", "mars-pro", "mars-instruct".
Defaults to "mars-flash" (fastest). Defaults to "mars-flash" (fastest).
base_url: Camb.ai API base URL. Defaults to production URL. base_url: Camb.ai API base URL. Defaults to production URL.
@@ -338,10 +338,8 @@ class CambTTSService(TTSService):
await self.start_tts_usage_metrics(text) await self.start_tts_usage_metrics(text)
yield TTSStartedFrame() yield TTSStartedFrame()
CHUNK_SIZE = self.chunk_size
async for frame in self._stream_audio_frames_from_iterator( async for frame in self._stream_audio_frames_from_iterator(
response.content.iter_chunked(CHUNK_SIZE), strip_wav_header=False response.content.iter_chunked(self.chunk_size), strip_wav_header=False
): ):
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
yield frame yield frame

View File

@@ -363,7 +363,7 @@ async def test_language_mapping():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_mars8_instruct_model(aiohttp_client): async def test_mars_instruct_model(aiohttp_client):
"""Test that user_instructions are included for mars-instruct model.""" """Test that user_instructions are included for mars-instruct model."""
received_payload = {} received_payload = {}