如何在shell脚本中将数字转换为时间格式?

如何在shell脚本中将数字转换为时间格式?

我想把一个视频剪成这样10分钟左右的部分。

ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 01.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 02.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 03.mp4

有了for它就会这样。

for i in `seq 10`; do ffmpeg -i video.mp4 -ss 00:${i}0:00 -t 00:10:00 -c copy ${i].mp4; done;

但它仅在持续时间低于一小时的情况下才有效。如何在 bash shell 中将数字转换为时间格式?

答案1

BASH 对于这个问题来说还不错。您只需要使用非常强大但未充分利用的date命令。

for i in {1..10}; do
  hrmin=$(date -u -d@$(($i * 10 * 60)) +"%H:%M")
  outfile=${hrmin/:/-}.mp4
  ffmpeg -i video.mp4 -ss ${hrmin}:00 -t 00:10:00 -c copy ${outfile}
done

date命令解释

date带有-d标志允许您设置哪个您想要显示的日期(而不是默认的当前日期和时间)。在本例中,我通过@在整数前添加符号将其设置为 UNIX 时间。本例中的整数是以十分钟为单位的时间(由 BASH 内置计算器计算:)$((...))

+符号表明date您想要指定显示结果的格式。在我们的例子中,我们只关心小时 ( %H) 和分钟 ( %M)。

最后,将-u显示为 UTC 时间而不是本地时间。这在本例中很重要,因为当我们给它 UNIX 时间时,我们将时间指定为 UTC(UNIX 时间始终为 UTC)。如果您未指定 ,则数字很可能不会从 0 开始-u

BASH 变量替换解释

date命令给了我们我们所需要的东西。但文件名中的冒号可能有问题/不标准。因此,我们将“:”替换为“-”。这可以通过sedorcut或命令来完成tr,但是因为这是一个如此简单的任务,为什么当 BASH 可以做到时生成一个新的子 shell 呢?

这里我们使用BASH的简单表达式替换。为此,变量必须包含在大括号 ( ${hrmin}) 内,然后使用标准的正斜杠表示法。第一个斜杠之后的第一个字符串是搜索模式。第二个斜杠之后的第二个字符串是替换。

BASH 变量替换和更多内容可以在以下位置找到http://tldp.org/LDP/abs/html/parameter-substitution.html

答案2

它稍微复杂一些,但你可以在 bash 中轻松完成。下面的示例是一个 2 小时的视频,您可以n<=11相应地设置限制 ( ):

k=0; 
i=00;
for ((n=0;n<=11;n++)); do
  if [ $i -ge 60 ]; then 
    let k++; i=00; 
  fi; 
  ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4; 
  let i+=10; 
done

echo您可以通过在该行中添加一个来查看它的作用ffmpeg

echo "ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4";

这将打印:

ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 000.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 010.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 020.mp4
ffmpeg -i video.mp4 -ss 00:30:00 -t 00:10:00 -c copy 030.mp4
ffmpeg -i video.mp4 -ss 00:40:00 -t 00:10:00 -c copy 040.mp4
ffmpeg -i video.mp4 -ss 00:50:00 -t 00:10:00 -c copy 050.mp4
ffmpeg -i video.mp4 -ss 01:00:00 -t 00:10:00 -c copy 100.mp4
ffmpeg -i video.mp4 -ss 01:10:00 -t 00:10:00 -c copy 110.mp4
ffmpeg -i video.mp4 -ss 01:20:00 -t 00:10:00 -c copy 120.mp4
ffmpeg -i video.mp4 -ss 01:30:00 -t 00:10:00 -c copy 130.mp4
ffmpeg -i video.mp4 -ss 01:40:00 -t 00:10:00 -c copy 140.mp4
ffmpeg -i video.mp4 -ss 01:50:00 -t 00:10:00 -c copy 150.mp4

答案3

这是一个简单的数学:小时数字是$((i%3600),分钟数字是$((i/60%60)),秒数字是$((i%60))。要在需要的地方添加前导零,一个简单的技巧是添加 100,然后去掉前导1。如果您想避免前导零,请对文件名执行相同的操作。

for i in $(seq 10); do
  minutes=$((i / 60 % 60 + 100)); minutes=${minutes#1}
  seconds=$((i%60)); seconds=${seconds#1}
  i=$((i+100)); i=${i#1}
  ffmpeg -i video.mp4 -ss $((i%3600):$minutes:$seconds -t 00:10:00 -c copy ${i}.mp4
done

答案4

我发现 ffmpeg 不仅接受 [HH:MM:SS] 作为时间戳格式,还接受简单的秒。

https://trac.ffmpeg.org/wiki/Seeking%20with%20FFmpeg

所以我可以这样写。

for i in `seq 10`; do ffmpeg -i video.mp4 -ss $((i*10*60)) -t 00:10:00 -c copy ${i].mp4; done;

相关内容