L'attività e perché è più complicata di quanto sembri

"Dammi un fotogramma al secondo da questa clip" è una delle attività video più comuni che ci siano. Un tester del QA ha bisogno di screenshot equidistanti da allegare a una segnalazione di bug. Un ricercatore ha bisogno di una sequenza di immagini campionate da inserire in uno strumento di annotazione. Un editor social ha bisogno di venti fotogrammi candidati da un montaggio di due minuti senza strofinare manualmente la sequenza temporale.

L'operazione in sé è semplice. Ciò che lo rende complicato è che "un fotogramma al secondo" è ambiguo nel momento in cui guardi da vicino. Intendi un fotogramma per ogni secondo di riproduzione o ogni Nesimo fotogramma dello stream codificato? Queste sono cose diverse: una clip da 24 fps e una clip da 60 fps producono lo stesso conteggio nella prima lettura e conteggi molto diversi nella seconda. Scegli quello sbagliato e otterrai una cartella di quasi duplicati o una sequenza troppo sparsa per essere utile.

Entrambi gli approcci riportati di seguito producono pixel identici. Differiscono nel modo in cui esprimi ciò che desideri e nella velocità con cui scopri di averlo espresso in modo errato.

Metodo 1: FFmpeg, parametro per parametro

Il comando canonico è breve:

ffmpeg -i input.mp4 -vf fps=1 -q:v 2 frame_%04d.jpg

Ogni parte è importante:

  • -i input.mp4 — il file sorgente. FFmpeg lo legge una volta, dall'inizio alla fine; non cerca di contrassegnare ogni data e ora individualmente.
  • -vf fps=1 — il filtro video che fa il lavoro vero e proprio. fps=1 significa un fotogramma di output al secondo di riproduzione, indipendentemente dal frame rate di origine. Utilizzare fps=1/5 per un fotogramma ogni cinque secondi o fps=2 per due al secondo. Questa è la lettura del tempo di riproduzione.
  • -q:v 2 — Qualità JPEG, su una scala invertita dove 2 è quasi senza perdita e 31 è fortemente compresso. Omettilo e otterrai il valore predefinito di FFmpeg, che è notevolmente più morbido di quanto la maggior parte delle persone si aspetti. Se desideri un risultato senza perdite, scrivi frame_%04d.png e rilascia completamente questo flag.
  • frame_%04d.jpg — il modello di output. %04d azzera il contatore su quattro cifre: frame_0001.jpg, frame_0002.jpg. L'imbottitura non è cosmetica; vedere il problema della numerazione di seguito.

Se vuoi che l'altro legga, ogni Nesimo fotogramma codificato anziché su ogni N secondi: il filtro cambia:

ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" -vsync vfr frame_%04d.png

Ciò mantiene i fotogrammi dove l'indice del fotogramma n è divisibile per 10 e -vsync vfr impedisce a FFmpeg di duplicare i fotogrammi per ottenere una velocità di output costante. Se lasci questo flag disattivato, otterrai molti più file di quelli richiesti, il che è un primo risultato comune e confuso.

Per limitare il lavoro a un segmento, inserisci -ss prima -i quindi FFmpeg cerca prima di decodificare anziché decodificare e scartare:

ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -vf fps=1 frame_%04d.png

Metodo 2: lo stesso lavoro in un browser

Il estrattore di frame su questo sito si associa alle stesse due letture, con l'ambiguità resa esplicita nell'interfaccia invece che nascosta in una stringa di filtro.

  1. Rilascia il file. Viene letto direttamente dal disco nella memoria del browser: non c'è caricamento, quindi una sorgente da 3 GB inizia l'elaborazione immediatamente anziché dopo un trasferimento.
  2. Scegli il metodo di estrazione. "Intervallo di tempo" è l'equivalente di fps=1/N — inserisci l'intervallo in pochi secondi. "Frame Rate (FPS)" è l'equivalente di select/mod filtro: inserisci N mantieni ogni Nesimo fotogramma.
  3. Leggi il suggerimento sul conteggio dei fotogrammi prima dell'estrazione. Questa è la parte che fa risparmiare più tempo. L'interfaccia mostra quante immagini verranno prodotte dalle tue impostazioni attuali prima Tutto funziona, quindi l'errore di 4.000 file diventa un numero che vedi anziché una cartella che scopri.
  4. Imposta formato e qualità. PNG per lossless, JPG o WebP con il cursore 10–100% quando le dimensioni contano. La posizione del cursore corrisponde a ciò -q:v controlli, espressi nel modo in cui la maggior parte delle persone li pensa.
  5. Ritaglia l'intervallo se necessario. Il dispositivo di scorrimento a doppia maniglia è il -ss/-to equivalente, con i timestamp mostrati mentre trascini.
  6. Esporta. I fotogrammi vengono visualizzati in anteprima griglia; fai clic su uno per salvarlo da solo o prendi l'intero set come un singolo ZIP.

Regola pratica per la scelta di un intervallo: per una registrazione di una persona parlante o dello schermo, 1 fotogramma ogni 2-5 secondi acquisisce ogni cambiamento di stato significativo. Per lo sport o qualsiasi cosa con movimento veloce, 2–5 fotogrammi al secondo. Prenota "ogni fotogramma" per un'analisi accurata al fotogramma: un minuto a 60 fps equivale a 3.600 immagini e diversi gigabyte di PNG.

Tre problemi che in realtà costano tempo alle persone

1. L'output è costituito da migliaia di fotogrammi quasi identici

Quasi sempre un errore di unità: intendevi "ogni 10 fotogrammi" e hai scritto fps=10, il che significa dieci fotogrammi al secondo — su una sorgente a 30 fps che contiene 3 volte più immagini rispetto alle ingenue aspettative, non 3 volte in meno.

Prima di eseguire qualsiasi cosa, esegui i calcoli. Modalità tempo di riproduzione: duration ÷ interval. Modalità indice fotogramma: duration × source_fps ÷ N. Una clip di 10 minuti a 30 fps a "ogni 10 fotogrammi" è 600 × 30 ÷ 10 = 1.800 immagini. Se quel numero ti sorprende, aggiustalo prima di iniziare piuttosto che dopo. Nello strumento browser la stessa figura appare automaticamente sotto il campo dell'intervallo.

2. L'estrazione si blocca a metà di un lungo video

Cause diverse per ciascun lato, quindi anche la correzione è diversa.

Con FFmpeg, uno stallo è solitamente correlato al disco: migliaia di PNG atterrano in una directory e il filesystem, non il decodificatore, diventa il collo di bottiglia. Scrivi in ​​una directory appena vuota, preferisci JPG quando non hai bisogno del lossless e dividi fonti molto lunghe in segmenti con -ss/-to.

Nel browser, il limite è la RAM: ogni fotogramma estratto viene mantenuto in memoria finché non scarichi ZIP. Alcune centinaia di 4K PNG equivalgono a diversi gigabyte e una scheda può essere uccisa per questo. Il modello affidabile è quello di lavorare in blocchi: usa il cursore dell'intervallo di tempo per prendere 0:00–2:00, scarica ZIP, quindi sposta l'intervallo su 2:00–4:00. Chiudere altre schede prima di un lavoro di grandi dimensioni aiuta davvero e JPG con una qualità dell'85-90% riduce di parecchie volte il carico di memoria senza alcuna differenza visibile per la maggior parte degli usi.

3. La numerazione dei fotogrammi interrompe l'ordine di importazione

Questo morde dopo che l'esportazione sembra a posto. Strumenti che ordinano i nomi dei file come testo (e la maggior parte lo fa) in ordine frame_10.png prima frame_2.png, perché "1" viene ordinato prima di "2" carattere per carattere. La sequenza viene riprodotta in modo criptato e non è chiaro il motivo.

La correzione è con riempimento zero, abbastanza ampia per il conteggio più grande che potrai mai fare. produrre. Questo è ciò che %04d è per; use %05d se potresti superare i 9.999 fotogrammi. Gli strumenti del browser si spostano automaticamente, che è il motivo principale per cui il suo output tende a cadere direttamente in un importatore di sequenze di immagini senza rinominarlo.

Quando FFmpeg è ancora la scelta giusta

Un sacco di tempo. Questo non è un caso in cui il browser vince su tutta la linea:

  • Tutto ciò che è scritto o pianificato. Un lavoro cron, un passaggio CI, una pipeline lato server: un browser non può affatto parteciparvi.
  • Batch su molti file. Un loop di shell su 200 clip è banale in FFmpeg e noioso altrove.
  • Codec che il browser non decodificherà. ProRes, DNxHD, formati fotocamera raw, contenitori insoliti. Se il browser non può riprodurlo, non può estrarlo. FFmpeg gestisce quasi tutto.
  • Filtro durante estrazione. Deinterlacciamento, ridimensionamento, conversione dello spazio colore, ritaglio, rilevamento del cambio di scena: tutto disponibile come filtri nello stesso passaggio.
  • Riproducibilità. Un comando in un README è esatto. "Imposta il cursore su qui" non lo è.

Lo strumento browser è la soluzione migliore per lavori una tantum, per chiunque non voglia installare e mantenere una toolchain per un'attività occasionale, quando la fonte è sufficientemente confidenziale da rendere importante l'elaborazione solo locale e quando si desidera esaminare i frame prima di impegnarsi nell'esportazione. Queste sono situazioni realmente diverse, non una classifica.

Riferimento rapido

Quello che vuoi FFmpeg Strumento browser
Un fotogramma al secondo -vf fps=1 Intervallo di tempo = 1
Un fotogramma ogni 5 secondi -vf fps=1/5 Intervallo di tempo = 5
Ogni decimo fotogramma codificato -vf "select=not(mod(n\,10))" -vsync vfr Modalità frame rate, N = 10
Solo dalle 13:30 alle 2:15 -ss 00:01:30 -to 00:02:15 cursore dell'intervallo di tempo
Output senza perdita di dati .png modello di output Formato = PNG
File più piccoli -q:v 5 con .jpg JPG + cursore qualità
Visualizza il conteggio prima dell'esecuzione Calcola manualmente Visualizzate sotto il campo dell'intervallo
Anteprima prima di salvare Apri la cartella di output Griglia di anteprima integrata
Automazione/batch Loop della shell, cron, CI Non possibile
ProRes, DNxHD, raw Supportato Solo ciò che il browser decodifica

Qualunque percorso tu prenda, la decisione sull'intervallo viene prima e lo strumento secondo. Scopri di quanti fotogrammi hai effettivamente bisogno, conferma il conteggio prima di iniziare e il resto è meccanico.