FFMPEG (libx264) "ketinggian tidak dapat dibagi 2"

188

Saya mencoba untuk menyandikan video .mp4 dari serangkaian bingkai menggunakan FFMPEG menggunakan codec libx264.

Ini adalah perintah yang saya jalankan:

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

Saya terkadang mendapatkan kesalahan berikut:

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

Setelah mencari-cari sedikit sepertinya masalah ini ada hubungannya dengan algoritma penskalaan dan dapat diperbaiki dengan menambahkan argumen -vf.

Namun, dalam kasus saya, saya tidak ingin melakukan penskalaan. Idealnya, saya ingin menjaga dimensi persis sama dengan bingkai. Ada saran? Apakah ada semacam rasio aspek yang diberlakukan H264?

Andy Hin
sumber
@AleksandrDubinsky Tapi jawaban LordNeckbeard tidak mempertahankan lebar dan tinggi asli. Di sini kita perlu menentukan lebar atau tinggi secara manual..dan jika kita menggunakan skala -vf = -2: ih atau -vf skala = iw: -2 ini tidak akan bekerja jika tinggi dan lebar keduanya tidak rata .. Tolong jelaskan bagaimana jawaban itu lebih optimal? .. terima kasih
varmashrivastava
1
@varmashrivastava Nah, cara SO bekerja adalah bahwa pada awalnya mungkin ada satu pertanyaan, dan kemudian Google mengirim lebih dari sekelompok orang dengan pertanyaan berbeda yang kemudian membajak halaman. Itu adalah apa adanya, cobalah untuk tidak melawannya. Jawaban yang benar untuk pertanyaan awal adalah -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2", yang bahkan bukan salah satu jawabannya. Jawaban yang benar untuk pertanyaan semua orang adalah milik LordNeckbeard.
Aleksandr Dubinsky
@varmashrivastava Saya telah pergi ke depan dan memperbaiki jawaban pertama. Semoga tidak dirusak oleh mod.
Aleksandr Dubinsky
@AleksandrDubinsky terima kasih .. dan pengguna dapat menggunakan "scale="alih-alih "pad="jika dia tidak ingin piksel padatan berwarna?
varmashrivastava

Jawaban:

269

Jawaban atas pertanyaan awal yang tidak ingin membuat skala video adalah:

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

Perintah:

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

Pada dasarnya, .h264 membutuhkan dimensi genap sehingga filter ini akan:

  1. Bagilah tinggi dan lebar asli dengan 2
  2. Membulatkannya ke piksel terdekat
  3. Kalikan dengan 2 lagi, sehingga membuatnya menjadi bilangan genap
  4. Tambahkan piksel padding hitam hingga ke nomor ini

Anda dapat mengubah warna padding dengan menambahkan parameter filter :color=white. Lihat dokumentasi pad .

Andy Hin
sumber
3
Itu bukan bug. Tidak masalah bahwa Anda tidak melakukan penskalaan karena output akan mewarisi ukuran bingkai input.
Logo
5
Sebagai catatan, saya hanya melakukan sesuatu di mana saya membuat video dari gambar, dan menggunakan yuvj444p sebagai format piksel; itu tidak peduli tentang ukuran video. Kemudian saya perlu mengubahnya ke yuv420p, dan kemudian peduli tentang ukuran video. Saya mencari yuv420p di wikipedia, saya pikir ini adalah format warna multi-pixel, yang membutuhkan gambar untuk ukuran tertentu. Namun, tidak yakin mengapa itu penting dikompresi.
lahwran
7
Anda mungkin lebih baik menggunakan pad daripada skala, untuk menambahkan baris / kolom hitam. Memperbesar gambar dengan satu piksel akan mengaburkannya.
Glenn Maynard
5
@NickeManarin, filter ini harus bekerja untuk menambah 1 pixel padding putih untuk dimensi vertikal, dengan video posisi kiri atas: -vf pad="width=iw:height=ih+1:x=0:y=0:color=white". Dokumentasi ffmpeg pad ada di sini: ffmpeg.org/ffmpeg-filters.html#pad-1 .
Mark Berry
4
Berikut adalah solusi yang hanya menambahkan pixel padding untuk dimensi yang aneh: -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2".
danneu
250

Gunakan saja -2

Dari dokumentasi filter skala :

Jika salah satu nilai adalah -ndengan n > 1, filter skala juga akan menggunakan nilai yang mempertahankan rasio aspek gambar input, dihitung dari dimensi tertentu lainnya. Namun setelah itu, pastikan bahwa dimensi yang dihitung dapat dibagi dengan ndan sesuaikan nilainya jika perlu.

Contohnya

Setel lebar menjadi 1280, dan tinggi akan secara otomatis dihitung untuk mempertahankan rasio aspek, dan tinggi akan dapat dibagi 2:

-vf scale=1280:-2

Sama seperti di atas, tetapi dengan tinggi yang dinyatakan sebagai gantinya; meninggalkan lebar untuk ditangani oleh filter:

-vf scale=-2:720

"habis dibagi 2"

Seperti yang disyaratkan oleh x264, "habis dibagi 2 untuk lebar dan tinggi" diperlukan untuk YUV 4: 2: 0 output yang di-subsampel kroma. 4: 2: 2 akan membutuhkan "dibagi 2 untuk lebar", dan 4: 4: 4 tidak memiliki batasan ini. Namun, sebagian besar pemain berbasis non-FFmpeg hanya dapat mendekode dengan benar 4: 2: 0, jadi itu sebabnya Anda sering melihat ffmpegperintah dengan -pix_fmt yuv420popsi saat menghasilkan video H.264.

Peringatan

Sayangnya Anda tidak dapat menggunakan -2untuk lebar dan tinggi, tetapi jika Anda sudah menentukan satu dimensi maka menggunakan -2adalah solusi sederhana.

llogan
sumber
14
Saya pikir tihis harus ditandai sebagai jawaban yang tepat karena tidak ada "trik" yang terlibat. Mengapa memilih lebih dari satu kali
LucaM
1
Kenapa -vf scale=-2:-2tidak berhasil? Dalam kasus saya, saya ingin mempertahankan ukuran file asli sebanyak mungkin. Apa yang berhasil untuk saya adalah -vf scale=-2:ih. Tapi itu tidak berhasil jika keduanya h / w tidak merata.
Pascal
2
@tuner Nilai yang dihasilkan dari -2tergantung pada nilai yang dinyatakan dari dimensi lain.
llogan
3
dalam kasus saya ini memberi saya kesalahan berikut: Size values less than -1 are not acceptable.tetapi jawaban dari @Zbyszek bekerja dengan sempurna.
Julien
1
@ Julien Itu tidakffmpeg . Anda dapat mengunduh bangunan statis .
Logan
64

Jika Anda ingin mengatur beberapa lebar keluaran dan memiliki keluaran dengan rasio yang sama seperti aslinya

scale=720:-1 

dan jangan sampai jatuh dengan masalah ini maka Anda bisa menggunakannya

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

(Hanya untuk orang yang mencari cara melakukannya dengan penskalaan)

Zbyszek
sumber
16
Dan untuk ketinggian tetapscale="trunc(oh*a/2)*2:720"
Tom
20

Masalah dengan scalesolusi di sini adalah bahwa mereka mengubah sumber gambar / video yang hampir tidak pernah seperti yang Anda inginkan.

Sebagai gantinya, saya telah menemukan solusi terbaik adalah menambahkan pad 1-pixel ke dimensi aneh. (Secara default, pading adalah hitam dan sulit untuk dilihat.)

Masalah dengan padsolusi lain adalah bahwa mereka tidak menyamaratakan dimensi sewenang-wenang karena mereka selalu pad.

Solusi ini hanya menambahkan pad 1-pixel untuk tinggi dan / atau lebar jika mereka aneh:

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

Ini ideal karena selalu melakukan hal yang benar bahkan ketika padding tidak diperlukan.

danneu
sumber
Solusi skala mengubah jumlah piksel paling banyak 1. Itu hampir tidak merusak gambar. Jika Anda khawatir tentang kecepatan pemfilteran, gunakan scale=iw+mod(iw,2):ih+mod(ih,2):flags=neighbor. Ini hanya dapat meningkatkan setiap dimensi dengan 1, jika diperlukan, dan akan menduplikasi baris / kolom terakhir.
Gyan
@Gyan Sudah terlalu lama sejak saya memiliki masalah yang diselesaikan (jawaban saya diekstraksi dari komentar yang saya buat sejak lama), tapi saya ingat bahwa penskalaan dengan satu piksel memang memperkenalkan artefak visual yang nyata dalam beberapa kondisi yang mengapa saya repot-repot di tempat pertama. Saya tidak ingat persis, mungkin jumlah blur yang tidak proporsional dari perubahan piksel tunggal? Mungkin hanya pada beberapa format vid / gambar? Yang bisa saya katakan adalah bahwa saya memproses ribuan video dengan perbaikan ini dan itu adalah transformasi yang menguntungkan.
danneu
19

Kemungkinan karena fakta bahwa video H264 biasanya dikonversi dari RGB ke ruang YUV sebagai 4: 2: 0 sebelum menerapkan kompresi (meskipun konversi format itu sendiri adalah algoritma kompresi lossy yang menghasilkan penghematan ruang 50%).

YUV-420 dimulai dengan gambar RGB (Merah Hijau Biru) dan mengubahnya menjadi YUV (pada dasarnya satu saluran intensitas dan dua saluran "rona"). Saluran Hue kemudian dicampurkan dengan membuat satu sampel rona untuk setiap 2X2 kotak rona itu.

Jika Anda memiliki jumlah piksel RGB ganjil baik secara horizontal maupun vertikal, Anda akan memiliki data yang tidak lengkap untuk kolom atau baris piksel terakhir dalam ruang rona yang disampelkan pada bingkai YUV.

Adisak
sumber
2
Fakta menarik lainnya ... saat Anda mendekode dengan Microsoft Media Foundation, Anda perlu menggunakan kelipatan 16 untuk H264. Jadi video 1080P sebenarnya diterjemahkan ke dalam buffer yang tingginya 1088 (meskipun Anda mengabaikan 8 baris terakhir).
Adisak
2

LordNeckbeard memiliki jawaban yang benar, sangat cepat

-vf scale=1280:-2

Untuk android, jangan lupa tambahkan

"-preset ultrafast" and|or "-threads n"
fallouter
sumber
Anda tidak perlu mendeklarasikan utas: itu ditangani secara otomatis. Saya percaya kelambatan Andriod saat penyandian ke H.264 adalah karena orang-orang menggunakan "WritingMinds / ffmpeg-android" yang populer yang menggunakan skrip build x264--disable-asm -nya . Ini menghasilkan kelambatan yang tidak perlu dan signifikan (Anda dapat memeriksa log ffmpeg dan jika itu menunjukkan maka itu buruk). Saya tidak yakin mengapa mereka menambahkan itu, tapi saya bukan pengembang Android. using cpu capabilties: none!
llogan
1

Anda juga dapat menggunakan bitandfungsi alih-alih trunc:

bitand (x, 65534)

akan melakukan hal yang sama trunc(x/2)*2dan lebih transparan menurut saya.
(Pertimbangkan 65534 angka ajaib di sini;))


Tugas saya adalah untuk skala banyak file video secara otomatis hingga setengah resolusi .

scale=-2,ih/2menyebabkan gambar sedikit kabur

alasan:

  • video input telah disetel rasio aspek tampilan (DAR)
  • scale skala dimensi bingkai nyata
  • selama pratinjau ukuran video baru harus dikoreksi menggunakan DAR yang dalam hal video resoution cukup rendah (360x288, DAR 16: 9) dapat menyebabkan pengaburan

larutan:

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

penjelasan:

  • output_height = input_height / 2
  • output_width = output_height * original_display_aspect_ratio
  • baik output_width dan output_height sekarang dibulatkan ke angka lebih kecil terdekat yang dapat dibagi 2
  • setsar=1berarti output_dimensions sekarang final, tidak ada koreksi rasio aspek yang harus diterapkan

Seseorang mungkin menganggap ini bermanfaat.

endigo
sumber