7

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

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

РЕДАКТИРОВАТЬ: Я ищу подходящие комбинации кодек / контейнер. Я не знаю, почему людям было трудно понять это, так как я сказал, что уже использовал трубу, и теперь мне нужно, чтобы она была без потерь.

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

3 ответа3

11

Как без потерь передавать видео и аудио из 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 - потоковое копирование или повторное смешивание входных данных для вывода. Перекодирование не выполняется, поэтому процесс выполняется без потерь. Неизвестно, является ли потоковое копирование приемлемым для задающего вопрос или нет. Может быть, желательно перекодирование?

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

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

6

Как я научился делать это (из частей предыдущих ответов) заключается в использовании rawvideo кодека для видео, pcm_s16le аудио кодек, и nut обертки FFmpeg для кодирования потока. 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 - ...

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

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

-1

Одна проблема с другим ответом состоит в том, что это 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, а затем смешать их позже или добавить их в вышеприведенные каналы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .