Использование ffmpeg с конвейерами: проблемы и решения
При работе с ffmpeg
многие пользователи сталкиваются с вопросами касательно конвейерного ввода. В частности, задача конкатенации видеофайлов с помощью -f concat
может привести к путанице, особенно если вы пытаетесь избежать временных файлов. В этой статье мы рассмотрим, как правильно использовать конвейеры с ffmpeg
, а также обсудим некоторые распространенные проблемы и их решения.
Проблема с конвейерами и временными файлами
Вы можете использовать команду ffmpeg -f concat
, чтобы объединить несколько видеофайлов. Однако, как показывает практика, использование временного файла часто оказывается более надежным. Пример ниже демонстрирует проблему:
#!/bin/zsh
o=test.mp4
tmp=test.tmp
if [[ "$1" == "x" ]] ; then
echo Temp file $tmp...
ls GX01000?.mp4 | perl -ne 'print "file $_"' > $tmp
ffmpeg -hide_banner -y -f concat -i $tmp -c copy $o
else
echo Pipe
ls GX01000?.mp4 | perl -ne 'print "file $_"' | \
ffmpeg -hide_banner -y -f concat -i - -c copy $o
fi
Когда вы запускаете этот скрипт с аргументом x
, он создает временный файл и все работает. Однако при вызове без аргумента (test.sh
) возникает ошибка. Примечания в коде указывают на попытки использовать -safe 0
и -protocol_whitelist
без успеха.
Ошибки и их причины
Вот результат сбоя, когда скрипт запускается без аргумента:
Pipe
[fd @ 0x6000015f0620] Protocol 'fd' not on whitelist 'crypto,data'!
[concat @ 0x12e7055f0] Impossible to open 'fd:GX010005.mp4'
[in#0 @ 0x6000002f0100] Error opening input: Invalid argument
Error opening input file -.
Error opening input files: Invalid argument
Эта ошибка указывает на то, что ffmpeg
не может распознать входные файлы, когда они передаются через конвейер. Это связано с тем, что директива -i -
ожидает файл, а не поток данных.
Альтернативные подходы
Для достижения чистоты кода и избежания использования временных файлов можно рассмотреть следующие варианты.
Использование именованных каналов
Именованные каналы позволяют избежать записи во временные файлы и могут быть использованы следующим образом:
mkfifo list.txt
echo -e "file '/home/rotem/Tmp/input1.mp4'\nfile '/home/rotem/Tmp/input2.mp4'" > list.txt &
ffmpeg -y -f concat -safe 0 -i list.txt -c copy output.mp4
- Команда
mkfifo list.txt
создает именованный канал. - Команда
echo
записывает список файлов в канал (с использованием полного пути). - Запуск команды в фоновом режиме необходим, так как запись в именованный канал является блокирующей операцией.
- Наконец,
ffmpeg
читает список файлов из именованного канала.
После использования можно удалить именованный канал командой rm list.txt
.
Существует ли возможность использовать замену процесса?
Вы также можете использовать замену процесса, чтобы подать вывод команды как файл следующим образом:
ffmpeg -hide_banner -y -f concat -i <(printf 'file %s\n' GX01000?.mp4) -c copy "$o"
Этот метод позволяет избежать проблем с анализом выходных данных команды ls
, что делает ваш скрипт более надежным.
Итог
Использование ffmpeg
с конвейерами может быть непростым, но изучив основные проблемы, вы сможете найти решения, которые соответствуют вашим требованиям. Применяя именованные каналы или замену процесса, вы сможете улучшить качество вашего кода и избежать ненужных временных файлов. Будьте внимательны к относительным и абсолютным путям к файлам — это ключ к успешной работе с ffmpeg
.