Canardoux / flutter_sound

Flutter plugin for sound. Audio recorder and player.
Mozilla Public License 2.0
875 stars 573 forks source link

Getting Error on Web #921

Open Yogesh-Dubey-Ayesavi opened 2 years ago

Yogesh-Dubey-Ayesavi commented 2 years ago

Flutter Web Bootstrap: Programmatic ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_player.dart 132:13 new ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 ctor: FlutterSoundPlayer() └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 140:13 new ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 ctor: FlutterSoundRecorder() └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_player.dart 511:13 _openAudioSession ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 FS:---> openAudioSession └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_player.dart 524:15 _openAudioSession ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 Resetting flutter_sound Player Plugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_player.dart 360:13 log ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 ---> resetPlugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_player.dart 360:13 log ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 <--- resetPlugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 372:13 openRecorder ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 FS:---> openAudioSession └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 381:13 _openAudioSession ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 ---> openAudioSession └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 396:17 _openAudioSession ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 Resetting flutter_sound Recorder Plugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 310:13 log ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 ---> resetPlugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ #0 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28 get current │ #1 packages/flutter_sound/public/flutter_sound_recorder.dart 310:13 log ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ 🐛 <--- resetPlugin └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── TypeError: dart.global.newPlayerInstance is not a function at flutter_sound_player_web.FlutterSoundPlayerWeb.new.openPlayer (http://localhost:58834/packages/flutter_sound_web/flutter_sound_player_web.dart.lib.js:69:42) at openPlayer.next () at runBody (http://localhost:58834/dart_sdk.js:40660:34) at Object._async [as async] (http://localhost:58834/dart_sdk.js:40691:7) at flutter_sound_player_web.FlutterSoundPlayerWeb.new.openPlayer (http://localhost:58834/packages/flutter_sound_web/flutter_sound_player_web.dart.lib.js:62:20) at flutter_sound_player.FlutterSoundPlayer.new._openAudioSession (http://localhost:58834/packages/flutter_sound/public/tau.dart.lib.js:1467:106) at _openAudioSession.next () at http://localhost:58834/dart_sdk.js:40641:33 at _RootZone.runUnary (http://localhost:58834/dart_sdk.js:40511:59) at _FutureListener.thenAwait.handleValue (http://localhost:58834/dart_sdk.js:35438:29) at handleValueCallback (http://localhost:58834/dart_sdk.js:35999:49) at _Future._propagateToListeners (http://localhost:58834/dart_sdk.js:36037:17) at async._AsyncCallbackEntry.new.callback (http://localhost:58834/dart_sdk.js:35753:27) at Object._microtaskLoop (http://localhost:58834/dart_sdk.js:40778:13) at _startMicrotaskLoop (http://localhost:58834/dart_sdk.js:40784:13) at http://localhost:58834/dart_sdk.js:36261:9 TypeError: dart.global.newRecorderInstance is not a function at flutter_sound_recorder_web.FlutterSoundRecorderWeb.new.openRecorder (http://localhost:58834/packages/flutter_sound_web/flutter_sound_recorder_web.dart.lib.js:65:42) at openRecorder.next () at runBody (http://localhost:58834/dart_sdk.js:40660:34) at Object._async [as async] (http://localhost:58834/dart_sdk.js:40691:7) at flutter_sound_recorder_web.FlutterSoundRecorderWeb.new.openRecorder (http://localhost:58834/packages/flutter_sound_web/flutter_sound_recorder_web.dart.lib.js:58:20) at flutter_sound_recorder.FlutterSoundRecorder.new._openAudioSession (http://localhost:58834/packages/flutter_sound/public/tau.dart.lib.js:595:97) at _openAudioSession.next () at http://localhost:58834/dart_sdk.js:40641:33 at _RootZone.runUnary (http://localhost:58834/dart_sdk.js:40511:59) at _FutureListener.thenAwait.handleValue (http://localhost:58834/dart_sdk.js:35438:29) at handleValueCallback (http://localhost:58834/dart_sdk.js:35999:49) at _Future._propagateToListeners (http://localhost:58834/dart_sdk.js:36037:17) at [_completeWithValue] (http://localhost:58834/dart_sdk.js:35872:23) at async._AsyncCallbackEntry.new.callback (http://localhost:58834/dart_sdk.js:35906:35) at Object._microtaskLoop (http://localhost:58834/dart_sdk.js:40778:13) at _startMicrotaskLoop (http://localhost:58834/dart_sdk.js:40784:13) at http://localhost:58834/dart_sdk.js:36261:9

Up are my logs now my code is


void main()  {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) => const MaterialApp(
    home: ChatPage(),
  );
}

class ChatPage extends StatefulWidget {
  const ChatPage({super.key});

  @override
  State<ChatPage> createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> {

  @override
  Widget build(BuildContext context) => Scaffold(
      backgroundColor: Colors.black,
      body:SimpleRecorder()
  );

}

Now Simplerecorder

import 'package:audio_session/audio_session.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter_sound_platform_interface/flutter_sound_recorder_platform_interface.dart';
import 'package:permission_handler/permission_handler.dart';

typedef _Fn = void Function();

/* This does not work. on Android we must have the Manifest.permission.CAPTURE_AUDIO_OUTPUT permission.
 * But this permission is _is reserved for use by system components and is not available to third-party applications._
 * Pleaser look to [this](https://developer.android.com/reference/android/media/MediaRecorder.AudioSource#VOICE_UPLINK)
 *
 * I think that the problem is because it is illegal to record a communication in many countries.
 * Probably this stands also on iOS.
 * Actually I am unable to record DOWNLINK on my Xiaomi Chinese phone.
 *
 */
//const theSource = AudioSource.voiceUpLink;
//const theSource = AudioSource.voiceDownlink;

const theSource = AudioSource.microphone;

/// Example app.
class SimpleRecorder extends StatefulWidget {
  @override
  _SimpleRecorderState createState() => _SimpleRecorderState();
}

class _SimpleRecorderState extends State<SimpleRecorder> {
  Codec _codec = Codec.mp3;
  String _mPath = 'tau_file.mp4';
  FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
  FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();
  bool _mPlayerIsInited = false;
  bool _mRecorderIsInited = false;
  bool _mplaybackReady = false;

  @override
  void initState() {
    _mPlayer!.openPlayer().then((value) {
      setState(() {
        _mPlayerIsInited = true;
      });
    });

    openTheRecorder().then((value) {
      setState(() {
        _mRecorderIsInited = true;
      });
    });
    super.initState();
  }

  @override
  void dispose() {
    _mPlayer!.closePlayer();
    _mPlayer = null;

    _mRecorder!.closeRecorder();
    _mRecorder = null;
    super.dispose();
  }

  Future<void> openTheRecorder() async {
    if (!kIsWeb) {
      var status = await Permission.microphone.request();
      if (status != PermissionStatus.granted) {
        throw RecordingPermissionException('Microphone permission not granted');
      }
    }
    await _mRecorder!.openRecorder();
    if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
      _codec = Codec.opusWebM;
      _mPath = 'tau_file.webm';
      if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
        _mRecorderIsInited = true;
        return;
      }
    }
    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,
    ));

    _mRecorderIsInited = true;
  }

  // ----------------------  Here is the code for recording and playback -------

  void record() {
    _mRecorder!
        .startRecorder(
      toFile: _mPath,
      codec: _codec,
      audioSource: theSource,
    )
        .then((value) {
      setState(() {});
    });
  }

  void stopRecorder() async {
    await _mRecorder!.stopRecorder().then((value) {
      setState(() {
        //var url = value;
        _mplaybackReady = true;
      });
    });
  }

  void play() {
    assert(_mPlayerIsInited &&
        _mplaybackReady &&
        _mRecorder!.isStopped &&
        _mPlayer!.isStopped);
    _mPlayer!
        .startPlayer(
        fromURI: _mPath,
        //codec: kIsWeb ? Codec.opusWebM : Codec.aacADTS,
        whenFinished: () {
          setState(() {});
        })
        .then((value) {
      setState(() {});
    });
  }

  void stopPlayer() {
    _mPlayer!.stopPlayer().then((value) {
      setState(() {});
    });
  }

// ----------------------------- UI --------------------------------------------

  _Fn? getRecorderFn() {
    if (!_mRecorderIsInited || !_mPlayer!.isStopped) {
      return null;
    }
    return _mRecorder!.isStopped ? record : stopRecorder;
  }

  _Fn? getPlaybackFn() {
    if (!_mPlayerIsInited || !_mplaybackReady || !_mRecorder!.isStopped) {
      return null;
    }
    return _mPlayer!.isStopped ? play : stopPlayer;
  }

  @override
  Widget build(BuildContext context) {
    Widget makeBody() {
      return Column(
        children: [
          Container(
            margin: const EdgeInsets.all(3),
            padding: const EdgeInsets.all(3),
            height: 80,
            width: double.infinity,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: Color(0xFFFAF0E6),
              border: Border.all(
                color: Colors.indigo,
                width: 3,
              ),
            ),
            child: Row(children: [
              ElevatedButton(
                onPressed: getRecorderFn(),
                //color: Colors.white,
                //disabledColor: Colors.grey,
                child: Text(_mRecorder!.isRecording ? 'Stop' : 'Record'),
              ),
              SizedBox(
                width: 20,
              ),
              Text(_mRecorder!.isRecording
                  ? 'Recording in progress'
                  : 'Recorder is stopped'),
            ]),
          ),
          Container(
            margin: const EdgeInsets.all(3),
            padding: const EdgeInsets.all(3),
            height: 80,
            width: double.infinity,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: Color(0xFFFAF0E6),
              border: Border.all(
                color: Colors.indigo,
                width: 3,
              ),
            ),
            child: Row(children: [
              ElevatedButton(
                onPressed: getPlaybackFn(),
                //color: Colors.white,
                //disabledColor: Colors.grey,
                child: Text(_mPlayer!.isPlaying ? 'Stop' : 'Play'),
              ),
              SizedBox(
                width: 20,
              ),
              Text(_mPlayer!.isPlaying
                  ? 'Playback in progress'
                  : 'Player is stopped'),
            ]),
          ),
        ],
      );
    }

    return Scaffold(
      backgroundColor: Colors.blue,
      appBar: AppBar(
        title: const Text('Simple Recorder'),
      ),
      body: makeBody(),
    );
  }
}
Nightwelf commented 2 years ago

same issue

rishabh-bector commented 1 year ago

me too

sergiocasero commented 1 year ago

Same issue for me, any solution? I'm using version 9.2.13

github-actions[bot] commented 11 months ago

This issue is stale because it has been open 90 days with no activity. Leave a comment or this will be closed in 7 days.

RA341 commented 1 month ago

running in the same issue flutter_sound: ^9.15.61

Larpoux commented 1 month ago

@RA341 : could you be more precise ? What is exactly your issue ?

RA341 commented 1 month ago

pretty much the same issue, do we have to include the js libraries

┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_player.dart 133:5                     new
│ #1   packages/client/service/microphone_manager.dart 15:18                             _internal
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 ctor: FlutterSoundPlayer()
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_recorder.dart 140:5                   new
│ #1   packages/client/service/microphone_manager.dart 16:20                             _internal
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 ctor: FlutterSoundRecorder()
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_player.dart 502:5            _openAudioSession
│ #1   packages/flutter_sound/public/flutter_sound_player.dart 501:47           [_openAudioSession]
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 FS:---> openAudioSession
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_player.dart 515:7            _openAudioSession
│ #1   packages/flutter_sound/public/flutter_sound_player.dart 501:47           [_openAudioSession]
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 Resetting flutter_sound Player Plugin
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_player.dart 347:5            log
│ #1   packages/flutter_sound_web/flutter_sound_player_web.dart 221:13          resetPlugin
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 ---> resetPlugin
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ #0   packages/flutter_sound/public/flutter_sound_player.dart 347:5            log
│ #1   packages/flutter_sound_web/flutter_sound_player_web.dart 227:13          resetPlugin
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ 🐛 <--- resetPlugin
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
TypeError: dart.global.newPlayerInstance is not a function
packages/flutter_sound_web/flutter_sound_player_web.dart 243:18     openPlayer
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54  runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 127:5  _async
packages/flutter_sound_web/flutter_sound_player_web.dart 232:25     openPlayer
packages/flutter_sound/public/flutter_sound_player.dart 526:12      _openAudioSession
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50  <fn>
dart-sdk/lib/async/zone.dart 1661:54                                runUnary
dart-sdk/lib/async/future_impl.dart 163:18                          handleValue
dart-sdk/lib/async/future_impl.dart 847:44                          handleValueCallback
dart-sdk/lib/async/future_impl.dart 876:13                          _propagateToListeners
dart-sdk/lib/async/future_impl.dart 472:9                           callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                    _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                     _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7  <fn>
Larpoux commented 1 month ago

A long time ago, it was necessary to load explicitly the Java Script library. But not anymore. I guess that you use the standard index.html provided by flutter. Don’t you do?

RA341 commented 1 month ago

yeah

RA341 commented 1 month ago

am i doing something wrong during initialization

initstate

Future<void> init() async {
    await player.openPlayer();
    await recorder.openRecorder();
  }
@override
  void initState() {
    init().then(
          (value) => setState(() {}),
        );
    super.initState();
  }
Larpoux commented 1 month ago

Flutter is supposed to load automatically the js scripts that are in your assets. But you aren’t the first developer having this issue. I don’t really understand why.

RA341 commented 1 month ago

A long time ago, it was necessary to load explicitly the Java Script library. But not anymore. I guess that you use the standard index.html provided by flutter. Don’t you do?

I do have minor modifications to the index.html, but they are cosmetic and should not affect the flutter itself (I think)

<body>
  <div id="loading">
    <img src="icons/mictest.gif" style="max-width: 480;"alt="loading">
  </div>
  <script>
    var loadingElement = document.getElementById('loading');

    function hideLoading() {
      loadingElement.classList.add('fade-out');
      // Remove the loading element from the DOM after the transition
      setTimeout(() => {
        loadingElement.style.display = 'none';
      }, 400); // This should match the transition duration in CSS
    }

    window.addEventListener("flutter-first-frame", function () {
      var element = document.getElementsByClassName("loading");
      hideLoading();
    });
  </script>

  <script src="flutter_bootstrap.js" async></script>
</body>
Larpoux commented 1 month ago

Of course you use the regular pubspec of flutter sound and not a modified plugin? The 3 js scripts are declared in flutter-sound-web pubspec

RA341 commented 1 month ago

Yep using the normal package

flutter_sound: ^9.15.61

from what i understand looking at the internet, the issue seems to be that the js libraries are not downloaded

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_function

Is a possible workaround to include the libraries in index anyway

Larpoux commented 1 month ago

I am going immediately test that every thing is ok on my side. Not many people use the web version, and it is possible that a bug has been introduced recently. Wait a moment, I am testing…

Larpoux commented 1 month ago

OK. The speed control example runs fine on my site. There is a little problem to play the "simple player" but I think that the problem is because the asset example is not correctly uploaded on my server. I will fix that.

Of course, you can load yourself the scripts, but I would would be glad to understand why it is necessary.

RA341 commented 1 month ago

Curious can you try running an empty flutter project from scratch, then copying the example

Regarding the scripts, just asking really I have no idea

RA341 commented 1 month ago

could this be flutter version issue ? I am using 3.24

Larpoux commented 1 month ago
Developer identity "Apple Development: Laurent Aries (6HKJS9QR6C)" selected for iOS code signing
larpoux@Mac-Studio:~/proj/tau/tauwaweb/example$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on macOS 14.6.1 23G93 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.92.2)
[✓] VS Code (version unknown)
    ✗ Unable to determine VS Code version.
[✓] VS Code (version unknown)
    ✗ Unable to determine VS Code version.
[✓] Connected device (6 available)
[✓] Network resources

• No issues found!
RA341 commented 1 month ago

Wait ok so this is weird

The app runs into that error when I first start building, but if I keep the program running and hot reload/restart, the initlization works perfectly and starts working

Larpoux commented 1 month ago

You are probably a better expert than me on web development.

Larpoux commented 1 month ago

You are not the first to have this problem. But I have never understood the reason.

Ricu commented 1 month ago

I am experiencing the same problem. I debug the app in chrome. My code is basically the sample recorder app.

From pubspec.yaml

flutter_sound: ^9.15.61
permission_handler: ^11.3.1
audio_session: ^0.1.21

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.24.1, on Microsoft Windows [Version 10.0.19045.4894], locale de-DE)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[√] Chrome - develop for the web
[X] Visual Studio - develop Windows apps
    X Visual Studio not installed; this is necessary to develop Windows apps.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components
[√] Android Studio (version 2024.1)
[√] VS Code (version 1.93.1)
[√] Connected device (3 available)
[√] Network resources

Code

import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:permission_handler/permission_handler.dart';
import 'package:audio_session/audio_session.dart';

// const theSource = AudioSource.microphone

typedef _Fn = void Function();

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
  Codec _codec = Codec.aacMP4;
  String _mPath = 'tau_file.mp4';
  FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
  FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();
  bool _mPlayerIsInited = false;
  bool _mRecorderIsInited = false;
  bool _mplaybackReady = false;

   @override
  void initState() {
    _mPlayer!.openPlayer().then((value) {
      setState(() {
        _mPlayerIsInited = true;
      });
    });

    openTheRecorder().then((value) {
      setState(() {
        _mRecorderIsInited = true;
      });
    });
    super.initState();
  }

  @override
  void dispose() {
    _mPlayer!.closePlayer();
    _mPlayer = null;

    _mRecorder!.closeRecorder();
    _mRecorder = null;
    super.dispose();
  }

  Future<void> openTheRecorder() async {
    if (!kIsWeb) {
      var status = await Permission.microphone.request();
      if (status != PermissionStatus.granted) {
        throw RecordingPermissionException('Microphone permission not granted');
      }
    }
    await _mRecorder!.openRecorder();
    if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
      _codec = Codec.opusWebM;
      _mPath = 'tau_file.webm';
      if (!await _mRecorder!.isEncoderSupported(_codec) && kIsWeb) {
        _mRecorderIsInited = true;
        return;
      }
    }
    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,
    ));

    _mRecorderIsInited = true;
  }

  // ----------------------  Here is the code for recording and playback -------

  void record() {
    _mRecorder!
        .startRecorder(
      toFile: _mPath,
      codec: _codec,
      // audioSource: theSource,
    )
        .then((value) {
      setState(() {});
    });
  }

  void stopRecorder() async {
    await _mRecorder!.stopRecorder().then((value) {
      setState(() {
        //var url = value;
        _mplaybackReady = true;
      });
    });
  }

  void play() {
    assert(_mPlayerIsInited &&
        _mplaybackReady &&
        _mRecorder!.isStopped &&
        _mPlayer!.isStopped);
    _mPlayer!
        .startPlayer(
            fromURI: _mPath,
            //codec: kIsWeb ? Codec.opusWebM : Codec.aacADTS,
            whenFinished: () {
              setState(() {});
            })
        .then((value) {
      setState(() {});
    });
  }

  void stopPlayer() {
    _mPlayer!.stopPlayer().then((value) {
      setState(() {});
    });
  }

  // ----------------------------- UI --------------------------------------------

  _Fn? getRecorderFn() {
    if (!_mRecorderIsInited || !_mPlayer!.isStopped) {
      return null;
    }
    return _mRecorder!.isStopped ? record : stopRecorder;
  }

  _Fn? getPlaybackFn() {
    if (!_mPlayerIsInited || !_mplaybackReady || !_mRecorder!.isStopped) {
      return null;
    }
    return _mPlayer!.isStopped ? play : stopPlayer;
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              FloatingActionButton(onPressed: getRecorderFn(), child: const Icon(Icons.mic)),
              const Text("Hello"),
            ],
          )
        ),
      ),
    );
  }
}
RA341 commented 1 month ago

@Ricu once the app fails can you hot restart see if it starts working

Ricu commented 1 month ago

@Ricu once the app fails can you hot restart see if it starts working

It does indeed work after hot restarting.

RA341 commented 1 month ago

@Larpoux can you confirm this is happening on your side

Larpoux commented 1 month ago

I never have any problem to load the scripts with the regular index.html from flutter. Hard for me to debug that, because I don’t reproduce the issue. Of course, if you understand what happens, I will do what is necessary in flutter sound

Larpoux commented 1 month ago

Perhaps a problem with your chrome?

RA341 commented 1 month ago

did you try with a fresh flutter project

Larpoux commented 1 month ago

The examples are very basic. You can try to run them and see if you have the same problem

RA341 commented 1 month ago

The examples work fine on my machine as well

Larpoux commented 1 month ago

Ok. This is interesting. I am sure that you are able to understand the issue. Note: flutter sound project was created a long time ago. And every thing was not cleanly polished at this time.

Larpoux commented 1 month ago

What is sure is that the problem is not in the dart code. And probably not in the js scripts themselves

Larpoux commented 1 month ago

I didn’t want to do that, because I am actually focused on the v10.0, but I think it is time today to recreate a flutter sound plugin with a completely new fresh flutter plugin

Larpoux commented 1 month ago

Also, that will fix the deprecated features that flutter sound actually uses

RA341 commented 1 month ago

I appreciate that, but unfortunately, I am on a deadline in 2 weeks.

are you aware of any methods that can programmatically 'hot restart' a widget as a temporary workaround

Larpoux commented 1 month ago

Oh, shit! Perhaps you can try to load the scripts your self, as you suggested. There is a good probability that it will be a correct work around.

tomorrow I will start to build a clean flutter sound. But I know that I will have problems and you can’t bet today on a new flutter sound in the next few days

Larpoux commented 1 month ago

But I will try. I promise

RA341 commented 1 month ago

where are the scripts

RA341 commented 1 month ago

But I will try. I promise

No worries take your time, I understand

Larpoux commented 1 month ago

There are in the src and howler directories of the flutter_sound_web repo

  assets:
  - howler/howler.js
  - src/flutter_sound.js
  - src/flutter_sound_player.js
  - src/flutter_sound_recorder.js
Larpoux commented 1 month ago

https://github.com/Larpoux/flutter_sound_web

Larpoux commented 1 month ago

Perhaps I can focus at first on just FlutterSoundWeb, and publish very soon a new plugin for web, without being bothered by iOS and Android. I can do that very quickly

Larpoux commented 1 month ago

I will give you some news tomorrow evening.

RA341 commented 1 month ago

thank you I appreciate it

Larpoux commented 1 month ago

I think I have an explanation for your app not working on a cold start, but working after a hot reload. For legacy reason, the JavaScript scripts are stored in two different places :

Probably the scripts are not loaded and re-loaded from the same place (I don't know why). Could you check two things :

If the two directories are not there just put them, and they will probably be loaded correctly during a cold start.

RA341 commented 1 month ago

I have both of them in my build/web/assets dir and it is loaded when the app runs

image

Larpoux commented 1 month ago

Haha :-D :-D : I think you live in Australia !!! because you don't sleep during the night !!!

RA341 commented 1 month ago

haha, no but I am kind of a night owl and my sleep schedule is fucked :)

Also, there is definitely a race condition, adding the delay fixes the issue I think its downloading the files and since my app is only single page it immediately attempts to initialize the player while it is being downloaded

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Future.delayed(const Duration(seconds: 2));
RA341 commented 1 month ago

I think thats the reason your examples work the first page does not initialize the class, since we have to navigate to a specific example allowing the libraries to fully download themselves