使用嵌套 while 循环进行 ffmpeg 处理

使用嵌套 while 循环进行 ffmpeg 处理

我正在尝试使用 的ffmpeg功能signature对文本文件中列出的数千个视频文件执行重复分析vids.list。我需要它,以便将每个文件与其他文件进行比较,然后删除列表中的该行。以下是我到目前为止所拥有的:

#!/bin/bash

home="/home/user/"
declare -i lineno=0

while IFS="" read -r i; do
    /usr/bin/ffmpeg -hide_banner -nostats -i "${i}" -i "$(while IFS="" read -r f; do
        echo "${f}"
    done < ${home}/vids.list)" \
    -filter_complex signature=detectmode=full:nb_inputs=2 -f null - < /dev/null
    let ++lineno
    sed -i "1 d" ${home}/vids.list
done < vids.list 2> ${home}/out.log

ffmpeg输出“太多参数”,因为内部 while 循环将所有文件名转储到第二个-i.我不确定是否需要wait某个地方(或格式化选项)来在顶部 while 循环完成时保持循环打开。只是为了澄清,我需要循环从带有路径的文本文件的第 1 行开始,将该文件与第 2、3、4...2000(或其他)行中的文件进行比较,删除第 1 行,然后继续。

答案1

回避确切的命令,我想你想要这样的东西(带有明显的四行输入)?

$ bash looploop.sh 
run ffmpeg with arguments 'alpha' and 'beta'
run ffmpeg with arguments 'alpha' and 'charlie'
run ffmpeg with arguments 'alpha' and 'delta'
run ffmpeg with arguments 'beta' and 'charlie'
run ffmpeg with arguments 'beta' and 'delta'
run ffmpeg with arguments 'charlie' and 'delta'

我们已经知道如何创建一个循环,所以让我们添加另一个循环,嵌套在第一个循环中。它本身会将所有输入行与其自身和所有对匹配两次,因此对行进行计数以跳过已处理的对。

#!/bin/bash

i=0
while IFS= read a; do 
        i=$((i + 1))
        j=0
        while IFS= read b; do
                j=$((j + 1))
                if [ "$j" -le "$i" ]; then continue; fi

                # insert the actual commands here
                printf "run ffmpeg with arguments '%s' and '%s'\n" "$a" "$b"
        done < vids.list
done < vids.list

或者就像您所做的那样,删除由外循环处理的行,这实际上更短:

#!/bin/bash
cp vids.list vids.list.tmp
while IFS= read a; do 
        while IFS= read b; do
                if [ "$a" = "$b" ]; then continue; fi
                # insert the actual commands here
                printf "run ffmpeg with arguments '%s' and '%s'\n" "$a" "$b"
        done < vids.list.tmp
        sed -i '1d' vids.list.tmp
done < vids.list.tmp
rm vids.list.tmp

我不确定到底是什么导致脚本中的“参数过多”,但参数-i是一个双引号字符串,内部仅包含命令替换,因此它将作为单身的参数ffmpeg(带有嵌入的换行符echo)。它不应该导致太多争论。

答案2

那这个呢:

readarray -t arr < file
counter=1
for i in "${arr[@]}"; do 
  for k in "${!arr[@]}"; do 
    if [[ ! -z "${arr[$k+$counter]}" ]]; then 
      f1="${i}"
      f2="${arr[$k+$counter]}"
      ffmpeg -hide_banner -nostats -i "${f1}" -i "${f2}" -filter_complex signature=detectmode=full:nb_inputs=2 -f null - < /dev/null
    else
      break
    fi
  done
  (( counter++ ))
done

相关内容