npm package: @linxai/voice-client
Description: LinxAI 语音对话客户端 - 支持多种传输协议
Latest version: 0.1.0

# @linxai/voice-client

LinxAI 语音对话客户端 - 支持多种传输协议的统一语音对话接口

## 特性

- 🎯 **统一接口** - 一套 API 支持多种传输协议
- 🔌 **多协议支持** - RTC (WebRTC), WebSocket, HTTP Streaming
- 🌐 **多平台集成** - Pipecat, Daily, Agora, LiveKit 等
- 🎨 **框架无关** - 核心逻辑与 React Hooks 分离
- 📦 **轻量级** - 按需加载，最小化打包体积
- 🔧 **易扩展** - 插件化架构，轻松添加新平台

## 安装

```bash
pnpm add @linxai/voice-client
```

## 快速开始

### 基本使用

```tsx
import { useVoiceClient } from '@linxai/voice-client'

function VoiceChat() {
  const [state, { startChat, stopChat }] = useVoiceClient({
    pipecatOptions: {
      webrtcUrl: 'http://localhost:7861/api/offer',
    },
    callbacks: {
      onBotStartedSpeaking: () => console.log('Bot 开始说话'),
      onBotStoppedSpeaking: () => console.log('Bot 停止说话'),
    },
  })

  return (
    <div>
      <p>状态: {state.status}</p>
      <button 
        onClick={state.isConnected ? stopChat : startChat}
        disabled={state.isConnecting}
      >
        {state.isConnected ? '结束对话' : '开始对话'}
      </button>
    </div>
  )
}
```

### 高级配置

```tsx
import { useVoiceClient } from '@linxai/voice-client'

function AdvancedVoiceChat() {
  const [state, actions] = useVoiceClient({
    protocol: 'rtc',
    rtcPlatform: 'pipecat',
    pipecatOptions: {
      webrtcUrl: 'https://my-server.com/api/offer',
      enableMic: true,
      enableCam: false,
      audioCodec: 'opus',
      videoCodec: 'vp8',
      clientOptions: {
        // 额外的 Pipecat 配置
      },
    },
    callbacks: {
      onBotStartedSpeaking: () => {
        console.log('Bot started speaking')
      },
      onBotStoppedSpeaking: () => {
        console.log('Bot stopped speaking')
      },
      onUserTranscript: (text, isFinal) => {
        console.log('User transcript:', text, isFinal)
      },
      onBotTranscript: (text) => {
        console.log('Bot transcript:', text)
      },
      onError: (error) => {
        console.error('Voice client error:', error)
      },
    },
  })

  return (
    <div>
      <p>Status: {state.status}</p>
      <p>Connected: {state.isConnected ? 'Yes' : 'No'}</p>
      <button onClick={actions.startChat}>Start</button>
      <button onClick={actions.stopChat}>Stop</button>
    </div>
  )
}
```

## 架构

```
@linxai/voice-client
├── types/              # 核心类型定义
├── transports/         # 传输层实现
│   ├── rtc/           # RTC 传输
│   │   ├── pipecat/   # Pipecat 实现
│   │   ├── daily/     # Daily 实现 (TODO)
│   │   └── agora/     # Agora 实现 (TODO)
│   ├── websocket/     # WebSocket 传输 (TODO)
│   └── http-streaming/ # HTTP Streaming (TODO)
└── hooks/             # React Hooks
    └── useVoiceClient.ts
```

## API

### useVoiceClient

主要的 React Hook，提供统一的语音对话接口。

**参数:**

```typescript
interface UseVoiceClientConfig {
  enabled?: boolean              // 是否启用（默认 true）
  protocol?: 'rtc'               // 传输协议
  rtcPlatform?: 'pipecat'        // RTC 平台
  pipecatOptions?: PipecatRTCOptions
  callbacks?: VoiceClientCallbacks
}
```

**返回值:**

```typescript
[VoiceClientState, VoiceClientActions]

interface VoiceClientState {
  status: ConnectionStatus
  isConnecting: boolean
  isConnected: boolean
  remoteStream: MediaStream | null
}

interface VoiceClientActions {
  startChat: () => Promise<void>
  stopChat: () => void
}
```

### VoiceClientCallbacks

```typescript
interface VoiceClientCallbacks {
  onBotStartedSpeaking?: () => void
  onBotStoppedSpeaking?: () => void
  onUserStartedSpeaking?: () => void
  onUserStoppedSpeaking?: () => void
  onUserTranscript?: (text: string, isFinal: boolean) => void
  onBotTranscript?: (text: string) => void
  onConnectionChange?: (isConnected: boolean) => void
  onError?: (error: Error) => void
}
```

## 传输协议

### RTC (WebRTC)

#### Pipecat

```tsx
const [state, actions] = useVoiceClient({
  protocol: 'rtc',
  rtcPlatform: 'pipecat',
  pipecatOptions: {
    webrtcUrl: 'http://localhost:7861/api/offer',
    enableMic: true,
    enableCam: false,
  },
})
```

#### Daily (TODO)

```tsx
const [state, actions] = useVoiceClient({
  protocol: 'rtc',
  rtcPlatform: 'daily',
  dailyOptions: {
    url: 'https://your-domain.daily.co/room',
    token: 'your-token',
  },
})
```

### WebSocket (TODO)

```tsx
const [state, actions] = useVoiceClient({
  protocol: 'websocket',
  websocketOptions: {
    url: 'wss://your-server.com/voice',
  },
})
```

## 扩展

### 添加新的 RTC 平台

1. 创建平台目录:

```bash
mkdir -p src/transports/rtc/daily
```

2. 实现 `RTCAdapter` 接口:

```typescript
// src/transports/rtc/daily/useDailyRTC.ts
import type { RTCAdapter } from '../types'

export const useDailyRTC = (config): RTCAdapter => {
  // 实现 connect, disconnect, status, remoteStream
  return { connect, disconnect, status, remoteStream }
}
```

3. 导出:

```typescript
// src/transports/rtc/index.ts
export * from './daily'
```

4. 在 `useVoiceClient` 中添加支持

## License

MIT