我有一个文件列表.ts
:
out1.ts ... out749.ts out8159.ts out8818.ts
如何获取所有这些文件的总持续时间(运行时间)?
答案1
我这里没有.ts
(仅.mp4
),但这应该适用于所有视频文件:
使用ffprobe
(部分ffmpeg
)获取以秒为单位的时间,例如:
ffprobe -v quiet -of csv=p=0 -show_entries format=duration Inception.mp4
275.690000
因此,对于所有视频文件,您可以使用循环for
并awk
计算总时间(以秒为单位):
for f in ./*.mp4
do ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$f"
done | awk '{sum += $1}; END{print sum}'
2735.38
要进一步处理输出以将总计转换为DD:HH:MM:SS
,请参阅答案这里。
另一种方式是 via exiftool
,它有一个内部ConvertDuration
:
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
}' ./*.mp4 | tail -n1
0:45:35
答案2
这使用ffmpeg
并打印总超时秒数:
times=()
for f in *.ts; do
_t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
times+=("$_t")
done
echo "${times[@]}" | sed 's/ /+/g' | bc
解释:
for f in *.ts; do
迭代每个以“.ts”结尾的文件
ffmpeg -i "$f" 2>&1
将输出重定向到 stderr
grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' '
隔离时间
awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
将时间转换为秒
times+=("$_t")
将秒数添加到数组中
echo "${times[@]}" | sed 's/ /+/g' | bc
展开每个参数并替换空格并将其通过管道传输到bc
常见的 Linux 计算器
答案3
精简@jmunsch 的回答,并使用paste
我刚刚学到的@slm 的回答,你最终可能会得到这样的结果:
for i in *.ts; do LC_ALL=C ffmpeg -i "$i" 2>&1 | \
awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done | paste -sd+ | bc
就像 jmunsch 所做的那样,我用来ffmpeg
打印持续时间,忽略有关丢失输出文件的错误,而是在错误输出中搜索持续时间行。我将ffmpeg
语言环境的所有方面强制为标准 C 语言环境进行调用,这样我就不必担心本地化的输出消息。
接下来我用一个单一的awk
而不是他的grep | grep | head | tr | awk
。该awk
调用会查找包含 的(希望是唯一的)行Duration:
。使用冒号作为分隔符,该标签是字段 1,小时是字段 2,分钟是字段 3,秒是字段 4。秒后面的逗号似乎不会打扰我awk
,但如果有人在那里遇到问题,他可以在和tr -d ,
之间的管道中包含。ffmpeg
awk
现在来自 slm 的部分:我用来用paste
加号替换换行符,但不影响尾随换行符(与tr \\n +
我在以前的版本这个答案)。这给出了可以输入到 的总和表达式bc
。
受到 slm 用于date
处理类似时间格式的想法的启发,这里有一个版本,它使用它来将结果秒格式化为带小数部分的天、小时、分钟和秒:
TZ=UTC+0 date +'%j %T.%N' --date=@$(for i in *.ts; do LC_ALL=C \
ffmpeg -i "$i" 2>&1 | awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done \
| paste -sd+ | bc) | awk '{print $1-1 "d",$2}' | sed 's/[.0]*$//'
里面的部分$(…)
和以前一模一样。使用该@
字符作为指示,我们将其用作自 1970 年 1 月 1 日以来的秒数。生成的“日期”格式为一年中的日期、时间和纳秒。我们从一年中的这一天减去一,因为输入零秒已经导致 1970 年的第一天。我认为没有办法让一年中的某一天从零开始计数。
最后的结果sed
去掉了多余的尾随零。该TZ
设置应该强制使用 UTC,这样夏令时就不会干扰真的大型视频收藏。不过,如果您有超过一年的视频,这种方法仍然行不通。