脚本分享-使用ffmepg对视频截图

介绍

依赖于ffmpeg,允许传递起始时间、截图间隔、截图数量、视频文件地址等四个参数,其中时间单位为秒。

我在Linux Alpine中使用,可能部分依赖在其它Linux环境中会遇到问题,欢迎评论告知。

示例

1
2
3

sh snapshot.sh 600 800 6 Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265.mkv

你会得到六个文件,文件命名如下:

1
2
3
4
5
6
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_001.jpg
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_002.jpg
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_003.jpg
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_004.jpg
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_005.jpg
Dune.Part.Two.2024.2160p.WEB-DL.DV.HDR10+.DDP5.1.Atmos.H265_frame_006.jpg





脚本文件

snapshot.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/sh

# 检查参数个数是否满足要求
if [ $# -lt 4 ]; then
echo "用法: sh ffmepg-snapshot.sh 起始时间 截图间隔 截图数量 视频文件"
exit 1
fi

# 获取起始时间、截图间隔和截图数量
start_time=$1 # 起始时间
interval=$2 # 截图间隔
num_images=$3 # 截图数量
input_video=$4 # 视频文件

# 检查起始时间、间隔和截图数量是否为正整数
if ! echo "$start_time" | grep -qE '^[0-9]+$' || ! echo "$interval" | grep -qE '^[0-9]+$' || ! echo "$num_images" | grep -qE '^[0-9]+$'; then
echo "错误:起始时间、时间间隔和截图数量必须是正整数!"
exit 1
fi

# 检查视频文件是否存在
if [ ! -f "$input_video" ]; then
echo "错误:视频文件 $input_video 不存在!"
exit 1
fi

# 获取视频文件名(去掉扩展名)
filename=$(basename -- "$input_video")
basename="${filename%.*}"

# 提取图像
i=0
while [ $i -lt $num_images ]; do
# 使用 expr 进行数学计算
timestamp=$(expr $start_time + $i \* $interval)

# 确保时间戳不为空并且格式正确
if [ -z "$timestamp" ] || [ "$timestamp" -lt 0 ]; then
echo "错误:无效的时间戳 $timestamp,跳过此帧。"
continue
fi

# 输出计算的时间戳
echo "提取图像,时间戳:$timestamp 秒"

# 使用 ffmpeg 提取图像
ffmpeg -ss "$timestamp" -i "$input_video" -vframes 1 -q:v 2 "${basename}_frame_$(printf "%03d" $(expr $i + 1)).jpg"

# 增加图片索引
i=$(expr $i + 1)
done

echo "已从视频 $input_video 提取 $num_images 张图像,文件名格式为 ${basename}_frame_001.jpg, ${basename}_frame_002.jpg, ..."