Pipecat and Livekit integrations examples#20
Conversation
|
Ian Lee seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
ab812bc to
86633ca
Compare
86633ca to
194b745
Compare
There was a problem hiding this comment.
Pull request overview
Adds Pipecat and LiveKit integration examples (quickstarts + benchmarks) to help developers test Inworld TTS and compare TTFB across multiple providers.
Changes:
- Added Pipecat quickstart bot + UV project config and environment template.
- Added Pipecat and LiveKit (Python + JS) HTTP/WebSocket TTFB benchmark scripts and docs.
- Introduced git submodules for Pipecat and LiveKit Agents repos, plus top-level integrations index.
Reviewed changes
Copilot reviewed 27 out of 32 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| integrations/pipecat/pipecat-quickstart/pyproject.toml | Adds UV project definition for the Pipecat quickstart. |
| integrations/pipecat/pipecat-quickstart/env.example | Provides example env vars for required API keys. |
| integrations/pipecat/pipecat-quickstart/bot.py | Implements a Pipecat voice bot example with STT/LLM/TTS and timestamp debugging. |
| integrations/pipecat/pipecat-quickstart/README.md | Documents local setup and running instructions for the Pipecat quickstart. |
| integrations/pipecat/pipecat | Adds Pipecat as a git submodule. |
| integrations/pipecat/benchmarks/benchmark_websocket_ttfb.py | Adds Pipecat WebSocket TTFB benchmark script. |
| integrations/pipecat/benchmarks/benchmark_streaming_ttfb.py | Adds Pipecat HTTP/streaming TTFB benchmark script. |
| integrations/pipecat/benchmarks/README.md | Documents running Pipecat benchmark scripts. |
| integrations/livekit/python/quickstart/test_inworld_voice_agent.py | Adds a LiveKit Python test agent for Inworld TTS plugin development. |
| integrations/livekit/python/quickstart/README.md | Documents running the LiveKit Python quickstart test agent. |
| integrations/livekit/python/quickstart/.env-example | Provides example LiveKit Python quickstart environment variables. |
| integrations/livekit/python/benchmarks/benchmark_websocket_ttfb.py | Adds LiveKit Python WebSocket TTFB benchmark script. |
| integrations/livekit/python/benchmarks/benchmark_http_ttfb.py | Adds LiveKit Python HTTP TTFB benchmark script. |
| integrations/livekit/python/benchmarks/README.md | Documents running LiveKit Python benchmark scripts. |
| integrations/livekit/python/benchmarks/.env-example | Provides example env vars for LiveKit Python benchmarks. |
| integrations/livekit/python/agents | Adds LiveKit Agents (Python) as a git submodule. |
| integrations/livekit/js/quickstart/test_agent.ts | Adds a LiveKit JS quickstart test agent for Inworld TTS. |
| integrations/livekit/js/quickstart/package.json | Adds package manifest for the LiveKit JS quickstart. |
| integrations/livekit/js/quickstart/README.md | Documents LiveKit JS quickstart setup and usage. |
| integrations/livekit/js/quickstart/.env-example | Provides example env vars for LiveKit JS quickstart. |
| integrations/livekit/js/benchmarks/package.json | Adds package manifest for LiveKit JS benchmarks. |
| integrations/livekit/js/benchmarks/benchmark_websocket_ttfb.ts | Adds LiveKit JS WebSocket TTFB benchmark script. |
| integrations/livekit/js/benchmarks/benchmark_http_ttfb.ts | Adds LiveKit JS HTTP TTFB benchmark script. |
| integrations/livekit/js/benchmarks/README.md | Documents running LiveKit JS benchmark scripts. |
| integrations/livekit/js/agents-js | Adds LiveKit Agents (JS) as a git submodule. |
| integrations/README.md | Adds an index README linking to quickstarts and benchmarks. |
| .gitmodules | Registers the new git submodules for Pipecat and LiveKit Agents. |
| .gitignore | Ignores generated benchmark audio output directory. |
Files not reviewed (3)
- integrations/livekit/js/benchmarks/package-lock.json: Language not supported
- integrations/livekit/js/benchmarks/pnpm-lock.yaml: Language not supported
- integrations/livekit/js/quickstart/pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)
integrations/pipecat/benchmarks/benchmark_streaming_ttfb.py:507
- The
--iterationshelp text says the default is 50, butdefault=20. Update the help string so it matches the actual default value.
"-n",
"--iterations",
type=int,
default=20,
help="Number of benchmark iterations to run (default: 50)",
)
integrations/livekit/js/benchmarks/benchmark_websocket_ttfb.ts:371
- The
--debugoption is parsed but not used anywhere in the script. Either wire it up (e.g., setinitializeLogger({ level: 'debug' })or enable more verbose output) or remove the option to avoid confusion.
const { values } = parseArgs({
options: {
'token-delay': { type: 'string', default: '50' },
text: { type: 'string' },
iterations: { type: 'string', short: 'n', default: '1' },
services: { type: 'string', default: 'all' },
'no-save-audio': { type: 'boolean', default: false },
debug: { type: 'boolean', default: false },
},
});
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async def _check_audio_done(self): | ||
| """Check if audio has stopped arriving and signal completion.""" | ||
| # Wait for first audio to arrive | ||
| while self.first_audio_time is None: | ||
| await asyncio.sleep(0.1) | ||
|
|
||
| # Now wait for audio to stop (no new audio for 2 seconds) | ||
| while True: | ||
| await asyncio.sleep(0.5) | ||
| if self.last_audio_time and (time.time() - self.last_audio_time) > 2.0: | ||
| logger.info(f"🏁 [{self.service_name}] Audio stream complete") | ||
| # Save audio files when done | ||
| self.save_audio_files() | ||
| self._done_event.set() | ||
| break |
There was a problem hiding this comment.
This completion logic can hang forever if no audio ever arrives (e.g., auth failure, provider error, or pipeline ends early). wait_for_completion() will block indefinitely because _done_event is never set. Add a timeout or an alternate completion path (e.g., set _done_event on EndFrame/terminal frames, or after N seconds without receiving any TTSAudioRawFrame).
| async def _check_audio_done(self): | ||
| """Check if audio has stopped arriving and signal completion.""" | ||
| # Wait for first audio to arrive | ||
| while self.first_audio_time is None: | ||
| await asyncio.sleep(0.1) | ||
|
|
||
| # Now wait for audio to stop (no new audio for 2 seconds) | ||
| while True: | ||
| await asyncio.sleep(0.5) | ||
| if self.last_audio_time and (time.time() - self.last_audio_time) > 2.0: | ||
| # Save audio files when done | ||
| self.save_audio_files() | ||
| self._done_event.set() | ||
| break |
There was a problem hiding this comment.
Same as the WebSocket benchmark: this will wait forever if no audio frames arrive, causing the benchmark run to hang. Consider setting _done_event when an EndFrame is observed (or when the pipeline is cancelled), and/or add a maximum wait timeout for the initial audio.
| service_configs = { | ||
| "inworld": { | ||
| "name": "Inworld HTTP", | ||
| "create_fn": create_inworld_http_tts, | ||
| "api_key_env": "BASE64_SECRET_KEY", | ||
| "extra_env": {}, | ||
| }, | ||
| "elevenlabs": { | ||
| "name": "ElevenLabs HTTP", | ||
| "create_fn": create_elevenlabs_http_tts, | ||
| "api_key_env": "ELEVEN_API_KEY", | ||
| "extra_env": {}, | ||
| }, | ||
| "cartesia": { | ||
| "name": "Cartesia HTTP", | ||
| "create_fn": create_cartesia_http_tts, | ||
| "api_key_env": "CARTESIA_API_KEY", | ||
| "extra_env": {}, | ||
| }, | ||
| } |
There was a problem hiding this comment.
The Inworld HTTP config reads the API key from BASE64_SECRET_KEY, but the user-facing error message (and the other benchmark scripts/READMEs in this PR) instruct using INWORLD_API_KEY. This mismatch will cause Inworld to be skipped even when INWORLD_API_KEY is set. Align on a single env var name (either change api_key_env to INWORLD_API_KEY or update the messaging/docs consistently).
|
|
||
| if not available_services: | ||
| print("No services available to benchmark. Please set the required API keys:") | ||
| print(" - INWORLD_API_KEY for Inworld HTTP") |
There was a problem hiding this comment.
The Inworld HTTP config reads the API key from BASE64_SECRET_KEY, but the user-facing error message (and the other benchmark scripts/READMEs in this PR) instruct using INWORLD_API_KEY. This mismatch will cause Inworld to be skipped even when INWORLD_API_KEY is set. Align on a single env var name (either change api_key_env to INWORLD_API_KEY or update the messaging/docs consistently).
| print(" - INWORLD_API_KEY for Inworld HTTP") | |
| print(" - BASE64_SECRET_KEY for Inworld HTTP") |
| console.log('[Inworld TTS] Configuration:'); | ||
| console.log(` - Base URL: ${baseURL}`); | ||
| console.log(` - WebSocket URL: ${wsURL}`); | ||
| console.log(` - API Key: ${apiKey ? apiKey.substring(0, 8) + '...' : 'NOT SET'}`); | ||
| console.log(` - Voice: ${process.env.INWORLD_VOICE || 'Alex'}`); |
There was a problem hiding this comment.
Logging even a partial API key can leak credentials into CI logs, crash reports, or shared terminals. Prefer logging only whether the key is set (e.g., API Key: SET/NOT SET) and avoid printing any part of the secret.
| "@livekit/agents": "link:../agents-js/agents", | ||
| "@livekit/agents-plugin-livekit": "link:../agents-js/plugins/livekit", | ||
| "@livekit/agents-plugin-silero": "link:../agents-js/plugins/silero", | ||
| "@livekit/rtc-node": "link:../agents-js/node_modules/.pnpm/@livekit+rtc-node@0.13.24/node_modules/@livekit/rtc-node", |
There was a problem hiding this comment.
This dependency points to a pnpm store path inside another workspace (node_modules/.pnpm/...), which is highly environment-specific and will break for most users. Use a normal semver dependency (e.g. ^0.13.24) or link to the package in the repo in a stable way (e.g. link:../agents-js/node_modules/@livekit/rtc-node if intentionally vendored, or preferably just a version range).
| "@livekit/rtc-node": "link:../agents-js/node_modules/.pnpm/@livekit+rtc-node@0.13.24/node_modules/@livekit/rtc-node", | |
| "@livekit/rtc-node": "^0.13.24", |
* Minor fix: Clean up config and fix HTTP library issue - Remove dev URL setting - Minor update to test line - Update Python version to resolve HTTP library error - Update INWORLD_API_KEY env name (BASE64_SECRET_KEY -> INWORLD_API_KEY)
…gents_js 3e0c6be, pipecat 02791cd) Made-with: Cursor
…ivekit_agents_js 3e0c6be, pipecat 02791cd)" This reverts commit de8f367.
* parallel runs
* finalize model choices and change 11lab voice id, change websocket default sentence * improved pipecat benchmark to reuse the same connection * fix pipecat benchmark to not prematurely start next turn * reduce intra iteration delay to 0.5s
No description provided.