Запись аудиоданных в существующий аудиофайл, используя FFmpeg API
Моя главная задача заключается в том, чтобы по запросу клиента, записывать полученные аудиоданные в уже существующий файл.
В качестве примера предположим, что я уже создал аудиофайл с длительностью аудиозаписи 1 час. Я хочу открыть его, записать дополнительный 1 час аудиоданных и закрыть его. В результате мы должны получить аудиофайл, содержащий 2-часовую звуковую дорожку. Я правильно понимаю, что в этом случае, если это возможно, мне придется удалить предыдущий записанный трейлер (он был записан благодаря функции av_write_trailer), записать полученные данные в конец файла, а при закрытии аудиофайла записать текущий трейлер ?
Ответы (2 шт):
В поставленном общем виде у этой задачи нет решения. Возможность дописать данные в существующий файл по сути невозможна для большинства аудиоформатов поскольку предполагает сочетание множества факторов: структура файла должна предполагать возможность дописывания с или без необходимостью совпадения форматов данных существующей и новой части; реализация соответствующего контейнера должны быть явно адаптирована к склейке; в большинстве случаев реализация будет предполагать считывание всего имеющегося фрагмента прежде чем первый байт может быть дописан, часто в т.ч. с использованием временного промежуточного файла/потока.
Из числа традиционных форматов данных существует лишь небольшое количество примеров, таких как MPEG TS, где принципиально предусмотрено дописывание. Стандартно склейка происходит из уже готовых кусков и путем полномасштабного пересоздания файла с копированием данных.
Предложу решение в лоб - записывать в формате MP3.
Формат MP3 состоит из простых блоков, которые склеиваются между собой без особых проблем. Но есть определенные требования к исходным данным:
- Частота и число каналов должны быть одинаковыми, чтобы потом не было проблем с воспроизведением.
- Настройки кодирования желательно сделать одинаковыми.
- Рекомендуется использовать постоянный битрейт для корректной навигации по полученному файлу.
- Отключите запись тега id3v2 и блока Xing, т.к. они будут создавать мусор в местах склейки.
Примерное решение через командную строку:
ffmpeg.exe -i input1.wav -codec:a libmp3lame -b:a 192k -write_xing 0 -id3v2_version 0 ouput1.mp3
ffmpeg.exe -i input2.wav -codec:a libmp3lame -b:a 192k -write_xing 0 -id3v2_version 0 ouput2.mp3
ffmpeg.exe -i input3.wav -codec:a libmp3lame -b:a 192k -write_xing 0 -id3v2_version 0 ouput3.mp3
COPY /B ouput1.mp3 + ouput2.mp3
COPY /B ouput1.mp3 + ouput3.mp3
Если надо написать на C/C++, то возьмите за основу официальный пример encode_audio.c, поменяйте кодек на MP3, пропишите свои параметры кодирования (тут могут быть сложности с доп. параметрами, т.к. в примере отсутсвуют) и пишите в бинарный файл, открытый в режиме добавления fopen(filename, "ab").
PS: Блок MP3 имеет фиксированную длительность (26,1 мс для 44100 Гц, 24 мс для 48000 Гц), что может иметь значение в некоторых сценариях использования.