我正在测试audio_service和flutter_sound,尝试同时使用它们。我的目标是停止背景中的音频并开始录制声音,然后在第二次点击时停止录制并开始声音。
我没有做到这一点,也没有单独使用它们(下面的代码)。最初,录音有效,但是在播放流之后,录音不再起作用。据我所知,我猜我必须在演奏完毕后启动flutter_sound,因为它会阻塞它,但我不知道该怎么做。有人可以向我解释为什么会这样以及如何解决吗?
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter_sound/android_encoder.dart';
MediaControl playControl = MediaControl(
androidIcon: 'drawable/ic_action_play_arrow',
label: 'Play',
action: MediaAction.play,
);
MediaControl pauseControl = MediaControl(
androidIcon: 'drawable/ic_action_pause',
label: 'Pause',
action: MediaAction.pause,
);
MediaControl stopControl = MediaControl(
androidIcon: 'drawable/ic_action_stop',
label: 'Stop',
action: MediaAction.stop,
);
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
bool _isRecording = false;
FlutterSound flutterSound;
PlaybackState _state;
StreamSubscription _playbackStateSubscription;
@override
void initState() {
super.initState();
flutterSound = new FlutterSound();
flutterSound.setSubscriptionDuration(0.01);
flutterSound.setDbPeakLevelUpdate(0.8);
flutterSound.setDbLevelEnabled(true);
WidgetsBinding.instance.addObserver(this);
connect();
}
@override
void dispose() {
disconnect();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
connect();
break;
case AppLifecycleState.paused:
disconnect();
break;
default:
break;
}
}
void connect() async {
await AudioService.connect();
if (_playbackStateSubscription == null) {
_playbackStateSubscription = AudioService.playbackStateStream
.listen((PlaybackState playbackState) {
setState(() {
_state = playbackState;
});
});
}
}
void disconnect() {
if (_playbackStateSubscription != null) {
_playbackStateSubscription.cancel();
_playbackStateSubscription = null;
}
AudioService.disconnect();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Audio Service Proba'),
),
body: new Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
audioPlayerButton(),
playButton(),
pauseButton(),
stopButton(),
],
),
SizedBox(
height: 40,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(
Icons.mic,
size: 30,
),
onPressed: () {
start_record();
}),
RaisedButton(
child: Icon(
Icons.stop,
size: 30,
),
onPressed: () {
stop_record();
})
],
),
],
),
),
),
);
}
start_record() async {
try {
String path = await flutterSound.startRecorder(
null,
androidEncoder: AndroidEncoder.AAC,
bitRate: 128000,
sampleRate: 96000,
);
print('startRecorder: $path');
this.setState(() {
this._isRecording = true;
});
} catch (err) {
print('startRecorder error: $err');
}
}
stop_record() async {
try {
String result = await flutterSound.stopRecorder();
print('stopRecorder: $result');
this.setState(() {
this._isRecording = false;
});
} catch (err) {
print('stopRecorder error: $err');
}
}
}
RaisedButton audioPlayerButton() =>
startButton('AudioPlayer', _backgroundAudioPlayerTask);
RaisedButton startButton(String label, Function backgroundTask) => RaisedButton(
child: Text(label),
onPressed: () {
AudioService.start(
backgroundTask: backgroundTask,
resumeOnClick: true,
androidNotificationChannelName: 'Audio Service Demo',
notificationColor: 0xFF2196f3,
androidNotificationIcon: 'mipmap/ic_launcher',
);
},
);
IconButton playButton() => IconButton(
icon: Icon(Icons.play_arrow),
iconSize: 40.0,
onPressed: AudioService.play,
);
IconButton pauseButton() => IconButton(
icon: Icon(Icons.pause),
iconSize: 40.0,
onPressed: AudioService.pause,
);
IconButton stopButton() => IconButton(
icon: Icon(Icons.stop),
iconSize: 40.0,
onPressed: AudioService.stop,
);
void _backgroundAudioPlayerTask() async {
CustomAudioPlayer player = CustomAudioPlayer();
AudioServiceBackground.run(
onStart: player.run,
onPlay: player.play,
onPause: player.pause,
onStop: player.stop,
onClick: (MediaButton button) => player.playPause(),
);
}
class CustomAudioPlayer {
static const streamUri = "http://traffic.libsyn.com/joeroganexp/p1300.mp3";
AudioPlayer _audioPlayer = new AudioPlayer();
Completer _completer = Completer();
Future<void> run() async {
MediaItem mediaItem = MediaItem(
id: 'audio_1',
album: 'Sample Album',
title: 'Sample Title',
artist: 'Sample Artist');
AudioServiceBackground.setMediaItem(mediaItem);
var playerStateSubscription = _audioPlayer.onPlayerStateChanged
.where((state) => state == AudioPlayerState.COMPLETED)
.listen((state) {
stop();
});
play();
await _completer.future;
playerStateSubscription.cancel();
}
void playPause() {
if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing) {
pause();
//start_record();
} else {
play();
//stop_record();
}
}
void play() {
_audioPlayer.play(streamUri);
AudioServiceBackground.setState(
controls: [pauseControl, stopControl],
basicState: BasicPlaybackState.playing,
);
}
void pause() {
_audioPlayer.pause();
AudioServiceBackground.setState(
controls: [playControl, stopControl],
basicState: BasicPlaybackState.paused,
);
}
void stop() {
_audioPlayer.stop();
AudioServiceBackground.setState(
controls: [],
basicState: BasicPlaybackState.stopped,
);
_completer.complete();
}
}