Pub.dev
https://pub.dev/packages/flutter_sound
pubspec.yaml
더보기
더보기
environment:
sdk: '>=2.12.0 <3.0.0'
flutter: ">=1.12.0"
dependencies:
flutter:
sdk: flutter
flutter_sound: ^9.1.2
cupertino_icons: ^1.0.2
path_provider: ^2.0.2
permission_handler: ^6.0.1
path: ^1.6.4
#flutter_ffmpeg: ^0.3.1
intl: ^0.17.0
just_audio: ^0.9.11
audio_session: ^0.1.6
dev_dependencies:
# flutter_test:
# sdk: flutter
pedantic: ^1.11.0
#effective_dart: ^1.3.0
#display.save( displayObject, options )effective_dart: ^1.0.0
#lint: ^1.1.1
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- res/icons/ic_play.png
- res/icons/ic_play_disabled.png
- res/icons/2.0x/ic_play.png
- res/icons/3.0x/ic_play.png
- res/icons/ic_stop.png
- res/icons/ic_stop_disabled.png
- res/icons/2.0x/ic_stop.png
- res/icons/3.0x/ic_stop.png
- res/icons/ic_pause.png
- res/icons/ic_pause_disabled.png
- res/icons/2.0x/ic_pause.png
- res/icons/3.0x/ic_pause.png
- res/icons/ic_mic.png
- res/icons/ic_mic_disabled.png
- res/icons/2.0x/ic_mic.png
- res/icons/3.0x/ic_mic.png
- res/icons/ic_volume_down.png
- res/icons/2.0x/ic_volume_down.png
- res/icons/3.0x/ic_volume_down.png
- res/icons/ic_volume_up.png
- res/icons/2.0x/ic_volume_up.png
- res/icons/3.0x/ic_volume_up.png
- assets/
- assets/samples/
- assets/noises/
Simple Playback
💬 간단한 사운드 재생 앱
UI
코드
더보기
더보기
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
final _exampleAudioFilePathMP3 =
'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3';
typedef Fn = void Function();
class SimplePlayback extends StatefulWidget {
@override
_SimplePlaybackState createState() => _SimplePlaybackState();
}
class _SimplePlaybackState extends State<SimplePlayback> {
FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
bool _mPlayerIsInited = false;
@override
void initState() {
super.initState();
_mPlayer!.openPlayer().then((value) {
setState(() {
_mPlayerIsInited = true;
});
});
}
@override
void dispose() {
stopPlayer();
// Be careful : you must `close` the audio session when you have finished with it.
_mPlayer!.closePlayer();
_mPlayer = null;
super.dispose();
}
// ------- Here is the code to playback a remote file -----------------------
void play() async {
await _mPlayer!.startPlayer(
fromURI: _exampleAudioFilePathMP3,
codec: Codec.mp3,
whenFinished: () {
setState(() {});
});
setState(() {});
}
Future<void> stopPlayer() async {
if (_mPlayer != null) {
await _mPlayer!.stopPlayer();
}
}
// --------------------- UI -------------------
Fn? getPlaybackFn() {
if (!_mPlayerIsInited) {
return null;
}
return _mPlayer!.isStopped
? play
: () {
stopPlayer().then((value) => setState(() {}));
};
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
return Column(
children: [
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getPlaybackFn(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer!.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer!.isPlaying
? 'Playback in progress'
: 'Player is stopped'),
]),
),
],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Simple Playback'),
),
body: makeBody(),
);
}
}
Multi Playback
💬 여러 사운드 동시 재생 앱
UI
코드
더보기
더보기
import 'dart:async';
import 'dart:typed_data';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter/services.dart' show rootBundle;
final _exampleAudioFilePathMP3 =
'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3';
typedef Fn = void Function();
class MultiPlayback extends StatefulWidget {
@override
_MultiPlaybackState createState() => _MultiPlaybackState();
}
class _MultiPlaybackState extends State<MultiPlayback> {
FlutterSoundPlayer? _mPlayer1 = FlutterSoundPlayer();
FlutterSoundPlayer? _mPlayer2 = FlutterSoundPlayer();
FlutterSoundPlayer? _mPlayer3 = FlutterSoundPlayer();
bool _mPlayer1IsInited = false; // 1번 음성 파일 실행할 준비가 되었는지?
bool _mPlayer2IsInited = false;
bool _mPlayer3IsInited = false;
Uint8List? buffer2;
Uint8List? buffer3;
String _playerTxt1 = '';
String _playerTxt2 = '';
String _playerTxt3 = '';
StreamSubscription? _playerSubscription1; // 스트림과 이벤트의 연결고리, 이벤트에 변경이 생기면 처리
StreamSubscription? _playerSubscription2;
StreamSubscription? _playerSubscription3;
Future<Uint8List> _getAssetData(String path) async { // Question
var asset = await rootBundle.load(path);
return asset.buffer.asUint8List();
}
@override
void initState() {
super.initState();
initializeDateFormatting(); // Question
_getAssetData(
'assets/samples/sample.aac',
).then((value) => setState(() {
buffer2 = value;
}));
_getAssetData(
'assets/samples/sample.mp4',
).then((value) => setState(() {
buffer3 = value;
}));
_mPlayer1!.openPlayer().then((value) {
setState(() {
_mPlayer1IsInited = true;
});
});
_mPlayer2!.openPlayer().then((value) {
setState(() {
_mPlayer2IsInited = true;
});
});
_mPlayer3!.openPlayer().then((value) {
setState(() {
_mPlayer3IsInited = true;
});
});
}
@override
void dispose() {
// Be careful : you must `close` the audio session when you have finished with it.
cancelPlayerSubscriptions1(); // Question
_mPlayer1!.closePlayer();
_mPlayer1 = null;
cancelPlayerSubscriptions2();
_mPlayer2!.closePlayer();
_mPlayer2 = null;
cancelPlayerSubscriptions3();
_mPlayer3!.closePlayer();
_mPlayer3 = null;
super.dispose();
}
// ------- Player1 play a remote file -----------------------
void play1() async { // 1번 음성 파일 재생
await _mPlayer1!.setSubscriptionDuration(Duration(milliseconds: 10));
_addListener1();
await _mPlayer1!.startPlayer(
fromURI: _exampleAudioFilePathMP3,
codec: Codec.mp3,
whenFinished: () {
setState(() {});
});
setState(() {});
}
void cancelPlayerSubscriptions1() { // 스트림 해제
if (_playerSubscription1 != null) {
_playerSubscription1!.cancel();
_playerSubscription1 = null;
}
}
Future<void> stopPlayer1() async {
cancelPlayerSubscriptions1();
if (_mPlayer1 != null) {
await _mPlayer1!.stopPlayer();
}
setState(() {});
}
Future<void> pause1() async {
if (_mPlayer1 != null) {
await _mPlayer1!.pausePlayer();
}
setState(() {});
}
Future<void> resume1() async {
if (_mPlayer1 != null) {
await _mPlayer1!.resumePlayer();
}
setState(() {});
}
// ------- Player2 play a OPUS file -----------------------
void play2() async {
await _mPlayer2!.setSubscriptionDuration(Duration(milliseconds: 10));
_addListener2();
await _mPlayer2!.startPlayer(
fromDataBuffer: buffer2,
codec: Codec.aacADTS,
whenFinished: () {
setState(() {});
});
setState(() {});
}
void cancelPlayerSubscriptions2() {
if (_playerSubscription2 != null) {
_playerSubscription2!.cancel();
_playerSubscription2 = null;
}
}
Future<void> stopPlayer2() async {
cancelPlayerSubscriptions2();
if (_mPlayer2 != null) {
await _mPlayer2!.stopPlayer();
}
setState(() {});
}
Future<void> pause2() async {
if (_mPlayer2 != null) {
await _mPlayer2!.pausePlayer();
}
setState(() {});
}
Future<void> resume2() async {
if (_mPlayer2 != null) {
await _mPlayer2!.resumePlayer();
}
setState(() {});
}
// ------- Player3 play a MP4 file -----------------------
void play3() async {
await _mPlayer3!.setSubscriptionDuration(Duration(milliseconds: 10));
_addListener3();
await _mPlayer3!.startPlayer(
fromDataBuffer: buffer3,
codec: Codec.aacMP4,
whenFinished: () {
setState(() {});
});
setState(() {});
}
void cancelPlayerSubscriptions3() {
if (_playerSubscription3 != null) {
_playerSubscription3!.cancel();
_playerSubscription3 = null;
}
}
Future<void> stopPlayer3() async {
cancelPlayerSubscriptions3();
if (_mPlayer3 != null) {
await _mPlayer3!.stopPlayer();
}
setState(() {});
}
Future<void> pause3() async {
if (_mPlayer3 != null) {
await _mPlayer3!.pausePlayer();
}
setState(() {});
}
Future<void> resume3() async {
if (_mPlayer3 != null) {
await _mPlayer3!.resumePlayer();
}
setState(() {});
}
// ---------------------------------------------------------------------------
void _addListener1() { // 스트림 연결하여 실행되고 있는 음성 파일의 시간을 출력
cancelPlayerSubscriptions1();
_playerSubscription1 = _mPlayer1!.onProgress!.listen((e) {
var date = DateTime.fromMillisecondsSinceEpoch(e.position.inMilliseconds,
isUtc: true);
var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
setState(() {
_playerTxt1 = txt.substring(0, 8);
});
});
}
Fn? getPlaybackFn1() {
if (!_mPlayer1IsInited) {
return null;
}
return _mPlayer1!.isStopped
? play1
: () {
stopPlayer1().then((value) => setState(() {}));
};
}
Fn? getPauseResumeFn1() {
if (!_mPlayer1IsInited || _mPlayer1!.isStopped) {
return null;
}
return _mPlayer1!.isPaused ? resume1 : pause1;
}
void _addListener2() {
cancelPlayerSubscriptions2();
_playerSubscription2 = _mPlayer2!.onProgress!.listen((e) {
var date = DateTime.fromMillisecondsSinceEpoch(e.position.inMilliseconds,
isUtc: true);
var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
setState(() {
_playerTxt2 = txt.substring(0, 8);
});
});
}
Fn? getPlaybackFn2() {
if (!_mPlayer2IsInited || buffer2 == null) {
return null;
}
return _mPlayer2!.isStopped
? play2
: () {
stopPlayer2().then((value) => setState(() {}));
};
}
Fn? getPauseResumeFn2() {
if (!_mPlayer2IsInited || _mPlayer2!.isStopped || buffer2 == null) {
return null;
}
return _mPlayer2!.isPaused ? resume2 : pause2;
}
void _addListener3() {
cancelPlayerSubscriptions3();
_playerSubscription3 = _mPlayer3!.onProgress!.listen((e) {
var date = DateTime.fromMillisecondsSinceEpoch(e.position.inMilliseconds,
isUtc: true);
var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
setState(() {
_playerTxt3 = txt.substring(0, 8);
});
});
}
Fn? getPlaybackFn3() {
if (!_mPlayer3IsInited || buffer3 == null) {
return null;
}
return _mPlayer3!.isStopped
? play3
: () {
stopPlayer3().then((value) => setState(() {}));
};
}
Fn? getPauseResumeFn3() {
if (!_mPlayer3IsInited || _mPlayer3!.isStopped || buffer3 == null) {
return null;
}
return _mPlayer3!.isPaused ? resume3 : pause3;
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
return Column(
children: [
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getPlaybackFn1(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer1!.isStopped ? 'Play' : 'Stop'),
),
SizedBox(
width: 20,
),
ElevatedButton(
onPressed: getPauseResumeFn1(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer1!.isPaused ? 'Resume' : 'Pause'),
),
SizedBox(
width: 20,
),
Text(
_playerTxt1,
style: TextStyle(
color: Colors.black,
),
),
]),
),
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getPlaybackFn2(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer2!.isStopped ? 'Play' : 'Stop'),
),
SizedBox(
width: 20,
),
ElevatedButton(
onPressed: getPauseResumeFn2(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer2!.isPaused ? 'Resume' : 'Pause'),
),
SizedBox(
width: 20,
),
Text(
_playerTxt2,
style: TextStyle(
color: Colors.black,
),
),
]),
),
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getPlaybackFn3(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer3!.isStopped ? 'Play' : 'Stop'),
),
SizedBox(
width: 20,
),
ElevatedButton(
onPressed: getPauseResumeFn3(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer3!.isPaused ? 'Resume' : 'Pause'),
),
SizedBox(
width: 20,
),
Text(
_playerTxt3,
style: TextStyle(
color: Colors.black,
),
),
]),
),
],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Multi Playback'),
),
body: makeBody(),
);
}
}
Simple Recorder
💬 하이브리드, 웹 모두 구동되는 간단한 녹음 기능 앱
UI
코드
더보기
더보기
import 'dart:async';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart';
import 'package:permission_handler/permission_handler.dart';
typedef _Fn = void Function();
const theSource = AudioSource.microphone;
class SimpleRecorder extends StatefulWidget {
@override
_SimpleRecorderState createState() => _SimpleRecorderState();
}
class _SimpleRecorderState extends State<SimpleRecorder> {
Codec _codec = Codec.aacMP4;
String _mPath = 'tau_file.mp4';
FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();
bool _mPlayerIsInited = false;
bool _mRecorderIsInited = false;
bool _mplaybackReady = false;
@override
void initState() {
_mPlayer!.openPlayer().then((value) {
setState(() {
_mPlayerIsInited = true;
});
});
openTheRecorder().then((value) {
setState(() {
_mRecorderIsInited = true;
});
});
super.initState();
}
@override
void dispose() {
_mPlayer!.closePlayer();
_mPlayer = null;
_mRecorder!.closeRecorder();
_mRecorder = null;
super.dispose();
}
Future<void> openTheRecorder() async {
if (!kIsWeb) { // 웹이 아니면 (안드로이드 | IOS)
var status = await Permission.microphone.request(); // 권한 요청
if (status != PermissionStatus.granted) {
throw RecordingPermissionException('Microphone permission not granted');
}
}
await _mRecorder!.openRecorder();
if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
_codec = Codec.opusWebM;
_mPath = 'tau_file.webm';
if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
_mRecorderIsInited = true;
return;
}
}
final session = await AudioSession.instance;
await session.configure(AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
avAudioSessionCategoryOptions:
AVAudioSessionCategoryOptions.allowBluetooth |
AVAudioSessionCategoryOptions.defaultToSpeaker,
avAudioSessionMode: AVAudioSessionMode.spokenAudio,
avAudioSessionRouteSharingPolicy:
AVAudioSessionRouteSharingPolicy.defaultPolicy,
avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
androidAudioAttributes: const AndroidAudioAttributes(
contentType: AndroidAudioContentType.speech,
flags: AndroidAudioFlags.none,
usage: AndroidAudioUsage.voiceCommunication,
),
androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
androidWillPauseWhenDucked: true,
));
_mRecorderIsInited = true;
}
// ---------------------- Here is the code for recording and playback -------
void record() {
_mRecorder!
.startRecorder(
toFile: _mPath,
codec: _codec,
audioSource: theSource,
)
.then((value) {
setState(() {});
});
}
void stopRecorder() async {
await _mRecorder!.stopRecorder().then((value) {
setState(() {
//var url = value;
_mplaybackReady = true;
});
});
}
void play() {
assert(_mPlayerIsInited &&
_mplaybackReady &&
_mRecorder!.isStopped &&
_mPlayer!.isStopped);
// 위의 조건이면 프로그램이 중단된다.
_mPlayer!
.startPlayer(
fromURI: _mPath,
//codec: kIsWeb ? Codec.opusWebM : Codec.aacADTS,
whenFinished: () {
setState(() {});
})
.then((value) {
setState(() {});
});
}
void stopPlayer() {
_mPlayer!.stopPlayer().then((value) {
setState(() {});
});
}
// ----------------------------- UI --------------------------------------------
_Fn? getRecorderFn() {
// 녹음 준비가 되어 있지 않거나 녹음 파일이 실행 중이라면,
if (!_mRecorderIsInited || !_mPlayer!.isStopped) {
return null;
}
return _mRecorder!.isStopped ? record : stopRecorder;
}
_Fn? getPlaybackFn() {
// 실행 준비가 되어 있지 않거나 녹음 중이라면,
if (!_mPlayerIsInited || !_mplaybackReady || !_mRecorder!.isStopped) {
return null;
}
return _mPlayer!.isStopped ? play : stopPlayer;
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
return Column(
children: [
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity, // 중요
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getRecorderFn(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mRecorder!.isRecording ? 'Stop' : 'Record'),
),
SizedBox(
width: 20,
),
Text(_mRecorder!.isRecording
? 'Recording in progress'
: 'Recorder is stopped'),
]),
),
Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 80,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Row(children: [
ElevatedButton(
onPressed: getPlaybackFn(),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer!.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer!.isPlaying
? 'Playback in progress'
: 'Player is stopped'),
]),
),
],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Simple Recorder'),
),
body: makeBody(),
);
}
}
Volume Control
💬 음원 재생 볼륨을 조절할 수 있는 앱
UI
코드
더보기
더보기
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
final _exampleAudioFilePathMP3_1 =
'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3';
typedef Fn = void Function();
class VolumeControl extends StatefulWidget {
@override
_VolumeControlState createState() => _VolumeControlState();
}
class _VolumeControlState extends State<VolumeControl> {
final FlutterSoundPlayer _mPlayer1 = FlutterSoundPlayer();
bool _mPlayerIsInited1 = false;
double _mVolume1 = 100.0;
@override
void initState() {
super.initState();
_mPlayer1.openPlayer().then((value) {
setState(() {
_mPlayerIsInited1 = true;
});
});
}
@override
void dispose() {
stopPlayer(_mPlayer1);
// Be careful : you must `close` the audio session when you have finished with it.
_mPlayer1.closePlayer();
super.dispose();
}
// ------- Here is the code to playback a remote file -----------------------
void play(FlutterSoundPlayer? player, String uri) async {
await player!.startPlayer(
fromURI: uri,
codec: Codec.mp3,
whenFinished: () {
setState(() {});
});
setState(() {});
}
Future<void> stopPlayer(FlutterSoundPlayer player) async {
await player.stopPlayer();
}
Future<void> setVolume1(double v) async // v is between 0.0 and 100.0
{
v = v > 100.0 ? 100.0 : v;
_mVolume1 = v;
setState(() {});
//await _mPlayer!.setVolume(v / 100, fadeDuration: Duration(milliseconds: 5000));
await _mPlayer1.setVolume(
v / 100,
);
}
// --------------------- UI -------------------
Fn? getPlaybackFn(FlutterSoundPlayer? player, String uri) {
if (!(_mPlayerIsInited1)) {
return null;
}
return player!.isStopped
? () {
play(player, uri);
}
: () {
stopPlayer(player).then((value) => setState(() {}));
};
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
//return Column(
//children: [
return Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 150,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Column(children: [
Row(children: [
ElevatedButton(
onPressed: getPlaybackFn(_mPlayer1, _exampleAudioFilePathMP3_1),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer1.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer1.isPlaying
? 'Playback #1 in progress'
: 'Player #1 is stopped'),
]),
Text('Volume:'),
Slider(
value: _mVolume1,
min: 0.0,
max: 100.0,
onChanged: setVolume1,
divisions: 100),
]),
//),
//],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Volume Control'),
),
body: makeBody(),
);
}
}
Speed Control
💬 음원 재생 속도를 조절할 수 있는 앱
UI
코드
더보기
더보기
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart' show rootBundle;
const _boum = 'assets/samples/sample2.aac';
typedef Fn = void Function();
class SpeedControl extends StatefulWidget {
@override
_SpeedControlState createState() => _SpeedControlState();
}
class _SpeedControlState extends State<SpeedControl> {
final FlutterSoundPlayer _mPlayer = FlutterSoundPlayer();
bool _mPlayerIsInited = false;
double _mSpeed = 100.0;
Uint8List? _boumData;
@override
void initState() {
super.initState();
init().then((value) {
setState(() {
_mPlayerIsInited = true;
});
});
}
@override
void dispose() {
stopPlayer(_mPlayer);
// Be careful : you must `close` the audio session when you have finished with it.
_mPlayer.closePlayer();
super.dispose();
}
Future<void> init() async {
await _mPlayer.openPlayer();
await _mPlayer.setSpeed(
1.0); // This dummy instruction is MANDATORY on iOS, before the first `startRecorder()`.
_boumData = await getAssetData(_boum);
}
Future<Uint8List> getAssetData(String path) async {
var asset = await rootBundle.load(path);
return asset.buffer.asUint8List();
}
// ------- Here is the code to playback -----------------------
void play(FlutterSoundPlayer? player) async {
await player!.startPlayer(
fromDataBuffer: _boumData,
codec: Codec.aacADTS,
whenFinished: () {
setState(() {});
});
setState(() {});
}
Future<void> stopPlayer(FlutterSoundPlayer player) async {
await player.stopPlayer();
}
Future<void> setSpeed(double v) async // v is between 0.0 and 100.0
{
v = v > 200.0 ? 200.0 : v;
_mSpeed = v;
setState(() {});
await _mPlayer.setSpeed(
v / 100,
);
}
// --------------------- UI -------------------
Fn? getPlaybackFn(FlutterSoundPlayer? player) {
if (!_mPlayerIsInited) {
return null;
}
return player!.isStopped
? () {
play(player);
}
: () {
stopPlayer(player).then((value) => setState(() {}));
};
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
//return Column(
//children: [
return Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 140,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Column(children: [
Row(children: [
ElevatedButton(
onPressed: getPlaybackFn(_mPlayer),
//color: Colors.white,
//disabledColor: Colors.grey,
child: Text(_mPlayer.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer.isPlaying
? 'Playback #1 in progress'
: 'Player #1 is stopped'),
]),
Text('Speed:'),
Slider(
value: _mSpeed,
min: 0.0,
max: 200.0,
onChanged: setSpeed,
//divisions: 100
),
]),
//),
//],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Speed Control'),
),
body: makeBody(),
);
}
}
Seek
💬 음원 재생의 상대적 위치를 실시간으로 표시하며, 드래그를 통하여 음원 재생 위치를 변경할 수 있다.
UI
코드
더보기
더보기
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'dart:typed_data';
import 'package:flutter/services.dart' show rootBundle;
const _boum = 'assets/samples/sample2.aac';
const int duration = 42673;
typedef Fn = void Function();
class Seek extends StatefulWidget {
@override
_SeekState createState() => _SeekState();
}
class _SeekState extends State<Seek> {
final FlutterSoundPlayer _mPlayer = FlutterSoundPlayer();
bool _mPlayerIsInited = false;
Uint8List? _boumData;
StreamSubscription? _mPlayerSubscription;
int pos = 0;
@override
void initState() {
super.initState();
init().then((value) {
setState(() {
_mPlayerIsInited = true;
});
});
}
@override
void dispose() {
stopPlayer(_mPlayer);
cancelPlayerSubscriptions();
// Be careful : you must `close` the audio session when you have finished with it.
_mPlayer.closePlayer();
super.dispose();
}
void cancelPlayerSubscriptions() {
if (_mPlayerSubscription != null) {
_mPlayerSubscription!.cancel();
_mPlayerSubscription = null;
}
}
Future<void> init() async {
await _mPlayer.openPlayer();
await _mPlayer.setSubscriptionDuration(Duration(milliseconds: 50));
_boumData = await getAssetData(_boum);
_mPlayerSubscription = _mPlayer.onProgress!.listen((e) {
setPos(e.position.inMilliseconds);
setState(() {});
});
}
Future<Uint8List> getAssetData(String path) async {
var asset = await rootBundle.load(path);
return asset.buffer.asUint8List();
}
void play(FlutterSoundPlayer? player) async {
await player!.startPlayer(
fromDataBuffer: _boumData,
codec: Codec.aacADTS,
whenFinished: () {
setState(() {});
});
setState(() {});
}
Future<void> stopPlayer(FlutterSoundPlayer player) async {
await player.stopPlayer();
}
Future<void> setPos(int d) async {
if (d > duration) {
d = duration;
}
setState(() {
pos = d;
});
}
Future<void> seek(double d) async {
await _mPlayer.seekToPlayer(Duration(milliseconds: d.floor()));
await setPos(d.floor());
}
// --------------------- UI -------------------
Fn? getPlaybackFn(FlutterSoundPlayer? player) {
if (!_mPlayerIsInited) {
return null;
}
return player!.isStopped
? () {
play(player);
}
: () {
stopPlayer(player).then((value) => setState(() {}));
};
}
@override
Widget build(BuildContext context) {
Widget makeBody() {
//return Column(
//children: [
return Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(3),
height: 140,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFAF0E6),
border: Border.all(
color: Colors.indigo,
width: 3,
),
),
child: Column(children: [
Row(children: [
ElevatedButton(
onPressed: getPlaybackFn(_mPlayer),
child: Text(_mPlayer.isPlaying ? 'Stop' : 'Play'),
),
SizedBox(
width: 20,
),
Text(_mPlayer.isPlaying
? 'Playback in progress'
: 'Player is stopped'),
SizedBox(
width: 20,
),
Text('Pos: $pos'),
]),
Text('Position:'),
Slider(
value: pos + 0.0,
min: 0.0,
max: duration + 0.0,
onChanged: seek,
//divisions: 100
),
]),
//),
//],
);
}
return Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
title: const Text('Seek Player'),
),
body: makeBody(),
);
}
}
'Flutter > Package' 카테고리의 다른 글
[ Flutter ] [ Package ] flutter_zoom_drawer (0) | 2022.03.01 |
---|---|
[ Flutter ] [ Package ] curved_navigation_bar (0) | 2022.03.01 |
[ Flutter ] [ Package ] carousel_slider (0) | 2022.02.26 |