答案1
缩略图过滤器的基本命令是
ffmpeg -i in.mp4 -vf thumbnail=n=100 -vsync 0 -frame_pts 1 out%d.png
这将从每 100 帧中选择一个代表帧。
-vsync 0
保留源时间戳。
-frame_pts 1
将该时间戳编码到输出文件名中。因此,如果您的视频为 24 fps,并且输出文件名为 out322.png,则该帧取自视频的时间戳322/24
= 。13.41s
这些是过滤器中的相关函数,
该滤镜适用于压缩的 8 位 RGB 像素帧,即
R1G1B1R2G2B2R3G3B3...
每帧的直方图计算如下,
// update current frame RGB histogram
for (j = 0; j < inlink->h; j++) {
for (i = 0; i < inlink->w; i++) {
hist[0*256 + p[i*3 ]]++;
hist[1*256 + p[i*3 + 1]]++;
hist[2*256 + p[i*3 + 2]]++;
}
p += frame->linesize[0];
}
对于每个像素,三个数组元素的值都会增加。它们的索引是这些像素组件的颜色值(根据上面显示的数据布局进行调整)。
然后,计算一个簇的平均直方图。
// average histogram of the N frames
for (j = 0; j < FF_ARRAY_ELEMS(avg_hist); j++) {
for (i = 0; i < nb_frames; i++)
avg_hist[j] += (double)s->frames[i].histogram[j];
avg_hist[j] /= nb_frames;
}
对于每个组成颜色值,它们在所有帧中的计数是平均的。
然后选择“最佳”框架,
// find the frame closer to the average using the sum of squared errors
for (i = 0; i < nb_frames; i++) {
sq_err = frame_sum_square_err(s->frames[i].histogram, avg_hist);
if (i == 0 || sq_err < min_sq_err)
best_frame_idx = i, min_sq_err = sq_err;
}
其中误差平方和如下
for (i = 0; i < HIST_SIZE; i++) {
err = median[i] - (double)hist[i];
sum_sq_err += err*err;
}
HIST_SIZE = 3 x 256 = 768。