sonix 1.0.1
sonix: ^1.0.1 copied to clipboard
Flutter audio waveform package with multi-format support (MP3, WAV, FLAC, OGG, Opus, MP4, M4A) using FFMPEG.
Sonix - Flutter Audio Waveform Package #
A comprehensive Flutter package for generating and displaying audio waveforms with isolate-based processing to prevent UI thread blocking. Sonix supports multiple audio formats (MP3, OGG, WAV, FLAC, Opus) using native C libraries through Dart FFI for optimal performance.
Features #
π Isolate-Based Processing: All audio processing runs in background isolates to keep UI responsive
β¨ Multi-format Support: MP3, OGG, WAV, FLAC, and Opus audio formats
π High Performance: Native C libraries via Dart FFI (no FFMPEG dependency)
π¨ Extensive Customization: Colors, gradients, styles, and animations
οΏ½ *Interactive Playback: Real-time position visualization and seeking
οΏ½ Insstance-Based API: Modern API with proper resource management
οΏ½ Easyi Integration: Simple API with comprehensive error handling
π Multiple Algorithms: RMS, Peak, Average, and Median downsampling
π― Optimized Presets: Ready-to-use configurations for different use cases
Getting Started #
Installation #
Add Sonix to your pubspec.yaml
:
dependencies:
sonix: <latest>
Then run:
flutter pub get
Note: Sonix includes pre-built native libraries (sonix_native
) for all supported platforms. These are automatically bundled with your app - no additional compilation required!
FFMPEG Setup #
Sonix uses FFMPEG for audio decoding. You need to install FFMPEG binaries in your Flutter app to use Sonix.
Automated Setup (Recommended)
Required Step: Use our automated setup tool to download and install FFMPEG binaries:
# From your Flutter app's root directory
dart run sonix:setup_ffmpeg_for_app
# Verify installation
dart run sonix:setup_ffmpeg_for_app --verify
This tool will:
- β Automatically detect your platform
- β Download compatible FFMPEG binaries from trusted sources
- β Install them to your app's build directories
- β Validate the installation
- β Enable Sonix to work with FFMPEG in your app
Requirements:
- Run from your Flutter app's root directory (where pubspec.yaml is located)
- Sonix must be added as a dependency in your pubspec.yaml
Supported Platforms
- β Android (API 21+) - FFMPEG binaries included in APK
- β iOS (11.0+) - FFMPEG binaries statically linked
- β Windows (Windows 10+) - Requires FFMPEG DLLs
- β macOS (10.14+) - Requires FFMPEG dylibs
- β Linux (Ubuntu 18.04+) - Requires FFMPEG shared objects
Manual Installation (Advanced)
If you prefer to install FFMPEG binaries manually, place them in your Flutter build directory:
- Windows:
build/windows/x64/runner/Debug/
- macOS:
build/macos/Build/Products/Debug/
- Linux:
build/linux/x64/debug/bundle/lib/
Required FFMPEG libraries: avformat
, avcodec
, avutil
, swresample
Quick Start #
Basic Waveform Generation #
import 'package:sonix/sonix.dart';
// Create a Sonix instance
final sonix = Sonix();
// Generate waveform from audio file (processed in background isolate)
final waveformData = await sonix.generateWaveform('path/to/audio.mp3');
// Display the waveform
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.soundCloud,
)
// Clean up when done
await sonix.dispose();
With Playback Position #
class AudioPlayer extends StatefulWidget {
@override
_AudioPlayerState createState() => _AudioPlayerState();
}
class _AudioPlayerState extends State<AudioPlayer> {
late Sonix sonix;
WaveformData? waveformData;
double playbackPosition = 0.0;
@override
void initState() {
super.initState();
sonix = Sonix(SonixConfig.mobile()); // Optimized for mobile
}
@override
void dispose() {
sonix.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
if (waveformData != null)
WaveformWidget(
waveformData: waveformData!,
playbackPosition: playbackPosition,
style: WaveformStylePresets.spotify,
onSeek: (position) {
setState(() {
playbackPosition = position;
});
// Update your audio player position
},
),
],
);
}
}
Usage Examples #
1. Different Waveform Styles #
// SoundCloud-style waveform
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.soundCloud,
)
// Spotify-style waveform
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.spotify,
)
// Custom style with gradient
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.filledGradient(
startColor: Colors.blue,
endColor: Colors.purple,
height: 100,
),
)
// Professional audio editor style
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.professional,
)
2. Instance Configuration #
// Mobile-optimized configuration
final mobileSonix = Sonix(SonixConfig.mobile());
// Desktop-optimized configuration
final desktopSonix = Sonix(SonixConfig.desktop());
// Custom configuration
final customSonix = Sonix(SonixConfig(
maxConcurrentOperations: 2,
isolatePoolSize: 1,
maxMemoryUsage: 50 * 1024 * 1024, // 50MB
enableProgressReporting: true,
));
3. Optimal Configuration for Use Cases #
// Get optimal config for specific use cases
final musicConfig = Sonix.getOptimalConfig(
useCase: WaveformUseCase.musicVisualization,
customResolution: 2000,
);
final podcastConfig = Sonix.getOptimalConfig(
useCase: WaveformUseCase.podcastPlayer,
);
final editorConfig = Sonix.getOptimalConfig(
useCase: WaveformUseCase.audioEditor,
customResolution: 5000, // High detail for editing
);
// Use with instance
final sonix = Sonix();
final waveformData = await sonix.generateWaveform(
'music.mp3',
config: musicConfig,
);
4. Resource Management #
// Check resource usage
final sonix = Sonix();
final stats = sonix.getResourceStatistics();
print('Active isolates: ${stats.activeIsolates}');
print('Completed tasks: ${stats.completedTasks}');
// Optimize resources when needed
sonix.optimizeResources();
// Cancel operations if needed
final activeOps = sonix.getActiveOperations();
for (final opId in activeOps) {
sonix.cancelOperation(opId);
}
// Always dispose when done
await sonix.dispose();
5. Pre-generated Waveform Data #
// Use pre-computed waveform data
final jsonData = await loadWaveformFromCache();
final waveformData = WaveformData.fromJson(jsonData);
// Or from amplitude array
final amplitudes = [0.1, 0.5, 0.8, 0.3, 0.7, ...];
final waveformData = WaveformData.fromAmplitudes(amplitudes);
WaveformWidget(
waveformData: waveformData,
style: WaveformStylePresets.professional,
)
6. Error Handling #
final sonix = Sonix();
try {
final waveformData = await sonix.generateWaveform('audio.mp3');
// Use waveformData
} on UnsupportedFormatException catch (e) {
print('Unsupported format: ${e.format}');
print('Supported formats: ${Sonix.getSupportedFormats()}');
} on DecodingException catch (e) {
print('Decoding failed: ${e.message}');
} on FileSystemException catch (e) {
print('File access error: ${e.message}');
} finally {
await sonix.dispose();
}
API Reference #
Main API Class #
Sonix
The main entry point for generating waveforms. This is an instance-based class that manages background isolates for processing.
Constructor:
Sonix([SonixConfig? config])
- Create a new instance with optional configuration
Instance Methods:
generateWaveform(String filePath, {...})
βFuture<WaveformData>
getResourceStatistics()
βIsolateStatistics
optimizeResources()
βvoid
cancelOperation(String taskId)
βbool
cancelAllOperations()
βint
getActiveOperations()
βList<String>
dispose()
βFuture<void>
Static Utility Methods:
isFormatSupported(String filePath)
βbool
getSupportedFormats()
βList<String>
getSupportedExtensions()
βList<String>
isExtensionSupported(String extension)
βbool
getOptimalConfig({required WaveformUseCase useCase, ...})
βWaveformConfig
Configuration #
SonixConfig
Configuration options for Sonix instances.
Factory Constructors:
SonixConfig.defaultConfig()
- Default configurationSonixConfig.mobile()
- Optimized for mobile devicesSonixConfig.desktop()
- Optimized for desktop devices
Properties:
maxConcurrentOperations
: Maximum concurrent operationsisolatePoolSize
: Size of the isolate poolisolateIdleTimeout
: Timeout for idle isolatesmaxMemoryUsage
: Maximum memory usage in bytesenableProgressReporting
: Whether to enable progress reporting
Widgets #
WaveformWidget
Interactive waveform display with playback position and seeking.
Properties:
waveformData
(required): The waveform data to displayplaybackPosition
: Current playback position (0.0 to 1.0)style
: Customization options (WaveformStyle)onTap
: Callback when user taps the widgetonSeek
: Callback when user seeks to a positionenableSeek
: Whether to enable touch interactionanimationDuration
: Duration for position animationsanimationCurve
: Animation curve for transitions
Data Models #
WaveformData
Contains processed waveform data and metadata.
Properties:
amplitudes
: List of amplitude values (0.0 to 1.0)duration
: Duration of the original audiosampleRate
: Sample rate of the original audiometadata
: Generation metadata
Methods:
toJson()
βMap<String, dynamic>
fromJson(Map<String, dynamic>)
βWaveformData
fromAmplitudes(List<double>)
βWaveformData
WaveformStyle
Customization options for waveform appearance.
Properties:
playedColor
: Color for played portionunplayedColor
: Color for unplayed portionheight
: Height of the waveformtype
: Visualization type (bars, line, filled)gradient
: Optional gradient overlayborderRadius
: Border radius for rounded corners
Style Presets #
WaveformStylePresets
Pre-configured styles for common use cases:
soundCloud
: SoundCloud-inspired orange and grey barsspotify
: Spotify-inspired green and grey barsminimalLine
: Minimal line-style waveformretro
: Vintage style with rounded bars and warm colorscompact
: Compact mobile-friendly stylepodcast
: Optimized for podcast/speech contentprofessional
: Clean style for professional audio applicationsfilledGradient({Color startColor, Color endColor, double height})
: Filled waveform with customizable gradientglassEffect({Color accentColor, double height})
: Modern glass-like effectneonGlow({Color glowColor, double height})
: Glowing neon effect with shadows
Performance & Monitoring #
Sonix includes performance monitoring and optimization tools for production applications.
Resource Monitoring #
Monitor isolate performance and resource usage:
final sonix = Sonix();
// Get current resource statistics
final stats = sonix.getResourceStatistics();
print('Active isolates: ${stats.activeIsolates}');
print('Completed tasks: ${stats.completedTasks}');
print('Failed tasks: ${stats.failedTasks}');
print('Average processing time: ${stats.averageProcessingTime}ms');
// Optimize resources when needed
sonix.optimizeResources();
Performance Profiling #
Profile operations to identify bottlenecks:
final profiler = PerformanceProfiler();
// Profile waveform generation
final result = await profiler.profile('waveform_generation', () async {
final sonix = Sonix();
final waveformData = await sonix.generateWaveform('audio.mp3');
await sonix.dispose();
return waveformData;
});
print('Processing took: ${result.duration.inMilliseconds}ms');
print('Memory used: ${result.memoryUsage}MB');
// Generate performance report
final report = profiler.generateReport();
print(report.toString());
Platform Validation #
Validate platform compatibility:
final validator = PlatformValidator();
// Validate current platform
final validation = await validator.validatePlatform();
print('Platform supported: ${validation.isSupported}');
// Check specific format support
final mp3Support = await validator.validateFormatSupport('mp3');
print('MP3 supported: ${mp3Support.isSupported}');
// Get optimization recommendations
final recommendations = validator.getOptimizationRecommendations();
for (final rec in recommendations) {
print('${rec.category}: ${rec.title}');
}
Best Practices #
- Use appropriate configuration: Choose
SonixConfig.mobile()
orSonixConfig.desktop()
based on your target platform - Dispose instances: Always call
dispose()
on Sonix instances when done to clean up isolates - Monitor resources: Use
getResourceStatistics()
to monitor isolate performance - Handle errors: Wrap operations in try-catch blocks for proper error handling
- Use optimal configs: Use
Sonix.getOptimalConfig()
for different use cases - Cancel when needed: Cancel long-running operations with
cancelOperation()
if user navigates away - Profile performance: Use
PerformanceProfiler
to identify bottlenecks in production - Validate formats: Check
Sonix.isFormatSupported()
before processing files
Platform-Specific Considerations #
Android
- Minimum API level 21 (Android 5.0)
- FFMPEG binaries are automatically included in APK during build
- Isolate processing works seamlessly on all Android versions
iOS
- Minimum iOS version 11.0
- FFMPEG binaries are statically linked during build
- Background isolates work within iOS app lifecycle constraints
Desktop (Windows/macOS/Linux)
- FFMPEG binaries must be present in build directory (use download tool)
- Full isolate pool support for maximum performance
- Runtime loading of FFMPEG libraries from build directory
Troubleshooting FFMPEG Setup
If you encounter issues with FFMPEG binaries:
# Check if binaries are properly installed
dart run sonix:setup_ffmpeg_for_app --verify
# Force reinstall if needed
dart run sonix:setup_ffmpeg_for_app --force
# Remove FFMPEG binaries
dart run sonix:setup_ffmpeg_for_app --clean
# Get help and see all options
dart run sonix:setup_ffmpeg_for_app --help
Common issues:
- "FFMPEG libraries not found": Run the download tool to install binaries
- "Unsupported platform": Check supported platforms list above
- "Binary validation failed": Try force reinstalling with
--force
flag
Supported Audio Formats #
Sonix supports multiple audio formats through FFMPEG integration:
Format | Extension | Decoder Backend | Notes |
---|---|---|---|
MP3 | .mp3 | FFMPEG | Most common audio format |
WAV | .wav | FFMPEG | Uncompressed audio |
FLAC | .flac | FFMPEG | Lossless compression |
OGG Vorbis | .ogg | FFMPEG | Open source format |
Opus | .opus | FFMPEG | Modern codec |
MP4/AAC | .mp4, .m4a | FFMPEG | Container with AAC |
Note: All audio decoding is handled by FFMPEG libraries. Ensure FFMPEG binaries are installed using the provided download tool.
Contributing #
We welcome contributions! Please see our Contributing Guide for details.
Development Setup #
- Clone the repository
- Run
flutter pub get
- Install FFMPEG binaries for development:
dart run tool/download_ffmpeg_binaries.dart
- Build native library for testing:
dart run tool/build_native_for_development.dart
- Run tests:
flutter test
- Run example:
cd example && flutter run
Note for Contributors:
- Use
dart run tool/build_native_for_development.dart
for quick development builds - Use
dart run tool/build_native_for_distribution.dart
for release builds - End users should use
dart run sonix:setup_ffmpeg_for_app
in their own apps
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Support #
- π Documentation
- π Issue Tracker
- π¬ Discussions
Changelog #
See CHANGELOG.md for a detailed list of changes.