我想知道如何计算帧中两个视频时间码之间的差异(在这种情况下,第二个等于30帧)。
假设A点是600(00:00:02),B点是120(00:00:04)。
如何计算pont A和B之间的差异,并使用bash以00:00:00.00格式(h:m:s)回显结果?
更新:
答案 0 :(得分:3)
首先,export
语句是多余的,因为当前的shell正在展开$A
和$B
。
要从时间戳中获取这些数字,GNU date
将有所帮助:
jinx:752 Z$ date -d 00:01:18.44 +%T.%N # to show that it works
00:01:18.440000000
jinx:753 Z$ date -d 00:01:18.44 +%s.%N
1299214878.440000000
现在你可以进行计算,然后在最后翻译显示(正如Edwin Buck所说,不要试图以这种格式存储中间结果):
jinx:754 Z$ date -d @1299214878.44 +%T.%N
00:01:18.440000000
答案 1 :(得分:1)
将所有时间保留在“帧”中,然后通过单个格式化例程将帧显示为时间。如果你试图转换为时间,你将使数学转换更加困难(因为时间是基础60系统)。
frames2date () {
local secs=$((2 * $1));
date --utc --date "1970-01-01 ${secs} sec" "+%T"
}
应将帧数转换为时间,请注意,如果时间超过24小时,则需要添加年,月和日。
答案 2 :(得分:0)
(不完美)解决方案:
在朋友的帮助下,这是我完整的bash脚本:
#!/bin/bash
#ffmpeg [inputfile] [starttimecode] [videoduration] [video details] [size] [audio details] [alltherest] [outputfile]
video=-'vcodec libx264 -vpre slower -crf 22'
size='-s 320x240'
audio='-acodec libmp3lame -aq 0 -ac 1'
in=$(date --utc --date "$3" +%s)
out=$(date --utc --date "$4" +%s)
dur=$(date --utc --date "1970-01-01 $[$out-$in] sec" "+%T")
ss=$(date --utc --date "1970-01-01 $[$in] sec" "+%T")
ffmpeg -i $1.$2 $video $size $audio -threads 0 -y $1.mp4
#ffmpeg -i t1.flv -ss 00:00:32 -t 00:00:04 -vcodec libx264 -vpre slower -crf 22 -s 320x240 -acodec libmp3lame -aq 0 -ac 1 -threads 0 -y t1.mp4
我将脚本保存为“v”,这是我从cli中调用它的方式:
v t1 flv 00:00:32.658 00:00:36.060
这样我可以直接从ffmpeg cli剪切视频文件的一部分。但是时间码之间的计算并不十分精确,所以我需要更多地研究它来实现这个目标:http://www.1728.com/angle.htm
答案 3 :(得分:0)
这是另一种不使用日期工具的方法:
function timecode_to_int() {
if [[ "$1" =~ ^((0*([0-9]+):)?0*([0-9]+):)?0*([0-9]+)(\.([0-9]{1,3}))? ]]; then
VALUE=$((${BASH_REMATCH[5]}))
[[ -n "${BASH_REMATCH[4]}" ]] && VALUE=$((${BASH_REMATCH[4]}*60+$VALUE))
[[ -n "${BASH_REMATCH[3]}" ]] && VALUE=$((${BASH_REMATCH[3]}*60*60+$VALUE))
VALUE=$(($VALUE*1000))
if [[ -n "${BASH_REMATCH[7]}" ]]; then
VALUE=$(($VALUE+10#$(printf %-3s ${BASH_REMATCH[7]} | sed s_\ _0_g)))
fi
echo "${VALUE}"
else
echo "Invalid timecode '$1', aborting." >&2
exit 1
fi
}
function int_to_timecode() {
MILLISECONDS="$(($1%1000))"
SECS="$(($1/1000%60))"
MINUTES="$(($1/1000/60%60))"
HOURS="$(($1/1000/60/60))"
if [[ $HOURS -ne 0 ]]; then
printf "%d:%02d:%02d" $HOURS $MINUTES $SECS
elif [[ $MINUTES -ne 0 ]]; then
printf "%d:%02d" $MINUTES $SECS
else
printf "%d" $SECS
fi
if [[ ${MILLISECONDS} -ne 0 ]]; then
printf ".%03d" $MILLISECONDS | sed s_0*\$__
fi
}
# To answer your question completely:
echo $(int_to_timecode $(($(timecode_to_int "00:00:04")-$(timecode_to_int "00:00:02"))))