Как исправить проблему с чтением списка файлов в ffmpeg -f concat из командной строки?

Использование 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
  1. Команда mkfifo list.txt создает именованный канал.
  2. Команда echo записывает список файлов в канал (с использованием полного пути).
  3. Запуск команды в фоновом режиме необходим, так как запись в именованный канал является блокирующей операцией.
  4. Наконец, ffmpeg читает список файлов из именованного канала.

После использования можно удалить именованный канал командой rm list.txt.

Существует ли возможность использовать замену процесса?

Вы также можете использовать замену процесса, чтобы подать вывод команды как файл следующим образом:

ffmpeg -hide_banner -y -f concat -i <(printf 'file %s\n' GX01000?.mp4) -c copy "$o"

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

Итог

Использование ffmpeg с конвейерами может быть непростым, но изучив основные проблемы, вы сможете найти решения, которые соответствуют вашим требованиям. Применяя именованные каналы или замену процесса, вы сможете улучшить качество вашего кода и избежать ненужных временных файлов. Будьте внимательны к относительным и абсолютным путям к файлам — это ключ к успешной работе с ffmpeg.

Источник

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *