FFmpeg: Ошибки при открытии аудиовходного потока на MacOS

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

Я очень часто сталкиваюсь со следующим предупреждением (из Audio Toolbox?) при открытии аудиопотока внешнего микрофона с помощью libavformat в ffmpeg на macOS:

CMIO_Unit_Converter_Audio.cpp:590:RebuildAudioConverter AudioConverterSetProperty(dbca) не удалось (1886547824)

Это предупреждение приводит к тому, что идентификатор кодека потока не распознается правильно, и он по умолчанию устанавливается на фиктивный AV_CODEC_ID_FIRST_AUDIO, который по умолчанию равен AV_CODEC_ID_PCM_S16LE, что приводит к искажению аудио при декодировании пакета, когда это не правильный кодек.

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

#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include <stdio.h>

const char inputDevice[] = ":0";

int main(int argc, char *argv[]) {
  const AVInputFormat *inputFormat;
  AVStream *inputStream = NULL;
  AVFormatContext *inputFormatContext = NULL;
  int ret;
  int i, j;

  // Инициализация ввода
  avdevice_register_all();

  inputFormat = av_find_input_format("avfoundation");

  for (i = 0; i < 10; i++) {
    ret = avformat_open_input(&inputFormatContext, inputDevice, inputFormat,
                              NULL);
    if (ret != 0) {
      fprintf(stderr, "Не удалось открыть входное аудиоустройство");
      break;
    }

    ret = avformat_find_stream_info(inputFormatContext, NULL);
    if (ret < 0) {
      fprintf(stderr, "Не удалось найти информацию о потоке.");
      break;
    }

    for (j = 0; j < inputFormatContext->nb_streams; j++) {
      if (inputFormatContext->streams[j]->codecpar->codec_type ==
          AVMEDIA_TYPE_AUDIO) {
        inputStream = inputFormatContext->streams[j];
        break;
      }
    }
    if (!inputStream) {
      fprintf(stderr, "Не удалось найти аудиопоток.");
      break;
    }
    printf("codecID: %s\n",
           inputStream->codecpar->codec_id == AV_CODEC_ID_FIRST_AUDIO
               ? "Некорректный"
               : "Корректный");
    avformat_close_input(&inputFormatContext);
  }
  return 0;
}

Пример вывода:

codecID: Корректный
codecID: Некорректный
codecID: Некорректный
codecID: Некорректный
codecID: Некорректный
codecID: Корректный
codecID: Некорректный
codecID: Некорректный
codecID: Некорректный
codecID: Корректный

Как можно избежать этого предупреждения? Что я делаю не так?

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

Проблема, с которой вы столкнулись, связана с тем, что FFmpeg, использующий библиотеку libavformat, иногда не может корректно открыть аудиопоток с внешнего микрофона на macOS и отдает вам предупреждение о неудаче при установке свойств аудиоконвертера. Это может приводить к неправильному определению кодека, как вы уже заметили, с последующим искажением аудио.

Ниже представлены несколько шагов и рекомендаций, которые могут помочь вам решить эту проблему:

1. Убедитесь, что устройство доступно

Первым делом проверьте, что все ваши микрофоны корректно подключены и распознаются системой. Вы можете использовать команду ffmpeg -f avfoundation -list_devices true -i "" для получения списка всех доступных устройств и проверки их доступности.

2. Используйте корректные параметры при открытии потока

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

AVDictionary *options = NULL;
av_dict_set(&options, "sample_rate", "44100", 0);
av_dict_set(&options, "channels", "2", 0); // Убедитесь, что количество каналов соответствует вашему устройству
ret = avformat_open_input(&inputFormatContext, inputDevice, inputFormat, &options);

3. Перепроверка кода

Ваш код уже достаточно близок к правильному, но убедитесь, что вы правильно обрабатываете открытие и закрытие мини-запросов. Также добавьте более детальный вывод ошибок:

if (ret < 0) {
    char errbuf[128];
    av_strerror(ret, errbuf, sizeof(errbuf));
    fprintf(stderr, "Couldn't open input audio device: %s\n", errbuf);
    break;
}

Это поможет вам получить более подробные сообщения о возникших ошибках и сделает диагностику проще.

4. Попробуйте разные устройства и настройки

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

5. Использование постоянного контекста

В вашем коде контекст inputFormatContext пересоздается каждый раз. Рассмотрите возможность использования постоянного контекста, чтобы избежать проблемы с инициализацией. Например:

if (i == 0) {
    ret = avformat_open_input(&inputFormatContext, inputDevice, inputFormat, NULL);
    if (ret < 0) {
        // Обработка ошибок
    }
} else {
    // Закрытие предыдущего и повторное использование inputFormatContext
}

6. Обновление FFmpeg

Также убедитесь, что вы используете последнюю версию FFmpeg, так как проблемы с библиотеками часто исправляются в новых релизах. Обновления могут включать исправления для поддержки аудио устройств на macOS.

Заключение

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

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

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