Flutter音频波形展示插件audio_waveforms的使用
Flutter音频波形展示插件audio_waveforms的使用
简介
audio_waveforms
是一个用于在Flutter中生成和显示音频文件波形的插件。它支持从文件或实时录音中生成波形,并提供了丰富的自定义选项,包括样式调整、手势控制等。
前提条件
- 添加依赖:在
pubspec.yaml
文件中添加audio_waveforms
依赖。dependencies: audio_waveforms: <latest-version>
- 清理项目:确保删除设备上的应用并执行
flutter clean
和flutter pub get
。
使用方法
录音功能
平台特定设置
-
Android:
- 修改
android/app/build.gradle
中的最小SDK版本为21(或更高)。minSdkVersion 21
- 在
AndroidManifest.xml
中添加录音权限。<uses-permission android:name="android.permission.RECORD_AUDIO" />
- 修改
-
iOS:
- 在
ios/Runner/Info.plist
中添加麦克风使用描述。<key>NSMicrophoneUsageDescription</key> <string>请允许访问麦克风以录制音频。</string>
- 确保
Podfile
中指定iOS版本为12.0或更高。platform :ios, '12.0'
- 在
快速示例
以下是一个简单的例子,展示了如何在录音时显示波形。
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
class RecorderExample extends StatefulWidget {
@override
_RecorderExampleState createState() => _RecorderExampleState();
}
class _RecorderExampleState extends State<RecorderExample> {
String? recordedFilePath;
final RecorderController recorderController = RecorderController();
@override
void initState() {
super.initState();
recorderController.checkPermission();
}
@override
void dispose() {
recorderController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
if (recorderController.hasPermission) {
recorderController.record(); // 默认保存文件名为当前时间戳
}
},
child: Text('Record'),
),
ElevatedButton(
onPressed: () {
recorderController.pause();
},
child: Text('Pause'),
),
ElevatedButton(
onPressed: () async {
if (recorderController.isRecording) {
recordedFilePath = await recorderController.stop();
}
},
child: Text('Stop'),
),
AudioWaveforms(
controller: recorderController,
size: Size(300, 50),
),
],
);
}
}
播放功能
快速示例
以下是一个简单的例子,展示了如何在播放音频文件时显示波形。
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
class PlayerExample extends StatefulWidget {
@override
_PlayerExampleState createState() => _PlayerExampleState();
}
class _PlayerExampleState extends State<PlayerExample> {
final PlayerController playerController = PlayerController();
@override
void initState() {
super.initState();
playerController.preparePlayer(path: '../myFile.mp3');
}
@override
void dispose() {
playerController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
playerController.startPlayer();
},
child: Text('Play'),
),
ElevatedButton(
onPressed: () {
playerController.pausePlayer();
},
child: Text('Pause'),
),
ElevatedButton(
onPressed: () {
playerController.stopPlayer();
},
child: Text('Stop'),
),
AudioFileWaveforms(
controller: playerController,
size: Size(300, 50),
),
],
);
}
}
自定义波形样式
你可以通过 WaveStyle
类来自定义波形的外观,例如颜色、渐变、间距等。
AudioWaveforms(
size: Size(MediaQuery.of(context).size.width, 200.0),
shouldCalculateScrolledPosition: true,
enableGesture: true,
waveStyle: WaveStyle(
waveColor: Colors.blue,
extendWaveform: true,
showMiddleLine: false,
waveGradient: LinearGradient(colors: [Colors.red, Colors.orange]),
),
)
高级特性
- 自定义录音参数:可以设置文件路径、编码器、输出格式等。
- 监听事件:可以通过流监听录音状态变化、进度更新等。
- 预计算波形数据:通过
extractWaveformData
方法提前计算波形数据,节省资源。 - 平滑动画:设置
updateFrequency
来控制波形动画的流畅度。
完整示例代码
以下是结合了录音和播放功能的完整示例代码:
import 'dart:io';
import 'package:audio_waveforms/audio_waveforms.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Audio Waveforms',
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({super.key});
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late final RecorderController recorderController;
late final PlayerController playerController;
String? path;
bool isRecording = false;
bool isRecordingCompleted = false;
bool isLoading = true;
late Directory appDirectory;
@override
void initState() {
super.initState();
_getDir();
_initialiseControllers();
}
void _getDir() async {
appDirectory = await getApplicationDocumentsDirectory();
path = "${appDirectory.path}/recording.m4a";
isLoading = false;
setState(() {});
}
void _initialiseControllers() {
recorderController = RecorderController()
..androidEncoder = AndroidEncoder.aac
..androidOutputFormat = AndroidOutputFormat.mpeg4
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
..sampleRate = 44100;
playerController = PlayerController();
}
@override
void dispose() {
recorderController.dispose();
playerController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Audio Waveforms')),
body: isLoading
? Center(child: CircularProgressIndicator())
: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: 1,
itemBuilder: (_, index) {
return Container(
height: 200,
color: Colors.grey[200],
child: Center(child: Text('Waveform Display Area')),
);
},
),
),
Row(
children: [
IconButton(
onPressed: () async {
if (isRecording) {
await recorderController.stop(false);
isRecordingCompleted = true;
} else {
await recorderController.record(path: path);
}
setState(() {
isRecording = !isRecording;
});
},
icon: Icon(isRecording ? Icons.stop : Icons.mic),
),
IconButton(
onPressed: () {
if (isRecording) recorderController.refresh();
},
icon: Icon(Icons.refresh),
),
Spacer(),
IconButton(
onPressed: () {
if (!isRecording && recordedFilePath != null) {
playerController.preparePlayer(path: recordedFilePath);
playerController.startPlayer();
}
},
icon: Icon(Icons.play_arrow),
),
IconButton(
onPressed: () {
playerController.pausePlayer();
},
icon: Icon(Icons.pause),
),
IconButton(
onPressed: () {
playerController.stopPlayer();
},
icon: Icon(Icons.stop),
),
],
),
if (isRecordingCompleted)
AudioWaveforms(
controller: recorderController,
size: Size(double.infinity, 50),
),
if (recordedFilePath != null)
AudioFileWaveforms(
controller: playerController,
size: Size(double.infinity, 50),
),
],
),
);
}
}
这个完整的示例展示了如何集成录音和播放功能,并动态显示波形。希望这能帮助你更好地理解和使用 audio_waveforms
插件。
更多关于Flutter音频波形展示插件audio_waveforms的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频波形展示插件audio_waveforms的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用audio_waveforms
插件来展示音频波形的示例代码。这个插件允许你从音频文件中生成并展示波形图。
首先,确保你已经在pubspec.yaml
文件中添加了audio_waveforms
依赖:
dependencies:
flutter:
sdk: flutter
audio_waveforms: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以按照以下步骤在你的Flutter应用中展示音频波形:
- 导入必要的包:
import 'package:flutter/material.dart';
import 'package:audio_waveforms/audio_waveforms.dart';
- 创建一个Widget来展示波形:
class AudioWaveformWidget extends StatefulWidget {
final String audioFilePath;
AudioWaveformWidget({required this.audioFilePath});
@override
_AudioWaveformWidgetState createState() => _AudioWaveformWidgetState();
}
class _AudioWaveformWidgetState extends State<AudioWaveformWidget> {
late AudioWaveformsController _controller;
late List<double> _waveformData;
@override
void initState() {
super.initState();
_controller = AudioWaveformsController();
_loadWaveformData();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _loadWaveformData() async {
try {
// 从音频文件路径加载波形数据
_waveformData = await _controller.loadFromFile(widget.audioFilePath);
setState(() {});
} catch (e) {
print("Error loading waveform data: $e");
}
}
@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(double.infinity, 200), // 根据需要调整大小
painter: WaveformPainter(_waveformData),
);
}
}
class WaveformPainter extends CustomPainter {
final List<double> waveformData;
final Paint paint = Paint()
..color = Colors.blue
..strokeWidth = 2.0
..style = PaintingStyle.stroke;
WaveformPainter(this.waveformData);
@override
void paint(Canvas canvas, Size size) {
final double canvasWidth = size.width;
final double canvasHeight = size.height;
final double scaleFactor = canvasWidth / waveformData.length;
for (int i = 0; i < waveformData.length - 1; i++) {
final double x1 = i * scaleFactor;
final double y1 = canvasHeight / 2 - waveformData[i] * (canvasHeight / 4);
final double x2 = (i + 1) * scaleFactor;
final double y2 = canvasHeight / 2 - waveformData[i + 1] * (canvasHeight / 4);
canvas.drawLine(Offset(x1, y1), Offset(x2, y2), paint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
- 在你的主应用中使用这个Widget:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Audio Waveform Demo'),
),
body: Center(
child: AudioWaveformWidget(
audioFilePath: 'path/to/your/audio/file.mp3', // 替换为你的音频文件路径
),
),
),
);
}
}
注意事项:
- 确保你提供了正确的音频文件路径。
AudioWaveformsController
的loadFromFile
方法是一个异步操作,因此你需要处理异步逻辑(例如使用Future
或async/await
)。WaveformPainter
类中的paint
方法负责根据波形数据绘制波形图。你可以根据需要调整Paint
对象的属性来改变波形的样式。
这段代码展示了如何使用audio_waveforms
插件从音频文件中加载波形数据,并使用CustomPaint
和CustomPainter
在Flutter应用中绘制波形图。如果你有任何进一步的问题或需要更详细的信息,请随时告诉我!