Flutter音频播放插件just_audio的使用
Flutter音频播放插件just_audio的使用
简介
just_audio
是一个功能丰富的音频播放器,适用于Android、iOS、macOS、Web、Linux和Windows平台。它提供了多种功能,包括从URL、文件、资产或字节流读取音频,支持DASH、HLS等流媒体协议,处理ICy元数据,以及更多高级特性如播放列表管理、无缝播放、循环播放、随机播放等。
快速概览
import 'package:just_audio/just_audio.dart';
void main() async {
final player = AudioPlayer(); // 创建播放器
await player.setUrl('https://foo.com/bar.mp3'); // 加载URL
player.play(); // 播放
await player.pause(); // 暂停
await player.seek(Duration(seconds: 10)); // 跳到10秒位置
await player.setSpeed(2.0); // 设置两倍速播放
await player.setVolume(0.5); // 设置半音量
await player.stop(); // 停止并释放资源
}
处理多个播放器
final player1 = AudioPlayer();
await player1.setUrl('...');
final player2 = AudioPlayer();
await player2.setUrl('...');
// 同时播放两个播放器
player1.play();
player2.play();
// 依次播放
await player1.play();
await player2.play();
// 循环播放player1直到player2结束
await player1.setLoopMode(LoopMode.one);
player1.play();
await player2.play();
await player1.pause();
// 释放资源
await player1.stop();
await player2.stop();
处理片段
await player.setClip(start: Duration(seconds: 2), end: Duration(seconds: 4));
await player.play();
await player.pause();
await player.setClip(start: Duration(seconds: 10), end: Duration(seconds: 12));
await player.play();
await player.pause();
await player.setClip(); // 清除片段区域
处理播放列表
final playlist = ConcatenatingAudioSource(
useLazyPreparation: true,
shuffleOrder: DefaultShuffleOrder(),
children: [
AudioSource.uri(Uri.parse('https://example.com/track1.mp3')),
AudioSource.uri(Uri.parse('https://example.com/track2.mp3')),
AudioSource.uri(Uri.parse('https://example.com/track3.mp3')),
],
);
await player.setAudioSource(playlist, initialIndex: 0, initialPosition: Duration.zero);
await player.seekToNext(); // 跳到下一曲
await player.seekToPrevious(); // 跳到上一曲
await player.seek(Duration.zero, index: 2); // 跳到track3.mp3的开头
await player.setLoopMode(LoopMode.all); // 设置播放列表循环
await player.setShuffleModeEnabled(true); // 打乱播放列表顺序
// 更新播放列表
await playlist.add(newChild1);
await playlist.insert(3, newChild2);
await playlist.removeAt(3);
示例代码:完整的Flutter应用示例
import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with WidgetsBindingObserver {
final _player = AudioPlayer();
@override
void initState() {
super.initState();
ambiguate(WidgetsBinding.instance)!.addObserver(this);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.black,
));
_init();
}
Future<void> _init() async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
_player.playbackEventStream.listen((event) {}, onError: (Object e, StackTrace stackTrace) {
print('A stream error occurred: $e');
});
try {
await _player.setAudioSource(AudioSource.uri(Uri.parse(
"https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3")));
} on PlayerException catch (e) {
print("Error loading audio source: $e");
}
}
@override
void dispose() {
ambiguate(WidgetsBinding.instance)!.removeObserver(this);
_player.dispose();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused) {
_player.stop();
}
}
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
_player.positionStream,
_player.bufferedPositionStream,
_player.durationStream,
(position, bufferedPosition, duration) => PositionData(
position, bufferedPosition, duration ?? Duration.zero));
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ControlButtons(_player),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (context, snapshot) {
final positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition: positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: _player.seek,
);
},
),
],
),
),
),
);
}
}
class ControlButtons extends StatelessWidget {
final AudioPlayer player;
const ControlButtons(this.player, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.volume_up),
onPressed: () {
showSliderDialog(
context: context,
title: "Adjust volume",
divisions: 10,
min: 0.0,
max: 1.0,
value: player.volume,
stream: player.volumeStream,
onChanged: player.setVolume,
);
},
),
StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (context, snapshot) {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(8.0),
width: 64.0,
height: 64.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 64.0,
onPressed: player.play,
);
} else if (processingState != ProcessingState.completed) {
return IconButton(
icon: const Icon(Icons.pause),
iconSize: 64.0,
onPressed: player.pause,
);
} else {
return IconButton(
icon: const Icon(Icons.replay),
iconSize: 64.0,
onPressed: () => player.seek(Duration.zero),
);
}
},
),
StreamBuilder<double>(
stream: player.speedStream,
builder: (context, snapshot) => IconButton(
icon: Text("${snapshot.data?.toStringAsFixed(1)}x",
style: const TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
showSliderDialog(
context: context,
title: "Adjust speed",
divisions: 10,
min: 0.5,
max: 1.5,
value: player.speed,
stream: player.speedStream,
onChanged: player.setSpeed,
);
},
),
),
],
);
}
}
总结
just_audio
插件为Flutter开发者提供了一个强大且易于使用的音频播放解决方案。通过上述示例代码和详细说明,您可以快速上手并在您的项目中集成音频播放功能。如果您需要更高级的功能,如后台播放、音频会话配置等,可以参考官方文档和相关教程。
更多关于Flutter音频播放插件just_audio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频播放插件just_audio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用just_audio
插件进行音频播放的代码示例。just_audio
是一个功能强大且灵活的音频播放插件,适用于需要精细控制音频播放的应用。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加just_audio
依赖:
dependencies:
flutter:
sdk: flutter
just_audio: ^0.9.15 # 请检查最新版本号
2. 导入包
在你的Dart文件中导入just_audio
包:
import 'package:just_audio/just_audio.dart';
import 'package:flutter/material.dart';
3. 创建AudioPlayer实例
在你的Flutter组件中创建一个AudioPlayer
实例:
class AudioPlayerScreen extends StatefulWidget {
@override
_AudioPlayerScreenState createState() => _AudioPlayerScreenState();
}
class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
late AudioPlayer audioPlayer;
@override
void initState() {
super.initState();
audioPlayer = AudioPlayer();
}
@override
void dispose() {
audioPlayer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Just Audio Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
// 替换为你的音频URL
final url = 'https://example.com/audiofile.mp3';
await audioPlayer.setUrl(url);
await audioPlayer.play();
},
child: Text('Play Audio'),
),
ElevatedButton(
onPressed: () {
audioPlayer.pause();
},
child: Text('Pause Audio'),
),
ElevatedButton(
onPressed: () {
audioPlayer.stop();
},
child: Text('Stop Audio'),
),
],
),
),
);
}
}
4. 监听播放状态(可选)
你可以监听音频播放器的状态变化,例如播放进度、缓冲状态等。以下是如何添加这些监听器的示例:
class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
late AudioPlayer audioPlayer;
late PositionInformation? positionInformation;
late bool isPlaying = false;
@override
void initState() {
super.initState();
audioPlayer = AudioPlayer();
// 监听播放位置变化
audioPlayer.positionStream.listen((position) {
setState(() {
positionInformation = position;
});
});
// 监听播放状态变化
audioPlayer.playingStream.listen((playing) {
setState(() {
isPlaying = playing;
});
});
}
@override
void dispose() {
audioPlayer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Just Audio Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
final url = 'https://example.com/audiofile.mp3';
await audioPlayer.setUrl(url);
await audioPlayer.play();
},
child: Text('Play Audio'),
),
ElevatedButton(
onPressed: () {
audioPlayer.pause();
},
child: Text('Pause Audio'),
),
ElevatedButton(
onPressed: () {
audioPlayer.stop();
},
child: Text('Stop Audio'),
),
if (positionInformation != null)
Text('Current Position: ${positionInformation!.position.inMilliseconds}ms'),
Text('Is Playing: $isPlaying'),
],
),
),
);
}
}
以上代码展示了如何使用just_audio
插件进行基本的音频播放控制,并监听播放位置和播放状态。你可以根据需要进一步扩展这些功能,例如添加音量控制、进度条等。