Flutter не может воспроизводить звук с записью.

Вопрос или проблема

Я создаю приложение для слухового аппарата на Flutter для тех, кто не слышит нормально. Идея заключается в том, что звук, который микрофон получает от пользователя, можно изменять, изменяя его частоту, высоту тона и другие настройки с помощью ползунка или чего-то подобного, а динамик воспроизводит этот звук с обработанными настройками. Проблема, с которой я сталкиваюсь, заключается в том, что Flutter сначала записывает звук, а затем воспроизводит его. Как сделать так, чтобы звук непосредственно воспроизводился с микрофона на динамик? Динамик может быть мобильным или гарнитурой.

Я ожидаю, что звук будет воспроизводиться наряду со звуком с микрофона.

import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';

class VoiceChanger extends StatefulWidget {
  @override
  _VoiceChangerState createState() => _VoiceChangerState();
}

class _VoiceChangerState extends State<VoiceChanger> {
  late final StreamController<Uint8List> _audioStreamController;

  FlutterSoundRecorder? _recorder;
  FlutterSoundPlayer? _player;
  bool isRecording = false;
  bool isPlayingBack = false;

  @override
  void initState() {
    super.initState();
    _recorder = FlutterSoundRecorder();
    _player = FlutterSoundPlayer();
    _audioStreamController = StreamController<Uint8List>();
    initAudio();
  }

  Future<void> initAudio() async {
    await _recorder!.openRecorder();
    await _player!.openPlayer();
    await _player!.setVolume(1.0);
  }

  Future<void> startRecording() async {
    if (await Permission.microphone.request().isGranted) {
      // Начинаем запись в поток
      await _recorder!.startRecorder(
        toStream: _audioStreamController.sink,
        codec: Codec.pcm16,
      );

      // Слушаем поток и воспроизводим аудиоданные в реальном времени
      _audioStreamController.stream.listen((data) async {
        // Обеспечиваем плавность воспроизведения
        if (!isPlayingBack) {
          isPlayingBack = true;
          await _player!.startPlayer(
            fromDataBuffer: data,
            codec: Codec.pcm16,
            whenFinished: () {
              isPlayingBack = false; // Установить флаг воспроизведения в false, когда закончится
            },
          );
        } else {
          // Подаем новые аудиоданные на воспроизведение без перерыва
          await _player!.feedFromStream(data);
        }
      });

      setState(() {
        isRecording = true;
      });
    } else {
      print("Разрешение на использование микрофона не предоставлено");
    }
  }

  Future<void> stopRecording() async {
    await _recorder!.stopRecorder();
    setState(() {
      isRecording = false;
      isPlayingBack = false; // Остановить воспроизведение
    });
  }

  @override
  void dispose() {
    _recorder?.closeRecorder();
    _player?.closePlayer();
    _audioStreamController.close(); // Убедиться, что поток закрыт
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Изменитель голоса'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: isRecording ? stopRecording : startRecording,
              child: Text(isRecording ? 'Остановить запись' : 'Начать запись'),
            ),
          ],
        ),
      ),
    );
  }
}

Чтобы достичь воспроизведения аудио в реальном времени во время записи, рассмотрите следующие подходы:

  1. Используйте метод feedFromStream от flutter_sound: Вы уже используете этот метод, но убедитесь, что подаете аудиоданные на воспроизведение сразу, как только они становятся доступными от рекордера.
  2. Используйте AudioTrack из пакета audioplayers: Создайте экземпляр AudioTrack и передайте записанные аудиоданные в его метод play.
  3. Изучите другие пакеты: dart_av: Предоставляет низкоуровневые возможности обработки аудио. audiomix: Позволяет смешивание аудиопотоков.
  4. Измените пакет flutter_sound: Если вышеуказанные решения не работают, рассмотрите возможность изменения пакета flutter_sound для включения воспроизведения в реальном времени. Вот обновленная версия вашего метода startRecording с использованием feedFromStream:
Future<void> startRecording() async {
  // ...
  _audioStreamController.stream.listen((data) async {
    if (_player!.isPlaying) {
      await _player!.feedFromStream(data);
    } else {
      await _player!.startPlayer(
        fromDataBuffer: data,
        codec: Codec.pcm16,
      );
    }
  });
  // ...
}

Ответ или решение

Проблема воспроизведения аудио во время записи в приложении Flutter

При разработке приложения слухового aids на Flutter, у вас возникла задача реализовать прямую передачу звука с микрофона на динамик без промежуточной записи. Это необходимо для того, чтобы пользователи могли настраивать параметры звука, такие как частота и высота тона, в реальном времени. Однако текущая реализация, как вы заметили, сначала записывает звук, а только потом воспроизводит его. Давайте рассмотрим возможные решения этой проблемы.

Варианты решения проблемы

  1. Использование метода feedFromStream из пакета flutter_sound.
    Вы уже на верном пути, применяя этот метод, однако важно убедиться, что данные аудио передаются в динамик сразу после их получения от рекордера. Это поможет избежать задержек в воспроизведении.

  2. Создание экземпляра AudioTrack из пакета audioplayers.
    Этот пакет позволяет более гибко управлять аудиопотоками. Возможно, вам потребуется создать экземпляр AudioTrack и передавать записанные аудиоданные в метод play.

  3. Изучение других пакетов.
    Рассмотрите возможность использования пакетов, таких как dart_av для низкоуровневой работы с аудио, или audiomix, который позволяет смешивать аудиопотоки. Эти решения могут дать вам больше контроля над обработкой звука и его воспроизведением.

  4. Модификация пакета flutter_sound.
    Если предложенные решения не подходят, возможно, стоит рассмотреть модификацию самого пакета flutter_sound, чтобы включить функцию воспроизведения в реальном времени. Это требует глубокого понимания внутренней структуры пакета, но может оказаться самым эффективным решением.

Пример доработки вашей функции startRecording

Вот обновленный вариант вашей функции startRecording, который включает в себя использование метода feedFromStream более эффективно:

Future<void> startRecording() async {
  if (await Permission.microphone.request().isGranted) {
    await _recorder!.startRecorder(
      toStream: _audioStreamController.sink,
      codec: Codec.pcm16,
    );

    _audioStreamController.stream.listen((data) async {
      if (_player!.isPlaying) {
        await _player!.feedFromStream(data);
      } else {
        await _player!.startPlayer(
          fromDataBuffer: data,
          codec: Codec.pcm16,
          whenFinished: () {
            isPlayingBack = false; // Сброс состояния воспроизведения
          },
        );
      }
    });

    setState(() {
      isRecording = true;
    });
  } else {
    print("Нет доступа к микрофону");
  }
}

Заключение

Практическое применение вышеописанных подходов позволит вам создать функциональность в вашем приложении, где звук будет воспроизводиться непосредственно из микрофона в реальном времени без постоянных задержек на запись. Важно тщательно протестировать каждое из решений, чтобы понять, какое из них наилучшим образом подходит для ваших требований. Надеюсь, предоставленные рекомендации помогут вам в реализации вашего проекта.

Оцените материал
Добавить комментарий

Капча загружается...