如何将示例 00:03:03.333、00:01:01.111 和 00:02:02.222 的总和放入变量中
EPOCH='jan 1 1970'
offset=$EPOCH
lsdvd -c VIDEO_TS | grep "Length:" | grep "Chapter:" | awk '{print($4)}' | while read -r len
do
len=${len:0:12}
offset="$(date -u -d "$EPOCH $len" +%T.%3N) + $(date -u -d "$offset" +%T.%3N)"
echo "need sum" $offset "then" ffmpeg -ss $offset ... -t $len ...
done
答案1
sh 只能进行整数算术,因此您必须使用其他东西,例如bc
(或可以进行非整数算术的语言,例如 awk 或 perl)。
要使用bc
,首先必须将 %H:%M:%S.%3N 格式转换为秒(包括小数部分),然后通过管道将其传输到bc
。
例如:
#!/bin/bash
epoch='1970-01-01'
len1='00:01:01.111'
len2='00:02:02.222'
# convert to seconds
len1_s=$(date -u -d "$epoch $len1" '+%s.%3N')
len2_s=$(date -u -d "$epoch $len2" '+%s.%3N')
# add the seconds
sum_s=$( echo "$len1_s + $len2_s" | bc )
echo $len1_s + $len2_s = $sum_s
# convert back to H:M:S.N
sum=$(date -u -d "@$sum_s" '+%T.%3N')
echo $len1 + $len2 = $sum
输出:
$ ./sum.sh
61.111 + 122.222 = 183.333
00:01:01.111 + 00:02:02.222 = 00:03:03.333
我将在 while 循环中将其实现留给您......但我会注意到它lsdvd
有一些有用的输出选项,可以在几秒钟内为您提供章节长度(因此您不需要转换它们)。最有用的可能是 XML 输出选项,然后可以使用它进行处理xmlstarlet
或xml2
提取章节长度。
例如,这里的lsdvd
XML 输出转换为面向行的格式(适合使用 awk 或其他方式处理),使用xml2
:
这是一个约 48 分钟的视频,共有 11 个章节,其中大部分长度约为 5 分钟(300 秒)。
$ lsdvd -c -Ox '/path/to/some/dvd.iso' | xml2
/lsdvd/device=/path/to/some/dvd.iso
/lsdvd/title=TITLE
/lsdvd/vmg_id=DVDVIDEO-VMG
/lsdvd/provider_id=PROVIDER
/lsdvd/track/ix=1
/lsdvd/track/length=2874.667
/lsdvd/track/vts_id=DVDVIDEO-VTS
/lsdvd/track/chapter/ix=1
/lsdvd/track/chapter/length=299.934
/lsdvd/track/chapter/startcell=1
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=2
/lsdvd/track/chapter/length=299.500
/lsdvd/track/chapter/startcell=2
/lsdvd/track/chapter
/lsdvd/track/chapter/ix=3
/lsdvd/track/chapter/length=300.000
/lsdvd/track/chapter/startcell=3
[...]
/lsdvd/track/chapter/ix=11
/lsdvd/track/chapter/length=176.734
/lsdvd/track/chapter/startcell=11
/lsdvd/longest_track=1
这是一个很多与默认的人类可读输出相比,在脚本中更容易处理lsdvd
。例如,如果我只想以秒为单位的章节长度:
$ lsdvd -c -Ox /path/to/some/dvd.iso' | xml2 | \
awk -F'[/=]' '$5 == "length" { print $6 }'
299.934
299.500
300.000
299.500
300.000
299.500
299.500
300.000
299.500
0.500
176.734
我还要指出,如果您使用 awk,则不需要 grep。因此,如果您想使用人类可读的输出,您的grep | grep | awk
(以及len=${len:0:12}
去除尾随逗号)可以减少为:
lsdvd -c VIDEO_TS | awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }' | \
while read len
字段分隔符此处定义为一个或多个空格或逗号。
$ lsdvd -c '/path/to/some/dvd.iso' | \
awk -F' +|,' '/Chapter:/ && /Length:/ { print $5 }'
00:04:59.934
00:04:59.500
00:05:00.000
00:04:59.500
00:05:00.000
00:04:59.500
00:04:59.500
00:05:00.000
00:04:59.500
00:00:00.500
00:02:56.734