Вопрос или проблема
Я очень часто сталкиваюсь со следующим предупреждением (из 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.
Заключение
Каждая из приведенных рекомендаций может привести к исправлению вашей проблемы с открытием аудиопотока. Внимательно выполните все шаги, добавьте обработку ошибок и убедитесь в доступности устройств. Если проблема продолжает возникать, рассмотрите возможность проверки оборудования на других операционных системах или с использованием других программ.