Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioRecorder.stop() is not saving file in linux #269

Closed
Mrprey opened this issue Jan 2, 2024 · 9 comments
Closed

AudioRecorder.stop() is not saving file in linux #269

Mrprey opened this issue Jan 2, 2024 · 9 comments
Labels

Comments

@Mrprey
Copy link

Mrprey commented Jan 2, 2024

Package version

record: ^5.0.4
Flutter version 3.16.1

Environment

  • OS: [Linux - Ubuntu 22.04.3 LTS]

Describe the bug

start is triggered, but when stop is requested the path returned does not contain the expected file

RecordConfig(encoder: rc.AudioEncoder.aacLc, numChannels: 1)

To Reproduce

Code:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_beep/flutter_beep.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pocket/components/audio/recorder/recorder_layout.dart';
import 'package:pocket/components/audio/recorder/recorder_layout_desktop.dart';
import 'package:pocket/models/attachment.dart';
import 'package:pocket/redux/actions/action_creator.dart';
import 'package:pocket/redux/state.dart';
import 'package:pocket/streams/audio_stream.dart';
import 'package:pocket/utils/platform_manager.dart';
import 'package:record/record.dart' as rc;

class AudioRecorder extends StatefulWidget {
  final String recordId;
  final String sheetId;
  final String columnKey;
  final String attachmentMode;
  final void Function(bool) isRecordingCallback;
  final int maxSecondsDuration;
  final AudioStream audioStream;

  const AudioRecorder(
    this.recordId,
    this.sheetId,
    this.columnKey,
    this.attachmentMode,
    this.isRecordingCallback,
    this.audioStream, {
    this.maxSecondsDuration = 300,
    Key? key,
  }) : super(key: key);

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

class _AudioRecorderState extends State<AudioRecorder> {
  final rc.AudioRecorder audioRecorder = rc.AudioRecorder();
  rc.RecordState recordState = rc.RecordState.stop;

  Timer? timer;
  int recordDuration = 0;
  double? maxSoundWavesWidth;

  late String audioRecordId;

  @override
  void initState() {
    super.initState();

    audioRecordId = DateTime.now().millisecondsSinceEpoch.toString();

    checkPermission().then((bool permission) {
      if (!permission) return;

      recordState = rc.RecordState.record;

      audioRecorder.onStateChanged().listen((rc.RecordState recordState) {
        if (mounted) {
          setState(() {
            this.recordState = recordState;
            if (recordState != rc.RecordState.stop) {
              widget.audioStream.updateStatus(AudioStreamState.isRecording);
              return widget.isRecordingCallback(true);
            }
            widget.audioStream.updateStatus(AudioStreamState.none);
            widget.isRecordingCallback(false);
          });
        }
      });

      start();
    });
  }

  @override
  void dispose() {
    timer?.cancel();
    audioRecorder.dispose();
    super.dispose();
  }

  Future<bool> checkPermission() async {
    bool permission = await audioRecorder.hasPermission();

    widget.isRecordingCallback(permission);

    return permission;
  }

  @override
  Widget build(BuildContext context) {
    if (PlatformManager.isDesktop())
      return RecorderLayoutDesktop(
        audioRecorder,
        recordDuration,
        recordState: recordState,
        onSend: () => stop(),
        onDiscard: () => discard(),
      );

    return RecorderLayout(
      audioRecorder,
      recordDuration,
      recordState: recordState,
      onSend: () => stop(),
      onDiscard: () => discard(),
    );
  }

  Future<void> discard() async {
    timer?.cancel();
    recordDuration = 0;
    await audioRecorder.stop();
  }

  Future<void> start() async {
    try {
      if (await audioRecorder.hasPermission()) {
        const config =
            rc.RecordConfig(encoder: rc.AudioEncoder.aacLc, numChannels: 1);

        String path = await getPath();

        await recordFile(audioRecorder, config, path);

        recordDuration = 0;
      }
    } catch (e) {
      return null;
    }
  }

  Future<void> stop() async {
    timer?.cancel();
    recordDuration = 0;

    String? path = await audioRecorder.stop();

    if (path == null) return;

    File file = File(filePath);

  // Verifica se o arquivo existe
  if (file.existsSync()) {
    print('YES');
  } else {
    print('NOT');
  }
  }

  void startTimer() {
    timer?.cancel();

    timer = Timer.periodic(const Duration(seconds: 1), (Timer t) async {
      setState(() {
        recordDuration++;
      });

      if (recordDuration >= widget.maxSecondsDuration) {
        FlutterBeep.beep();

        await stop();
      }
    });
  }

  Future<void> recordFile(
    rc.AudioRecorder recorder,
    rc.RecordConfig config,
    String path,
  ) async {
    await recorder.start(config, path: path);
  }

  Future<String> getPath() async {
    String audioExtension = '.m4a';
    String dir = '';

    dir = (await getApplicationDocumentsDirectory()).path;

    String path = dir + '/' + audioRecordId + audioExtension;
    return path;
  }
}




Log:

flutter: AudioPlayers Exception: AudioPlayerException( DeviceFileSource(path: /home/anderson/Documentos/1704232220808.m4a), PlatformException(LinuxAudioError, Failed to set source. For troubleshooting, see: https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, Unable to set the pipeline from GST_STATE_READY to GST_STATE_PAUSED., null) [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(LinuxAudioError, Failed to set source. For troubleshooting, see: https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md, Unable to set the pipeline from GST_STATE_READY to GST_STATE_PAUSED., null)

@tiagogoncalves
Copy link

image

@Mrprey
Copy link
Author

Mrprey commented Jan 3, 2024

@tiagogoncalves this error is from AudioPlayers, the problem of Issue is happening before that, the file is not being saved, so the player cannot find it along the way

@llfbandit
Copy link
Owner

Well..., I'm completely blind on Linux platform as I don't have any instance of it.
Can you ensure that record_linux is set to 0.7.1 in your pubspec.lock?

fmedia seems to start, otherwise you would obtain an exception so it may be related to parameters.
But I can't find any break in changelog or documentation.
Also what is the version of fmedia? I started to implement linux platform with v1.27

Finally, when the recording is started do you see the incoming file at your given path?

@Mrprey
Copy link
Author

Mrprey commented Jan 18, 2024

@llfbandit
I will test the 0.7.1 version that you requested

'Also what is the version of fmedia?' fmedia is v1.31 (linux-amd64)

'Finally, when the recording is started do you see the incoming file at your given path?' No, I tested for other path/dir and didn't find them either

@pandora-house
Copy link

In my case, first run created file but second run not. I think this happen because first run somehow break process. But I discovered that such command [ '--record', '-o', _path, '-y', '--globcmd=listen'], ['--globcmd=stop'] work well

@llfbandit
Copy link
Owner

Is there any issue on Linux platform?
If so, can you fill a PR to update it?

@Vinayak006
Copy link

We are also facing the same issue.

After record.stop() is called,
- On Android: The recorded file exists as recordedFile.existsSync() returns true.
- On Linux Desktop: The recorded file does not exist as recordedFile.existsSync() returns false.

import 'package:path_provider/path_provider.dart';
import 'dart:io';

final record = Record();

Future<void> startRecording() async {
  if (await record.hasPermission()) {
    final tempDir = await getTemporaryDirectory();
    await record.start(path: '${tempDir.path}/voice.m4a');
  }
}

Future<File?> stopRecording() async {
  final path = await record.stop();
  if (path != null) {
    final recordedFile = File(path);
    return recordedFile;
  }
  return null;
}

void main() async {
  await startRecording();
  // Record audio for some time
  final recordedFile = await stopRecording();
  if (recordedFile != null && recordedFile.existsSync()) {
    print('File exists at: ${recordedFile.path}');
  } else {
    print('File does not exist.');
  }
}```

@TheOther255
Copy link
Contributor

the file does exist but is not accessible...problem should be fixed when my pull request is merged.

@llfbandit
Copy link
Owner

record_linux 0.7.2 has just been published with the fix above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants