O comando básico para o filtro de miniaturas é
ffmpeg -i in.mp4 -vf thumbnail=n=100 -vsync 0 -frame_pts 1 out%d.png
Isso selecionará um quadro representativo de cada 100 quadros.
-vsync 0
preserva os timestamps de origem.
-frame_pts 1
codifica esse registro de data e hora no nome do arquivo de saída. Por isso, se o seu vídeo tiver 24 fps e o nome do ficheiro de saída for out322.png, esse frame foi retirado do timestamp 322/24
= 13.41s
do vídeo.
Estas são as funções relevantes no filtro
O filtro funciona com quadros de pixels RGB de 8 bits compactados, ou seja,
R1G1B1R2G2B2R3G3B3...
O histograma de cada quadro é calculado da seguinte forma,
// 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];
}
Para cada pixel, os valores de três elementos da matriz são incrementados. Seu índice é os valores de cor (ajustados conforme o layout de dados mostrado acima) desses componentes de pixel.
Em seguida, o histograma médio de um cluster é calculado.
// 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;
}
Para cada valor de cor do componente, é calculada a média de sua contagem em todos os quadros.
Em seguida, o quadro "melhor" é escolhido,
// 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;
}
em que a soma dos erros quadrados é a seguinte
for (i = 0; i < HIST_SIZE; i++) {
err = median[i] - (double)hist[i];
sum_sq_err += err*err;
}
HIST_SIZE = 3 x 256 = 768.