Как передавать данные без потерь в FFmpeg и обратно?

Как передавать данные без потерь в FFmpeg и обратно?

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

Я подозреваю, что на эту проблему существует более одного ответа, поэтому бонусные баллы даются тому, кто предоставит исчерпывающий список решений (совместимые контейнеры и кодеки, которые можно передать по конвейеру). Бонусные баллы также даются тому, кто учитывает другие данные, например, субтитры.

EDIT: Я ищу подходящие комбинации кодека/контейнера. Я не знаю, почему у людей возникли трудности с этим, поскольку я сказал, что уже использовал канал, и теперь мне нужно, чтобы он был без потерь.

Я не знаю, как объяснить это, не выглядя самодовольным, но это сайт FAQ. Задавание вопросов, требующих крайне конкретных ответов, не поможет миллионам пользователей, которые попадают на этот сайт, вводя свои собственные проблемы в поисковые системы. Мой вопрос был разработан, чтобы помочь всем, кому нужно без потерь передавать данные между экземплярами FFmpeg, не отвлекая всех стеной повествования и кода, объясняющего, что я делаю, почему это не работает и почему это единственный вариант.

решение1

Как без потерь передавать видео и аудио ffmpegизffmpeg

Требования к задающему вопрос:

  • без потерь передавать по каналу от одного экземпляра ffmpegк другому
  • неважно, идет ли он туда и обратно/dev/null

Пример:

ffmpeg -s 1280x720 -f rawvideo -i /dev/zero -ar 48000 -ac 2 -f s16le -i \
/dev/zero -c copy -f nut pipe:1 | ffmpeg -y -i pipe:0 -c copy -f nut /dev/null

Я не вижу причин, по которым кто-либо мог бы это сделать.Кроме того, существует очень мало причин для конвейерной передачи, ffmpegкогда ffmpegвы, скорее всего, можете просто использовать один ffmpegпроцесс для выполнения любых задач.

Что делают опции:

  • -s 1280x720 -f rawvideo– Варианты описания ввода, поскольку/dev/zeroне является типичным форматом ввода, поэтому требуются эти дополнительные параметры.

  • -i /dev/zero– Видеовход. Он используется в этом примере для генерации видеопотока из «ничего». Он был использован в примере, потому что задавший вопрос отказался предоставить какую-либо информацию об используемых входах.

  • -ar 48000 -ac 2 -f s16le– Варианты описания ввода, поскольку/dev/zeroне является типичным аудиоформатом.

  • -i /dev/zero– Аудиовход. В этом примере он используется для генерации аудиопотока из «ничего».

  • -c copyПотоковая копия, или re-mux, входы в выход. Перекодирование не выполняется, поэтому процесс происходит без потерь. Неизвестно, приемлемо ли копирование потока для задавшего вопрос или нет. Может быть, вместо этого желательно перекодирование?

  • -f nut– Вам нужно указать, ffmpegкакой формат использовать для канала. Nut – это формат контейнера. ffmpeg -formatsПолный список см. здесь. Другой гибкий формат – -f matroska, но невозможно предложить подходящий или конкретный формат выходного контейнера для использования без дополнительной информации от задавшего вопрос.

  • pipe:1- Использоватьpipeпротоколдля вывода на stdout. В качестве альтернативы, номер можно опустить (просто pipe:), и по умолчанию дескриптор файла stdout будет использоваться для записи, а stdin — для чтения.

решение2

Я научился делать это (из частей предыдущих ответов), используя rawvideoкодек для видео, pcm_s16leаудиокодек и оболочку FFmpeg nutдля кодирования потока. nutне поддерживается основными программами за пределами FFmpeg, но это единственный контейнер, который, как мне известно на данный момент, может поддерживать несжатые форматы, необходимые для эффективной передачи данных между процессами.

Аргументы в пользу этой кодировки могут выглядеть следующим образом:

... -c:v rawvideo -c:a pcm_16le -f nut - ...

Некоторые аудиофайлы хранятся с 24-битными или более крупными сэмплами, и для них вам следует использовать pcm_24leили другой формат. Полный список несжатых аудиоформатов будет выведен при запуске ffmpeg -codecs(вам придется искать их в списке). Если вы не знаете, каков размер сэмпла вашего аудиофайла, использование pcm_16leне должно вызвать заметной потери качества.

На принимающем конце канала установите стандартный ввод, и ffmpeg определит формат и декодирует поток.

... ffmpeg -i - ...

Многоточия (...) в этом ответе не являются частью кода. Это то, куда идет ваш код. Одинокие дефисы (-) говорят FFmpeg использовать либо стандартный ввод, либо стандартный вывод, в зависимости от того, где они появляются.

ОБНОВЛЯТЬ:

Я попробовал провести простой эксперимент, чтобы улучшить это, и, похоже, лучшим контейнером является AVI, потому что другие программы его поймут (по крайней мере, VLC).

... -c:v rawvideo -c:a pcm_16le -f avi - ...

Эта версия будет работать точно так же, как и старая, с дополнительным бонусом в виде совместимости.

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

решение3

Единственная проблема с другим ответом в том, что это pcm_s16le, а не s16le. Кроме того, он включает в себя много избыточных параметров.

Я бы использовал PCM вместо Flac в конвейере, потому что его обработка занимает гораздо меньше времени (PCM — это необработанный звук, а кодирование FLAC занимает много времени).

В любом случае, вот как я бы это сделал.

ffmpeg -i <input video file/stream> -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -f rawvideo -i - -vcodec <video output codec> -acodec <audio output codec> -vb <video bitrate if applicable> -ab <audio bitrate if applicable> <final-output-filename>

Это сработало у меня, когда я пробовал в последний раз, но моей целью было передать ffmpeg в ffplay, что представляет собой немного другой процесс.

пример:

Это перенаправляет видео из ffmpeg в другой экземпляр как необработанный видеовыход и 16-битный прямой порядок байтов PCM (оба без потерь, если у вас нет 24-битного PCM, тогда замените pcm_s24le.) Затем он преобразует их в h.264 во втором экземпляре с помощью библиотеки fraunhoefer AAC из проекта Android ( libfaacчаще всего включается в сборки ffmpeg. Вы можете заменить ее этим.)

ffmpeg -i montypythonsflyingcircus-s1e1.avi -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -i - -vcodec libx264 -acodec libfdk_aac -vb 1200k -ab 96k mpfc-s1e01-output.mkv

Если это не поможет вам передать субтитры, вы всегда можете скопировать их в SRT, а затем объединить их позже или легко добавить их в каналы выше.

Связанный контент