使用 ffmpeg 进行缩略图选择

使用 ffmpeg 进行缩略图选择

这是来自这里。我想使用及其过滤器kn给定视频的帧数中抽取帧。有一篇帖子FFMpegthumbnail这里提供一些如何选择的见解有意义的帧。然而,在那道题中,要求是选择场景变化高于%40阈值的帧。在我的例子中,情况正好相反。我认为我们应该选择具有最低场景与之前相比发生了变化(通常在视频中当某个东西聚焦时,场景更稳定并且相机不会移动太多)。

如何使用 来实现这一点FFMpeg?我们还可以对框架进行聚类并挑选代表吗?

答案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。

相关内容