recordAudio method

Future<Uint8List> recordAudio({
  1. Duration? silenceCutoffLength = const Duration(seconds: 3),
  2. Duration maxLength = const Duration(seconds: 30),
})

Records audio from the microphone.

Args: silenceCutoffLength (Duration?): The length of silence to allow before stopping the recording. Defaults to 3 seconds. maxLength (Duration): The maximum length of the recording. Defaults to 30 seconds.

Returns: Future

Throws: StateError: If no audio data is recorded.

Implementation

Future<Uint8List> recordAudio({
  Duration? silenceCutoffLength = const Duration(seconds: 3),
  Duration maxLength = const Duration(seconds: 30),
}) async {
  if (!frame.useLibrary) {
    throw Exception("Cannot record audio via SDK without library helpers");
  }
  await frame.runLua('frame.microphone.stop()', checked: true);

  if (silenceCutoffLength != null) {
    _silenceCutoffLength = silenceCutoffLength.inMilliseconds / 1000.0;
  } else {
    _silenceCutoffLength = null;
  }
  _maxLengthInSeconds = maxLength.inMilliseconds / 1000.0;
  _audioBuffer = Uint8List(0);
  _audioFinishedCompleter = Completer<void>();
  StreamSubscription<Uint8List> subscription = frame.bluetooth
      .getDataOfType(FrameDataTypePrefixes.micData)
      .listen(_audioBufferHandler);

  _lastSoundTime = DateTime.now().millisecondsSinceEpoch / 1000;

  logger.info('Starting audio recording at $_sampleRate Hz, $_bitDepth-bit');
  await frame.runLua(
    'microphoneRecordAndSend($_sampleRate,$_bitDepth,nil)',
  );

  await _audioFinishedCompleter.future;
  subscription.cancel();
  await frame.bluetooth.sendBreakSignal();
  await frame.runLua('frame.microphone.stop()');
  await Future.delayed(const Duration(milliseconds: 100));
  await frame.runLua('frame.microphone.stop()');

  if (_audioBuffer == null || _audioBuffer!.isEmpty) {
    throw StateError('No audio data recorded');
  }

  final lengthInSeconds =
      _audioBuffer!.length / (_bitDepth ~/ 8) / _sampleRate;
  final didTimeout = lengthInSeconds >= _maxLengthInSeconds;

  if (!didTimeout && silenceCutoffLength != null) {
    final trimLength = (silenceCutoffLength.inMilliseconds - 500) *
        _sampleRate *
        (_bitDepth ~/ 8) ~/
        1000;
    if (_audioBuffer!.length > trimLength) {
      _audioBuffer =
          _audioBuffer!.sublist(0, _audioBuffer!.length - trimLength.toInt());
    }
  }

  logger.info(
      'Audio recording finished with ${_audioBuffer!.length / (_bitDepth ~/ 8) / _sampleRate} seconds of audio');

  return _audioBuffer!;
}