Định dạng WEBM sử dụng chuẩn codec vp8 của Google. Và để convert video thành WEBM với FFmpeg, bạn có thể sử dụng thư viện libvpx để encode video và thư viện libvorbis để encode audio.
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4)
-f dùng để xác định format của file output, sau đó là tên định dạng (webm).
-c:v dùng để xác định codec sử dụng cho video, sau đó là tên thư viện sử dụng libvpx
-b:v dùng để xác định bitrate cho video đầu ra. Sau đó là số bitrate 1M. Chú ý: ở đây mình sử dụng số liệu chính xác là 1M. Trong khi với MP4, mình chỉ có thể xác định maxrate.
-c:a dùng để xác định codec sử dụng cho audio, sau đó là tên thư viện sử dụng libvorbis
output.webm là tên file output.
-hide_banner dùng để ẩn những thông tin liên quan đến FFmpeg (phiên bản, các thư viện sử dụng,…)
Kết quả:
Convert video thành WEBM
Ngoài ra, bạn cũng có thể thêm các tham số để điều chỉnh về độ phân giải (-vf scale=1280:729) hoặc tốc độ framerate (-r 20),… để được kết quả như mong đợi.
So sánh WEBM với MP4
WEBM sử dụng thư viện libvpx để encode video theo chuẩn vp8 và thư viện libvorbis để encode audio. Còn MP4 sử dụng thư viện libx264 để encode video theo chuẩn H264 và thư viện aac để encode audio.
Convert video thành WEBM thường lâu hơn rất nhiều so với convert video thành MP4.
WEBM nén tốt hơn, cho video chất lượng tốt hơn với dung lượng nhỏ hơn MP4.
WEBM phù hợp với việc sử dụng video trên nền web. Tuy nhiên, không phải trình duyệt nào cũng hỗ trợ như MP4.
Lời kết
Trên đây là câu lệnh cơ bản để convert video thành WEBM với FFmpeg. Nếu có gì thắc mắc, vui lòng để lại câu hỏi trong phần bình luận nhé. Mình sẽ cố gắng giải đáp nếu có thể.
Giả sử mình có một video dài 1 tiếng (60 phút) và mình muốn chia nhỏ video này thành các phần nhỏ hơn, mỗi phần có độ dài 5 phút. Khi đó, câu lệnh FFmpeg là:
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4).
-c copy dùng để thông báo với FFmpeg rằng bạn muốn copy video và audio từ input sang output mà không phải encode lại. Tham số này tương đương với -vcodec copy -acodec copy.
-f segment nghĩa là bạn muốn chia video này thành các segment (đoạn).
-segment_time 300: xác định độ dài mỗi đoạn là 300 giây (tương đương với 5 phút).
-reset_timestamps 1: để bắt mỗi segment bắt đầu với timestamp sấp xỉ 0.
%03d.mp4: định dạng file output. Trong trường hợp này, tên các file có độ dài là 3 kí tự, tức 001.mp4, 002.mp4,…
Lời kết
Trên đây là cách để cut video vời FFmpeg. Nếu có gì thắc mắc hay góp ý, bạn vui lòng để lại câu hỏi xuống phần bình luận. Mình sẽ cố gắng giải đáp.
-i là cờ dùng để xác định input, sau đó là tên file (video1.mp4, video2.avi)
-filter_complex dùng để áp dụng filter, sau đó là công thức filter – nằm trong cặp dấu ngoặc kép
[0:v:0] là video stream của file thứ nhất[0:a:0] là audio stream của file thứ nhất[1:v:0] là video stream của file thứ hai[1:a:0] là audio stream của file thứ haiconcat=n=2:v=1:a=1để xác định FFmpeg sẽ ghép nối (concat) 2 video (n=2) thành 1 video với 1 video stream (v=1) và 1 audio stream (a=1).[v] [a] lần lượt là kết quả của video stream và audio stream, để sử dụng trong phần sau
-map “[v]” -map “[a]” dùng để xác định rằng FFmpeg sẽ sử dụng video stream và audio stream từ bước trước (thay vì input) để đưa ra output.
output.mp4 là tên file output
Chú ý: Nếu file input có kích thước, tốc độ framerate và SAR khác nhau thì bạn cần phải xử lý video trước cho chúng về cùng kích thước, cùng tốc độ framerate và cùng SAR.
Trên đây là cách để ghép nối 2 video. Còn nếu bạn muốn ghép 3 video (hoặc nhiều hơn) thì câu lệnh sẽ trở thành:
Nếu bạn muốn ghép nối video nhưng trong đó không có audio stream, bạn chỉ cần áp dụng công thức tương tự như trên nhưng bỏ đi những thành phần liên quan đến audio là được.
Trên đây là một số cách để ghép nối video với FFmpeg. Nếu có gì thắc mắc hay góp ý, bạn vui lòng để lại câu hỏi xuống phần bình luận. Mình sẽ cố gắng giải đáp.
Trước khi làm việc này bạn cần phải biết định dạng audio sử dụng trong một số loại video, ví dụ:
Nếu video định dạng MP4 thì audio dạng .aac
Nếu video định dạng WEBM thì audio dạng .oga
… (chắc còn nhiều nhưng mình không rành lắm)
Giả sử mình muốn tách nguyên gốc audio từ video MP4, thì câu lệnh là:
ffmpeg -i input.mp4 -vn -acodec copy output.aac
Trong đó:
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4)
-vn là cờ dùng để xác định rằng mình không sử dụng video ở output
-acodec copy là cờ dùng để xác định rằng FFmpeg sẽ copy audio từ input sang output mà không encode lại.
output.aac là tên file output
Kết quả là mình đã có một file raw audio là output.aac.
Tách audio từ video và encode sang định dạng khác
Bạn có thể tách audio từ video rồi encode nó sang định dạng khác quen thuộc hơn, như mp3, wma,…
Giả sử mình muốn encode video thành mp3 thì câu lệnh là:
ffmpeg -i input.mp4 -vn output.mp3
Câu lệnh này gần giống câu lệnh trên. Chỉ khác ở chỗ mình bỏ qua tham số liên quan đến copy audio (-acodec copy) và file audio đầu ra với đuôi là định dạng mình muốn convert (mp3).
FFmpeg sẽ dựa vào đuôi này để biết rằng nó sẽ phải encode audio như thế nào.
Ngoài ra, bạn cũng có thể chỉ định rõ định dạng output theo chuẩn nào.
Chú ý: Nếu làm theo cách này, bạn cần biết rõ định dạng file tương ứng với chuẩn encode.
-acodec mp3 ứng với định dạng .mp3
-acodec aac ứng với định dạng .aac
-acodec libvorbis ứng với định dạng .oga
Lời kết
Trên đây là một số cách để tách audio từ video với FFmpeg. Nếu có gì thắc mắc hay góp ý, bạn vui lòng để lại câu hỏi xuống phần bình luận. Mình sẽ cố gắng giải đáp.
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4)
-ss (start timestamp) dùng để xác định thời điểm bắt đầu cắt video, theo định dạng (giờ:phút:giây:mili-giây). Trong câu lệnh trên 00:00:02.0000 ứng với thời điểm giây thứ 2. Ngoài ra, nếu bạn chỉ dùng -ss 2 thì FFmpeg cũng mặc định hiểu rằng, đó là thời điểm 2 giây.
-t là cờ dùng để xác định thời lượng bạn muốn cắt. Sau đó là con số chỉ thời lượng đó, ở đây là 3 giây.
output.mp4 là tên file output
Trong câu lệnh trên, ngoài tham số -t, bạn có thể sử dụng tham số -to để thay thế. Tham số -todùng đề xác định thời điểm kết thúc bạn muốn cắt video. Ví dụ mình muốn cắt video ở thời điểm 5 giây thì có thể sử dụng một trong 2 câu lệnh dưới đây:
Kết quả thu được hoàn toàn giống với câu lệnh ban đầu.
Tuy nhiên, có một điều bạn cần lưu ý là câu lệnh trên sẽ encode lại video dựa theo những tham số mặc định của FFmpeg. Nếu bạn muốn giữ nguyên thông tin video, không encode lại video thì mời bạn theo dõi phần dưới đây.
Không encode lại video
Để làm điều này, bạn có thể sử dụng thêm option -c copy (hoặc -vcodec copy với video và -acodec copy với audio) để FFmpeg copy trực tiếp video từ input sang output mà không cần phải encode lại video nữa.
Điều này có 2 ưu điểm:
Giữ nguyên chất lượng video ban đầu
Giúp cắt video nhanhhơn
Câu lệnh cần dùng là:
ffmpeg -i input.mp4 -ss 2 -t 3 -c copy output.mp4
Lời kết
Trên đây là cách để cut video với FFmpeg. Nếu có gì thắc mắc hay góp ý, bạn vui lòng để lại câu hỏi xuống phần bình luận. Mình sẽ cố gắng giải đáp.
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4)
-vf dùng để thông báo việc sử dụng video filter. Tiếp theo đó là công thức sử dụng. Để crop video với FFmpeg thì mình sử dụng công thức là crop=w:h:x:y.
w: là chiều rộng video mà bạn muốn thu được.h: là chiều cao video mà bạn muốn thu được.x: là toạ độ trên trục x điểm top, left của video mong muốn, mặc định x = 0.y: là toạ độ trên trục y điểm top, left của video mong muốn, mặc định y = 0.
output.mp4 là tên file output
Hệ trục toạ độ
Có thể bạn vẫn chưa hiểu rõ câu lệnh trên cho lắm. Nên mình đã chuẩn bị một hình minh hoạ cho bạn dễ hiểu hơn:
Hệ trục tọa độ trên video
Ví dụ minh hoạ
Giả sử mình có một video với độ phân giải 1920×1080. Mình muốn crop lấy video với độ phân giải 1280×720 và điểm top, lef có toạ độ là (320, 180).
Khi đó, mình có w = 1280, h = 720, x = 320, y = 180. Suy ra câu lệnh cần dùng là:
Trong ví dụ trên, mình cố tình cắt lấy video nằm ở chính giữa của video gốc (cách đều 4 phía).
Vì mình đã chủ động tính toán:
x = 320 = (1920 – 1280) / 2
y = 180 = (1080 – 720) / 2
Hay tổng quát hoá: để cắt lấy video có kích thước w, h từ video gốc W, H và cách đều 4 phíathì:
x = (W – w) / 2
y = (H – h) / 2
Trong đó:
Giá trị w, h là giá trị mình mong muốn
Giá trị W, H là giá trị kích thước video ban đầu. Dĩ nhiên, bạn có thể lấy được kích thước của video này thủ công. Hoặc bạn có thể sử dụng biến số có sẵn cung cấp bởi FFmpeg. Đó là in_w tương ứng với chiều rộng video gốc, in_h tương ứng với chiều cao video gốc.
Nếu áp dụng biến số này thì câu lệnh trong ví dụ trên trở thành:
Giả sử mình có 1 video dạng flv và muốn convert nó thành mp4. Khi đó, câu lệnh cơ bản cần dùng là:
ffmpeg -i input.flv output.mp4 -hide_banner
Trong đó:
-i là cờ dùng để xác định input, sau đó là tên file (input.flv)
output.mp4 là tên file output. Đặc biệt, FFmpeg sẽ dựa vào phần đuôi .mp4 để xác định rằng nó sẽ convert ra file MP4 với chuẩn H264 dành cho video và chuẩn aac dành cho audio.
-hide_banner dùng để ẩn những thông tin liên quan đến FFmpeg (phiên bản, các thư viện sử dụng,…)
Kết quả:
Kết quả convert video thành MP4 cơ bản
Kết quả cho ra file output.mp4 với kích thước khá nhỏ ~ 600KB, so với video gốc ~ 4MB (có gì đó không ổn thì phải).
Sử dụng một số tuỳ chọn cơ bản
Trong phần trước, khi bạn sử dụng câu lệnh cơ bản thì FFmpeg sẽ dùng những thông số mặc định để convert video thành MP4.
Thường thì kết quả thu được là khá OK rồi. Tuy nhiên, sẽ có những lúc kết quả thu được không tốt lắm, chất lượng video bị giảm đi đáng kể.
Lúc này, bạn cần phải tuỳ chỉnh các thông số sao cho hợp lý để thu được kết quả như mong muốn.
-i là cờ dùng để xác định input, sau đó là tên file (input.flv)
-f là cờ để xác định format đầu ra, tiếp theo là tên format (ở đây là mp4)
-vcodec libx264 là cờ để xác định codec sử dụng cho video. Ở đây, mình sử dụng libx264 vì đó là thư viện dùng để encode video theo chuẩn H264. Ngoài ra, bạn có thể thay thế nó bằng -c:v libx264 cũng cho kết quả tương tự.
-preset medium để xác định preset sử dụng là medium. FFmpeg hỗ trợ các loại preset là ultrafast, superfast, veryfast, faster, fast, medium, slow, slower và veryslow. Trong đó, ultrafast cho phép encode nhanh nhất, nhưng chất lượng thấp nhất. Ngược lại, veryslowcho phép encode chậm nhất nhưng chất lượng tốt nhất.
-profile:v baseline dùng để xác định profile sử dụng cho video là baseline. FFmpeg hỗ trợ một số loại profile là: baseline, main, high, high10, high422, và high444. Trong đó, mỗi profile cho phép video thu được tương thích với các loại thiết bị khác nhau. Trong đó, profile baseline được hỗ trợ bởi hầu hết mọi loại thiết bị.
-acodec aac là cờ xác định codec sử dụng cho audio là aac. Tương tự như với video, ở đây bạn cũng có thể sử dụng -c:a aac vẫn cho kết quả tương tự.
output-custom-1.mp4 là tên file output.
-hide_banner dùng để ẩn những thông tin liên quan đến FFmpeg (phiên bản, các thư viện sử dụng,…)
Kết quả:
Convert video thành MP4 sử dụng thêm tùy chọn
Kích thước output lần này lớn hơn bên trên 1 chút, cỡ ~ 700KB. Nhưng chất lượng thì khác bọt. Bạn cứ thử đi rồi sẽ thấy.
Sử dụng một số tuỳ chọn khác
Ngoài những tuỳ chọn cơ bản trên, bạn còn có thể sử dụng thêm các tuỳ chọn khác như sau.
CRF (Constant Rate Factor)
CRF là hệ số dùng để xác định chất lượng mong muốn của video. Nó có giá trị từ 0 đến 51, và mặc định là 23.
Giá trị CRF càng nhỏ thì chất lượng video càng tốt. Ngược lại, giá trị CRF càng cao thì chất lượng video càng kém.
Đặc biệt, với CRF = 0, người ta thu được video dạng lossless (không suy giảm).
Kích thước output lần này thậm chí còn lớn hơn video gốc, cỡ ~ 10MB. Tuy nhiên, kết quả theo mình thấy thì cũng không tốt hơn là mấy.
Thực tế, giá trị CRF hợp lý sẽ là 17 hoặc 18 để có thể cân bằng giữa chất lượng và dung lượng video.
Bitrate
Giả sử bạn đang muốn Live Streaming một video. Video này có bitrate cỡ 4Mbps. Tuy nhiên, tốc độ mạng cho phép chỉ trong khoảng 1Mbps. Lúc này, bạn cần phải giảm bitrate của video xuống nhỏ hơn 1Mbps.
Ví dụ câu lệnh sau sẽ giới hạn bitrate của video xuống nhỏ hơn hoặc bằng 1Mbps:
bufsize 2M: xác định buffer cho việc encode video là 2MB.
Kết quả:
Convert video thành MP4 với bitrate
Ngoài ra, để kiểm tra lại xem bitrate của video bằng bao nhiêu, bạn sử dụng câu lệnh:
ffmpeg -i output-custom-3.mp4 -hide_banner
Kết quả:
Xem thông tin video
Rõ ràng, video output có bitrate là 776 kb/s, thoả mãn điều kiện maxrate 1Mb/s.
Cờ faststart dành cho web video
Cờ này là bắt buộc nếu bạn muốn dùng video online. Vì FFmpeg sẽ đưa những thông tin metadata cần thiết của video lên trên đầu của file. Nhờ đó mà video có thể play khi mà nó chưa load xong.
-i là cờ dùng để xác định input, sau đó là tên file (input.mp4)
output.gif là tên file output. Đồng thời, phần đuôi .gif giúp FFmpeg hiểu rằng bạn đang muốn chuyển video thành ảnh động GIF.
-hide_banner dùng để ẩn những thông tin liên quan đến FFmpeg (phiên bản, các thư viện sử dụng,…)
Ví dụ mình convert thử một video dài 7s, kích thước 1920×1080, dung lượng ~ 5MB với câu lệnh trên và kết quả:
Convert video thành ảnh động GIF với câu lệnh đơn giản
Ảnh động GIF có kích thước cỡ ~21MB (gấp 4 lần video gốc).
Tại sao ảnh động GIF lại nặng hơn nhiều so với video tương ứng?
Bởi vì, ảnh động GIF được tạo bởi các ảnh riêng lẻ ứng với ảnh gốc. Trong khi đó, video chỉ lưu chúng lại thành các frame dạng I, P, B. Mà chỉ frame I là frame đầy đủ, còn frame P và B chỉ dùng để lưu lại sự thay đổi nhỏ giữa các frame. Điều này giải thích tại sao ảnh động GIF lại nặng hơn so với video tương ứng.
Vậy làm sao tối ưu được kích thước của ảnh động GIF?
Tối ưu kích thước ảnh động GIF
Thực ra, nếu nói tối ưu thì cũng không hẳn. Chỉ đơn giản là mình giảm kích thước của nó đi thôi.
Có 3 cách để giảm kích thước của ảnh động GIF là:
Giảm thời lượng của ảnh động GIF. Ví dụ: thay vì độ dài 20 giây thì mình chỉ lấy 10 giây, bắt đầu từ giây thứ 5 đến giây thứ 15 chẳng hạn.
Giảm kích thước của ảnh động GIF. Ví dụ: thay vì kích thước Full HD (1920×1080) thì mình giảm xuống HD (1280×720).
Giảm tốc độ framerate (tức số frame trên 1 giây). Ví dụ: thay vì fps=30 thì mình giảm xuống còn fps=20.
Xem thêm: [FFmpeg tutorial] Những câu lệnh FFmpeg xử lý video
Giảm thời lượng ảnh động GIF
Video input.mp4 bên trên có độ dài 7 giây. Mình muốn ảnh động GIF sẽ có độ dài 4 giây, bắt đầu từ giây thứ 2 đến giây thứ 6.
Để làm việc này, mình có thể sử dụng 1 trong 2 câu lệnh sau: