Skip to content

feat: add Camb.ai TTS extension#1940

Open
eRuaro wants to merge 5 commits intoTEN-framework:mainfrom
eRuaro:feat/camb-ai-tts
Open

feat: add Camb.ai TTS extension#1940
eRuaro wants to merge 5 commits intoTEN-framework:mainfrom
eRuaro:feat/camb-ai-tts

Conversation

@eRuaro
Copy link

@eRuaro eRuaro commented Jan 4, 2026

Summary

  • Add camb_tts extension for text-to-speech using Camb.ai's MARS API
  • Follows the established HTTP-based TTS pattern
  • Includes unit tests with mock client

Features

  • MARS model family support (mars-flash, mars-pro, mars-instruct)
  • 140+ languages supported
  • Real-time HTTP streaming
  • Configurable voice, language, and model

Configuration

{
  "params": {
    "api_key": "${env:CAMB_API_KEY|}",
    "voice_id": 147320,
    "language": "en-us",
    "speech_model": "mars-flash",
    "format": "pcm_s16le"
  }
}

Test plan

  • Manual API test with real Camb.ai API key
  • Audio playback verified
  • Unit tests with TEN Framework test harness

Add camb_tts_python extension for text-to-speech using Camb.ai's MARS-8 API.

Features:
- MARS-8 model family support (mars-8, mars-8-flash, mars-8-instruct)
- 140+ languages
- Real-time HTTP streaming
- 24kHz audio output
@plutoless
Copy link
Contributor

hi @eRuaro thanks for your pr! please run the formatter and lint and fix relevant issues so that we can merge your pr after ci passes. thx!

@eRuaro
Copy link
Author

eRuaro commented Jan 23, 2026

will do! thanks!

@eRuaro
Copy link
Author

eRuaro commented Jan 29, 2026

@plutoless sorry for the delay! this recent commit fixes the formatting errors you mentioned.

@eRuaro
Copy link
Author

eRuaro commented Feb 4, 2026

@plutoless hey ethan! following up on this - would love to see camb ai on ten!

@plutoless
Copy link
Contributor

@eRuaro the format check still fails. could you pls check?

@github-actions
Copy link

Pull Request Review: Camb.ai TTS Extension (#1940)

Overview

This PR adds a new TTS extension for Camb.ai's MARS API. The implementation follows the established HTTP-based TTS pattern and includes comprehensive tests. Overall, this is a well-structured contribution that aligns with the codebase conventions.

✅ Strengths

Code Quality

  1. Follows Established Patterns: The implementation correctly uses AsyncTTS2HttpExtension and AsyncTTS2HttpClient base classes, matching other HTTP-based TTS extensions (OpenAI, Groq, PlayHT).

  2. Proper Architecture: Clean separation of concerns with config.py, camb_tts.py, extension.py, and addon.py

  3. Good Documentation: Clear README with configuration tables and helpful inline comments

  4. Comprehensive Testing: Includes tests for dump functionality and flush logic with mocked client


🔴 Critical Issues

1. Bug: Incorrect Sample Rate in Tests

Location: tests/test_basic.py:856

Problem: According to your README and MODEL_SAMPLE_RATES dict, mars-flash uses 22050 Hz, not 24000. This will cause audio duration calculations to be incorrect in the flush test.

Fix: Change line 856 to use 22050 instead of 24000


2. Resource Leak: Missing Session Cleanup

Location: camb_tts.py:156-160

Problem: The aiohttp.ClientSession is created lazily in _ensure_session() but only closed in clean(). If get() is called but clean() is never called, the session will leak resources.

Fix: Initialize the session in __init__ instead of lazy loading, then remove _ensure_session() and use self._session directly.

Reference: The openai_tts2_python extension creates the httpx client in __init__ for proper lifecycle management.


⚠️ Important Issues

3. Silent Text Truncation

Location: camb_tts.py:190-195

Problem: Silently truncating text at 3000 characters could lead to unexpected behavior.

Recommendation: Return an ERROR event instead of truncating silently.


4. Missing 403 Handling

Location: camb_tts.py:233-242

Current: Only checking for 401 status code for authentication errors

Recommendation: Also check for 403 (Forbidden) and treat it as an invalid key error.


💡 Suggestions

5. Test Coverage Gaps

Currently tested:

  • ✅ Dump functionality
  • ✅ Flush logic

Missing tests:

  • ❌ Empty text handling
  • ❌ Text too short (< 3 chars)
  • ❌ Text too long (> 3000 chars)
  • ❌ 401/403 authentication errors
  • ❌ Model-specific sample rates

Recommendation: Add test cases for edge cases


6. Missing Usage Example in README

Suggestion: Add an example showing how to configure this extension in a graph. See README files in other TTS extensions for examples.


7. Consider Retry Logic

The groq_tts_python extension includes retry logic for transient network errors. Consider adding similar functionality for production robustness.

Note: This can be added in a follow-up PR if needed.


🟢 Best Practices Followed

  1. ✅ Proper use of AsyncTTS2HttpExtension base class
  2. ✅ Correct event type usage (RESPONSE, END, ERROR, INVALID_KEY_ERROR, FLUSH)
  3. ✅ Sensitive data encryption in to_str() method
  4. ✅ Environment variable support in property.json
  5. ✅ Cancellation support with _is_cancelled flag
  6. ✅ Proper logging categories (LOG_CATEGORY_VENDOR)
  7. ✅ request_id tracking in all log messages
  8. ✅ Model-specific sample rates with fallback
  9. ✅ Addon registration follows standard pattern
  10. ✅ Comprehensive README

🎯 Summary

Verdict: Request Changes (minor issues to address)

Required Changes:

  1. Fix sample rate in test (24000 → 22050)
  2. Initialize aiohttp session in __init__ instead of lazy loading
  3. Return ERROR for text > 3000 chars instead of silent truncation
  4. Add 403 to authentication error check

Recommended Improvements:

  1. Add edge case tests
  2. Add usage example to README
  3. Consider retry logic (future PR)

🤝 Final Notes

Great work overall! The implementation is clean, follows TEN Framework conventions well, and includes good tests. Once the critical issues (sample rate bug and session lifecycle) are fixed, this will be an excellent addition.

Thank you for the contribution! 🎉


Detailed Code References

Similar Extensions for Reference

  • ai_agents/agents/ten_packages/extension/openai_tts2_python/ - HTTP-based with httpx
  • ai_agents/agents/ten_packages/extension/groq_tts_python/ - HTTP-based with retry logic
  • ai_agents/agents/ten_packages/extension/playht_tts_python/ - Similar aiohttp usage pattern

Key Files Reviewed

  • camb_tts.py:108-299 - Main client implementation
  • config.py:305-360 - Configuration and validation
  • extension.py:361-438 - Extension integration
  • tests/test_basic.py:671-990 - Test implementation
  • manifest.json:439-504 - Package metadata
  • property.json:506-521 - Default configuration
  • README.md:1-58 - Documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants