bsutton / sounds

Flutter plugin for sound. Audio recorder and player.
GNU Lesser General Public License v3.0
78 stars 25 forks source link

[BUG] SoundRecorder stopes when playing asset with SoundPlayer at the same time #59

Closed diegogarciar closed 3 years ago

diegogarciar commented 3 years ago

Sounds Version :


Severity


Platforms you faced the error


Logs

starting ProgressTimer interval:0.800000 2021-01-09 14:46:04.501054-0700 Runner[3810:1561402] setProgressInterval called interval:0.100000 2021-01-09 14:46:04.968316-0700 Runner[3810:1561402] starting ProgressTimer interval:0.100000 2021-01-09 14:46:04.968397-0700 Runner[3810:1561402] started ProgressTimer 2021-01-09 14:46:05.069459-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:05.069798-0700 Runner[3810:1561402] sending updateProgress: {"duration": "381.1337868480726", "current_position": "57.18820861678005"} 2021-01-09 14:46:05.169471-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:05.169776-0700 Runner[3810:1561402] sending updateProgress: {"duration": "381.1337868480726", "current_position": "157.1655328798186"} 2021-01-09 14:46:05.269253-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:05.269494-0700 Runner[3810:1561402] sending updateProgress: {"duration": "381.1337868480726", "current_position": "256.8934240362812"} 2021-01-09 14:46:05.299052-0700 Runner[3810:1561402] updateProgress: {"current_position": "816.5625", "decibels":"23.187123"} 2021-01-09 14:46:05.369524-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:05.370126-0700 Runner[3810:1561402] sending updateProgress: {"duration": "381.1337868480726", "current_position": "357.4149659863946"} 2021-01-09 14:46:05.400350-0700 Runner[3810:1561402] audioPlayerDidFinishPlaying 2021-01-09 14:46:05.400759-0700 Runner[3810:1561402] stopping ProgressTimer 2021-01-09 14:46:05.457127-0700 Runner[3810:1561609] flutter: chat conversationScreen _scheduleSetSeen 2021-01-09 14:46:06.089833-0700 Runner[3810:1561402] [avas] AVAudioSession_iOS.mm:1149 Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session. 2021-01-09 14:46:06.098291-0700 Runner[3810:1561402] updateProgress: {"current_position": "1442.4375", "decibels":"11.733077"} 2021-01-09 14:46:06.456124-0700 Runner[3810:1561609] flutter: chat conversationScreen _scheduleSetSeen 2021-01-09 14:46:06.898842-0700 Runner[3810:1561402] updateProgress: {"current_position": "1442.4375", "decibels":"11.733077"} 2021-01-09 14:46:07.458808-0700 Runner[3810:1561609] flutter: chat conversationScreen _scheduleSetSeen 2021-01-09 14:46:07.697862-0700 Runner[3810:1561402] updateProgress: {"current_position": "1442.4375", "decibels":"11.733077"} 2021-01-09 14:46:08.460349-0700 Runner[3810:1561609] flutter: chat conversationScreen _scheduleSetSeen 2021-01-09 14:46:08.498798-0700 Runner[3810:1561402] updateProgress: {"current_position": "1442.4375", "decibels":"11.733077"} 2021-01-09 14:46:08.849750-0700 Runner[3810:1561609] flutter: onComplete 2021-01-09 14:46:08.862511-0700 Runner[3810:1561609] flutter: ending recording 2021-01-09 14:46:08.862743-0700 Runner[3810:1561609] flutter: stopRecorder save true duration: 4 2021-01-09 14:46:08.862818-0700 Runner[3810:1561609] flutter: 4 2021-01-09 14:46:09.086798-0700 Runner[3810:1561402] starting ProgressTimer interval:0.100000 2021-01-09 14:46:09.086887-0700 Runner[3810:1561402] started ProgressTimer 2021-01-09 14:46:09.187941-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:09.188329-0700 Runner[3810:1561402] sending updateProgress: {"duration": "420.125", "current_position": "58.8125"} 2021-01-09 14:46:09.288007-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:09.288461-0700 Runner[3810:1561402] sending updateProgress: {"duration": "420.125", "current_position": "158.875"} 2021-01-09 14:46:09.380888-0700 Runner[3810:1561609] flutter: chat conversationScreen _scheduleSetSeen 2021-01-09 14:46:09.387035-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:09.387322-0700 Runner[3810:1561402] sending updateProgress: {"duration": "420.125", "current_position": "257.84375"} 2021-01-09 14:46:09.488004-0700 Runner[3810:1561402] entered updateProgress 2021-01-09 14:46:09.488299-0700 Runner[3810:1561402] sending updateProgress: {"duration": "420.125", "current_position": "358.78125"} 2021-01-09 14:46:09.559103-0700 Runner[3810:1561402] audioPlayerDidFinishPlaying 2021-01-09 14:46:09.559250-0700 Runner[3810:1561402] stopping ProgressTimer 2021-01-09 14:46:10.374906-0700 Runner[3810:1561634] BackgroundSession <00AC9947-A361-4FCA-8255-2C93A76A022F> connection to background transfer daemon invalidated


flutter doctor :

[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-MX)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 12.3) [✓] Android Studio (version 4.1) [✓] VS Code (version 1.52.1) [✓] Connected device (4 available)

flutter pub deps :


Describe the bug I am using this package for a chat messages, I also want to play a sound when the recording starts. But when I play the recording, the soundrecorder stops recording.

To Reproduce

  1. Start recording
  2. Play small asset audio
  3. Record for a longer time that the player audio
  4. Stop recording
  5. see recorded length

Expected behavior Recorder should still record after audio file is played


Additional context**

This is my recorder

class VoiceRecorder extends ChangeNotifier {
  SoundRecorder _mRecorder = SoundRecorder();

  String _mPath;

  File get audioFile => File(_mPath);

  VoiceRecorder() {
    _mPath = Track.tempFile(WellKnownMediaFormats.adtsAac);
    print("open recorder");

    // openTheRecorder();
  }
  var duration = 0;
  var isRecording = false;

  Timer timer;

  startRecording() async {
    // assert(_mPlayer.isStopped);

    final track =
        Track.fromFile(_mPath, mediaFormat: WellKnownMediaFormats.adtsAac);
    resetTimer();
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      duration += 1;
      notifyListeners();
    });

    _mRecorder.record(track);
    // MyPlayer.SoundPlayer.playSound(MyPlayer.SoundEffect.Start);
    playSoundEffect(SoundEffect.Start);
    isRecording = true;
    notifyListeners();
  }

  String get recordedSeconds {
    final minutes = duration / 60 % 60;
    final seconds = duration % 60;
    return "${minutes.toInt()}:${seconds.toString().padLeft(2, "0")}";
  }

  Future<bool> stopRecorder(bool save) async {
    var shouldSave = false;

    try {
      await _mRecorder.stop();
      if (save && duration > 1) {
        print("ending recording");
        playSoundEffect(SoundEffect.End);
        shouldSave = true;
      } else {
        print("canceling recording");
        playSoundEffect(SoundEffect.Error);
      }
    } on Object catch (err) {
      print('stopRecorder error: $err');
      playSoundEffect(SoundEffect.Error);
    }
    timer?.cancel();
    isRecording = false;
    notifyListeners();
    print("stopRecorder save $save duration: $duration");
    return shouldSave;
  }

  resetTimer() {
    timer?.cancel();
    duration = 0;
  }

  var player = SoundPlayer.noUI();
  playSoundEffect(SoundEffect effect) {
    // return; // when uncommented, recorder works fine
    String soundStr;
    switch (effect) {
      case SoundEffect.Start:
        soundStr = "assets/sounds/record_start.wav";
        break;
      case SoundEffect.End:
        soundStr = "assets/sounds/record_finished.wav";
        break;
      case SoundEffect.Error:
        soundStr = "assets/sounds/record_error.wav";
        break;
    }
    if (soundStr != null) {
      var track = Track.fromAsset(soundStr);
      player.play(track);
    }
  }

  @override
  dispose() {
    _mRecorder?.release();
    player.release();
    _mRecorder = null;
    if (_mPath != null) {
      var outputFile = File(_mPath);
      if (outputFile.existsSync()) {
        outputFile.delete();
      }
    }
    super.dispose();
  }
}
diegogarciar commented 3 years ago

it seems that setting autoFocus: false on the SoundPlayer solved the issue

bsutton commented 3 years ago

I'm trying to understand if this is a bug.

I wouldn't expect the auto focus to affect the recording when operating in the same app.

On Sun, 10 Jan 2021, 9:43 am Diego Garcia, notifications@github.com wrote:

it seems that setting autoFocus: false on the SoundPlayer solved the issue

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/bsutton/sounds/issues/59#issuecomment-757378518, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAG32OD62DO3Y3WMEEGI64TSZDL2FANCNFSM4V34V7MQ .

diegogarciar commented 3 years ago

It seems that the autofocus was unfocusing on completion, inactivating the audio session, which is a shared instance.

diegogarciar commented 3 years ago

So for it to work I also had to call focus manually so the unfocused wouldn’t be called.

bsutton commented 3 years ago

Would you mind posting the code.

At the very least we should document the solution.

On Mon, 11 Jan 2021, 2:51 pm Diego Garcia, notifications@github.com wrote:

So for it to work I also had to call focus manually so the unfocused wouldn’t be called.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/bsutton/sounds/issues/59#issuecomment-757610486, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAG32OEKT4355ZUHVNIG6ATSZJYTDANCNFSM4V34V7MQ .

bsutton commented 3 years ago

Ok, that make sense.

Feels like the correct approach is to document this.

We have an update coming with better focus management.

On Mon, 11 Jan 2021, 2:50 pm Diego Garcia, notifications@github.com wrote:

It seems that the autofocus was unfocusing on completion, inactivating the audio session, which is a shared instance.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/bsutton/sounds/issues/59#issuecomment-757610258, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAG32OAWSZD2Y773QSNVVC3SZJYPDANCNFSM4V34V7MQ .

diegogarciar commented 3 years ago

Sure, I'm glad this was helpful, below is what I ended up doing, Its looks similar to what QuickPlay does, but QuickPlay has autofocus set to true by default, player.audioFocus(AudioFocus.hushOthersWithResume) was the secret ingredient that took me 2 hours to find.

playSoundEffect(Track track) {
      final player = SoundPlayer.noUI(autoFocus: false);
      player.onStopped = ({wasUser}) => player.release();
      player.audioFocus(AudioFocus.hushOthersWithResume);
      player.play(track);
  }