flutter_audio_recorder_kit 0.1.0
flutter_audio_recorder_kit: ^0.1.0 copied to clipboard
Drop-in audio recorder for Flutter with live waveform, playback, WAV trimming, file upload, and full theming. Supports Android foreground-service background recording, auto-pause on call, and a headle [...]
flutter_audio_recorder_kit #
A drop-in audio recording kit for Flutter — themeable recorder UI with live waveform, playback panel, WAV trimming, foreground-service recording, and auto-pause-on-call for Android. Every feature is individually toggleable.
Screenshots #
| Ready | Recording | Stopped | Playback & Trim |
|---|---|---|---|
| [Ready state] | [Recording in progress] | [Recording stopped] | [Playback and trim panel] |
Features #
- Drop-in widget — embed
AudioRecorderWidgetanywhere: aScaffold, a bottom sheet, a tab, or a dialog. It is a plain widget, not a screen. - Live waveform — animated bar visualization driven by real-time microphone amplitude.
- Elapsed timer — centisecond-precision elapsed time display with pause-aware accumulation.
- Status pill — READY / RECORDING / PAUSED indicator that updates automatically.
- Playback panel — built-in play/pause button and seek slider for the recorded or uploaded file.
- WAV trimming — pure-Dart in-app start/end trim with a range slider, no native code required.
- File upload — optional "Upload audio" button to load an existing file from the device.
- Format selector — WAV or AAC (.m4a) switchable from within the UI before recording starts.
- Foreground-service recording (Android) — keeps the recording alive in the background with a persistent notification.
- Auto-pause on call — pauses automatically when a phone call (Android) or audio interruption (iOS) begins, then resumes when it ends.
- Full theming — every color is overridable via
AudioRecorderTheme, with afromColorSchemefactory to match your Material theme. - Headless API — use
AudioRecorderControllerdirectly to build a completely custom UI. - Feature flags —
RecorderFeatureslets you toggle recording, playback, trimming, and upload independently per widget instance.
Platform Support #
| Platform | Minimum version | Notes |
|---|---|---|
| Android | API 24 (Android 7.0) | Foreground service + telephony auto-pause |
| iOS | iOS 13 | Background audio mode + interruption auto-pause |
Installation #
Add the package to your pubspec.yaml:
dependencies:
flutter_audio_recorder_kit: ^0.1.0
Then run:
flutter pub get
Android Setup #
1. Permissions in AndroidManifest.xml #
The package automatically merges RECORD_AUDIO, FOREGROUND_SERVICE, and FOREGROUND_SERVICE_MICROPHONE into your app's manifest. You must declare the privacy-sensitive permissions yourself:
<!-- Required for recording -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- Required on Android 13+ if useForegroundService is true -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Required for auto-pause-on-call (autoPauseOnCall: true) -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Note:
POST_NOTIFICATIONSandREAD_PHONE_STATEare intentionally not merged automatically because they are privacy-sensitive optional features. Only add them if you use those features.
2. Request permissions at runtime #
Use permission_handler (already a transitive dependency) or any other package to request RECORD_AUDIO, and optionally POST_NOTIFICATIONS / READ_PHONE_STATE, before starting a recording.
iOS Setup #
1. Info.plist #
Add a microphone usage description:
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record audio.</string>
2. Background audio capability #
To keep recording running when the app moves to the background, enable the Background Modes capability in Xcode and check Audio, AirPlay, and Picture in Picture.
Or add directly to ios/Runner/Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
Quick Start #
import 'package:flutter_audio_recorder_kit/flutter_audio_recorder_kit.dart';
Scaffold(
body: AudioRecorderWidget(
onRecordingComplete: (path) {
print('Saved to: $path');
},
),
)
That's it. The widget handles permissions, the foreground service, waveform visualization, playback, and trimming out of the box.
Usage #
Basic — default feature set #
Recording + playback + trimming, no upload button:
AudioRecorderWidget(
onRecordingComplete: (path) => print('Recorded: $path'),
)
All features enabled #
AudioRecorderWidget(
features: RecorderFeatures.all, // recording + playback + trimming + upload
onRecordingComplete: (path) => print('Recorded: $path'),
onUploadComplete: (path) => print('Uploaded: $path'),
onTrimComplete: (path) => print('Trimmed: $path'),
)
Record only (no result panel) #
AudioRecorderWidget(
features: RecorderFeatures.recordOnly,
onRecordingComplete: (path) => handleAudio(path),
)
Custom feature combination #
AudioRecorderWidget(
features: const RecorderFeatures(
recording: true,
playback: true,
trimming: false,
upload: false,
),
)
Playback + upload of existing files #
AudioRecorderWidget(
features: RecorderFeatures.playbackOnly,
onUploadComplete: (path) => handleAudio(path),
)
Custom recording configuration #
AudioRecorderWidget(
config: const RecordingConfig(
format: RecordingFormat.aacM4a,
sampleRate: 48000,
bitRate: 192000,
numChannels: 1,
notificationTitle: 'Voice memo',
notificationText: 'Recording in progress…',
useForegroundService: true,
autoPauseOnCall: true,
),
onRecordingComplete: (path) => handleAudio(path),
)
Match your app's Material theme #
AudioRecorderWidget(
theme: AudioRecorderTheme.fromColorScheme(Theme.of(context).colorScheme),
onRecordingComplete: (path) => handleAudio(path),
)
Transparent background (blend into your own background) #
AudioRecorderWidget(
theme: AudioRecorderTheme.fallback.copyWith(
backgroundStart: Colors.transparent,
backgroundEnd: Colors.transparent,
),
)
Hide the built-in title bar (use your own AppBar) #
Scaffold(
appBar: AppBar(title: const Text('Record')),
body: AudioRecorderWidget(
showAppBarRow: false,
onRecordingComplete: (path) => handleAudio(path),
),
)
Standalone playback panel #
To play back (and trim) a file you already have, without the recording controls:
AudioPlaybackPanel(
filePath: '/path/to/audio.wav',
enableTrim: true,
onTrimComplete: (path) => print('Trimmed: $path'),
)
Headless controller (custom UI) #
final controller = AudioRecorderController(
config: const RecordingConfig(format: RecordingFormat.wav),
);
// Listen to amplitude for a custom waveform
controller.amplitudeStream.listen((db) => updateWaveform(db));
// Listen for call interruptions
controller.callInterruptionStream.listen((interrupted) {
if (interrupted) print('Call started – recording paused');
else print('Call ended – recording resumed');
});
await controller.start();
// … later …
final path = await controller.stop();
await controller.dispose();
API Reference #
AudioRecorderWidget #
The main drop-in widget.
| Parameter | Type | Default | Description |
|---|---|---|---|
controller |
AudioRecorderController? |
null |
Provide your own controller; the widget creates one from config if omitted. |
config |
RecordingConfig |
RecordingConfig() |
Recording settings (format, sample rate, foreground service, etc.). Ignored when controller is provided. |
theme |
AudioRecorderTheme? |
AudioRecorderTheme.fallback |
Color theme. |
features |
RecorderFeatures |
RecorderFeatures() |
Which capabilities to show. |
showAppBarRow |
bool |
true |
Show the built-in title / subtitle / format-selector row. |
showFormatSelector |
bool |
true |
Show the WAV / AAC format pill. |
title |
String |
'Audio Recorder' |
Title in the top row. |
subtitle |
String |
'Record · Play · Trim' |
Subtitle in the top row. |
onRecordingComplete |
ValueChanged<String>? |
— | Called with the file path when a recording finishes. |
onUploadComplete |
ValueChanged<String>? |
— | Called with the file path when the user picks a file. |
onTrimComplete |
ValueChanged<String>? |
— | Called with the new file path after a successful trim. |
onError |
void Function(Object, StackTrace)? |
— | Called when any operation fails. |
onCallInterruption |
ValueChanged<bool>? |
— | Called with true on interruption start, false on resume. |
RecorderFeatures #
Controls which parts of the UI are visible.
| Flag | Default | Description |
|---|---|---|
recording |
true |
Record/pause/resume/stop controls, waveform, timer. |
playback |
true |
Play/pause button and seek slider after recording. |
trimming |
true |
WAV trim slider and Trim & save button. |
upload |
false |
"Upload audio" button to pick an existing file. |
Presets:
| Preset | recording | playback | trimming | upload |
|---|---|---|---|---|
RecorderFeatures() |
✓ | ✓ | ✓ | — |
RecorderFeatures.all |
✓ | ✓ | ✓ | ✓ |
RecorderFeatures.recordOnly |
✓ | — | — | — |
RecorderFeatures.recordAndTrim |
✓ | — | ✓ | — |
RecorderFeatures.playbackOnly |
— | ✓ | — | ✓ |
RecordingConfig #
| Field | Type | Default | Description |
|---|---|---|---|
format |
RecordingFormat |
.wav |
Output format: wav or aacM4a. |
sampleRate |
int |
44100 |
Sample rate in Hz. |
bitRate |
int |
128000 |
Bit rate for compressed formats (bps). |
numChannels |
int |
1 |
1 = mono, 2 = stereo. |
outputDirectory |
String? |
null |
Absolute path for output files. Defaults to <documents>/recordings. |
fileNameBuilder |
String Function()? |
null |
Custom file name (no extension). Defaults to recording_<timestamp>. |
useForegroundService |
bool |
true |
Android foreground service with background recording. |
autoPauseOnCall |
bool |
true |
Auto-pause on phone call / audio interruption. |
notificationTitle |
String |
'Recording audio' |
Android notification title. |
notificationText |
String |
'Audio recording is running in the background' |
Android notification body. |
AudioRecorderTheme #
All colors have sensible defaults (dark, purple-accented). Use copyWith to override individual fields, or fromColorScheme to derive the whole theme from your app's ColorScheme.
| Field | Description |
|---|---|
primary |
Main accent: idle record button, play button, seek slider. |
primaryLight / primaryDark |
Gradient shades of primary. |
recording / recordingLight |
Record button and RECORDING pill color. |
waveformActive / waveformActiveLight |
Waveform bars while recording. |
waveformIdle |
Waveform bars while idle. |
success |
READY pill, resume button, trim slider and button. |
warning |
PAUSED pill. |
accent |
Upload button. |
backgroundStart / backgroundEnd |
Radial gradient background. Set both to Colors.transparent to disable. |
surface |
Format dropdown surface color. |
textPrimary |
Main text and icon color. |
timerTextStyle |
Optional override for the large elapsed-time readout. |
AudioRecorderController #
Headless recording API for custom UIs.
| Method / Property | Description |
|---|---|
start() |
Request microphone permission and start recording. |
pause() |
Pause the current recording. |
resume() |
Resume a paused recording. |
stop() → Future<String?> |
Stop and finalise; returns the file path. |
dispose() |
Release all resources. Call when done. |
config |
Read/write the RecordingConfig (only write between recordings). |
amplitudeStream |
Stream<double> — amplitude in dBFS (~120 ms interval). Feed to WaveformWidget. |
callInterruptionStream |
Stream<bool> — true on interruption start, false on resume. |
AudioPlaybackPanel #
Standalone playback and trim panel for any audio file path.
AudioPlaybackPanel(
filePath: '/path/to/audio.wav',
theme: myTheme, // optional
showPlayer: true, // show play/pause + seek slider
enableTrim: true, // show trim range slider
onTrimComplete: (path) {}, // called after successful trim
onError: (e, st) {}, // called on failure
)
AudioTrimService #
Pure-Dart PCM WAV trimmer. Works on WAV files only.
final trimmed = await AudioTrimService.trim(
sourcePath: '/path/to/original.wav',
startSeconds: 1.5,
endSeconds: 8.0,
);
print('Trimmed file: $trimmed');
WaveformWidget #
Standalone animated bar waveform. Accepts any List<double> of amplitude samples (−∞ to 0 dBFS; the widget normalises them automatically).
WaveformWidget(
samples: myAmplitudeSamples,
isRecording: true,
theme: myTheme,
)
Trimming Notes #
- Trimming is only supported for WAV files. The trim controls are hidden automatically for
.m4aand other formats. AudioTrimServicereads and rewrites PCM data in Dart — no native code, no FFI.- Trimmed files are written to the same directory as the source with a
_trimmedsuffix appended to the file name.
Foreground Service (Android) #
When RecordingConfig.useForegroundService is true (the default), the plugin starts an Android foreground service before recording begins. This keeps the recording alive when the app is backgrounded.
- The service shows a persistent notification. On Android 13+ the notification is only visible if the app has the
POST_NOTIFICATIONSpermission. - The service is stopped automatically when
controller.stop()is called or the widget is disposed. - Set
useForegroundService: falseif you only need in-foreground recording or are building a form where the user will not leave the app.
Auto-Pause on Call #
When RecordingConfig.autoPauseOnCall is true (the default):
- Android: Listens for telephony state changes via
TelephonyCallback(API 31+) or the legacyPhoneStateListener. Requires theREAD_PHONE_STATEpermission. When the permission is absent, recording continues uninterrupted. - iOS: Listens for
AVAudioSessioninterruption events (Siri, phone calls, alarms). No extra permission required.
The onCallInterruption callback on AudioRecorderWidget (and callInterruptionStream on AudioRecorderController) fire for every interruption event regardless of whether the auto-pause actually changes recording state.
License #
MIT License
Copyright (c) 2026 Midhun Murali
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.