question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Operationg multiple flutter_sound instance independently

See original GitHub issue

Version of flutter_sound

flutter_sound: ^2.0.4

flutter doctor

[√] Flutter (Channel stable, v1.12.13+hotfix.8, on Microsoft Windows [Version 10.0.17763.1039], locale ja-JP)

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.3) [√] Android Studio (version 3.6) [√] VS Code, 64-bit edition (version 1.42.1) [√] Connected device (1 available)

Platforms you faced the error (IOS or Android or both?)

Tested on Android

Expected behavior

  1. Call only one onRecorderDbPeakChanged callback within the multiple FlutterSound instances.
  2. Able to stop any recorder one of them.

Actual behavior

  1. onRecorderDbPeakChanged for all FlutterSound instances.
  2. Can only control the recorder that started last.
Restarted application in 1,157ms.
D/FlutterSoundPlugin(11332): rawAmplitude: 0.0 Base DB: 0.0
I/flutter (11332): startRecorder: /data/user/0/com.dooboolab.fluttersoundexample/cache/file_dbLevel_disable.aac
D/FlutterSoundPlugin(11332): rawAmplitude: 0.0 Base DB: 0.0
I/flutter (11332):
I/flutter (11332): got dB update of  file_dbLevel_disable -> 0.0
I/flutter (11332): 	2020-03-04T15:24:33.141111
I/flutter (11332): startRecorder: /data/user/0/com.dooboolab.fluttersoundexample/cache/file_dbLevel_enable.aac
D/FlutterSoundPlugin(11332): rawAmplitude: 1410.0 Base DB: 42.67625931342095
I/flutter (11332):
I/flutter (11332): got dB update of  file_dbLevel_disable -> 42.67625931342095
I/flutter (11332): 	2020-03-04T15:24:34.111216
I/flutter (11332):
I/flutter (11332): got dB update of  file_dbLevel_enable -> 42.67625931342095
I/flutter (11332): 	2020-03-04T15:24:34.111296
D/FlutterSoundPlugin(11332): rawAmplitude: 1175.0 Base DB: 41.09263439246845
I/flutter (11332):
I/flutter (11332): got dB update of  file_dbLevel_disable -> 41.09263439246845
I/flutter (11332): 	2020-03-04T15:24:35.112086
I/flutter (11332):
I/flutter (11332): got dB update of  file_dbLevel_enable -> 41.09263439246845
I/flutter (11332): 	2020-03-04T15:24:35.112165
I/flutter (11332): STOP!!!
I/flutter (11332): stopRecorder: /data/user/0/com.dooboolab.fluttersoundexample/cache/file_dbLevel_enable.aac

Tested environment (Emulator? Real Device?)

  • Android API 29 (Emulator)

Steps to reproduce the behavior

  1. l.29 Declare two instances with FlutterSound member.

    • One of them is set to flutterSound.setDbLevelEnabled(false), another is flutterSound.setDbLevelEnabled(true).
  2. l.39 Execute flutterSound.startRecorder against both instance.

    • The order of execution is ‘setDbLevelEnabled(false) one’ -> ‘setDbLevelEnabled(true) one’ .
  3. Result of two onRecorderDbPeakChanged callback are shown.

  4. l.57 Call flutterSound.stopRecorder() of the dBLevel Disabled instance.

  5. flutterSound.stopRecorder() of the dBLevel Enabled instance is called.

    • The audio recorder in FlutterSound is overwritten?
  6. Exception has occurred due to _recorderSubscription of the dBLevel Enabled instance called against null recorder.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'package:intl/date_symbol_data_local.dart';
import 'dart:async';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart' show getTemporaryDirectory;

void main() async {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var recorder_dbLevel_disable = AudioRecorder(isEnableDbPeak: false); //iInstance DbLevel Disabled
  var recorder_dbLevel_enable = AudioRecorder(isEnableDbPeak: true); //Instance DbLevel Enabled

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    recorder_dbLevel_disable.startRecorder(fileName: "file_dbLevel_disable"); //Start recording from  DbLevel Disabled instance
    recorder_dbLevel_enable.startRecorder(fileName: "file_dbLevel_enable");
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('App Name'),
      ),
      floatingActionButton: new FloatingActionButton(
          child: new Icon(Icons.add_circle), onPressed: fabPressed),
    );
  }

  void fabPressed() {
    print("STOP!!!");
    recorder_dbLevel_disable.stopRecorder();
  }
}

class AudioRecorder {
  StreamSubscription _dbPeakSubscription;
  StreamSubscription _recorderSubscription;
  FlutterSound flutterSound;

  t_CODEC _codec = t_CODEC.CODEC_AAC;

  AudioRecorder({bool isEnableDbPeak}) {
    flutterSound = new FlutterSound();
    flutterSound.setDbPeakLevelUpdate(1.0);
    flutterSound.setDbLevelEnabled(isEnableDbPeak);
    flutterSound.setSubscriptionDuration(1.0);
    initializeDateFormatting();
  }

  void startRecorder({String fileName}) async {
    try {
      Directory tempDir = await getTemporaryDirectory();

      String path = await flutterSound.startRecorder(
        uri: '${tempDir.path}/' + fileName + '.aac',
        codec: _codec,
      );
      print('startRecorder: $path');

      _dbPeakSubscription =
          flutterSound.onRecorderDbPeakChanged.listen((value) {
        print("\ngot dB update of  "+ fileName +" -> $value");
        print("\t" + DateTime.now().toIso8601String());
      });

      _recorderSubscription = flutterSound.onRecorderStateChanged.listen((e) {
      DateTime date = new DateTime.fromMillisecondsSinceEpoch(
          e.currentPosition.toInt(),
          isUtc: true);
      String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);

      //print(fileName + ":" + txt);
    });
    } catch (err) {
      print('startRecorder error: $err');
    }
  }

  void stopRecorder() async {
    try {
      String result = await flutterSound.stopRecorder();
      print('stopRecorder: $result');

      if (_dbPeakSubscription != null) {
        _dbPeakSubscription.cancel();
        _dbPeakSubscription = null;
      }
      if ( _recorderSubscription != null ) {
        _recorderSubscription.cancel ();
        _recorderSubscription = null;
      }
    } catch (err) {
      print('stopRecorder error: $err');
    }
  }
}


It seems that onRecorderDbPeakChanged is excused against all FlutterSound instances, because of _dbPeakController is static. I avoid this problem by changing _dbPeakController to non-static (I’m not sure this solution is safe or not… ). However I have not resolved ‘recorder overwritten problem’ yet.

Is there any reason FlutterSound does not support the multiple audio recording?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:5

github_iconTop GitHub Comments

1reaction
Larpouxcommented, Mar 29, 2020

PR #257 is a major re-design of flutter_sound architecture. flutter_sound module is now split into :

  • FlautoRecorder
  • FlautoPlayer All modules are re-entrant. It is possible to start several FlautoPlayer and several FlautoRecorder at the same time.

Complete backward compatibility is provided by two deprecated modules :

  • FlutterSound.dart
  • Flauto.dart

@kiha-la : This PR is still in beta-version, and is still not merged in Flutter-Sound Master branch. In the meantime, it will be great if you can test it.

1reaction
Larpouxcommented, Mar 15, 2020

The new flutter_sound version has two different modules:

  • The legacy flutter_sound with some improvments like some tools to control the Audio-focus
  • Flauto, wich adds @salvatore373 improvements .

Those two modules are completely separated. This has two benefits:

  • Separated functionalities means easier maintenance
  • The legacy flutter_sound module is totally backward compatible

My project would be to split again the legacy flutter_sound module into two different modules :

  • FlutterSoundRecorder
  • FlutterSoundPlayer Those two functionalities are not related together, and there is no reason to have just one module. Having two smaller modules will let the maintenance easier.

For having backward compatibility, the FlutterSoundPlayer module will be called simply FlutterSound and will inherit from flutterSoundRecorder. But new developer will be encouraged to use the FlutterSoundRecorder module for recording.

Then, we will have three modules :

  • Flauto (which inherit from `FlutterSoundPlayer)
  • FlutterSoundPlayer (which inherit from FlutterSoundRecorder for backward compatibility)
  • FlutterSoundRecorder

Then, I think it will be easier to address #232 (which has been closed by its creator, but for me this issue is still valid and interesting).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Operationg multiple flutter_sound instance independently #232
The new flutter_sound version has two different modules: The legacy flutter_sound with some improvments like some tools to control the Audio- ...
Read more >
Flutter: AudioPlayers how to stop multiple sounds at once?
I guess The problem is, that every time i call _playFile() (press Button 1) a new instance of AudioPlayer is assigned to the...
Read more >
Background audio in Flutter with Audio Service and Just Audio
The Flutter audio_service plugin solves the problems described above by allowing users to listen to audio outside of the app and also by...
Read more >
Multithreading in Flutter using Dart isolates - LogRocket Blog
Learn how to leverage multithreading in Flutter with Dart isolates for ... An isolate is meant to run independently of other isolates.
Read more >
FAQ - Flutter documentation
What operating systems can I use to build a Flutter app? What language is Flutter written in? Why did Flutter choose to use...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found