Làm cách nào để giảm kích thước video bằng ffmpeg?


201

Làm cách nào tôi có thể sử dụng ffmpegđể giảm kích thước của video bằng cách giảm chất lượng (tối thiểu nhất có thể, nhưng tôi cần nó để chạy trên thiết bị di động không có nhiều dung lượng trống)?

Tôi quên viết một điều chưa. Khi video có thể sử dụng phụ đề (* .srt hoặc * .sub) Tôi cũng muốn chuyển đổi chúng để phù hợp với các tham số của tệp video được chuyển đổi.


4
Tôi đã không sử dụng nó nhưng ffmpegtrang man hiển thị một -fstùy chọn để giới hạn kích thước đầu ra, có gì giống như ffmpeg -i in.avi -fs 100M out.avicông việc không?
Kevin

1
Tôi sẽ không chuyển hướng bạn đến trang người đàn ông:man ffmpeg | wc -l --> 5254

3
Đây .avikhông phải là vấn đề chính .. avichỉ là một container. Vấn đề chính là bạn sử dụng codec nào .. Nhiều .avivids (hầu hết?) Sử dụng codec kiểu cũ (ví dụ XviD) đều tốt, nhưng lớn hơn với cùng chất lượng khi so sánh với thế hệ codec sau này .. Bạn thường có thể nhận được mã hóa chặt chẽ bằng cách sử dụng H.264tiêu chuẩn nén video (ví dụ: codec x264) và aacnén cho âm thanh .. Hộp chứa và codec bạn sử dụng tùy thuộc vào bạn và điện thoại của bạn ... .mp4Hộp chứa được chấp nhận tốt .. (nhưng điện thoại của bạn có thể xử lý được không: xem liên kết này
Peter.O

@Kevin Điều này muốn nhiều tham số để chuyển đổi.
xralf

@hesse Nghĩa là gì?
xralf

Câu trả lời:


277

Xem câu trả lời này . Trích dẫn dưới đây để thuận tiện:

Tính toán tốc độ bit bạn cần bằng cách chia 1 GB cho thời lượng video tính bằng giây. Vì vậy, đối với video có độ dài 16:40 (1000 giây), hãy sử dụng tốc độ bit 1000000 byte / giây:

ffmpeg -i input.mp4 -b 1000000 output.mp4

Các tùy chọn bổ sung có thể đáng xem xét là thiết lập Hệ số tỷ lệ không đổi, làm giảm tốc độ bit trung bình, nhưng vẫn giữ được chất lượng tốt hơn. Thay đổi CRF trong khoảng từ 18 đến 24 - càng thấp, tốc độ bit càng cao.

ffmpeg -i input.mp4 -vcodec libx265 -crf 20 output.mp4

Thay đổi codec khi cần - libx264 có thể có sẵn nếu libx265 không có, với chi phí kích thước tệp kết quả lớn hơn một chút.


Video có kích thước 338 MB đã giảm trên kích thước 130 MB. Chất lượng nhanh chóng hạ xuống. Có một số lời giải thích cho quá trình này? Các tác giả ban đầu không giải thích hướng dẫn của mình.
xralf

13
Lệnh thứ hai, sử dụng -crf 24đã lấy một video 255,3 MB mà tôi có và giảm xuống còn 72,7 MB mà không làm giảm chất lượng đáng chú ý. Có một upvote!
Patrick Roberts

2
Giảm đáng kể video ~ 2G xuống còn 14 MB, trông vẫn ổn, đây là kết quả tìm kiếm đầu tiên và đó chính xác là những gì tôi đang tìm kiếm, cảm ơn!
sinisterstuf

5
Có thể tốt để lưu ý rằng bây giờ bạn có thể sử dụng libx265để giảm kích thước hơn nữa.
ZN13

6
Được sử dụng ffmpeg -i input.avi -vcodec libx264 -crf 24 output.avi. Nó giảm video 100mb xuống còn 9mb .. Rất ít thay đổi về chất lượng video. Cảm ơn bạn!
alpha_989

32

Trừ khi bạn đang tìm kiếm một bitrate cụ thể, tôi sẽ khuyên bạn nên -crftùy chọn. Đây là cách thường được sử dụng nhất để x264mã hóa: http://slhck.info/articles/crf

Nói tóm lại: CRF 23 sẽ tạo phim chất lượng "DVD" (~ 700MB-1GB) và giá trị CRF thấp hơn sẽ có chất lượng cao hơn (tệp lớn hơn).


3
Vui lòng cho ví dụ về lệnh đầy đủ thay vì liên kết đến một trang web bên ngoài (có thể bị hỏng vào một ngày nào đó :)
Jake Berger

1
@Vicky Chijwani cung cấp mã trong ví dụ trên. Điều này phù hợp hơn với một bình luận nhưng đó là hoạt động đầu tiên của tôi trên trang web này. Liên kết có thêm lời giải thích về tùy chọn crf nhưng không cần thiết để mã hoạt động.
Tom Kelly

27

Bạn đã đề cập đến việc muốn giảm kích thước tệp để phù hợp với nhiều video hơn trên thiết bị di động, đó cũng là usecase của tôi. Tất cả các câu trả lời ở đây là để giảm chất lượng nén nhưng không ai đề cập đến việc giảm kích thước khung hình video. Nó nhanh hơn rất nhiều, nhanh hơn khoảng 3 đến 5 lần so với việc giải nén theo kinh nghiệm của tôi. Xem tài liệu ffmpeg về nhân rộng để biết thêm thông tin.

ffmpeg -i input.mkv -vf "scale=iw/2:ih/2" half_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/3:ih/3" a_third_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/4:ih/4" a_fourth_the_frame_size.mkv

20

Tôi đã thử nghiệm hầu hết các câu trả lời được đề xuất cho câu hỏi này. Các kết luận dữ liệu thử nghiệm dưới đây. Đây là những câu trả lời được đề xuất mà tôi đã thử nghiệm:

(BR) Sửa đổi bitrate, sử dụng:

ffmpeg -i $infile -b $bitrate $newoutfile 

(CR) Thay đổi hệ số tỷ lệ không đổi, sử dụng:

ffmpeg -i $infile -vcodec libx264 -crf 23 $outfile

(SZ) Thay đổi kích thước màn hình video (ví dụ: một nửa kích thước pixel của nó), sử dụng:

ffmpeg -i $infile -vf "scale=iw/2:ih/2" $outfile

(BL) Thay đổi cấu hình H.264 thành "đường cơ sở", sử dụng:

ffmpeg -i $infile -profile:v baseline $outfile

(DF) Sử dụng xử lý ffmpeg mặc định, sử dụng:

ffmpeg -i $infile $outfile

DỮ LIỆU

  • "size" - kích thước phần trăm pixel của video được chuyển đổi so với bản gốc.
  • "Bitrate" - bitrate của video gốc và video được chuyển đổi.
  • "định nghĩa" - kích thước pixel của video.
  • "convert" - thời gian để chuyển đổi video trong vài giây.

Tôi đã tính toán tốc độ bit đích cho (BL) bằng phương pháp đề xuất.

=== Tệp A - Cách nút giúp đẩy Angular-Fnbixa7Ts6M.mkv ===

            original    BR         CR         SZ         BL         DF
            --------    ---        --         --         --         --
size        64152 kb    214%       76%        40%        83%        76%
bitrate     411 kb/s    883        313        165        342        313
definition  1920x1080   1920x1080  1920x1080  960x540    1920x1080  1920x1080
convert     --          648        509        225        427        510

=== Tệp B - Sử dụng GraphQL với Angular _ By - Lee Costello-OGyFxqt5INw.mkv ===

            original    BR         CR         SZ         BL         DF
            --------    ---        --         --         --         --
size        410301 kb   33%        109%       28%        143%       109%
bitrate     2687 kb/s   880        2920       764        3843       2920
definition  3840x2160   3840x2160  3840x2160  1920x1080  3840x2160  3840x2160   
convert     --           2307       3188       1116       2646       3278

KẾT LUẬN

  • Phương pháp (SZ) chắc chắn là phương pháp nhanh nhất. Nó nhanh hơn gấp 2 lần đến 4 lần. Đây có thể là một vấn đề rất lớn đối với các video có độ phân giải cao, vì tất cả các phương pháp khác mất nhiều thời gian để chuyển đổi hơn độ dài thực tế của video! Ví dụ: Phương pháp (CR) mất 53 phút để chuyển đổi video 21 phút.

  • Phương pháp (SZ) chắc chắn là phương pháp tốt nhất nếu định nghĩa của video lớn hơn định nghĩa của màn hình sẽ hiển thị. Ví dụ: nếu điện thoại của bạn chỉ có thể hiển thị hình ảnh 1080p, thì việc gửi video 3840x2160 chỉ là lãng phí. Nó sẽ là tốt nhất để một nửa kích thước của nó đến 1080p.

  • Một số câu trả lời được đề xuất thực sự TĂNG kích thước của một số video. Ví dụ: phương pháp (BR) nhiều hơn gấp đôi kích thước của mẫu 1080p. Tuy nhiên, nó đã làm cho kích thước 2160p một phần ba. Đối với mẫu có độ phân giải cao, các phương thức (CR), (BL) và (DF) đều TĂNG kích thước của video.

Trả lời đúng (hoặc tốt nhất)

Trước tiên, tốt nhất là hạ độ phân giải xuống mức tối đa được hỗ trợ bởi màn hình mục tiêu của bạn.

Nếu bạn muốn giảm kích thước tập tin hơn nữa, nó sẽ phụ thuộc vào lựa chọn cá nhân. Bạn có thể giảm nội dung thông tin hoặc tăng độ nén.

  • Bạn có thể hạ thấp độ phân giải nhiều hơn nếu đó không phải là điều khiến bạn lo lắng.

  • Nếu video không bao gồm các cảnh hành động nhanh, bạn có thể muốn giảm tốc độ khung hình.

  • Nếu bạn có bộ xử lý mạnh và không gian là vấn đề duy nhất, bạn có thể tăng tốc độ nén.

  • Tốc độ bit là sự kết hợp của nhiều yếu tố. Vì vậy, chỉ cần nói với ffmpeg để giảm tốc độ bit có thể không cung cấp cho bạn kết quả bạn muốn.

  • Một cách khác của nội dung thông tin thấp hơn là giảm độ sâu màu. Làm thế nào để làm điều này đã không được thảo luận.


13

Lưu ý rằng có vẻ như ffmpeg đã thực hiện một số tối ưu hóa khi chạy mà không có tùy chọn, vì vậy trước khi thử sử dụng cài đặt, bạn không hiểu hoặc quyết định mất thông tin rõ ràng, hãy thử chuyển đổi mặc định:

ffmpeg -i input.mp4 output.mp4

Trong trường hợp của tôi, nó đã giảm tốc độ bit của cả video và âm thanh (bạn có thể kiểm tra và so sánh tệp đầu vào và đầu ra bằng cách chạy ffprobetrên chúng), chuyển đổi video 700 Mb thành chất lượng có vẻ tương tự 60 Mb.


1
Đã đi từ 4Gb đến 2Gb với điều này, cảm ơn !!
Sam Hosseini

1
(từ 10Mo đến 1,2Mb, ffmpeg tự động chuyển đổi video của tôi trong VP8 thành VP9 )
sodimel

Điều này đã tăng kích thước video của tôi từ 10,8 MB lên
MB

3

Tôi có một công thức ban đầu tôi tự rèn để chuyển đổi video Motion JPEG mà máy ảnh cũ của tôi tạo ra (chúng là những video rất lớn, vì mỗi khung hình là toàn bộ hình ảnh JPEG) thành h264. Đây là một bản chuyển thể cho các loại video khác (các khóa học, v.v.).

Tôi không sử dụng ffmpeg , nhưng mplayer và mencoder . Đầu tiên, chúng ta phải giải mã âm thanh với mplayer:

mplayer -vo null -ao pcm:fast:file=<audio_pcm.wav> <video>
  • Các tham số -vo null-ao nullthông báo cho mplayer không trích xuất video.

Trong các bước tiếp theo, chúng tôi sẽ thực hiện nén 3 lần với mencoder. Ở lần đầu tiên, chúng tôi sẽ chọn chế độ nén Chế độ chất lượng không đổi ( tham số crf ) phù hợp làm điểm bắt đầu:

mencoder <video> -ovc x264 \ 
         -x264encopts ratetol=100:preset=veryslow:crf=<value>:pass=1 \
         -nosound -o video1.h264
  • Bạn có thể thêm tham số Slow_firstpass vào -x264encopts nếu bạn bị hoang tưởng với chất lượng cuối cùng của video. Hướng dẫn sử dụng Mencoder nói rằng tùy chọn này vô hiệu hóa một số tham số giúp cải thiện đáng kể tốc độ mã hóa trong khi có ít hoặc không ảnh hưởng đến chất lượng của pass pass cuối cùng. Vì vậy, chỉ sử dụng nó ở bước cuối cùng.

  • Bạn nên thử một vài giá trị cho crf - hãy thử bắt đầu từ 25 và tiếp tục tăng cho đến khi bạn ghi chú các tạo tác vào video kết quả (giá trị cao hơn sẽ nén nhiều hơn). Hãy nhớ các lần mã hóa tiếp theo sẽ cải thiện chất lượng bạn đã chọn cho crf .

  • Lựa chọn thay thế cho veryslow cài sẵn là chậm , chậm , vừa vv Xem mencoder dẫn sử dụng cho danh sách đầy đủ.

  • ratetol kiểm soát biến thể bitrate - Tôi không chắc liệu mình có làm đúng ở đây không, nhưng tôi đặt nó ở giá trị tối đa để cho phép tự do hoàn toàn cho mencoder chọn bitrate phù hợp cho mỗi cảnh.

Sau lần vượt qua đầu tiên, bạn sẽ lưu ý rằng dòng cuối cùng cung cấp cho bạn tốc độ bit trung bình bạn sẽ sử dụng ở các bước tiếp theo:

(...)
x264 [info]: kb/s:526.43

Thay đổi tham số crf , được khuyến nghị ở lần đầu tiên, thành bitrate , được yêu cầu ở các lần tiếp theo:

mencoder <video> -ovc x264 \
       -x264encopts slow_firstpass:ratetol=100:preset=veryslow:bitrate=526:pass=3 \
       -nosound -o video2.h264

Mã hóa pass thứ hai này sẽ đọc số liệu thống kê được tạo ở pass đầu tiên ( divx2pass.logdivx2pass.log.mbtree) để tối ưu hóa việc nén.

  • Lưu ý rằng bạn sẽ sử dụng cùng một đầu vào video, không phải được tạo bởi lần đầu tiên vượt qua - video đầu ra của pass đầu tiên chỉ hữu ích để kiểm tra chất lượng ban đầu.

  • Cũng lưu ý rằng pass=3( không pass=2 ) sẽ tạo một tệp thống kê mới, vì vậy bạn có thể lặp lại bước cuối cùng bao nhiêu lần bạn muốn. Tôi thường làm pass=3hai lần, luôn chú ý đến bitrate kết quả.

Trong khi đó, bạn cũng có thể nén âm thanh bằng cách sử dụng lamehoặc oggenc:

oggenc -q<n> <audio_pcm.wav>

Cuối cùng, chúng tôi sẽ phát lại âm thanh và video

mencoder -audiofile <audio>.ogg video2.h264 -oac copy -ovc copy \
         -of lavf -lavfopts format=mp4 -o <video>.mp4
  • Việc -of lavf -lavfopts format=mp4tạo mp4định dạng tệp bằng cách sử dụng các bộ trộn lavopts.

3

Tôi đã nén bản trình bày video HD 40 phút từ 505MB xuống còn 183 MB
Điều đó giống như đi từ 100MB → 36MB.
Video gốc là HD và đầu ra gần như không có sự khác biệt đáng chú ý.
Đó là một tệp video "Tôi muốn giữ xung quanh, nhưng HD là quá mức cần thiết."
Đây là lệnh tôi đã sử dụng với lý do:

ffmpeg -n -loglevel error -i inputfile.mp4 -vcodec libx264 -crf 28 -preset faster -tune film outputfilename.mp4

  • -n: tránh ghi đè các tệp đầu ra (an toàn hơn để kiểm tra sau đó theo đợt)
  • -loglevel error : hiển thị lỗi và ẩn các hàng và hàng tiến trình
  • -i inputfile.mp4 : tên tệp đầu vào
  • -vcodec libx264: vuốt từ câu trả lời trên
  • -crf 28: Single-pass nén với sự khác biệt đáng chú ý nhỏ ( "0 = lossless, 23 = mặc định, 51 = tồi tệ nhất; chủ quan phạm vi lành mạnh là 17- 28 " ) docs ref
  • -preset faster: trông nhanh hơn gấp 2 lần so với thời gian mã hóa mặc định của tài liệu ref 'trung bình'
  • -tune film: chỉ định đầu vào là video HQ (các tùy chọn khác bao gồm 'phim hoạt hình', 'ảnh tĩnh' ..) tài liệu tham khảo
  • outputfilename.mp4 : tên tệp xuất ra

Đối với một thư mục của tập tin video:

for i in *.{avi,flv,m4v,mov,wmv,mp4,MP4,TS,mkv}; do ffmpeg -n -loglevel error -i "$i" -vcodec libx264 -crf 28 -preset faster -tune film "cc${i}"; done

Các vấn đề:

  • một cách sạch hơn để thu thập "tất cả các tệp video" mà không cần tất cả các phần mở rộng trong lệnh
  • một cách sạch hơn để xuất tên tệp mà không cần tiền tố "cc" và có thể xác nhận video trước khi xóa
  • .webmtập tin không hoạt động với lệnh. Phải trao đổi "cc${i}""${i%.*}.mp4"

Phanh tay là một thay thế nguồn mở với giao diện người dùng


Nó hoạt động. nhưng nó mất quá nhiều thời gian Có cải thiện nào cho thời gian thực hiện ít hơn không
Nirali


1

Tôi đã viết một tập lệnh bash để giảm kích thước của video và tự động thử các giá trị crf khác nhau.

Về cơ bản bạn sẽ

  • chọn một loạt các giá trị crf
  • chạy kịch bản
  • kiểm tra kích thước của video được tạo và chọn video bạn muốn

Điều này thực sự tiện dụng khi bạn có giới hạn kích thước bạn muốn đạt được và bạn không biết giá trị crf nào sẽ cho phép bạn làm điều đó.

Tôi hy vọng điều này sẽ giúp được ai đó. Tôi đã chia sẻ với các đồng nghiệp của tôi và mọi người thấy nó hữu ích.

#!/bin/bash

# bigger values of crf will lead to a bigger compression (smaller video size)
#for i in 1 2 3 4 5
for i in {25..28}
do
# you can remove the option -y if you want to be asked if to overwrite a file with the same name (leave the -y only if you understand what you are doing, otherwise you might rewrite an important file)
   ffmpeg -y -i NAMEOFTHEVIDEOTOCOMPRESS.mp4 -c:v libx264 -crf $i -preset veryfast -profile:v baseline -level 3.0 -strict -2 out_$i.mp4
   printf "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Done compression at crf=$i \n\n"
done
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.