# Realtime Plugin 使用示例 ## 基本用法 ```dart import 'package:realtime/realtime.dart'; class VoiceCallPage extends StatefulWidget { @override _VoiceCallPageState createState() => _VoiceCallPageState(); } class _VoiceCallPageState extends State { final RealtimeService _realtimeService = RealtimeService(); StreamSubscription? _eventSubscription; ConnectionStatus _connectionStatus = ConnectionStatus.disconnected; VoiceStatus _voiceStatus = VoiceStatus.idle; @override void initState() { super.initState(); _setupEventListener(); _initializeService(); } void _setupEventListener() { _eventSubscription = _realtimeService.eventStream.listen((event) { switch (event.type) { case 'connectionStatusChanged': setState(() { _connectionStatus = _parseConnectionStatus(event.data); }); break; case 'voiceStatusChanged': setState(() { _voiceStatus = _parseVoiceStatus(event.data); }); break; case 'textReceived': print('收到文本: ${event.data}'); break; case 'error': print('错误: ${event.data}'); break; } }); } Future _initializeService() async { try { final success = await _realtimeService.initialize( serverUrl: 'wss://your-vocode-server.com/ws', sampleRate: 16000, channels: 1, bitsPerSample: 16, ); if (success) { print('Realtime服务初始化成功'); } else { print('Realtime服务初始化失败'); } } catch (e) { print('初始化错误: $e'); } } Future _connect() async { try { final success = await _realtimeService.connect(); if (!success) { print('连接失败'); } } catch (e) { print('连接错误: $e'); } } Future _disconnect() async { try { await _realtimeService.disconnect(); } catch (e) { print('断开连接错误: $e'); } } Future _startRecording() async { try { final success = await _realtimeService.startRecording(); if (!success) { print('开始录音失败'); } } catch (e) { print('录音错误: $e'); } } Future _stopRecording() async { try { final success = await _realtimeService.stopRecording(); if (!success) { print('停止录音失败'); } } catch (e) { print('停止录音错误: $e'); } } ConnectionStatus _parseConnectionStatus(String status) { switch (status) { case 'connected': return ConnectionStatus.connected; case 'connecting': return ConnectionStatus.connecting; case 'disconnected': return ConnectionStatus.disconnected; case 'error': return ConnectionStatus.error; default: return ConnectionStatus.disconnected; } } VoiceStatus _parseVoiceStatus(String status) { switch (status) { case 'recording': return VoiceStatus.recording; case 'processing': return VoiceStatus.processing; case 'playing': return VoiceStatus.playing; case 'idle': return VoiceStatus.idle; default: return VoiceStatus.idle; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('实时语音聊天'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 连接状态显示 Text('连接状态: ${_connectionStatus.name}'), SizedBox(height: 20), // 语音状态显示 Text('语音状态: ${_voiceStatus.name}'), SizedBox(height: 40), // 连接按钮 ElevatedButton( onPressed: _connectionStatus == ConnectionStatus.disconnected ? _connect : _disconnect, child: Text(_connectionStatus == ConnectionStatus.disconnected ? '连接' : '断开'), ), SizedBox(height: 20), // 录音按钮 ElevatedButton( onPressed: _connectionStatus == ConnectionStatus.connected ? (_voiceStatus == VoiceStatus.recording ? _stopRecording : _startRecording) : null, child: Text(_voiceStatus == VoiceStatus.recording ? '停止录音' : '开始录音'), ), ], ), ), ); } @override void dispose() { _eventSubscription?.cancel(); _realtimeService.dispose(); super.dispose(); } } ``` ## GetX控制器中的使用 ```dart import 'package:get/get.dart'; import 'package:realtime/realtime.dart'; class VoiceController extends GetxController { final RealtimeService _realtimeService = RealtimeService(); final RxBool isConnected = false.obs; final RxBool isRecording = false.obs; StreamSubscription? _eventSubscription; @override void onInit() { super.onInit(); _setupEventListener(); _initializeService(); } void _setupEventListener() { _eventSubscription = _realtimeService.eventStream.listen((event) { switch (event.type) { case 'connectionStatusChanged': isConnected.value = event.data == 'connected'; break; case 'voiceStatusChanged': isRecording.value = event.data == 'recording'; break; } }); } Future _initializeService() async { await _realtimeService.initialize( serverUrl: 'wss://your-server/ws', ); } Future toggleConnection() async { if (isConnected.value) { await _realtimeService.disconnect(); } else { await _realtimeService.connect(); } } Future toggleRecording() async { if (isRecording.value) { await _realtimeService.stopRecording(); } else { await _realtimeService.startRecording(); } } @override void onClose() { _eventSubscription?.cancel(); _realtimeService.dispose(); super.onClose(); } } ``` ## 权限配置 ### iOS 在 `ios/Runner/Info.plist` 中添加: ```xml NSMicrophoneUsageDescription 应用需要麦克风权限进行语音录制 ``` ## 服务器配置示例 需要一个支持WebSocket的Vocode服务器,具体实现可参考Vocode官方文档。 服务器需要: 1. 接收16kHz/16-bit/单声道的PCM音频数据 2. 返回相同格式的音频数据 3. 支持文本消息交换 ## 注意事项 1. 确保网络连接稳定 2. 音频格式必须与服务器保持一致 3. 及时处理事件流中的错误 4. 在适当时机释放资源