Flutter音频播放插件ogg_opus_player的使用
Flutter音频播放插件ogg_opus_player的使用
简介
ogg_opus_player
是一个用于Flutter应用程序的插件,支持播放OGG Opus格式的音频文件。该插件支持多个平台,包括iOS、macOS、Windows、Linux和Android。
支持的平台及最低系统版本要求
平台 | 是否支持 | 最低系统版本 |
---|---|---|
iOS | ✅ | 10.0 |
macOS | ✅ | 10.12 |
Windows | ✅ | - |
Linux | ✅ | - |
Android | ✅ | minSdk 21 |
快速开始
1. 添加依赖
在 pubspec.yaml
文件中添加 ogg_opus_player
依赖:
dependencies:
ogg_opus_player: $latest_version
2. 使用 OggOpusPlayer 播放 OGG Opus 文件
以下是一个简单的示例,展示了如何使用 OggOpusPlayer
播放 OGG Opus 文件:
import 'package:ogg_opus_player/ogg_opus_player.dart';
void playOggOpusFile() {
// 初始化播放器,传入音频文件路径
final player = OggOpusPlayer("file_path");
// 播放音频
player.play();
// 暂停音频
player.pause();
// 释放资源
player.dispose();
}
完整示例 Demo
下面是一个完整的示例应用,展示了如何在Flutter应用中使用 ogg_opus_player
插件来播放和录制 OGG Opus 音频文件。
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ogg_opus_player/ogg_opus_player.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final tempDir = await getTemporaryDirectory();
final workDir = p.join(tempDir.path, 'ogg_opus_player');
debugPrint('workDir: $workDir');
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: [
_PlayAssetExample(directory: workDir),
const SizedBox(height: 20),
_RecorderExample(dir: workDir),
],
),
),
),
);
}
class _PlayAssetExample extends StatefulWidget {
const _PlayAssetExample({Key? key, required this.directory}) : super(key: key);
final String directory;
@override
_PlayAssetExampleState createState() => _PlayAssetExampleState();
}
class _PlayAssetExampleState extends State<_PlayAssetExample> {
bool _copyCompleted = false;
String _path = '';
@override
void initState() {
super.initState();
_copyAssets();
}
Future<void> _copyAssets() async {
final dir = await getApplicationDocumentsDirectory();
final dest = File(p.join(dir.path, "test.ogg"));
_path = dest.path;
if (await dest.exists()) {
setState(() {
_copyCompleted = true;
});
return;
}
// 从 assets 中加载音频文件并保存到本地
final bytes = await rootBundle.load('audios/test.ogg');
await dest.writeAsBytes(bytes.buffer.asUint8List());
setState(() {
_copyCompleted = true;
});
}
@override
Widget build(BuildContext context) {
return _copyCompleted
? _OpusOggPlayerWidget(
path: _path,
key: ValueKey(_path),
)
: const Center(
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(),
),
);
}
}
class _OpusOggPlayerWidget extends StatefulWidget {
const _OpusOggPlayerWidget({Key? key, required this.path}) : super(key: key);
final String path;
@override
State<_OpusOggPlayerWidget> createState() => _OpusOggPlayerWidgetState();
}
class _OpusOggPlayerWidgetState extends State<_OpusOggPlayerWidget> {
OggOpusPlayer? _player;
Timer? timer;
double _playingPosition = 0;
static const _kPlaybackSpeedSteps = [0.5, 1.0, 1.5, 2.0];
int _speedIndex = 1;
@override
void initState() {
super.initState();
// 每50毫秒更新一次播放进度
timer = Timer.periodic(const Duration(milliseconds: 50), (timer) {
setState(() {
_playingPosition = _player?.currentPosition ?? 0;
});
});
}
@override
void dispose() {
timer?.cancel();
_player?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final state = _player?.state.value ?? PlayerState.idle;
return Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('position: ${_playingPosition.toStringAsFixed(2)}'), // 显示当前播放位置
const SizedBox(height: 8),
if (state == PlayerState.playing)
IconButton(
onPressed: () {
_player?.pause(); // 暂停播放
},
icon: const Icon(Icons.pause),
)
else
IconButton(
onPressed: () {
_player?.dispose();
_speedIndex = 1;
_player = OggOpusPlayer(widget.path); // 初始化播放器
_player?.play(); // 开始播放
_player?.state.addListener(() {
setState(() {});
if (_player?.state.value == PlayerState.ended) {
_player?.dispose();
_player = null;
}
});
},
icon: const Icon(Icons.play_arrow),
),
IconButton(
onPressed: () {
setState(() {
_player?.dispose();
_player = null;
});
},
icon: const Icon(Icons.stop), // 停止播放
),
if (_player != null)
TextButton(
onPressed: () {
_speedIndex++;
if (_speedIndex >= _kPlaybackSpeedSteps.length) {
_speedIndex = 0;
}
_player?.setPlaybackRate(_kPlaybackSpeedSteps[_speedIndex]); // 设置播放速度
},
child: Text('X${_kPlaybackSpeedSteps[_speedIndex]}'),
),
],
),
);
}
}
class _RecorderExample extends StatefulWidget {
const _RecorderExample({
Key? key,
required this.dir,
}) : super(key: key);
final String dir;
@override
State<_RecorderExample> createState() => _RecorderExampleState();
}
class _RecorderExampleState extends State<_RecorderExample> {
late String _recordedPath;
OggOpusRecorder? _recorder;
@override
void initState() {
super.initState();
_recordedPath = p.join(widget.dir, 'test_recorded.ogg');
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 8),
if (_recorder == null)
IconButton(
onPressed: () {
final file = File(_recordedPath);
if (file.existsSync()) {
File(_recordedPath).deleteSync();
}
File(_recordedPath).createSync(recursive: true);
final recorder = OggOpusRecorder(_recordedPath);
recorder.start(); // 开始录音
setState(() {
_recorder = recorder;
});
},
icon: const Icon(Icons.keyboard_voice_outlined),
)
else
IconButton(
onPressed: () async {
await _recorder?.stop(); // 停止录音
debugPrint('recording stopped');
debugPrint('duration: ${await _recorder?.duration()}'); // 打印录音时长
debugPrint('waveform: ${await _recorder?.getWaveformData()}'); // 打印波形数据
_recorder?.dispose();
setState(() {
_recorder = null;
});
},
icon: const Icon(Icons.stop),
),
const SizedBox(height: 8),
if (_recorder == null && File(_recordedPath).existsSync())
_OpusOggPlayerWidget(path: _recordedPath), // 播放录制的音频
],
);
}
}
特殊平台要求
Linux
在Linux上使用 ogg_opus_player
时,需要安装 SDL2 和 Opus 库:
sudo apt-get install libsdl2-dev
sudo apt-get install libopus-dev
iOS/macOS
如果您的应用需要使用麦克风进行录音,请确保在 Info.plist
文件中添加 NSMicrophoneUsageDescription
键,并提供一段说明,解释应用为何需要访问麦克风。例如:
<key>NSMicrophoneUsageDescription</key>
<string>Example uses your microphone to record voice for test.</string>
对于 macOS,还需要在 DebugProfile.entitlements
和 ReleaseProfile.entitlements
文件中添加以下权限:
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
更多关于Flutter音频播放插件ogg_opus_player的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频播放插件ogg_opus_player的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用ogg_opus_player
插件进行音频播放的代码示例。这个插件专门用于播放OGG Opus格式的音频文件。
首先,确保你已经在pubspec.yaml
文件中添加了ogg_opus_player
依赖:
dependencies:
flutter:
sdk: flutter
ogg_opus_player: ^最新版本号 # 替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,创建一个Flutter应用并实现音频播放功能。以下是一个简单的示例:
main.dart
import 'package:flutter/material.dart';
import 'package:ogg_opus_player/ogg_opus_player.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Ogg Opus Player Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
OggOpusPlayer? _player;
bool _isPlaying = false;
@override
void initState() {
super.initState();
_initPlayer();
}
@override
void dispose() {
_player?.dispose();
super.dispose();
}
Future<void> _initPlayer() async {
// 替换为你的OGG Opus音频文件路径
String audioUrl = 'assets/audio/sample.opus'; // 如果是本地文件,确保在pubspec.yaml中声明
// 如果是网络URL,则直接使用URL字符串
// String audioUrl = 'https://example.com/audio/sample.opus';
_player = OggOpusPlayer();
_player!.setDataSource(audioUrl);
_player!.prepare();
}
void _playPause() async {
if (_isPlaying) {
await _player!.pause();
} else {
await _player!.start();
}
setState(() {
_isPlaying = !_isPlaying;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Ogg Opus Player Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$_isPlaying',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _playPause,
child: Text(_isPlaying ? 'Pause' : 'Play'),
),
],
),
),
);
}
}
pubspec.yaml (部分)
如果你使用的是本地音频文件,确保在pubspec.yaml
中声明资源:
flutter:
assets:
- assets/audio/sample.opus
注意事项
- 音频文件路径:确保音频文件路径正确。如果是本地文件,路径应与
pubspec.yaml
中声明的路径一致。如果是网络URL,直接使用URL字符串。 - 错误处理:在实际应用中,你可能需要添加错误处理逻辑,例如处理音频文件加载失败或播放错误。
- 生命周期管理:在
dispose
方法中释放_player
资源,以避免内存泄漏。
这个示例展示了如何使用ogg_opus_player
插件在Flutter应用中播放OGG Opus格式的音频文件。你可以根据需要进一步扩展和自定义这个示例。