远程获取服务器上的视频文件的截图或生成缩略图

whdahanh 发布于 2025-09-29 165 次阅读


服务器安装FFmpeg

FFmpeg 可以直接解码某一帧输出为图片,而不需要完整播放。

sudo apt install ffmpeg   # Debian/Ubuntu
sudo yum install ffmpeg   # CentOS/RHEL

截取第10秒的一帧为jpg图片:

ffmpeg -ss 10 -i input.mp4 -frames:v 1 -q:v 2 output.jpg

参数说明:
-ss 10:跳转到第 10 秒
-frames:v 1:只取 1 帧
-q:v 2:输出图片质量(1-31,数值越小质量越高)

生成缩略图拼图

每隔100帧取一帧,缩放后拼成 4x4 的缩略图。
输出文件 preview.jpg 只有一张图片。
图片上包含 最多 16 帧的缩略图(4x4)。
如果视频很短,不够16帧,tile会显示实际帧数。

ffmpeg -i input.mp4 -vf "select=not(mod(n\,100)),scale=320:-1,tile=4x4" -frames:v 1 preview.jpg

从服务器上下载截图

可以使用scp命令或者使用python直接启动一个web服务器。

#scp 命令
scp root@ip:/root/downloads/snapshot_1.jpg .
#python http服务器
python3 -m http.server 8080

一键脚本

一键截图的脚本,根据入参可以控制生成N张截图或者生成tile缩略图,完整脚本放在文章最后面。

# 创建脚本
vim snapshot.sh
# 赋予执行权限
chmod +x snapshot.sh
# 单张截图,脚本single模式 默认3张,后面可以指定数量
./snapshot.sh "视频路径.mp4" single 4
# 合成缩略图 默认模式16帧聚合的4*4缩略图
./snapshot.sh "视频路径.mp4" tile
# 合成缩略图 tile 后可以跟帧数 聚合的行列
./snapshot.sh "视频路径.mp4" tile 4 2 2
./snapshot.sh "视频路径.mp4" tile 16 4 4
./snapshot.sh "视频路径.mp4" tile 12 3 4

single模式生成多张截图

single模式可以生成多张独立的截图,默认生成3张截图,后面可以跟参数生成指定数量的截图。

# single 模式
root:/root/snapshot# ./snapshot.sh ./Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv single
生成独立截图: ./snapshot_1.jpg (时间点: 8991s)
生成独立截图: ./snapshot_2.jpg (时间点: 8623s)
生成独立截图: ./snapshot_3.jpg (时间点: 6047s)
# 目录下已经生成了三张截图
root:/root/snapshot# ls -l
-rwxrwx--x+ 1 root root 7900246136 Sep  4 21:48 Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv
-rw-rw----+ 1 root root     110018 Sep  4 21:51 snapshot_1.jpg
-rw-rw----+ 1 root root      87851 Sep  4 21:51 snapshot_2.jpg
-rw-rw----+ 1 root root      80915 Sep  4 21:51 snapshot_3.jpg

# 指定数量的single模式
root:/root/snapshot# ./snapshot.sh ./Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv single 4
root:/root/snapshot# ./snapshot.sh ./Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv single 8

tile模式生成缩略图

tile模式可以生成多张截图聚合而成的一张完整的缩略图,默认是16张截图生成的4*4的缩略图。
后面可以跟帧数,行数,列数三个参数,帧数的值要等于行数列数的乘积,例如16 4 412 3 4

# tile 模式 默认生成16张截图合成的缩略图
root:/root/snapshot# ./snapshot.sh Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv tile
生成临时截图: ./tmp_0.jpg (时间点: 218s)
生成临时截图: ./tmp_1.jpg (时间点: 687s)
生成临时截图: ./tmp_2.jpg (时间点: 1831s)
生成临时截图: ./tmp_3.jpg (时间点: 2687s)
生成临时截图: ./tmp_4.jpg (时间点: 2747s)
生成临时截图: ./tmp_5.jpg (时间点: 3773s)
生成临时截图: ./tmp_6.jpg (时间点: 4340s)
生成临时截图: ./tmp_7.jpg (时间点: 4825s)
生成临时截图: ./tmp_8.jpg (时间点: 5832s)
生成临时截图: ./tmp_9.jpg (时间点: 6393s)
生成临时截图: ./tmp_10.jpg (时间点: 6851s)
生成临时截图: ./tmp_11.jpg (时间点: 7583s)
生成临时截图: ./tmp_12.jpg (时间点: 8277s)
生成临时截图: ./tmp_13.jpg (时间点: 9201s)
生成临时截图: ./tmp_14.jpg (时间点: 9687s)
生成临时截图: ./tmp_15.jpg (时间点: 10841s)
生成 4x4 缩略图: ./preview.jpg

# 指定数量的tile模式
root:/root/snapshot# ./snapshot.sh Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv tile 12 3 4
root:/root/snapshot# ./snapshot.sh Avengers.Endgame.2019.BluRay.1080p.x265.10bit.MNHD.mkv tile 4 2 2

完整脚本内容

#!/bin/bash
# 用法: ./snapshot.sh <视频路径> <模式: single|tile> [数量] [tile行数] [tile列数]
# single 模式下数量可选,默认 3 张
# tile 模式下数量、行数、列数可选,默认 16 帧、4x4,截图均匀分布
 
VIDEO="$1"
MODE="$2"
COUNT="$3"
TILEROW="$4"
TILECOL="$5"
OUTDIR="."  # 输出当前目录
 
if [ -z "$VIDEO" ] || [ -z "$MODE" ]; then
  echo "用法: $0 <视频路径> <模式: single|tile> [数量] [tile行数] [tile列数]"
  exit 1
fi
 
# 获取视频时长(秒)
DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$VIDEO")
DURATION=${DURATION%.*}
 
if [ "$MODE" == "single" ]; then
  if [ -z "$COUNT" ]; then COUNT=3; fi  # 默认 3 张
  for i in $(seq 1 $COUNT); do
    RAND=$(shuf -i 0-$((DURATION-1)) -n 1)
    OUT="$OUTDIR/snapshot_$i.jpg"
    ffmpeg -ss "$RAND" -i "$VIDEO" -frames:v 1 -q:v 2 "$OUT" -y -loglevel quiet
    echo "生成独立截图: $OUT (时间点: ${RAND}s)"
  done
 
elif [ "$MODE" == "tile" ]; then
  if [ -z "$COUNT" ]; then COUNT=16; fi
  if [ -z "$TILEROW" ]; then TILEROW=4; fi
  if [ -z "$TILECOL" ]; then TILECOL=4; fi
 
  TMPFILES=()
 
  # 均匀分布生成随机时间点
  INTERVAL=$((DURATION / COUNT))
  for i in $(seq 0 $((COUNT-1))); do
    START=$((i * INTERVAL))
    END=$(((i+1) * INTERVAL - 1))
    if [ $END -lt $START ]; then END=$START; fi
    RAND=$(shuf -i $START-$END -n 1)
    TMP="$OUTDIR/tmp_$i.jpg"
    TMPFILES+=("$TMP")
    ffmpeg -ss "$RAND" -i "$VIDEO" -frames:v 1 -q:v 2 "$TMP" -y -loglevel quiet
    echo "生成临时截图: $TMP (时间点: ${RAND}s)"
  done
 
  # 使用 glob 模式生成 tile
  ffmpeg -pattern_type glob -i "$OUTDIR/tmp_*.jpg" -filter_complex "tile=${TILECOL}x${TILEROW}" -frames:v 1 "$OUTDIR/preview.jpg" -y -loglevel info
 
  # 检查拼图是否生成成功,再删除临时文件
  if [ -f "$OUTDIR/preview.jpg" ]; then
    rm -f "${TMPFILES[@]}"
    echo "生成 ${TILEROW}x${TILECOL} 缩略图: $OUTDIR/preview.jpg"
  else
    echo "拼图生成失败,请检查 FFmpeg 日志"
  fi
 
else
  echo "模式错误,只能是 single 或 tile"
  exit 1
fi


微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2025-09-29