SimformSolutionsPvtLtd / audio_waveforms

Use this plugin to generate waveforms while recording audio in any file formats supported by given encoders or from audio files. We can use gestures to scroll through the waveforms or seek to any position while playing audio and also style waveforms
https://pub.dev/packages/audio_waveforms
MIT License
275 stars 141 forks source link

E/AudioWaveforms( 5594): Failed to stop initialize recorder #306

Open gautam8404 opened 3 months ago

gautam8404 commented 3 months ago

Describe the bug Recorder controller failed to initialize, it was working before but now it fails to initialize and i can't figure out why

i use following widget to use audio recorder

class AudioRecorder extends StatefulWidget {
  final AudioModel audioModel;
  final double height;
  final Duration? maxDuration;
  final void Function(Duration)? onRecordEnd;

  const AudioRecorder({
    super.key,
    required this.audioModel,
    required this.height,
    this.maxDuration,
    this.onRecordEnd,
  });

  @override
  State<AudioRecorder> createState() => _AudioRecorderState();
}

class _AudioRecorderState extends State<AudioRecorder> {
  late RecorderController recorder;
  late StreamSubscription<RecorderState> recordSub;
  late StreamSubscription<Duration> durationSub;
  late StreamSubscription<Duration> recordEndSub;

  final recorderWaveStyle =
  const WaveStyle(showDurationLabel: true, durationLinesColor: Colors.red);

  @override
  void initState() {
    super.initState();
    recorder = RecorderController();

    recordSub = recorder.onRecorderStateChanged.listen((_) {
      setState(() {});
    });
    durationSub = recorder.onCurrentDuration.listen((dur) {
      if (widget.maxDuration != null && widget.maxDuration! >= dur) {
        recorder.stop();
        setState(() {});
      }
    });
    recordEndSub = recorder.onRecordingEnded.listen((dur) {
      if (widget.onRecordEnd != null) {
        widget.onRecordEnd!(dur);
      }
    });
  }

  @override
  void dispose() {
    recordSub.cancel();
    durationSub.cancel();
    recordEndSub.cancel();
    recorder.dispose();
    super.dispose();
  }

  Future<bool> _hasPermission() {
    final status = Permission.microphone.request();
    final storage = Permission.storage.request();

    return status.isGranted;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        AudioWaveforms(
          size: Size(MediaQuery.of(context).size.width, widget.height),
          recorderController: recorder,
          waveStyle: recorderWaveStyle,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (!recorder.recorderState.isInitialized)
              IconButton(
                icon: const Icon(Icons.mic),
                onPressed: () async {
                  if (await _hasPermission()) {
                    await recorder.record(path: widget.audioModel.path);
                  } else {
                    throw CustomException(
                        "microphone permission not granted");
                  }
                },
              ),
            if (!recorder.recorderState.isStopped)
              IconButton(
                onPressed: () async {
                  recorder.recorderState.isRecording
                      ? await recorder.pause()
                      : await recorder.record();
                },
                icon: Icon(
                  recorder.recorderState.isRecording ? Icons.stop : Icons.play_arrow,
                ),
              ),

            if (!recorder.recorderState.isStopped)
              IconButton(onPressed: recorder.stop, icon: const Icon(Icons.stop))
          ],
        )
      ],
    );
  }
}

and its used here

class Media extends StatefulWidget {
  final String _applicationID;

  const Media(this._applicationID, {super.key});

  @override
  State<Media> createState() => _MediaState();
}

class _MediaState extends State<Media> {
  bool _showPlayer = false;

  void _setShowPlayer(bool val) {
    setState(() {
      _showPlayer = val;
    });
  }

  Widget _buildAudioCard(MediaProvider media) {
    if (media.audio == null) {
      // Audio is not initialized yet
      return const CircularProgressIndicator();
    }

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: !_showPlayer
            ? AudioRecorder(audioModel: media.audio!, height: 200)
            : AudioPlayer(audioModel: media.audio!, height: 200),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    MediaProvider media = Provider.of<MediaProvider>(context, listen: false);

    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            _buildAudioCard(media),
            // AudioCard(),
            const SizedBox(height: 20),
            // ImageCard(),
          ],
        ),
      ),
    );
  }
}

although i tired using it in other ways too it didn't work

To Reproduce try init RecorderController or use AudioRecorder

Expected behavior RecorderController initialises

Smartphone (please complete the following information):

Additional context it worked before but it suddenly stopped working, i have tried different ways but it just seems to stop at initialization phase with "E/AudioWaveforms( 5594): Failed to stop initialize recorder" as error log when try to record

i also tried it in different emulators and device it still didn't work

Illia-Dulebov commented 2 months ago

Same for me

tentamens commented 2 weeks ago

Same here did you find any fix?