Grabación y reproducción de flutter-flutter_sound

Introducción al complemento:

flutter_soundEste complemento puede realizar iOS和Androidlas funciones de grabación y reproducción de la plataforma. Es decir, puede reproducir archivos de audio locales y archivos URL remotos. Aquí presentaré el uso de este complemento y cómo resolver algunos problemas comunes encontrados.

  • flutter_sound admite múltiples formatos de grabación

  • flutter_sound admite múltiples formatos de reproducción

  • flutter_sound admite tamaño de amplitud de audio

Información del complemento:

Dirección del complemento: github.com/ryanheise/a…

Versión del complemento: 9.2.9

Preparación antes de usar el plugin

Establecer descripción de permiso de micrófono

  • iOS: debe agregar permisos al archivo info.plist
<key>NSMicrophoneUsageDescription</key>
<string>描述你使用麦克风用来干嘛</string>
复制代码

Captura de pantalla 2022-04-23 3.09.07 pm.png

注意:还需要在Podfile文件中配置

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  target.build_configurations.each do |config|

        config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
          '$(inherited)',
          ## dart: PermissionGroup.microphone
          'PERMISSION_MICROPHONE=1',
        ]
      end
    end
  end
复制代码

También necesita agregar una libc++.tbdbiblioteca al proyecto iOS, la ruta específica

Captura de pantalla 2022-05-14 17.05.47.png

  • Android: requiere configuraciónAndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
复制代码

Captura de pantalla 2022-04-23 3.11.31 pm.png

Los siguientes complementos también se utilizan aquí

Complemento de administración de permisos allow_handler

Información del complemento:permission_handler: ^9.2.0

Dirección del complemento: pub.flutter-io.cn/packages/pe…

Complemento de configuración de hardware de audio audio_session

Información del complemento:audio_session: ^0.1.6

Dirección del complemento: github.com/ryanheise/a…

complemento de animación

Información del complemento:lottie: 1.2.1

Dirección del complemento: pub.flutter-io.cn/packages/fl...

Métodos comúnmente utilizados

Métodos comunes de grabación

Inicializar el objeto de grabación

FlutterSoundRecorder recorderModule = FlutterSoundRecorder();
复制代码

activar la grabación

Future<void> init() async {
  //开启录音
  await recorderModule.openRecorder();
  //设置订阅计时器
  await recorderModule
      .setSubscriptionDuration(const Duration(milliseconds: 10));
  //初始化日期插件
  await initializeDateFormatting();
}
复制代码

Permisos de micrófono

Future<bool> getPermissionStatus() async {
  Permission permission = Permission.microphone;
  //granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示
  PermissionStatus status = await permission.status;
  if (status.isGranted) {
    return true;
  } else if (status.isDenied) {
    requestPermission(permission);
  } else if (status.isPermanentlyDenied) {
    openAppSettings();
  } else if (status.isRestricted) {
    requestPermission(permission);
  } else {}
  return false;
}

///申请权限
void requestPermission(Permission permission) async {
  PermissionStatus status = await permission.request();
  if (status.isPermanentlyDenied) {
    openAppSettings();
  }
}
复制代码

empezar a grabar

/// 开始录音
_startRecorder() async {
  try {
    //获取麦克风权限
    await getPermissionStatus().then((value) async {
      if (!value) {
        return;
      }
      //用户允许使用麦克风之后开始录音
      Directory tempDir = await getTemporaryDirectory();
      var time = DateTime.now().millisecondsSinceEpoch;
      String path = '${tempDir.path}/$time${ext[Codec.aacADTS.index]}';
      
      //这里我录制的是aac格式的,还有其他格式
      await recorderModule.startRecorder(
        toFile: path,
        codec: Codec.aacADTS,
        bitRate: 8000,
        numChannels: 1,
        sampleRate: 8000,
      );

      /// 监听录音
      _recorderSubscription = recorderModule.onProgress!.listen((e) {
        var date = DateTime.fromMillisecondsSinceEpoch(
            e.duration.inMilliseconds,
            isUtc: true);
        var txt = DateFormat('mm:ss:SS', 'en_GB').format(date);
        //设置了最大录音时长
        if (date.second >= _maxLength) {
          _stopRecorder();
          return;
        }
        setState(() {
          //更新录音时长
          _recordText = txt.substring(1, 5);
        });
      });
      setState(() {
         //更新录音状态和录音文件路径
        _state = RecordPlayState.recording;
        _path = path;
      });
    });
  } catch (err) {
    setState(() {
      _stopRecorder();
      _state = RecordPlayState.record;
      _cancelRecorderSubscriptions();
    });
  }
}
复制代码

finalizar grabación

/// 结束录音
_stopRecorder() async {
  try {
    await recorderModule.stopRecorder();
    _cancelRecorderSubscriptions();
    // _getDuration();
  } catch (err) {}
  setState(() {
    _state = RecordPlayState.record;
  });
}

///销毁录音
void dispose() {
  super.dispose();
  _cancelRecorderSubscriptions();
  _releaseFlauto();
}

/// 取消录音监听
void _cancelRecorderSubscriptions() {
  if (_recorderSubscription != null) {
    _recorderSubscription!.cancel();
    _recorderSubscription = null;
  }
}

/// 释放录音
Future<void> _releaseFlauto() async {
  try {
    await recorderModule.closeRecorder();
  } catch (e) {}
}

/// 判断文件是否存在
Future<bool> _fileExists(String path) async {
  return await File(path).exists();
}
复制代码

Reproducir métodos comunes

Inicializar el reproductor

FlutterSoundPlayer playerModule = FlutterSoundPlayer();
复制代码

operación de inicialización

init() async {
  await playerModule.closePlayer();
  await playerModule.openPlayer();
  await playerModule
      .setSubscriptionDuration(const Duration(milliseconds: 10));

//这块是设置音频,暂时没用到可以不用设置
  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,
  ));
}
复制代码

empezar a jugar

///开始播放,这里做了一个播放状态的回调
void startPlayer(PlayStateBack callBack) async {
  try {
    if (path.contains('http')) {
      await playerModule.startPlayer(
          fromURI: path,
          codec: Codec.mp3,
          sampleRate: 44000,
          whenFinished: () {
            stopPlayer();
            callBack(0);
          });
    } else {
      //判断文件是否存在
      if (await _fileExists(path)) {
        if (playerModule.isPlaying) {
          playerModule.stopPlayer();
        }
        await playerModule.startPlayer(
            fromURI: path,
            codec: Codec.aacADTS,
            sampleRate: 44000,
            whenFinished: () {
              stopPlayer();
              callBack(0);
            });
      } else {}
    }

    //监听播放进度
    _playerSubscription = playerModule.onProgress!.listen((e) {});
    callBack(1);
  } catch (err) {
    callBack(0);
  }
}
复制代码

finalizar reproducción

/// 结束播放
void stopPlayer() async {
  try {
    await playerModule.stopPlayer();
    cancelPlayerSubscriptions();
  } catch (err) {}
}

/// 取消播放监听
void cancelPlayerSubscriptions() {
  if (_playerSubscription != null) {
    _playerSubscription!.cancel();
    _playerSubscription = null;
  }
}

///获取播放状态
Future<PlayerState> getPlayState() async {
  return await playerModule.getPlayerState();
}

/// 释放播放器
void releaseFlauto() async {
  try {
    await playerModule.closePlayer();
  } catch (e) {
    print(e);
  }
}

/// 判断文件是否存在
Future<bool> _fileExists(String path) async {
  return await File(path).exists();
}
复制代码

Implementación de animación

En el proceso de grabación y reproducción es inevitable utilizar animación, aquí te diré cómo cargarla.gif和动画文件

Cargando gifs animados

Visibility(
  visible: (item.playing.value == 1) ? true : false,
  child: Image.asset('assets/-comm/comm_audio_paly.gif', width: 20, height: 20,),
  replacement: const Image(
    image: AssetImage('assets/-comm/comm_audio_icon.png'),
    width: 20,
    height: 20,
  ),
)
复制代码

Cargar archivo de animación

Lottie.asset('assets/-comm/record_audio_animation.json',
    height: 25,
    width: ScreenAdapter.screenWidth() -ScreenAdapter.width(160),
    animate: true)
复制代码

subir archivos

Subir archivos de audio

var map = {
  "file": MultipartFile.fromBytes(
      await File.fromUri(Uri(path: path)).readAsBytes(),
      filename: "$fileName.mp3",
      contentType: MediaType.parse("audio/mp3"))
};
复制代码

Resumir

Lo anterior describe cómo grabar, cómo reproducir archivos de audio locales y remotos, cómo implementar animaciones y cómo cargar archivos de audio después de la grabación Estos son los problemas que generalmente encontramos al usar esta función. También se enumeran los problemas encontrados en el proceso de uso, espero poder ayudarlo.

Supongo que te gusta

Origin juejin.im/post/7098131435273322526
Recomendado
Clasificación