Der grundlegende Befehl für den Miniaturbildfilter lautet
ffmpeg -i in.mp4 -vf thumbnail=n=100 -vsync 0 -frame_pts 1 out%d.png
Dadurch wird aus 100 Frames ein repräsentativer Frame ausgewählt.
-vsync 0
behält die Quellzeitstempel bei.
-frame_pts 1
codiert diesen Zeitstempel im Ausgabedateinamen. Wenn Ihr Video also 24 fps hat und der Ausgabedateiname out322.png ist, wurde der Frame vom Zeitstempel 322/24
= 13.41s
des Videos übernommen.
Dies sind die relevanten Funktionen im Filter.
Der Filter arbeitet mit gepackten 8-Bit-RGB-Pixel-Frames
R1G1B1R2G2B2R3G3B3...
Das Histogramm jedes Frames wird wie folgt berechnet:
// 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]; }
Für jedes Pixel werden die Werte von drei Feldelementen inkrementiert. Ihr Index sind die Farbwerte (gemäß dem oben gezeigten Datenlayout angepasst) dieser Pixelkomponenten.
Dann wird das durchschnittliche Histogramm eines Clusters berechnet.
// 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; }
Für jeden Komponentenfarbwert wird die Anzahl über alle Frames gemittelt.
Dann wird der beste Rahmen gewählt.
// 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; }
wobei die Summe der Fehlerquadrate wie folgt ist
for (i = 0; i < HIST_SIZE; i++) { err = median[i] - (double)hist[i]; sum_sq_err += err*err; }
HIST_SIZE = 3 x 256 = 768.