FFMPEG (libx264) “altezza non divisibile per 2”


188

Sto cercando di codificare un video .mp4 da un set di frame usando FFMPEG usando il codec libx264.

Questo è il comando che sto eseguendo:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4

A volte ricevo il seguente errore:

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)

Dopo aver cercato un po 'in giro sembra che il problema abbia qualcosa a che fare con l'algoritmo di ridimensionamento e può essere risolto aggiungendo un argomento -vf.

Tuttavia, nel mio caso non voglio fare alcun ridimensionamento. Idealmente, voglio mantenere le dimensioni esattamente uguali ai frame. Qualche consiglio? Esiste una sorta di rapporto di formato che h264 applica?


@AleksandrDubinsky Ma la risposta di LordNeckbeard non conserva la larghezza e l'altezza originali. Qui dobbiamo specificare manualmente la larghezza o l'altezza ... e se utilizziamo -vf scale = -2: ih o -vf scale = iw: -2 questo non lo farà funziona se sia l'altezza che la larghezza non sono uniformi..Per favore spiega come quella risposta è più ottimale? .. grazie
varmashrivastava

1
@varmashrivastava Bene, il modo in cui funziona SO è che in origine potrebbe esserci stata una domanda, quindi Google invia un gruppo di persone con una domanda diversa che poi dirottano la pagina. È quello che è, cerca di non combatterlo. La risposta corretta alla domanda originale è -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2", che non è nemmeno una delle risposte. La risposta corretta alla domanda di tutti è quella di LordNeckbeard.
Aleksandr Dubinsky,

@varmashrivastava Sono andato avanti e ho risolto la prima risposta. Spero che non venga vandalizzato dalle mod.
Aleksandr Dubinsky,

@AleksandrDubinsky grazie..e l'utente può utilizzare "scale="invece che "pad="se non desidera pixel di riempimento imbottiti?
Varmashrivastava,

Risposte:


269

La risposta alla domanda originale che non vuole ridimensionare il video è:

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

Comando:

ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

Fondamentalmente, .h264 ha bisogno di dimensioni uniformi, quindi questo filtro dovrà:

  1. Dividi l'altezza e la larghezza originali per 2
  2. Arrotondalo al pixel più vicino
  3. Moltiplicalo di nuovo per 2, rendendolo così un numero pari
  4. Aggiungi pixel di imbottitura neri fino a questo numero

È possibile modificare il colore dell'imbottitura aggiungendo il parametro filter :color=white. Vedi la documentazione del pad .


3
Non è un bug. Non importa che non si stia eseguendo il ridimensionamento poiché l'output erediterà la dimensione del frame dell'input.
Llogan,

5
Per la cronaca, stavo solo facendo qualcosa in cui ho creato un video da un'immagine e ha usato yuvj444p come formato pixel; non importava delle dimensioni del video. Quindi ho dovuto convertirlo in yuv420p e poi mi sono preoccupato delle dimensioni del video. Ho cercato yuv420p su wikipedia, penso che sia un formato di colore multi-pixel, che ha bisogno che l'immagine abbia una dimensione specifica. Non sono sicuro del motivo per cui è compresso, però.
Lahwran,

7
Probabilmente stai meglio usando il pad piuttosto che ridimensionare, per aggiungere una riga / colonna nera. Il ridimensionamento di un'immagine di un pixel la sfuocerà.
Glenn Maynard,

5
@NickeManarin, questo filtro dovrebbe funzionare aggiungere 1 pixel di imbottitura bianca alla dimensione verticale, con il video posizionato in alto a sinistra: -vf pad="width=iw:height=ih+1:x=0:y=0:color=white". La documentazione del pad di ffmpeg è qui: ffmpeg.org/ffmpeg-filters.html#pad-1 .
Mark Berry,

4
Ecco una soluzione che aggiunge solo un pixel di imbottitura per dimensioni che sono dispari: -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2".
danneu,

250

Basta usare -2

Dalla documentazione del filtro bilancia :

Se uno dei valori è -ncon n > 1, il filtro di scala utilizzerà anche un valore che mantiene le proporzioni dell'immagine di input, calcolate dall'altra dimensione specificata. Dopodiché, si assicurerà che la dimensione calcolata sia divisibile per ne, se necessario, regolerà il valore.

Esempi

Imposta la larghezza su 1280 e l'altezza verrà calcolata automaticamente per preservare le proporzioni e l'altezza sarà divisibile per 2:

-vf scale=1280:-2

Come sopra, ma con un'altezza dichiarata; lasciando la larghezza a carico del filtro:

-vf scale=-2:720

"divisibile per 2"

Come richiesto da x264, il "divisibile per 2 per larghezza e altezza" è necessario per le uscite sottocampionate chroma YUV 4: 2: 0. 4: 2: 2 avrebbe bisogno di "divisibile per 2 per larghezza", e 4: 4: 4 non ha queste restrizioni. Tuttavia, la maggior parte dei lettori non basati su FFmpeg può solo decodificare correttamente 4: 2: 0, quindi è per questo che spesso vedi i ffmpegcomandi con l' -pix_fmt yuv420popzione quando emetti video H.264.

Avvertimento

Sfortunatamente non puoi usare -2sia la larghezza che l' altezza, ma se hai già specificato una dimensione, l'utilizzo -2è una soluzione semplice.


14
Penso che questo dovrebbe essere contrassegnato come la risposta giusta a causa della mancanza di "trucchi". Desiderio di votare più di una volta
Luca M

1
Perché -vf scale=-2:-2non funziona? Nel mio caso, voglio preservare il più possibile le dimensioni del file originale. Ciò che ha funzionato per me è stato -vf scale=-2:ih. Ma non funziona se entrambe le h / w sono irregolari.
Pascal,

2
@tuner Il valore risultante di -2dipende dal valore dichiarato dell'altra dimensione.
Llogan,

3
nel mio caso questo mi ha dato il seguente errore: Size values less than -1 are not acceptable.ma la risposta di @Zbyszek ha funzionato perfettamente.
Julien,


64

Se si desidera impostare una larghezza di output e avere output con lo stesso rapporto dell'originale

scale=720:-1 

e non cadere con questo problema, allora puoi usare

scale="720:trunc(ow/a/2)*2"

(Solo per le persone che cercano come farlo con il ridimensionamento)


16
E per un'altezza fissa èscale="trunc(oh*a/2)*2:720"
Tom

20

Il problema con le scalesoluzioni qui è che distorcono l'immagine / video sorgente che non è quasi mai quello che vuoi.

Invece, ho trovato la soluzione migliore è quella di aggiungere un pad da 1 pixel alla dimensione dispari. (Per impostazione predefinita, il pading è nero e difficile da notare.)

Il problema con le altre padsoluzioni è che non si generalizzano su dimensioni arbitrarie perché si adattano sempre.

Questa soluzione aggiunge un pad di 1 pixel in altezza e / o larghezza solo se dispari:

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"

Questo è l'ideale perché fa sempre la cosa giusta anche quando non è necessaria alcuna imbottitura.


Le soluzioni di scala modificano al massimo il numero di pixel di 1. Ciò difficilmente distorce l'immagine. Se sei preoccupato per la velocità di filtraggio, usa scale=iw+mod(iw,2):ih+mod(ih,2):flags=neighbor. Questo può aumentare ogni dimensione di 1 solo se necessario e duplicherà l'ultima riga / colonna.
Gyan,

@Gyan È passato troppo tempo da quando ho risolto il problema (la mia risposta è stata estratta da un commento che ho fatto molto tempo fa), ma ricordo che il ridimensionamento di un singolo pixel ha introdotto artefatti visivi evidenti in alcune condizioni, motivo per cui mi sono preoccupato innanzitutto. Non ricordo esattamente, forse una quantità sproporzionata di sfocatura da un singolo cambiamento di pixel? Forse solo su alcuni formati video / immagine? Tutto quello che posso dire è che ho elaborato migliaia di video con questa correzione ed è stata la trasformazione favorevole.
danneu

19

È probabilmente dovuto al fatto che il video H264 viene solitamente convertito dallo spazio RGB a YUV come 4: 2: 0 prima dell'applicazione della compressione (sebbene la conversione del formato stesso sia un algoritmo di compressione con perdita di dati con un risparmio di spazio del 50%).

YUV-420 inizia con un'immagine RGB (rosso verde blu) e la converte in YUV (sostanzialmente un canale di intensità e due canali "hue"). I canali di tonalità vengono quindi ricampionati creando un campione di tonalità per ogni quadrato 2X2 di quella tonalità.

Se si dispone di un numero dispari di pixel RGB in orizzontale o in verticale, si avranno dati incompleti per l'ultima colonna o riga di pixel nello spazio di tonalità ricampionato del frame YUV.


2
Un altro fatto interessante ... quando decodifichi con roba di Microsoft Media Foundation, devi usare multipli di 16 per H264. Quindi il video 1080P si decodifica in un buffer alto 1088 (anche se si ignorano le ultime 8 righe).
Adisak,

2

LordNeckbeard ha la risposta giusta, molto velocemente

-vf scale=1280:-2

Per Android, non dimenticare di aggiungere

"-preset ultrafast" and|or "-threads n"

Non è necessario dichiarare le discussioni: questo viene gestito automaticamente. Credo che la lentezza di Andriod durante la codifica su H.264 sia dovuta alle persone che usano il popolare "WritingMinds / ffmpeg-android" che usa --disable-asmnel suo script di build x264 . Ciò comporta una lentezza non necessaria e significativa (è possibile controllare il registro ffmpeg e se mostra using cpu capabilties: none!che non va bene). Non sono sicuro del motivo per cui l'hanno aggiunto, ma non sono uno sviluppatore Android.
Llogan,

1

È inoltre possibile utilizzare la bitandfunzione anziché trunc:

bitand (x, 65534)

farà lo stesso trunc(x/2)*2ed è più trasparente secondo me.
(Considera 65534 un numero magico qui;))


Il mio compito era ridimensionare automaticamente molti file video a metà risoluzione .

scale=-2,ih/2portare a immagini leggermente sfocate

Motivo:

  • i video di input avevano il formato di visualizzazione (DAR) impostato
  • scale ridimensiona le dimensioni reali della cornice
  • durante l'anteprima, le dimensioni dei nuovi video devono essere corrette utilizzando DAR che, in caso di video a bassa risoluzione (360x288, DAR 16: 9), potrebbe sfocare

soluzione:

-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"

spiegazione:

  • output_height = input_height / 2
  • output_width = output_height * original_display_aspect_ratio
  • sia output_width e output_height sono ora arrotondato al minor numero divisibile per 2
  • setsar=1significa che output_dimensions è ora definitivo, non è necessario applicare alcuna correzione delle proporzioni

Qualcuno potrebbe trovarlo utile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.