FFMPEG (libx264) Chiều cao không chia hết cho 2


185

Tôi đang cố mã hóa video .mp4 từ một bộ khung bằng FFMPEG bằng codec libx264.

Đây là lệnh tôi đang chạy:

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

Đôi khi tôi nhận được lỗi sau:

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

Sau khi tìm kiếm xung quanh một chút, có vẻ như vấn đề có liên quan đến thuật toán chia tỷ lệ và có thể được khắc phục bằng cách thêm đối số -vf.

Tuy nhiên, trong trường hợp của tôi, tôi không muốn thực hiện bất kỳ tỷ lệ nào. Lý tưởng nhất, tôi muốn giữ kích thước giống hệt như khung. Có lời khuyên nào không? Có một số loại tỷ lệ khung hình mà h264 thực thi?


@AleksandrDubinsky Nhưng câu trả lời của LordNeckbeard không bảo toàn chiều rộng và chiều cao ban đầu. Chúng tôi cần chỉ định thủ công chiều rộng hoặc chiều cao..và nếu w sử dụng -vf scale = -2: ih hoặc -vf scale = iw: -2 thì điều này sẽ không làm việc nếu cả chiều cao và chiều rộng không đồng đều..Xin giải thích làm thế nào câu trả lời đó tối ưu hơn? .. cảm ơn
varmashrivastava

1
@varmashrivastava Chà, cách SO hoạt động là ban đầu có thể có một câu hỏi, và sau đó Google gửi cho một nhóm người với một câu hỏi khác, sau đó chiếm quyền điều khiển trang. Đó là những gì nó được, cố gắng không chiến đấu với nó. Câu trả lời đúng cho câu hỏi ban đầu là -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2", thậm chí không phải là một trong những câu trả lời. Câu trả lời chính xác cho câu hỏi của người khác là của LordNeckbeard.
Alexanderr Dubinsky

@varmashrivastava Tôi đã đi trước và sửa câu trả lời đầu tiên. Hy vọng rằng nó không bị phá hoại bởi các mod.
Alexanderr Dubinsky

@AleksandrDubinsky cảm ơn..và người dùng có thể sử dụng "scale="thay vì "pad="nếu anh ấy / cô ấy không muốn các pixel đệm được tô màu?
varmashrivastava

Câu trả lời:


267

Câu trả lời cho câu hỏi ban đầukhông muốn mở rộng quy mô các video là:

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

Chỉ huy:

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

Về cơ bản, .h264 cần các kích thước chẵn nên bộ lọc này sẽ:

  1. Chia chiều cao và chiều rộng ban đầu cho 2
  2. Làm tròn nó đến pixel gần nhất
  3. Nhân số đó với 2 lần nữa, do đó biến nó thành số chẵn
  4. Thêm pixel đệm màu đen lên đến số này

Bạn có thể thay đổi màu của phần đệm bằng cách thêm tham số bộ lọc :color=white. Xem tài liệu của pad .


3
Đó không phải là một lỗi. Việc bạn không thực hiện chia tỷ lệ là không quan trọng vì đầu ra sẽ kế thừa kích thước khung của đầu vào.
llogan

5
Để ghi lại, tôi chỉ đang làm một cái gì đó mà tôi đã tạo một video từ một hình ảnh và nó đã sử dụng yuvj444p làm định dạng pixel; nó không quan tâm đến kích thước video. Sau đó, tôi cần phải chuyển đổi nó thành yuv420p, và sau đó nó quan tâm đến kích thước video. Tôi đã tra cứu yuv420p trên wikipedia, tôi nghĩ đó là định dạng màu nhiều pixel, cần hình ảnh phải có kích thước cụ thể. Không chắc chắn tại sao nó quan trọng nén, mặc dù.
lahwran

7
Có lẽ bạn nên sử dụng pad hơn là chia tỷ lệ, để thêm một hàng / cột màu đen. Thu nhỏ hình ảnh lên một pixel sẽ làm mờ nó.
Glenn Maynard

5
@NickeManarin, bộ lọc này sẽ hoạt động để thêm 1 pixel đệm trắng vào kích thước dọc, với video được đặt ở phía trên bên trái : -vf pad="width=iw:height=ih+1:x=0:y=0:color=white". Tài liệu pad ffmpeg có ở đây: ffmpeg.org/ffmpeg-filters.html#pad-1 .
Mark Berry

4
Đây là một giải pháp chỉ thêm một pixel đệm vào các kích thước lẻ : -vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2".
danneu

247

Chỉ dùng -2

Từ tài liệu lọc tỷ lệ :

Nếu một trong các giá trị đi -ncùng n > 1, bộ lọc tỷ lệ cũng sẽ sử dụng giá trị duy trì tỷ lệ khung hình của hình ảnh đầu vào, được tính từ kích thước được chỉ định khác. Tuy nhiên, sau đó sẽ đảm bảo rằng kích thước được tính chia hết cho nvà điều chỉnh giá trị nếu cần.

Ví dụ

Đặt chiều rộng thành 1280 và chiều cao sẽ tự động được tính để duy trì tỷ lệ khung hình chiều cao sẽ chia hết cho 2:

-vf scale=1280:-2

Tương tự như trên, nhưng với một chiều cao khai báo thay thế; để lại chiều rộng được xử lý bởi bộ lọc:

-vf scale=-2:720

"chia hết cho 2"

Theo yêu cầu của x264, "chia hết cho 2 cho chiều rộng và chiều cao" là cần thiết cho các đầu ra mẫu phụ của YUV 4: 2: 0. 4: 2: 2 sẽ cần "chia hết cho 2 cho chiều rộng" và 4: 4: 4 không có những hạn chế này. Tuy nhiên, hầu hết các trình phát không dựa trên FFmpeg chỉ có thể giải mã chính xác 4: 2: 0, vì vậy đó là lý do tại sao bạn thường thấy ffmpegcác lệnh với -pix_fmt yuv420ptùy chọn khi xuất video H.264.

Hãy cẩn thận

Thật không may, bạn không thể sử dụng -2cho cả chiều rộng chiều cao, nhưng nếu bạn đã chỉ định một chiều thì sử dụng -2là một giải pháp đơn giản.


14
Tôi nghĩ rằng tihis nên được đánh dấu là câu trả lời đúng vì không có "thủ thuật" liên quan. Whish tovote nhiều hơn một lần
LucaM

1
Tại sao -vf scale=-2:-2không hoạt động? Trong trường hợp của tôi, tôi muốn duy trì kích thước tệp gốc càng nhiều càng tốt. Những gì làm việc cho tôi là -vf scale=-2:ih. Nhưng nó không hoạt động nếu cả hai h / w không đồng đều.
Pascal

2
@tuner Giá trị kết quả -2phụ thuộc vào giá trị khai báo của kích thước khác.
llogan

3
trong trường hợp của tôi, điều này đã cho tôi lỗi sau: Size values less than -1 are not acceptable.nhưng câu trả lời từ @Zbyszek đã hoạt động hoàn hảo.
Julien


64

Nếu bạn muốn đặt một số chiều rộng đầu ra và có đầu ra với cùng tỷ lệ như ban đầu

scale=720:-1 

và không rơi vào vấn đề này thì bạn có thể sử dụng

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

(Chỉ dành cho những người tìm kiếm cách thực hiện điều đó với tỷ lệ)


16
Và đối với chiều cao cố định làscale="trunc(oh*a/2)*2:720"
Tom

20

Vấn đề với các scalegiải pháp ở đây là chúng làm biến dạng hình ảnh / video nguồn gần như không bao giờ là thứ bạn muốn.

Thay vào đó, tôi đã tìm thấy giải pháp tốt nhất là thêm một pixel 1 pixel vào kích thước lẻ. (Theo mặc định, phần đệm có màu đen và khó nhận thấy.)

Vấn đề với các padgiải pháp khác là chúng không khái quát trên các kích thước tùy ý vì chúng luôn đệm.

Giải pháp này chỉ thêm một miếng đệm 1 pixel cho chiều cao và / hoặc chiều rộng nếu chúng là số lẻ:

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

Điều này là lý tưởng bởi vì nó luôn luôn làm đúng ngay cả khi không cần đệm.


Các giải pháp tỷ lệ thay đổi số lượng pixel nhiều nhất là 1. Điều đó hầu như không làm biến dạng hình ảnh. Nếu bạn lo lắng về tốc độ lọc, hãy sử dụng scale=iw+mod(iw,2):ih+mod(ih,2):flags=neighbor. Điều này chỉ có thể tăng mỗi thứ nguyên thêm 1, nếu cần và sẽ nhân đôi hàng / cột cuối cùng.
Gyan

@Gyan Đã quá lâu kể từ khi tôi gặp vấn đề mà vấn đề này đã giải quyết (câu trả lời của tôi đã được trích xuất từ ​​một bình luận tôi đã đưa ra từ lâu), nhưng tôi nhớ rằng việc chia tỷ lệ bằng một pixel đã giới thiệu các tạo tác hình ảnh đáng chú ý trong một số điều kiện khiến tôi bận tâm ở nơi đầu tiên Tôi không nhớ chính xác, có thể số lượng mờ không tương xứng từ một thay đổi pixel? Có lẽ chỉ trên một số định dạng vid / hình ảnh? Tất cả những gì tôi có thể nói là tôi đã xử lý hàng ngàn vids với bản sửa lỗi này và đó là sự biến đổi thuận lợi.
danneu

19

Có khả năng là do video H264 thường được chuyển đổi từ không gian RGB sang YUV thành 4: 2: 0 trước khi áp dụng nén (mặc dù bản thân chuyển đổi định dạng là thuật toán nén mất dữ liệu giúp tiết kiệm không gian 50%).

YUV-420 bắt đầu bằng hình ảnh RGB (Red Green Blue) và chuyển đổi nó thành YUV (về cơ bản là một kênh cường độ và hai kênh "màu"). Các kênh Huế sau đó được ghép lại bằng cách tạo một mẫu màu cho mỗi ô vuông 2X2 của màu đó.

Nếu bạn có số lượng pixel RGB lẻ theo chiều ngang hoặc chiều dọc, bạn sẽ có dữ liệu không đầy đủ cho cột hoặc hàng pixel cuối cùng trong không gian màu được ghép lại của khung YUV.


2
Một sự thật thú vị khác ... khi bạn giải mã bằng công cụ Microsoft Media Foundation, bạn cần sử dụng bội số 16 cho H264. Vì vậy, video 1080P thực sự giải mã thành một bộ đệm cao 1088 (mặc dù bạn bỏ qua 8 dòng cuối cùng).
Adisak

2

LordNeckbeard có câu trả lời đúng, rất nhanh

-vf scale=1280:-2

Đối với Android, đừng quên thêm

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

Bạn không cần phải khai báo chủ đề: điều đó được xử lý tự động. Tôi tin rằng sự chậm chạp của Andriod khi mã hóa thành H.264 là do mọi người sử dụng "WritingMinds / ffmpeg-android" phổ biến sử dụng --disable-asmtrong tập lệnh xây dựng x264 của nó . Điều này dẫn đến sự chậm chạp không cần thiết và đáng kể (bạn có thể kiểm tra nhật ký ffmpeg và nếu nó hiển thị using cpu capabilties: none!thì điều đó thật tệ). Tôi không chắc tại sao họ lại thêm điều đó, nhưng tôi không phải là nhà phát triển Android.
llogan

1

Bạn cũng có thể sử dụng bitandchức năng thay vì trunc:

bitand (x, 65534)

sẽ làm như vậy trunc(x/2)*2và nó minh bạch hơn theo ý kiến ​​của tôi.
(Hãy xem xét 65534 một con số kỳ diệu ở đây;))


Nhiệm vụ của tôi là tự động thu nhỏ rất nhiều tệp video thành một nửa độ phân giải .

scale=-2,ih/2dẫn đến hình ảnh hơi mờ

lý do:

  • video đầu vào có tỷ lệ khung hình hiển thị (DAR) được đặt
  • scale chia tỷ lệ kích thước khung hình thực
  • trong khi xem trước, kích thước của video mới phải được sửa bằng DAR , trong trường hợp video có độ phân giải khá thấp (360x288, DAR 16: 9) có thể dẫn đến mờ

giải pháp:

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

giải trình:

  • output_height = input_height / 2
  • output_creen = output_height * original_display_aspect_ratio
  • cả output_creenoutput_height hiện được làm tròn thành số nhỏ hơn gần nhất chia hết cho 2
  • setsar=1có nghĩa là output_dimensions hiện là cuối cùng, không nên áp dụng hiệu chỉnh tỷ lệ khung hình

Ai đó có thể tìm thấy điều này hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.