Ffmpeg в трубе bash
У меня есть список путей к файлу rmvb и вы хотите преобразовать эти файлы в файлы mp4. Поэтому я надеюсь использовать конвейер bash для его обработки. Код
Convert() {
ffmpeg -i "$1" -vcodec mpeg4 -sameq -acodec aac -strict experimental "$1.mp4"
}
Convert_loop(){
while read line; do
Convert $line
done
}
cat list.txt | Convert_loop
Однако он обрабатывает только первый файл, и труба выходит.
Итак, ffmpeg влияет на канал bash?
Ответы
Ответ 1
Предостережение: я никогда не использовал ffmpeg
, но при работе с другими вопросами, касающимися программы, кажется, что, например, ssh
, ffmpeg
читает со стандартного ввода, фактически не используя его, поэтому первый вызов Convert
потребляет оставшуюся часть списка файлов после того, как read
получает первую строку. Попробуйте это
Convert() {
ffmpeg -i "$1" -vcodec mpe4 -sameq -acodec aac \
-strict experimental "$1.mp4" < /dev/null
}
Таким образом, ffmpeg
не будет "захватывать" данные со стандартного ввода, предназначенного для команды read
.
Ответ 2
[...]
for i in `cat list.txt`
Никогда не используйте этот синтаксис:
for i in $(command); do ...; done # or
for i in `command`; do ...; done
Этот синтаксис читает вывод командного слова по слову, а не строку за строкой, что часто создает неожиданные проблемы (например, когда строка содержит некоторые пробелы и когда вы хотите читать строку, например, например, элемент).
Всегда есть более разумное решение:
command|while read -r; do ...; done # better general case to read command output in a loop
while read -r; do ...; done <<< "$(command)" # alternative to the previous solution
while read -r; do ...; done < <(command) # another alternative to the previous solution
for i in $DIR/*; do ...; done # instead of "for i in $(ls $DIR); do ...; done
for i in {1..10}; do ...; done # instead of "for i in $(seq 1 10); do ...; done
for (( i=1 ; i<=10 ; i++ )); do ...; done # such that the previous command
while read -r; do ...; done < file # instead of "cat file|while read -r; do ...; done"
# ...
Я написал курс с более подробной информацией об этом предмете и повторяющимися ошибками, но по-французски, к сожалению:)
Чтобы ответить на исходный вопрос, вы можете использовать что-то вроде:
Convert() {
ffmpeg -i "$1" -vcodec mpe4 -sameq -acodec aac -strict experimental "$1.mp4"
}
Convert_loop(){
while read -r; do
Convert $REPLY
done < $1
}
Convert_loop list.txt
Ответ 3
KISS! =)
convert() {
ffmpeg -i "$1" \
-vcodec mpe4 \
-sameq -acodec aac \
-strict experimental "${1%.*}.mp4"
}
while read line; do
convert "$line"
done < list.txt