voice_audio_visualizer 1.0.0
voice_audio_visualizer: ^1.0.0 copied to clipboard
A comprehensive Flutter audio package with recording, playback, editing, and waveform visualization. Features customizable widgets, voice message bubbles, and cross-platform support.
Audio Visualizer #
A comprehensive, fully customizable Flutter audio package with recording, playback, editing, and waveform visualization. Works on all platforms.
Features #
- 🎙️ Recording - Record audio with live waveform visualization
- 🎵 Playback - Play audio files and URLs with waveform display
- ✂️ Editing - Trim, delete, and edit audio with visual selection
- 💬 Voice Bubbles - Chat-style voice message widgets
- 🎨 Fully Customizable - Themes, builders, styles for everything
- 📱 Cross-platform - iOS, Android, Web, macOS, Windows, Linux
Installation #
dependencies:
audio_visualizer: ^0.0.1
Quick Start #
import 'package:audio_visualizer/audio_visualizer.dart';
// Recording
AudioRecorderWidget(
onRecordingComplete: (file) => print('Recorded: ${file.path}'),
)
// Playback
AudioPlayerWidget(
url: 'https://example.com/audio.mp3',
)
// Voice Message
VoiceMessageBubble(
filePath: '/path/to/audio.m4a',
style: VoiceBubbleStyle.whatsApp,
)
Full Customization #
Global Theming #
Apply consistent styling across all widgets:
MaterialApp(
theme: ThemeData(
extensions: [
AudioVisualizerTheme(
waveformStyle: WaveformStyle(
waveColor: Colors.blue,
playedColor: Colors.green,
type: WaveformType.mirrored,
),
recorderTheme: RecorderTheme(
primaryColor: Colors.purple,
recordingColor: Colors.red,
buttonSize: 80,
),
playerTheme: PlayerTheme.spotify,
voiceBubbleStyle: VoiceBubbleStyle.whatsApp,
),
],
),
)
Custom Builders #
Override any part of the UI:
AudioRecorderWidget(
// Custom waveform
waveformBuilder: (context, controller) {
return MyCustomWaveform(amplitudes: controller.amplitudes);
},
// Custom record button
recordButtonBuilder: (context, controller, onTap) {
return FloatingActionButton(
onPressed: onTap,
child: Icon(controller.isRecording ? Icons.stop : Icons.mic),
);
},
// Custom duration display
durationBuilder: (context, controller) {
return Text('Recording: ${controller.duration.inSeconds}s');
},
// Custom controls
controlsBuilder: (context, controller) {
return Row(
children: [
IconButton(icon: Icon(Icons.cancel), onPressed: controller.cancel),
IconButton(icon: Icon(Icons.mic), onPressed: controller.start),
IconButton(icon: Icon(Icons.check), onPressed: controller.stop),
],
);
},
)
Player Customization #
AudioPlayerWidget(
url: 'https://example.com/audio.mp3',
// Theme
theme: PlayerTheme(
primaryColor: Colors.green,
backgroundColor: Colors.black,
buttonSize: 64,
iconSize: 32,
),
// Waveform style
waveformStyle: WaveformStyle(
type: WaveformType.soundCloud,
waveColor: Colors.grey,
playedColor: Colors.orange,
),
// Options
showSpeedControl: true,
showVolumeControl: true,
showSkipButtons: true,
speedOptions: [0.5, 1.0, 1.5, 2.0],
skipDuration: Duration(seconds: 15),
// Custom icons
playIcon: Icons.play_circle_filled,
pauseIcon: Icons.pause_circle_filled,
// Custom play button
playButtonBuilder: (context, controller, onTap) {
return GestureDetector(
onTap: onTap,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.purple, Colors.blue]),
shape: BoxShape.circle,
),
child: Icon(
controller.isPlaying ? Icons.pause : Icons.play_arrow,
color: Colors.white,
size: 40,
),
),
);
},
// Callbacks
onReady: () => print('Ready'),
onPlaying: () => print('Playing'),
onPaused: () => print('Paused'),
onComplete: () => print('Complete'),
onPositionChanged: (pos) => print('Position: $pos'),
onSpeedChanged: (speed) => print('Speed: $speed'),
)
Voice Bubble Customization #
VoiceMessageBubble(
url: 'https://example.com/voice.mp3',
// Style
style: VoiceBubbleStyle(
bubbleColor: Color(0xFFDCF8C6),
iconColor: Color(0xFF25D366),
textColor: Colors.black87,
borderRadius: 16,
padding: EdgeInsets.all(10),
),
// Message properties
isSent: true,
timestamp: DateTime.now(),
senderName: 'John',
senderAvatar: 'https://example.com/avatar.jpg',
// Read status
showReadStatus: true,
isRead: true,
isDelivered: true,
// Dimensions
maxWidth: 300,
waveformHeight: 40,
playButtonSize: 44,
// Visibility
showDuration: true,
showTimestamp: true,
showAvatar: true,
// Custom builders
playButtonBuilder: (context, controller, onTap) {
return CircleAvatar(
backgroundColor: Colors.green,
child: IconButton(
icon: Icon(controller.isPlaying ? Icons.pause : Icons.play_arrow),
onPressed: onTap,
color: Colors.white,
),
);
},
timestampBuilder: (context, timestamp) {
return Text(
'${timestamp.hour}:${timestamp.minute}',
style: TextStyle(fontSize: 10, color: Colors.grey),
);
},
// Callbacks
onTap: () => print('Tapped'),
onLongPress: () => print('Long pressed'),
onDoubleTap: () => print('Double tapped'),
)
Editor Customization #
AudioEditorWidget(
filePath: '/path/to/audio.m4a',
// Theme
theme: EditorTheme(
primaryColor: Colors.blue,
selectionColor: Colors.blue.withOpacity(0.3),
cursorColor: Colors.red,
backgroundColor: Colors.grey[100]!,
),
// Visibility
showTrimButton: true,
showDeleteButton: true,
showUndoRedo: true,
showPreviewButton: true,
showSaveButton: true,
showTimeline: true,
showPlaybackControls: true,
// Selection
selectionHandleColor: Colors.blue,
selectionHandleWidth: 3,
// Custom icons
trimIcon: Icons.cut,
deleteIcon: Icons.delete,
undoIcon: Icons.undo,
redoIcon: Icons.redo,
// Custom edit button
editButtonBuilder: (context, controller, label, icon, onPressed) {
return ElevatedButton.icon(
onPressed: onPressed,
icon: Icon(icon),
label: Text(label),
);
},
// Callbacks
onSaved: (file) => print('Saved: ${file.path}'),
onTrimmed: () => print('Trimmed'),
onDeleted: () => print('Deleted'),
onSelectionChanged: (start, end) => print('Selected: $start - $end'),
)
Waveform Styles #
// Bar style
WaveformStyle(type: WaveformType.bars)
// Line style
WaveformStyle(type: WaveformType.line)
// Rounded bars
WaveformStyle(type: WaveformType.rounded)
// Mirrored (like audio editors)
WaveformStyle(type: WaveformType.mirrored)
// SoundCloud style
WaveformStyle(type: WaveformType.soundCloud)
// Full customization
WaveformStyle(
waveColor: Colors.grey,
playedColor: Colors.blue,
backgroundColor: Colors.black,
waveWidth: 4.0,
waveSpacing: 2.0,
borderRadius: 2.0,
showMiddleLine: true,
middleLineColor: Colors.white24,
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
),
type: WaveformType.bars,
)
Preset Themes #
// Recorder themes
RecorderTheme.defaultTheme
RecorderTheme.dark
RecorderTheme.minimal
// Player themes
PlayerTheme.defaultTheme
PlayerTheme.dark
PlayerTheme.spotify
// Voice bubble styles
VoiceBubbleStyle.defaultStyle
VoiceBubbleStyle.whatsApp
VoiceBubbleStyle.telegram
// Editor themes
EditorTheme.defaultTheme
EditorTheme.dark
Controllers #
Use controllers for programmatic control:
// Recorder
final recorder = AudioRecorderController();
await recorder.start();
await recorder.pause();
await recorder.resume();
final file = await recorder.stop();
await recorder.cancel();
// Player
final player = AudioPlayerController();
await player.loadFile('/path/to/audio.m4a');
await player.loadUrl('https://example.com/audio.mp3');
await player.play();
await player.pause();
await player.seek(Duration(seconds: 30));
await player.setSpeed(1.5);
await player.setVolume(0.8);
// Editor
final editor = AudioEditorController();
await editor.loadFile('/path/to/audio.m4a');
editor.selectRegion(Duration(seconds: 5), Duration(seconds: 15));
await editor.trim();
await editor.deleteSelection();
editor.undo();
editor.redo();
final saved = await editor.save();
Platform Setup #
Android #
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
iOS #
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record audio</string>
macOS #
<key>com.apple.security.device.audio-input</key>
<true/>
Supported Formats #
MP3, WAV, AAC, M4A, OGG, FLAC, OPUS, WMA, WebM, AMR
License #
MIT License