如何获取当前文件夹和子目录中所有视频文件的总时长

如何获取当前文件夹和子目录中所有视频文件的总时长

我试图获取当前目录及其子目录中所有以 .mp4 结尾的一堆文件的持续时间。我正在尝试使用 ffprobe。为了简单起见,我没有使用 find,而是使用 ls。如果它只列出以秒为单位的持续时间,那就没问题了,因为将它们全部总结起来可能超出了我的范围!

我目前的努力是这样的:

 ls -a * |grep .mp4$|xargs ffprobe

由此可见

参数“SomeVideo.mp4”作为输入文件名提供,但已指定“DifferentVideo.mp4”。

我怎样才能做到这一点? ffprobe 不能一次只处理通过管道传递的一个文件吗?

答案1

exiftool

$ exiftool -ext mp4 -r -n -q -p '${Duration;$_ = ConvertDuration(our $total += $_)}' . | tail -n 1
4 days 22:14:59

主要区别于@don_cristi 对一个非常相似的问题的回答,它-r -ext mp4让 exiftool 可以递归地查找带有extensions 的文件r

答案2

为了满足您的基本需求,您应该迭代这些文件,一次将它们传递到ffprobe.这将允许您获取以小时、分钟、秒为单位的持续时间。

for mp4 in *.mp4
do
    echo "Processing $mp4"
    ffprobe "$mp4" 2>&1 | awk '/Duration/ {print $2}'
done

稍微环顾四周更仔细地,可以ffprobe直接传递秒数

for mp4 in *.mp4
do
    echo "Processing $mp4"
    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$mp4"
done

完成此操作后,将它们全部加在一起并不是一个巨大的飞跃

for mp4 in *.mp4
do
    echo "Processing $mp4"
    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$mp4"
done |
    awk -F '
        { sec += $1 }                                                # Total time (seconds)
        END {
            h = int(sec / 3600);                                     # Hours
            m = int((sec - (h*3600)) / 60);                          # Minutes
            s = sec - (h*3600) - (m*60);                             # Seconds
            printf "%d (%d hour, %d min, %d sec)\n", sec, h, m, s    # Print the result
        }
    '

最后,为了不仅处理当前目录下的文件,还处理所有子目录下的文件,请修改外层循环。下一步使用允许匹配子目录的bash功能**

shopt -s globstar                                                    # Enable extended globbing
for mp4 in **/*.mp4
do
    echo "Processing $mp4"
    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$mp4"
done |
    # Continue as before...

答案3

xargs将在命令中添加尽可能多的输入参数 - 它不知道单个文件的限制ffprobe

如果您想ffprobe每个输入运行一次,请使用

 ... | xargs -l ffprobe 

或者

 ... |  xargs -L 1 ffprobe

为了理解,只需比较这两个命令的输出

  seq 1 3 | xargs echo
  seq 1 3 | xargs -l echo

请注意,ls出于多种原因,不鼓励使用 -output 作为输入。

更好地使用find- 尽管你努力简化 - 最好使用 -NULL分隔符来避免特殊字符的问题:

find -maxdepth 1 -name '*mp4' -print0 | xargs -0 ffprobe

ffprobe下一个问题是- get Seconds only 就像 did 的输出这里。然后你可以使用例如来总结它awk

相关内容