connect method
Implementation
Future<void> connect({
required AudioCodec codec,
required int sampleRate,
String language = 'en-US',
String? userId,
bool includeSpeechProfile = true,
String? websocketUrl,
String? apiKey,
Map<String, String>? customHeaders,
Map<String, String>? customParams,
}) async {
if (_state == WebSocketState.connected) {
print('WebSocket already connected');
return;
}
if (_state == WebSocketState.connecting) {
throw Exception('Connection already in progress');
}
// Store connection parameters
_lastCodec = codec;
_lastSampleRate = sampleRate;
_lastLanguage = language;
_lastUserId = userId;
_lastWebsocketUrl = websocketUrl;
_lastApiKey = apiKey;
_updateState(WebSocketState.connecting);
print('Connecting to WebSocket...');
try {
// FIXED: Proper URL construction
String baseUrl;
if (websocketUrl != null) {
// Use provided URL, ensure it's wss://
baseUrl = websocketUrl
.replaceFirst('https://', 'wss://')
.replaceFirst('http://', 'ws://');
// Remove any duplicate paths
if (baseUrl.contains('/v1/listen/v1/listen')) {
baseUrl = baseUrl.replaceAll('/v1/listen/v1/listen', '/v1/listen');
}
} else {
// Default Deepgram URL
baseUrl = 'wss://api.deepgram.com/v1/listen';
}
// Build query parameters for Deepgram
final params = <String, String>{
'language': language,
'sample_rate': sampleRate.toString(),
'channels': '1',
'encoding': _getEncodingForCodec(codec),
'model': 'nova-2',
'smart_format': 'true',
'interim_results': 'true',
'punctuate': 'true',
'endpointing': '300',
'vad_events': 'true',
'diarize': 'true',
};
// Add custom parameters
if (customParams != null) {
params.addAll(customParams);
}
if (userId != null) {
params['uid'] = userId;
}
final queryString = params.entries
.map((e) => '${e.key}=${Uri.encodeComponent(e.value)}')
.join('&');
// FIXED: Proper URI construction
final uri = Uri.parse('$baseUrl?$queryString');
// Set up headers
final headers = <String, dynamic>{};
final effectiveApiKey = apiKey ?? _config.apiKey;
if (effectiveApiKey != null) {
headers['Authorization'] = 'Token $effectiveApiKey';
}
if (customHeaders != null) {
headers.addAll(customHeaders);
}
print('Connecting to: $uri');
print('Using codec: $codec, sample rate: $sampleRate Hz');
_channel = IOWebSocketChannel.connect(
uri,
headers: headers.isNotEmpty ? headers : null,
pingInterval: Duration(seconds: 20),
connectTimeout: Duration(seconds: 15),
);
await _channel!.ready;
_updateState(WebSocketState.connected);
_reconnectAttempts = 0;
_audioPacketsSent = 0;
_totalAudioBytesSent = 0;
print('WebSocket connected successfully');
_startHeartbeat();
// Listen for messages
_channel!.stream.listen(
(message) {
try {
_handleMessage(message);
} catch (e) {
print('Error handling WebSocket message: $e');
}
},
onError: (error) {
print('WebSocket stream error: $error');
_updateState(WebSocketState.error);
_scheduleReconnect();
},
onDone: () {
print('WebSocket connection closed');
_updateState(WebSocketState.disconnected);
if (_config.autoReconnect) {
_scheduleReconnect();
}
},
);
} catch (e) {
print('WebSocket connection failed: $e');
_updateState(WebSocketState.error);
if (_config.autoReconnect) {
_scheduleReconnect();
}
rethrow;
}
}