Flutter Auto Echo Cancellation WebSocket

pub package License: MIT

A Flutter plugin for real-time voice communication with automatic echo cancellation (AEC) over WebSocket. Perfect for building voice agents, real-time voice chat, and AI voice assistants.

โœจ Features

  • ๐ŸŽค Native AEC - Hardware-level echo cancellation on iOS and Android
  • ๐Ÿ”Š Full Duplex Audio - Simultaneous recording and playback
  • ๐ŸŒ WebSocket Streaming - Real-time audio streaming over WebSocket
  • ๐Ÿ“ฑ Cross-Platform - iOS and Android support
  • ๐Ÿ”‡ Audio Controls - Mute/unmute, speaker control
  • ๐Ÿ“Š Audio Levels - Real-time input/output level monitoring
  • ๐Ÿ”„ Auto Reconnect - Automatic reconnection on connection loss
  • ๐Ÿ“ Transcripts - Support for speech-to-text transcripts

๐ŸŽฏ Why This Plugin?

Standard audio recording in Flutter doesn't include echo cancellation. When building voice agents or real-time voice chat, the microphone picks up the speaker output, creating an echo feedback loop. This plugin solves that by using native platform APIs that provide hardware-level AEC.

The Problem

โŒ Without AEC:
Microphone captures speaker output โ†’ Echo feedback โ†’ Agent hears itself

โœ… With This Plugin:
VoiceProcessingIO (iOS) / AcousticEchoCanceler (Android) โ†’ Clean audio

๐Ÿ“ฆ Installation

Add to your pubspec.yaml:

dependencies:
  flutter_auto_echo_cancellation_websocket: ^1.0.0

iOS Setup

Add to your ios/Runner/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access for voice communication</string>

Android Setup

Add to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

๐Ÿš€ Quick Start

import 'package:flutter_auto_echo_cancellation_websocket/flutter_auto_echo_cancellation_websocket.dart';

// Create plugin instance
final voicePlugin = VoicePlugin();

// Listen to events
voicePlugin.eventStream.listen((event) {
  if (event is TranscriptEvent) {
    print('${event.isUser ? "User" : "Agent"}: ${event.text}');
  } else if (event is ConnectionStateEvent) {
    print('Connection: ${event.state}');
  } else if (event is AgentStateEvent) {
    print('Agent: ${event.state}');
  }
});

// Connect to your voice server
await voicePlugin.connect(VoicePluginConfig(
  endpoint: 'wss://your-voice-server.com/websocket',
  agentId: 'your-agent-id',
  publicKey: 'your-public-key',
  metadata: {
    'user_id': 'user-123',
    'name': 'John Doe',
  },
));

// Control audio
await voicePlugin.setMicrophoneMuted(true);
await voicePlugin.setSpeakerMuted(false);

// Disconnect when done
voicePlugin.disconnect();
voicePlugin.dispose();

๐Ÿ“– API Reference

VoicePlugin

The main class for voice communication.

Properties

Property Type Description
connectionState VoiceConnectionState Current connection state
agentState VoiceAgentState Current agent state
isConnected bool Whether connected to server
isMicrophoneMuted bool Whether microphone is muted
isSpeakerMuted bool Whether speaker is muted
isAECEnabled bool Whether AEC is active
isAECSupported bool Whether device supports AEC
eventStream Stream<VoicePluginEvent> Stream of plugin events

Methods

Method Description
connect(config) Connect to voice server
disconnect() Disconnect from server
setMicrophoneMuted(muted) Mute/unmute microphone
setSpeakerMuted(muted) Mute/unmute speaker
toggleMicrophoneMute() Toggle microphone mute
toggleSpeakerMute() Toggle speaker mute
setSpeakerphoneOn(on) Switch between speaker/earpiece
clearPlaybackBuffer() Clear audio playback buffer
sendEvent(type, data) Send custom event to server
getAudioInfo() Get audio configuration info
checkAECAvailability() Check if AEC is available
dispose() Release all resources

VoicePluginConfig

Configuration for connecting to the voice server.

VoicePluginConfig(
  // Required
  endpoint: 'wss://your-server.com/websocket',
  agentId: 'your-agent-id',
  publicKey: 'your-public-key',
  
  // Optional
  metadata: {'user_id': 'user-123'},
  includeMetadataInPrompt: true,
  sampleRate: 16000,
  channels: 1,
  audioQuality: AudioQuality.standard,
  enableNoiseSuppression: true,
  enableAutoGainControl: true,
  bufferDurationMs: 20,
  connectionTimeoutSeconds: 30,
  autoReconnect: true,
  maxReconnectAttempts: 3,
  reconnectDelayMs: 1000,
  enableDebugLogs: false,
)

Events

Listen to events via the eventStream:

Event Description
ConnectionStateEvent Connection state changed
AgentStateEvent Agent state changed
TranscriptEvent Speech transcript received
ErrorEvent Error occurred
SessionReadyEvent Session is ready
SessionEndedEvent Session ended
AudioLevelEvent Audio level update
AECStatusEvent AEC status changed

๐Ÿ—๏ธ Architecture

iOS Implementation

Uses VoiceProcessingIO Audio Unit for hardware AEC:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚       VoiceProcessingIO Audio Unit      โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
โ”‚   โ”‚    Mic    โ”‚       โ”‚  Speaker  โ”‚    โ”‚
โ”‚   โ”‚   Input   โ”‚       โ”‚  Output   โ”‚    โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
โ”‚         โ”‚   AEC CORRELATES  โ”‚          โ”‚
โ”‚         โ”‚   BOTH STREAMS    โ”‚          โ”‚
โ”‚         โ–ผ                   โ–ผ          โ”‚
โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚
โ”‚   โ”‚  Echo Cancellation Engine   โ”‚      โ”‚
โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Android Implementation

Uses AudioRecord with VOICE_COMMUNICATION source and AcousticEchoCanceler:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚    AudioRecord (VOICE_COMMUNICATION)    โ”‚
โ”‚              +                          โ”‚
โ”‚    AcousticEchoCanceler                 โ”‚
โ”‚              +                          โ”‚
โ”‚    AudioTrack (same session ID)         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿงช Testing Checklist

  • iOS: No echo when agent speaks
  • iOS: Clear audio capture from microphone
  • iOS: Works with speaker (not just earpiece)
  • Android: No echo when agent speaks
  • Android: AEC enabled on device
  • Both: Metadata received by agent
  • Both: Transcripts work correctly
  • Both: Auto-reconnection works
  • Both: Clean disconnect without artifacts

๐Ÿ“ฑ Supported Platforms

Platform Minimum Version AEC Method
iOS 12.0+ VoiceProcessingIO
Android API 21+ AcousticEchoCanceler

๐Ÿค Contributing

Contributions are welcome! Please read our contributing guidelines first.

๐Ÿ“„ License

MIT License - see LICENSE file for details.

๐Ÿ‘ค Author

Ashraf K Salim

๐Ÿ™ Acknowledgments

Libraries

flutter_auto_echo_cancellation_websocket
Flutter Auto Echo Cancellation WebSocket Plugin