[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M717WPVVCZG6CJNFJRXES941":3,"skill-same:01M717WPVVCZG6CJNFJRXES941":64},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":14,"repositoryHtmlUrl":47,"repositoryHomepageUrl":6,"ownerHtmlUrl":48,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":49,"install":50,"resources":63},"01M717WPVVCZG6CJNFJRXES941","azure-ai-voicelive-ts",null,"Azure AI Voice Live SDK for JavaScript\u002FTypeScript. Build real-time voice AI applications with bidirectional WebSocket communication.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fazure-ai-voicelive-ts\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"azure ai voicelive ts","azure ai","azure","voice","sdk","build","with","javascript","applications","real-time","for","websocket","live","typescript","2026","communication","unknown","time","community","2026-11-10 10:12:30",false,"---\nname: azure-ai-voicelive-ts\ndescription: Azure AI Voice Live SDK for JavaScript\u002FTypeScript. Build real-time voice AI applications with bidirectional WebSocket communication.\nrisk: unknown\nsource: community\ndate_added: '2026-02-27'\n---\n\n# @azure\u002Fai-voicelive (JavaScript\u002FTypeScript)\n\nReal-time voice AI SDK for building bidirectional voice assistants with Azure AI in Node.js and browser environments.\n\n## Installation\n\n```bash\nnpm install @azure\u002Fai-voicelive @azure\u002Fidentity\n# TypeScript users\nnpm install @types\u002Fnode\n```\n\n**Current Version**: 1.0.0-beta.3\n\n**Supported Environments**:\n- Node.js LTS versions (20+)\n- Modern browsers (Chrome, Firefox, Safari, Edge)\n\n## Environment Variables\n\n```bash\nAZURE_VOICELIVE_ENDPOINT=https:\u002F\u002F\u003Cresource>.cognitiveservices.azure.com\n# Optional: API key if not using Entra ID\nAZURE_VOICELIVE_API_KEY=\u003Cyour-api-key>\n# Optional: Logging\nAZURE_LOG_LEVEL=info\n```\n\n## Authentication\n\n### Microsoft Entra ID (Recommended)\n\n```typescript\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst credential = new DefaultAzureCredential();\nconst endpoint = \"https:\u002F\u002Fyour-resource.cognitiveservices.azure.com\";\n\nconst client = new VoiceLiveClient(endpoint, credential);\n```\n\n### API Key\n\n```typescript\nimport { AzureKeyCredential } from \"@azure\u002Fcore-auth\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst endpoint = \"https:\u002F\u002Fyour-resource.cognitiveservices.azure.com\";\nconst credential = new AzureKeyCredential(\"your-api-key\");\n\nconst client = new VoiceLiveClient(endpoint, credential);\n```\n\n## Client Hierarchy\n\n```\nVoiceLiveClient\n└── VoiceLiveSession (WebSocket connection)\n    ├── updateSession()      → Configure session options\n    ├── subscribe()          → Event handlers (Azure SDK pattern)\n    ├── sendAudio()          → Stream audio input\n    ├── addConversationItem() → Add messages\u002Ffunction outputs\n    └── sendEvent()          → Send raw protocol events\n```\n\n## Quick Start\n\n```typescript\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst credential = new DefaultAzureCredential();\nconst endpoint = process.env.AZURE_VOICELIVE_ENDPOINT!;\n\n\u002F\u002F Create client and start session\nconst client = new VoiceLiveClient(endpoint, credential);\nconst session = await client.startSession(\"gpt-4o-mini-realtime-preview\");\n\n\u002F\u002F Configure session\nawait session.updateSession({\n  modalities: [\"text\", \"audio\"],\n  instructions: \"You are a helpful AI assistant. Respond naturally.\",\n  voice: {\n    type: \"azure-standard\",\n    name: \"en-US-AvaNeural\",\n  },\n  turnDetection: {\n    type: \"server_vad\",\n    threshold: 0.5,\n    prefixPaddingMs: 300,\n    silenceDurationMs: 500,\n  },\n  inputAudioFormat: \"pcm16\",\n  outputAudioFormat: \"pcm16\",\n});\n\n\u002F\u002F Subscribe to events\nconst subscription = session.subscribe({\n  onResponseAudioDelta: async (event, context) => {\n    \u002F\u002F Handle streaming audio output\n    const audioData = event.delta;\n    playAudioChunk(audioData);\n  },\n  onResponseTextDelta: async (event, context) => {\n    \u002F\u002F Handle streaming text\n    process.stdout.write(event.delta);\n  },\n  onInputAudioTranscriptionCompleted: async (event, context) => {\n    console.log(\"User said:\", event.transcript);\n  },\n});\n\n\u002F\u002F Send audio from microphone\nfunction sendAudioChunk(audioBuffer: ArrayBuffer) {\n  session.sendAudio(audioBuffer);\n}\n```\n\n## Session Configuration\n\n```typescript\nawait session.updateSession({\n  \u002F\u002F Modalities\n  modalities: [\"audio\", \"text\"],\n  \n  \u002F\u002F System instructions\n  instructions: \"You are a customer service representative.\",\n  \n  \u002F\u002F Voice selection\n  voice: {\n    type: \"azure-standard\",  \u002F\u002F or \"azure-custom\", \"openai\"\n    name: \"en-US-AvaNeural\",\n  },\n  \n  \u002F\u002F Turn detection (VAD)\n  turnDetection: {\n    type: \"server_vad\",      \u002F\u002F or \"azure_semantic_vad\"\n    threshold: 0.5,\n    prefixPaddingMs: 300,\n    silenceDurationMs: 500,\n  },\n  \n  \u002F\u002F Audio formats\n  inputAudioFormat: \"pcm16\",\n  outputAudioFormat: \"pcm16\",\n  \n  \u002F\u002F Tools (function calling)\n  tools: [\n    {\n      type: \"function\",\n      name: \"get_weather\",\n      description: \"Get current weather\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          location: { type: \"string\" }\n        },\n        required: [\"location\"]\n      }\n    }\n  ],\n  toolChoice: \"auto\",\n});\n```\n\n## Event Handling (Azure SDK Pattern)\n\nThe SDK uses a subscription-based event handling pattern:\n\n```typescript\nconst subscription = session.subscribe({\n  \u002F\u002F Connection lifecycle\n  onConnected: async (args, context) => {\n    console.log(\"Connected:\", args.connectionId);\n  },\n  onDisconnected: async (args, context) => {\n    console.log(\"Disconnected:\", args.code, args.reason);\n  },\n  onError: async (args, context) => {\n    console.error(\"Error:\", args.error.message);\n  },\n  \n  \u002F\u002F Session events\n  onSessionCreated: async (event, context) => {\n    console.log(\"Session created:\", context.sessionId);\n  },\n  onSessionUpdated: async (event, context) => {\n    console.log(\"Session updated\");\n  },\n  \n  \u002F\u002F Audio input events (VAD)\n  onInputAudioBufferSpeechStarted: async (event, context) => {\n    console.log(\"Speech started at:\", event.audioStartMs);\n  },\n  onInputAudioBufferSpeechStopped: async (event, context) => {\n    console.log(\"Speech stopped at:\", event.audioEndMs);\n  },\n  \n  \u002F\u002F Transcription events\n  onConversationItemInputAudioTranscriptionCompleted: async (event, context) => {\n    console.log(\"User said:\", event.transcript);\n  },\n  onConversationItemInputAudioTranscriptionDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  \n  \u002F\u002F Response events\n  onResponseCreated: async (event, context) => {\n    console.log(\"Response started\");\n  },\n  onResponseDone: async (event, context) => {\n    console.log(\"Response complete\");\n  },\n  \n  \u002F\u002F Streaming text\n  onResponseTextDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  onResponseTextDone: async (event, context) => {\n    console.log(\"\\n--- Text complete ---\");\n  },\n  \n  \u002F\u002F Streaming audio\n  onResponseAudioDelta: async (event, context) => {\n    const audioData = event.delta;\n    playAudioChunk(audioData);\n  },\n  onResponseAudioDone: async (event, context) => {\n    console.log(\"Audio complete\");\n  },\n  \n  \u002F\u002F Audio transcript (what assistant said)\n  onResponseAudioTranscriptDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  \n  \u002F\u002F Function calling\n  onResponseFunctionCallArgumentsDone: async (event, context) => {\n    if (event.name === \"get_weather\") {\n      const args = JSON.parse(event.arguments);\n      const result = await getWeather(args.location);\n      \n      await session.addConversationItem({\n        type: \"function_call_output\",\n        callId: event.callId,\n        output: JSON.stringify(result),\n      });\n      \n      await session.sendEvent({ type: \"response.create\" });\n    }\n  },\n  \n  \u002F\u002F Catch-all for debugging\n  onServerEvent: async (event, context) => {\n    console.log(\"Event:\", event.type);\n  },\n});\n\n\u002F\u002F Clean up when done\nawait subscription.close();\n```\n\n## Function Calling\n\n```typescript\n\u002F\u002F Define tools in session config\nawait session.updateSession({\n  modalities: [\"audio\", \"text\"],\n  instructions: \"Help users with weather information.\",\n  tools: [\n    {\n      type: \"function\",\n      name: \"get_weather\",\n      description: \"Get current weather for a location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          location: {\n            type: \"string\",\n            description: \"City and state or country\",\n          },\n        },\n        required: [\"location\"],\n      },\n    },\n  ],\n  toolChoice: \"auto\",\n});\n\n\u002F\u002F Handle function calls\nconst subscription = session.subscribe({\n  onResponseFunctionCallArgumentsDone: async (event, context) => {\n    if (event.name === \"get_weather\") {\n      const args = JSON.parse(event.arguments);\n      const weatherData = await fetchWeather(args.location);\n      \n      \u002F\u002F Send function result\n      await session.addConversationItem({\n        type: \"function_call_output\",\n        callId: event.callId,\n        output: JSON.stringify(weatherData),\n      });\n      \n      \u002F\u002F Trigger response generation\n      await session.sendEvent({ type: \"response.create\" });\n    }\n  },\n});\n```\n\n## Voice Options\n\n| Voice Type | Config | Example |\n|------------|--------|---------|\n| Azure Standard | `{ type: \"azure-standard\", name: \"...\" }` | `\"en-US-AvaNeural\"` |\n| Azure Custom | `{ type: \"azure-custom\", name: \"...\", endpointId: \"...\" }` | Custom voice endpoint |\n| Azure Personal | `{ type: \"azure-personal\", speakerProfileId: \"...\" }` | Personal voice clone |\n| OpenAI | `{ type: \"openai\", name: \"...\" }` | `\"alloy\"`, `\"echo\"`, `\"shimmer\"` |\n\n## Supported Models\n\n| Model | Description | Use Case |\n|-------|-------------|----------|\n| `gpt-4o-realtime-preview` | GPT-4o with real-time audio | High-quality conversational AI |\n| `gpt-4o-mini-realtime-preview` | Lightweight GPT-4o | Fast, efficient interactions |\n| `phi4-mm-realtime` | Phi multimodal | Cost-effective applications |\n\n## Turn Detection Options\n\n```typescript\n\u002F\u002F Server VAD (default)\nturnDetection: {\n  type: \"server_vad\",\n  threshold: 0.5,\n  prefixPaddingMs: 300,\n  silenceDurationMs: 500,\n}\n\n\u002F\u002F Azure Semantic VAD (smarter detection)\nturnDetection: {\n  type: \"azure_semantic_vad\",\n}\n\n\u002F\u002F Azure Semantic VAD (English optimized)\nturnDetection: {\n  type: \"azure_semantic_vad_en\",\n}\n\n\u002F\u002F Azure Semantic VAD (Multilingual)\nturnDetection: {\n  type: \"azure_semantic_vad_multilingual\",\n}\n```\n\n## Audio Formats\n\n| Format | Sample Rate | Use Case |\n|--------|-------------|----------|\n| `pcm16` | 24kHz | Default, high quality |\n| `pcm16-8000hz` | 8kHz | Telephony |\n| `pcm16-16000hz` | 16kHz | Voice assistants |\n| `g711_ulaw` | 8kHz | Telephony (US) |\n| `g711_alaw` | 8kHz | Telephony (EU) |\n\n## Key Types Reference\n\n| Type | Purpose |\n|------|---------|\n| `VoiceLiveClient` | Main client for creating sessions |\n| `VoiceLiveSession` | Active WebSocket session |\n| `VoiceLiveSessionHandlers` | Event handler interface |\n| `VoiceLiveSubscription` | Active event subscription |\n| `ConnectionContext` | Context for connection events |\n| `SessionContext` | Context for session events |\n| `ServerEventUnion` | Union of all server events |\n\n## Error Handling\n\n```typescript\nimport {\n  VoiceLiveError,\n  VoiceLiveConnectionError,\n  VoiceLiveAuthenticationError,\n  VoiceLiveProtocolError,\n} from \"@azure\u002Fai-voicelive\";\n\nconst subscription = session.subscribe({\n  onError: async (args, context) => {\n    const { error } = args;\n    \n    if (error instanceof VoiceLiveConnectionError) {\n      console.error(\"Connection error:\", error.message);\n    } else if (error instanceof VoiceLiveAuthenticationError) {\n      console.error(\"Auth error:\", error.message);\n    } else if (error instanceof VoiceLiveProtocolError) {\n      console.error(\"Protocol error:\", error.message);\n    }\n  },\n  \n  onServerError: async (event, context) => {\n    console.error(\"Server error:\", event.error?.message);\n  },\n});\n```\n\n## Logging\n\n```typescript\nimport { setLogLevel } from \"@azure\u002Flogger\";\n\n\u002F\u002F Enable verbose logging\nsetLogLevel(\"info\");\n\n\u002F\u002F Or via environment variable\n\u002F\u002F AZURE_LOG_LEVEL=info\n```\n\n## Browser Usage\n\n```typescript\n\u002F\u002F Browser requires bundler (Vite, webpack, etc.)\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\nimport { InteractiveBrowserCredential } from \"@azure\u002Fidentity\";\n\n\u002F\u002F Use browser-compatible credential\nconst credential = new InteractiveBrowserCredential({\n  clientId: \"your-client-id\",\n  tenantId: \"your-tenant-id\",\n});\n\nconst client = new VoiceLiveClient(endpoint, credential);\n\n\u002F\u002F Request microphone access\nconst stream = await navigator.mediaDevices.getUserMedia({ audio: true });\nconst audioContext = new AudioContext({ sampleRate: 24000 });\n\n\u002F\u002F Process audio and send to session\n\u002F\u002F ... (see samples for full implementation)\n```\n\n## Best Practices\n\n1. **Always use `DefaultAzureCredential`** — Never hardcode API keys\n2. **Set both modalities** — Include `[\"text\", \"audio\"]` for voice assistants\n3. **Use Azure Semantic VAD** — Better turn detection than basic server VAD\n4. **Handle all error types** — Connection, auth, and protocol errors\n5. **Clean up subscriptions** — Call `subscription.close()` when done\n6. **Use appropriate audio format** — PCM16 at 24kHz for best quality\n\n## Reference Links\n\n| Resource | URL |\n|----------|-----|\n| npm Package | https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@azure\u002Fai-voicelive |\n| GitHub Source | https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-for-js\u002Ftree\u002Fmain\u002Fsdk\u002Fai\u002Fai-voicelive |\n| Samples | https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-for-js\u002Ftree\u002Fmain\u002Fsdk\u002Fai\u002Fai-voicelive\u002Fsamples |\n| API Reference | https:\u002F\u002Flearn.microsoft.com\u002Fjavascript\u002Fapi\u002F@azure\u002Fai-voicelive |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n","# @azure\u002Fai-voicelive (JavaScript\u002FTypeScript)\n\nReal-time voice AI SDK for building bidirectional voice assistants with Azure AI in Node.js and browser environments.\n\n## Installation\n\n```bash\nnpm install @azure\u002Fai-voicelive @azure\u002Fidentity\n# TypeScript users\nnpm install @types\u002Fnode\n```\n\n**Current Version**: 1.0.0-beta.3\n\n**Supported Environments**:\n- Node.js LTS versions (20+)\n- Modern browsers (Chrome, Firefox, Safari, Edge)\n\n## Environment Variables\n\n```bash\nAZURE_VOICELIVE_ENDPOINT=https:\u002F\u002F\u003Cresource>.cognitiveservices.azure.com\n# Optional: API key if not using Entra ID\nAZURE_VOICELIVE_API_KEY=\u003Cyour-api-key>\n# Optional: Logging\nAZURE_LOG_LEVEL=info\n```\n\n## Authentication\n\n### Microsoft Entra ID (Recommended)\n\n```typescript\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst credential = new DefaultAzureCredential();\nconst endpoint = \"https:\u002F\u002Fyour-resource.cognitiveservices.azure.com\";\n\nconst client = new VoiceLiveClient(endpoint, credential);\n```\n\n### API Key\n\n```typescript\nimport { AzureKeyCredential } from \"@azure\u002Fcore-auth\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst endpoint = \"https:\u002F\u002Fyour-resource.cognitiveservices.azure.com\";\nconst credential = new AzureKeyCredential(\"your-api-key\");\n\nconst client = new VoiceLiveClient(endpoint, credential);\n```\n\n## Client Hierarchy\n\n```\nVoiceLiveClient\n└── VoiceLiveSession (WebSocket connection)\n    ├── updateSession()      → Configure session options\n    ├── subscribe()          → Event handlers (Azure SDK pattern)\n    ├── sendAudio()          → Stream audio input\n    ├── addConversationItem() → Add messages\u002Ffunction outputs\n    └── sendEvent()          → Send raw protocol events\n```\n\n## Quick Start\n\n```typescript\nimport { DefaultAzureCredential } from \"@azure\u002Fidentity\";\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\n\nconst credential = new DefaultAzureCredential();\nconst endpoint = process.env.AZURE_VOICELIVE_ENDPOINT!;\n\n\u002F\u002F Create client and start session\nconst client = new VoiceLiveClient(endpoint, credential);\nconst session = await client.startSession(\"gpt-4o-mini-realtime-preview\");\n\n\u002F\u002F Configure session\nawait session.updateSession({\n  modalities: [\"text\", \"audio\"],\n  instructions: \"You are a helpful AI assistant. Respond naturally.\",\n  voice: {\n    type: \"azure-standard\",\n    name: \"en-US-AvaNeural\",\n  },\n  turnDetection: {\n    type: \"server_vad\",\n    threshold: 0.5,\n    prefixPaddingMs: 300,\n    silenceDurationMs: 500,\n  },\n  inputAudioFormat: \"pcm16\",\n  outputAudioFormat: \"pcm16\",\n});\n\n\u002F\u002F Subscribe to events\nconst subscription = session.subscribe({\n  onResponseAudioDelta: async (event, context) => {\n    \u002F\u002F Handle streaming audio output\n    const audioData = event.delta;\n    playAudioChunk(audioData);\n  },\n  onResponseTextDelta: async (event, context) => {\n    \u002F\u002F Handle streaming text\n    process.stdout.write(event.delta);\n  },\n  onInputAudioTranscriptionCompleted: async (event, context) => {\n    console.log(\"User said:\", event.transcript);\n  },\n});\n\n\u002F\u002F Send audio from microphone\nfunction sendAudioChunk(audioBuffer: ArrayBuffer) {\n  session.sendAudio(audioBuffer);\n}\n```\n\n## Session Configuration\n\n```typescript\nawait session.updateSession({\n  \u002F\u002F Modalities\n  modalities: [\"audio\", \"text\"],\n  \n  \u002F\u002F System instructions\n  instructions: \"You are a customer service representative.\",\n  \n  \u002F\u002F Voice selection\n  voice: {\n    type: \"azure-standard\",  \u002F\u002F or \"azure-custom\", \"openai\"\n    name: \"en-US-AvaNeural\",\n  },\n  \n  \u002F\u002F Turn detection (VAD)\n  turnDetection: {\n    type: \"server_vad\",      \u002F\u002F or \"azure_semantic_vad\"\n    threshold: 0.5,\n    prefixPaddingMs: 300,\n    silenceDurationMs: 500,\n  },\n  \n  \u002F\u002F Audio formats\n  inputAudioFormat: \"pcm16\",\n  outputAudioFormat: \"pcm16\",\n  \n  \u002F\u002F Tools (function calling)\n  tools: [\n    {\n      type: \"function\",\n      name: \"get_weather\",\n      description: \"Get current weather\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          location: { type: \"string\" }\n        },\n        required: [\"location\"]\n      }\n    }\n  ],\n  toolChoice: \"auto\",\n});\n```\n\n## Event Handling (Azure SDK Pattern)\n\nThe SDK uses a subscription-based event handling pattern:\n\n```typescript\nconst subscription = session.subscribe({\n  \u002F\u002F Connection lifecycle\n  onConnected: async (args, context) => {\n    console.log(\"Connected:\", args.connectionId);\n  },\n  onDisconnected: async (args, context) => {\n    console.log(\"Disconnected:\", args.code, args.reason);\n  },\n  onError: async (args, context) => {\n    console.error(\"Error:\", args.error.message);\n  },\n  \n  \u002F\u002F Session events\n  onSessionCreated: async (event, context) => {\n    console.log(\"Session created:\", context.sessionId);\n  },\n  onSessionUpdated: async (event, context) => {\n    console.log(\"Session updated\");\n  },\n  \n  \u002F\u002F Audio input events (VAD)\n  onInputAudioBufferSpeechStarted: async (event, context) => {\n    console.log(\"Speech started at:\", event.audioStartMs);\n  },\n  onInputAudioBufferSpeechStopped: async (event, context) => {\n    console.log(\"Speech stopped at:\", event.audioEndMs);\n  },\n  \n  \u002F\u002F Transcription events\n  onConversationItemInputAudioTranscriptionCompleted: async (event, context) => {\n    console.log(\"User said:\", event.transcript);\n  },\n  onConversationItemInputAudioTranscriptionDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  \n  \u002F\u002F Response events\n  onResponseCreated: async (event, context) => {\n    console.log(\"Response started\");\n  },\n  onResponseDone: async (event, context) => {\n    console.log(\"Response complete\");\n  },\n  \n  \u002F\u002F Streaming text\n  onResponseTextDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  onResponseTextDone: async (event, context) => {\n    console.log(\"\\n--- Text complete ---\");\n  },\n  \n  \u002F\u002F Streaming audio\n  onResponseAudioDelta: async (event, context) => {\n    const audioData = event.delta;\n    playAudioChunk(audioData);\n  },\n  onResponseAudioDone: async (event, context) => {\n    console.log(\"Audio complete\");\n  },\n  \n  \u002F\u002F Audio transcript (what assistant said)\n  onResponseAudioTranscriptDelta: async (event, context) => {\n    process.stdout.write(event.delta);\n  },\n  \n  \u002F\u002F Function calling\n  onResponseFunctionCallArgumentsDone: async (event, context) => {\n    if (event.name === \"get_weather\") {\n      const args = JSON.parse(event.arguments);\n      const result = await getWeather(args.location);\n      \n      await session.addConversationItem({\n        type: \"function_call_output\",\n        callId: event.callId,\n        output: JSON.stringify(result),\n      });\n      \n      await session.sendEvent({ type: \"response.create\" });\n    }\n  },\n  \n  \u002F\u002F Catch-all for debugging\n  onServerEvent: async (event, context) => {\n    console.log(\"Event:\", event.type);\n  },\n});\n\n\u002F\u002F Clean up when done\nawait subscription.close();\n```\n\n## Function Calling\n\n```typescript\n\u002F\u002F Define tools in session config\nawait session.updateSession({\n  modalities: [\"audio\", \"text\"],\n  instructions: \"Help users with weather information.\",\n  tools: [\n    {\n      type: \"function\",\n      name: \"get_weather\",\n      description: \"Get current weather for a location\",\n      parameters: {\n        type: \"object\",\n        properties: {\n          location: {\n            type: \"string\",\n            description: \"City and state or country\",\n          },\n        },\n        required: [\"location\"],\n      },\n    },\n  ],\n  toolChoice: \"auto\",\n});\n\n\u002F\u002F Handle function calls\nconst subscription = session.subscribe({\n  onResponseFunctionCallArgumentsDone: async (event, context) => {\n    if (event.name === \"get_weather\") {\n      const args = JSON.parse(event.arguments);\n      const weatherData = await fetchWeather(args.location);\n      \n      \u002F\u002F Send function result\n      await session.addConversationItem({\n        type: \"function_call_output\",\n        callId: event.callId,\n        output: JSON.stringify(weatherData),\n      });\n      \n      \u002F\u002F Trigger response generation\n      await session.sendEvent({ type: \"response.create\" });\n    }\n  },\n});\n```\n\n## Voice Options\n\n| Voice Type | Config | Example |\n|------------|--------|---------|\n| Azure Standard | `{ type: \"azure-standard\", name: \"...\" }` | `\"en-US-AvaNeural\"` |\n| Azure Custom | `{ type: \"azure-custom\", name: \"...\", endpointId: \"...\" }` | Custom voice endpoint |\n| Azure Personal | `{ type: \"azure-personal\", speakerProfileId: \"...\" }` | Personal voice clone |\n| OpenAI | `{ type: \"openai\", name: \"...\" }` | `\"alloy\"`, `\"echo\"`, `\"shimmer\"` |\n\n## Supported Models\n\n| Model | Description | Use Case |\n|-------|-------------|----------|\n| `gpt-4o-realtime-preview` | GPT-4o with real-time audio | High-quality conversational AI |\n| `gpt-4o-mini-realtime-preview` | Lightweight GPT-4o | Fast, efficient interactions |\n| `phi4-mm-realtime` | Phi multimodal | Cost-effective applications |\n\n## Turn Detection Options\n\n```typescript\n\u002F\u002F Server VAD (default)\nturnDetection: {\n  type: \"server_vad\",\n  threshold: 0.5,\n  prefixPaddingMs: 300,\n  silenceDurationMs: 500,\n}\n\n\u002F\u002F Azure Semantic VAD (smarter detection)\nturnDetection: {\n  type: \"azure_semantic_vad\",\n}\n\n\u002F\u002F Azure Semantic VAD (English optimized)\nturnDetection: {\n  type: \"azure_semantic_vad_en\",\n}\n\n\u002F\u002F Azure Semantic VAD (Multilingual)\nturnDetection: {\n  type: \"azure_semantic_vad_multilingual\",\n}\n```\n\n## Audio Formats\n\n| Format | Sample Rate | Use Case |\n|--------|-------------|----------|\n| `pcm16` | 24kHz | Default, high quality |\n| `pcm16-8000hz` | 8kHz | Telephony |\n| `pcm16-16000hz` | 16kHz | Voice assistants |\n| `g711_ulaw` | 8kHz | Telephony (US) |\n| `g711_alaw` | 8kHz | Telephony (EU) |\n\n## Key Types Reference\n\n| Type | Purpose |\n|------|---------|\n| `VoiceLiveClient` | Main client for creating sessions |\n| `VoiceLiveSession` | Active WebSocket session |\n| `VoiceLiveSessionHandlers` | Event handler interface |\n| `VoiceLiveSubscription` | Active event subscription |\n| `ConnectionContext` | Context for connection events |\n| `SessionContext` | Context for session events |\n| `ServerEventUnion` | Union of all server events |\n\n## Error Handling\n\n```typescript\nimport {\n  VoiceLiveError,\n  VoiceLiveConnectionError,\n  VoiceLiveAuthenticationError,\n  VoiceLiveProtocolError,\n} from \"@azure\u002Fai-voicelive\";\n\nconst subscription = session.subscribe({\n  onError: async (args, context) => {\n    const { error } = args;\n    \n    if (error instanceof VoiceLiveConnectionError) {\n      console.error(\"Connection error:\", error.message);\n    } else if (error instanceof VoiceLiveAuthenticationError) {\n      console.error(\"Auth error:\", error.message);\n    } else if (error instanceof VoiceLiveProtocolError) {\n      console.error(\"Protocol error:\", error.message);\n    }\n  },\n  \n  onServerError: async (event, context) => {\n    console.error(\"Server error:\", event.error?.message);\n  },\n});\n```\n\n## Logging\n\n```typescript\nimport { setLogLevel } from \"@azure\u002Flogger\";\n\n\u002F\u002F Enable verbose logging\nsetLogLevel(\"info\");\n\n\u002F\u002F Or via environment variable\n\u002F\u002F AZURE_LOG_LEVEL=info\n```\n\n## Browser Usage\n\n```typescript\n\u002F\u002F Browser requires bundler (Vite, webpack, etc.)\nimport { VoiceLiveClient } from \"@azure\u002Fai-voicelive\";\nimport { InteractiveBrowserCredential } from \"@azure\u002Fidentity\";\n\n\u002F\u002F Use browser-compatible credential\nconst credential = new InteractiveBrowserCredential({\n  clientId: \"your-client-id\",\n  tenantId: \"your-tenant-id\",\n});\n\nconst client = new VoiceLiveClient(endpoint, credential);\n\n\u002F\u002F Request microphone access\nconst stream = await navigator.mediaDevices.getUserMedia({ audio: true });\nconst audioContext = new AudioContext({ sampleRate: 24000 });\n\n\u002F\u002F Process audio and send to session\n\u002F\u002F ... (see samples for full implementation)\n```\n\n## Best Practices\n\n1. **Always use `DefaultAzureCredential`** — Never hardcode API keys\n2. **Set both modalities** — Include `[\"text\", \"audio\"]` for voice assistants\n3. **Use Azure Semantic VAD** — Better turn detection than basic server VAD\n4. **Handle all error types** — Connection, auth, and protocol errors\n5. **Clean up subscriptions** — Call `subscription.close()` when done\n6. **Use appropriate audio format** — PCM16 at 24kHz for best quality\n\n## Reference Links\n\n| Resource | URL |\n|----------|-----|\n| npm Package | https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@azure\u002Fai-voicelive |\n| GitHub Source | https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-for-js\u002Ftree\u002Fmain\u002Fsdk\u002Fai\u002Fai-voicelive |\n| Samples | https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-for-js\u002Ftree\u002Fmain\u002Fsdk\u002Fai\u002Fai-voicelive\u002Fsamples |\n| API Reference | https:\u002F\u002Flearn.microsoft.com\u002Fjavascript\u002Fapi\u002F@azure\u002Fai-voicelive |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n",{"name":5,"risk":35,"source":37,"date_added":43,"description":7},"2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fglobal\u002Fazure-ai-voicelive-ts","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill azure-ai-voicelive-ts",{"tool":56,"command":57},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill azure-ai-voicelive-ts",{"tool":59,"command":60},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill azure-ai-voicelive-ts","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fazure-ai-voicelive-ts\u002FSKILL.md",true,[],[65,88,112,122,135,154],{"skillNo":66,"name":67,"nameZh":6,"description":68,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":76,"publishedAt":38},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[71],{"categoryNo":72,"categoryName":73,"taxonomyType":74,"taxonomyTypeDesc":75},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[77,78,79,80,81,82,83,84,85,86,87,25],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch",{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":38},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[95,96,97,98,99,36,79,100,101,102,103,104,105,31,106,107,108,109,110,111],"trend","trend tap","tap","api keys","Bash","trending","hacker","aggregator","do","when","brew","data","google","install","read","across","api",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":38},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[119,120,95,105,31,106,107,99,79,109,121,110,111,104,102,101,100,108,36,98],"trend radar","radar","pulse",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":38},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[129,130,131,132,133,134],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":146,"publishedAt":38},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":144,"taxonomyTypeDesc":145},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[137,85,147,148,149,25,105,150,151,152,97,153,108],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":38},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[156,161,162,163,108,164,151,165,166,167,168,169],"status","play","go","latest","github","discover","control","cmd","volume"]