JSPM

@ariaflowagents/livekit-plugin-transport-twilio

1.0.0
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 60
    • Score
      100M100P100Q103694F
    • License Apache-2.0

    Twilio Media Streams transport adapter for AriaFlow agents. Works with Node.js, Bun, Deno, and any WebSocket-compatible runtime.

    Package Exports

    • @ariaflowagents/livekit-plugin-transport-twilio

    Readme

    @ariaflow/livekit-plugin-transport-twilio

    Twilio Media Streams transport adapter for AriaFlow voice agents. Works with Node.js, Bun, Deno, and any WebSocket-enabled runtime. Cloudflare Workers support is currently unstable.

    Features

    • ⚠️ Cloudflare Workers Compatible (Unstable) - No Node.js dependencies
    • Twilio Media Streams Support - Native integration with Twilio's API
    • Automatic Codec Conversion - G.711 μ-law ↔ PCM with resampling (8kHz ↔ 24kHz)
    • AriaFlow Native - Works with createAriaFlowSession and AriaFlow Runtime
    • Session Management - Full lifecycle management with SessionManager

    Installation

    # Using npm
    npm install @ariaflow/livekit-plugin @ariaflow/livekit-plugin-transport-twilio
    
    # Using bun
    bun add @ariaflow/livekit-plugin @ariaflow/livekit-plugin-transport-twilio

    Quick Start

    Cloudflare Workers (Unstable)

    ⚠️ Note: The Cloudflare Workers integration is currently unstable and not officially supported. Use at your own risk.

    // wrangler.toml:
    // name = "ariaflow-twilio-agent"
    // compatibility_date = "2024-01-01"
    // compatibility_flags = ["nodejs_compat"]
    
    import { createTwilioWorker } from '@ariaflow/livekit-plugin-transport-twilio/cloudflare';
    import { createAriaFlowSession } from '@ariaflow/livekit-plugin';
    import { GeminiLiveSTT, GeminiLiveTTS } from '@ariaflow/livekit-plugin/gemini';
    
    const agentConfig = {
      agents: [{ id: 'assistant', prompt: 'You are helpful.' }],
      defaultAgentId: 'assistant',
    };
    
    export default createTwilioWorker({
      agent: () => createAriaFlowSession({
        runtime: agentConfig,
        stt: new GeminiLiveSTT(),
        tts: new GeminiLiveTTS(),
        greeting: 'Hello! How can I help?',
      }),
    });

    Node.js / Deno / Any WebSocket

    import { WebSocketServer } from 'ws';
    import { TwilioTransportAdapter } from '@ariaflow/livekit-plugin-transport-twilio';
    import { createAriaFlowSession } from '@ariaflow/livekit-plugin';
    import { SessionManager } from '@ariaflow/livekit-plugin';
    import { GeminiLiveSTT, GeminiLiveTTS } from '@ariaflow/livekit-plugin/gemini';
    
    const wss = new WebSocketServer({ port: 8080 });
    const sessionManager = new SessionManager();
    
    const agentConfig = {
      agents: [{ id: 'assistant', prompt: 'You are helpful.' }],
      defaultAgentId: 'assistant',
    };
    
    wss.on('connection', (ws) => {
      const transport = new TwilioTransportAdapter({
        send: (msg) => ws.send(msg),
      });
    
      ws.on('message', (data) => {
        transport.handleMessage(data.toString());
      });
    
      ws.on('close', async () => {
        await transport.close();
      });
    
      // Wait for 'connected' event before starting session
      ws.once('message', async (data) => {
        const event = JSON.parse(data.toString());
        if (event.event === 'connected') {
          const { agent, sessionOptions } = createAriaFlowSession({
            runtime: agentConfig,
            stt: new GeminiLiveSTT(),
            tts: new GeminiLiveTTS(),
          });
    
          await sessionManager.startSession(transport, agent, sessionOptions);
        }
      });
    });

    TwiML Setup

    Create a TwiML bin in your Twilio console:

    <?xml version="1.0" encoding="UTF-8"?>
    <Response>
      <Say>Connecting to AI assistant...</Say>
      <Connect>
        <Stream url="wss://your-worker.workers.dev/voice/stream" />
      </Connect>
    </Response>

    Audio Specifications

    Direction Twilio Format Internal Format Sample Rate
    Inbound G.711 μ-law PCM S16 LE 8kHz → 24kHz
    Outbound PCM S16 LE G.711 μ-law 24kHz → 8kHz

    The transport handles all codec conversion and resampling automatically.

    API Reference

    TwilioTransportAdapter

    Main transport adapter class.

    const transport = new TwilioTransportAdapter({
      id: 'optional-custom-id',
      send: (message: string) => {
        // Send message to WebSocket
        ws.send(message);
      },
    });

    Properties:

    • id: string - Unique identifier for this transport
    • audioInput: TwilioAudioInput - Audio input stream
    • audioOutput: TwilioAudioOutput - Audio output stream
    • textOutput: TwilioTextOutput - Text output stream
    • config: TransportAdapterConfig - Configuration object
    • isOpen: boolean - Whether the transport is active

    Methods:

    • handleMessage(message: string) - Process incoming Twilio message
    • clearAudio() - Clear audio buffer
    • close() - Close the transport

    createTwilioWorker(options) (Unstable)

    ⚠️ Note: This Cloudflare Workers integration helper is currently unstable and not officially supported.

    Cloudflare Workers integration helper.

    export default createTwilioWorker({
      agent: () => createAriaFlowSession({...}),
    });

    Options:

    • agent: () => Agent | { agent: Agent; sessionOptions: any } - Agent factory
    • stt?: any - STT instance (for raw LiveKit pattern)
    • llm?: any - LLM instance
    • tts?: any - TTS instance
    • vad?: any - VAD instance
    • turnDetection?: any - Turn detection config

    Environment Compatibility

    Runtime WebSocket Support Status
    Cloudflare Workers ✅ Native ⚠️ Unstable
    Node.js ✅ via ws package ✅ Supported
    Deno ✅ Native ✅ Supported
    Bun ✅ Native ✅ Supported
    Browser ✅ Native ✅ Supported (development only)

    Limitations

    1. Twilio Sample Rate: Twilio uses 8kHz G.711 μ-law. The transport resamples to 24kHz for AriaFlow, but this adds slight latency.
    2. Codec: Only G.711 μ-law is supported (Twilio's standard).
    3. Latency: Expect 500-1000ms additional latency compared to direct WebRTC.
    4. Full Duplex: Twilio Media Streams is full-duplex, but the implementation treats inbound/outbound as separate streams.

    Troubleshooting

    Audio cutting out

    • Check your WebSocket connection is stable
    • Verify send callback is working correctly
    • Check for errors in the console

    Poor audio quality

    • The 8kHz sample rate is lower than typical 24kHz
    • This is a Twilio limitation, not the transport
    • Consider using Twilio's programmable voice SDK for higher quality

    Connection issues

    • Ensure your WebSocket URL is publicly accessible
    • Check Twilio can reach your server (no firewall blocking)
    • Verify CORS headers if using browser-based testing

    Examples

    See examples/ directory for:

    • cloudflare_worker.ts - Complete Cloudflare Worker example (⚠️ Unstable)
    • wrangler.toml - Deployment configuration

    License

    Apache-2.0

    • @ariaflow/livekit-plugin - Core AriaFlow LiveKit integration
    • @ariaflow/livekit-plugin/gemini - Gemini STT/TTS plugins
    • @ariaflow/livekit-plugin-transport-ws - WebSocket transport
    • @ariaflow/livekit-plugin-transport-http - HTTP/SSE transport