flutter_sound

官方介绍:这个插件为android和ios平台提供了简单的记录器和播放器功能。这只支持每个平台的默认文件扩展名。这个插件处理来自远程url的文件。这个插件可以处理本地播放流(通过桥接来同步准确的时间)。

插件网址:https://pub.dev/packages/flutter_sound

安装

在pubspec.yaml添加依赖

dependencies:

...

flutter_sound: ^1.1.5

接着在控制台运行flutter packages get获取依赖,最重要一点需要在AndroidManifest.xml文件中添加,权限请求

代码(copy 官方)

期间出现的插件,请自行安装,方法同上

import 'package:flutter/material.dart';

import 'package:intl/intl.dart' show DateFormat;

import 'package:intl/date_symbol_data_local.dart';

import 'dart:io';

import 'dart:async';

import 'package:flutter_sound/flutter_sound.dart';

import 'package:flutter_sound/android_encoder.dart';

import 'dart:convert';

class RecorderPage extends StatelessWidget {

const RecorderPage({Key key}) : super(key: key);

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("音频录制页面"),

),

body: RecorderContent(),

);

}

}

class RecorderContent extends StatefulWidget {

RecorderContent({Key key}) : super(key: key);

_RecorderContentState createState() => _RecorderContentState();

}

class _RecorderContentState extends State{

bool _isRecording = false;

bool _isPlaying = false;

StreamSubscription _recorderSubscription;

StreamSubscription _dbPeakSubscription;

StreamSubscription _playerSubscription;

FlutterSound flutterSound;

String _recorderTxt = '00:00:00';

String _playerTxt = '00:00:00';

double _dbLevel;

double slider_current_position = 0.0;

double max_duration = 1.0;

@override

void initState() {

super.initState();

flutterSound = new FlutterSound();

flutterSound.setSubscriptionDuration(0.01);

flutterSound.setDbPeakLevelUpdate(0.8);

flutterSound.setDbLevelEnabled(true);

initializeDateFormatting();

}

void startRecorder() async {

try {

String path = await flutterSound.startRecorder(null);

print("数据$path");

_recorderSubscription = flutterSound.onRecorderStateChanged.listen((e) {

DateTime date = new DateTime.fromMillisecondsSinceEpoch(

e.currentPosition.toInt(),

isUtc: true);

// print("时长$date");

String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);

this.setState(() {

this._recorderTxt = txt.substring(0, 8);

});

});

// _dbPeakSubscription =

// flutterSound.onRecorderDbPeakChanged.listen((value) {

// print("got update -> $value");

// setState(() {

// this._dbLevel = value;

// });

// });

this.setState(() {

this._isRecording = true;

});

} catch (err) {

print('startRecorder error: $err');

}

}

void stopRecorder() async {

try {

String result = await flutterSound.stopRecorder();

print('停止录音返回结果: $result');

if (_recorderSubscription != null) {

_recorderSubscription.cancel();

_recorderSubscription = null;

}

if (_dbPeakSubscription != null) {

_dbPeakSubscription.cancel();

_dbPeakSubscription = null;

}

this.setState(() {

this._isRecording = false;

});

} catch (err) {

print('stopRecorder error: $err');

}

}

void startPlayer() async {

String path = await flutterSound.startPlayer(null);

File file= await new File(path);

List contents = await file.readAsBytesSync();

// return print("file文件:$contents");

await flutterSound.setVolume(1.0);

print('startPlayer: $path');

try {

_playerSubscription = flutterSound.onPlayerStateChanged.listen((e) {

if (e != null) {

slider_current_position = e.currentPosition;

max_duration = e.duration;

DateTime date = new DateTime.fromMillisecondsSinceEpoch(

e.currentPosition.toInt(),

isUtc: true);

String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);

this.setState(() {

this._isPlaying = true;

this._playerTxt = txt.substring(0, 8);

});

}

});

} catch (err) {

print('error: $err');

}

}

void stopPlayer() async {

try {

String result = await flutterSound.stopPlayer();

print('stopPlayer: $result');

if (_playerSubscription != null) {

_playerSubscription.cancel();

_playerSubscription = null;

}

this.setState(() {

this._isPlaying = false;

});

} catch (err) {

print('error: $err');

}

}

void pausePlayer() async {

String result = await flutterSound.pausePlayer();

print('pausePlayer: $result');

}

void resumePlayer() async {

String result = await flutterSound.resumePlayer();

print('resumePlayer: $result');

}

void seekToPlayer(int milliSecs) async {

String result = await flutterSound.seekToPlayer(milliSecs);

print('seekToPlayer: $result');

}

@override

Widget build(BuildContext context) {

return Container(

child: ListView(

children: [

Column(

crossAxisAlignment: CrossAxisAlignment.center,

mainAxisAlignment: MainAxisAlignment.center,

children: [

Container(

margin: EdgeInsets.only(top: 24.0, bottom: 16.0),

child: Text(

this._recorderTxt,

style: TextStyle(

fontSize: 48.0,

color: Colors.black,

),

),

),

_isRecording

? LinearProgressIndicator(

value: 100.0 / 160.0 * (this._dbLevel ?? 1) / 100,

valueColor: AlwaysStoppedAnimation(Colors.green),

backgroundColor: Colors.red,

)

: Container()

],

),

Row(

children: [

Container(

width: 56.0,

height: 56.0,

child: ClipOval(

child: FlatButton(

onPressed: () {

if (!this._isRecording) {

return this.startRecorder();

}

this.stopRecorder();

},

padding: EdgeInsets.all(8.0),

child: this._isRecording ? Text("停止") : Text("开始录音")),

),

),

],

mainAxisAlignment: MainAxisAlignment.center,

crossAxisAlignment: CrossAxisAlignment.center,

),

Column(

crossAxisAlignment: CrossAxisAlignment.center,

mainAxisAlignment: MainAxisAlignment.center,

children: [

Container(

margin: EdgeInsets.only(top: 60.0, bottom: 16.0),

child: Text(

this._playerTxt,

style: TextStyle(

fontSize: 48.0,

color: Colors.black,

),

),

),

],

),

Row(

children: [

Container(

width: 56.0,

height: 56.0,

child: ClipOval(

child: FlatButton(

onPressed: () {

startPlayer();

},

padding: EdgeInsets.all(8.0),

child: Text("开始"),

),

),

),

Container(

width: 56.0,

height: 56.0,

child: ClipOval(

child: FlatButton(

onPressed: () {

pausePlayer();

},

padding: EdgeInsets.all(8.0),

child: Text("暂停"),

),

),

),

Container(

width: 56.0,

height: 56.0,

child: ClipOval(

child: FlatButton(

onPressed: () {

stopPlayer();

},

padding: EdgeInsets.all(8.0),

child: Text("停止"),

),

),

),

],

mainAxisAlignment: MainAxisAlignment.center,

crossAxisAlignment: CrossAxisAlignment.center,

),

Container(

height: 56.0,

child: Slider(

value: slider_current_position,

min: 0.0,

max: max_duration,

onChanged: (double value) async {

await flutterSound.seekToPlayer(value.toInt());

},

divisions: max_duration.toInt()))

],

));

}

}

音频录制出现音质很差的问题

在出现这个问题的时候,经过一系列的排查,这行代码出现的问题

void startRecorder() async {

try {

String path = await flutterSound.startRecorder(null);

print("数据$path");

_recorderSubscription = flutterSound.onRecorderStateChanged.listen((e) {

DateTime date = new DateTime.fromMillisecondsSinceEpoch(

e.currentPosition.toInt(),

isUtc: true);

// print("时长$date");

String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);

this.setState(() {

this._recorderTxt = txt.substring(0, 8);

});

});

// _dbPeakSubscription =

// flutterSound.onRecorderDbPeakChanged.listen((value) {

// print("got update -> $value");

// setState(() {

// this._dbLevel = value;

// });

// });

this.setState(() {

this._isRecording = true;

});

} catch (err) {

print('startRecorder error: $err');

}

}

通过查看它的的参数源码

FuturestartRecorder(String uri,

{int sampleRate = 44100, int numChannels = 2, int bitRate,

AndroidEncoder androidEncoder = AndroidEncoder.AAC,

IosQuality iosQuality = IosQuality.LOW

}) async {

try {

...

有一个bitRate的参数,这个要设置,会改变这个录制的音质

我的这个加的320000

String path = await flutterSound.startRecorder(null,bitRate:320000);

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐