Làm cách nào tôi có thể điều chỉnh video phù hợp với một kích thước nhất định, nhưng không thể nâng cấp video đó bằng FFmpeg?


13

Tôi cần điều chỉnh video thành 640x360 (trình phát điện thoại tối đa của tôi có thể xử lý), đồng thời duy trì tỷ lệ khung hình , nhưng tôi cũng muốn video không thay đổi nếu nó nhỏ hơn 640x360 (rốt cuộc không có điểm nào tăng tỷ lệ).

Có cách nào để có được hành vi này bằng cách sử dụng dòng lệnh của ffmpeg không?


Tôi không nghĩ rằng điều này có thể được thực hiện chỉ trong ffmpeg, nhưng nếu bạn sẵn sàng viết kịch bản, nó hoàn toàn có thể được thực hiện.
evilsoup 16/03/13

Tôi đã viết kịch bản, nhưng tôi muốn dọn sạch mã của mình trong trường hợp không cần thiết.
sashoalm

Có thể có một bộ lọc tỷ lệ sử dụng các chức năng như min(…)nhưng chắc chắn dễ dàng hơn với một tập lệnh đơn giản phân tích các kích thước. Xem lệnh của tôi ở đây để biết ví dụ về những gì có thể được thực hiện: superuser.com/questions/547296/
Khăn

Câu trả lời:


9

Với các phiên bản ffmpeg mới hơn, bạn có thể sử dụng tùy chọn scalecủa bộ lọc force_original_aspect_ratio. Ví dụ: để điều chỉnh video thành 1280 × 720 mà không cần nâng cấp (xem bài đăng này để biết thêm thông tin):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Ở đây, scalebộ lọc chia tỷ lệ thành 1280 × 720 nếu video đầu vào lớn hơn thế. Nếu nó nhỏ hơn, nó sẽ không được nâng cấp. Bộ padlọc là cần thiết để đưa video đầu ra lên 1280 × 720, trong trường hợp tỷ lệ khung hình hoặc kích thước của nó khác với kích thước mục tiêu.


Với các phiên bản ffmpeg cũ hơn, có một cách giải quyết có phần khó khăn. Đầu tiên, xác định chiều rộng, chiều cao và tỷ lệ khung hình của đầu ra của bạn. Điều này sẽ tiết kiệm cho chúng tôi một số gõ.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Bây giờ, hãy áp dụng lệnh bộ lọc siêu phức tạp mà Jim Worrall đã viết :

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

Tôi sẽ không thực sự giải thích tất cả những gì nó làm, nhưng về cơ bản, bạn có thể cung cấp cho nó bất kỳ video nào và nó sẽ chỉ hạ thấp, không cao cấp. Nếu bạn sẵn sàng, bạn có thể phân tích bộ lọc thành các biểu thức riêng lẻ. Có thể rút ngắn điều này, nhưng nó cũng hoạt động như vậy.


1
+1 nhưng đó là một lệnh thực sự khủng khiếp: P
evilsoup

Tôi biết phải không? Tôi đã dành mười phút để cố gắng chia nó thành các phần hợp lý và sau đó chèn một số giá trị nhưng tôi đã từ bỏ. Nó hơi cũ và có lẽ có thể viết nó ngắn gọn hơn nhiều so với điều này.
slhck

13

Một phiên bản dễ đọc hơn có thể trông như sau:

-filter_complex "scale=iw*min(1\,min(640/iw\,360/ih)):-1"

640 / iw là hệ số tỷ lệ ngang và 360 / ih là hệ số tỷ lệ dọc

Bạn muốn điều chỉnh hình ảnh được chia tỷ lệ bên trong hộp đầu ra và giữ tỷ lệ khung hình (lưu trữ). Bạn làm điều này bằng cách chọn hệ số tỷ lệ nhỏ nhất với hàm tối thiểu: min (640 / iw, 360 / ih)

Bạn muốn ngăn chặn mọi sự nâng cấp (tức là hệ số tỷ lệ> 1.0) để bạn thêm một hàm tối thiểu khác: min (1, min (640 / iw, 360 / ih))

Bước tiếp theo là tính toán độ phân giải đầu ra bằng cách nhân hệ số tỷ lệ với chiều rộng đầu vào và chiều cao đầu vào:
output-width = iw * min (1, min (640 / iw, 360 / ih))
output-height = ih * tối thiểu (1, phút (640 / giờ, 360 / giờ))

Bước cuối cùng là xây dựng lệnh lọc. Không cần chỉ định chiều cao đầu ra, bạn có thể chỉ định -1 và ffmpeg sẽ giữ tỷ lệ khung hình bằng cách áp dụng cùng hệ số tỷ lệ như đối với chiều rộng.


A + Hoạt động ra khỏi hộp. Giải pháp của câu trả lời được chọn không bảo toàn tỷ lệ khung hình. Nó bóp khung.
287352

5

Tôi cũng gặp vấn đề tương tự, nhưng đã giải quyết bằng cách lắp video vào hình vuông 640x640 (vì video dọc được làm bằng điện thoại thông minh).

Vì vậy, sử dụng logic immerzi và một số nghiên cứu tôi kết thúc với điều này:

-vf "scale=iw*min(1\,if(gt(iw\,ih)\,640/iw\,(640*sar)/ih)):(floor((ow/dar)/2))*2"

phần cuối cùng là để có chiều cao chia hết cho 2 mà nhiều bộ mã hóa cần.

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.