Tác vụ và lý do nó khó hơn vẻ ngoài
"Hãy cho tôi một khung hình mỗi giây từ clip này" là một trong những công việc video phổ biến nhất. Người kiểm tra QA cần các ảnh chụp màn hình cách đều nhau để đính kèm vào báo cáo lỗi. Nhà nghiên cứu cần một chuỗi hình ảnh được lấy mẫu để đưa vào công cụ chú thích. Một biên tập viên mạng xã hội cần 20 bức ảnh tĩnh ứng cử viên trong một đoạn cắt dài hai phút mà không cần phải xem lại dòng thời gian bằng tay.
Bản thân nhiệm vụ này rất đơn giản. Điều khiến nó trở nên khó hiểu là "một khung hình trên giây" không rõ ràng khi bạn nhìn kỹ. Ý bạn là một khung hình cho mỗi giây thời gian phát lại hay mỗi Nthứ của luồng được mã hóa? Đó là những thứ khác nhau: một clip 24 khung hình / giây và một clip 60 khung hình / giây tạo ra cùng một số lượng trong lần đọc đầu tiên và các số lượng cực kỳ khác nhau trong lần đọc thứ hai. Chọn sai và bạn sẽ nhận được một thư mục chứa gần như trùng lặp hoặc một chuỗi quá thưa thớt không hữu ích.
Cả hai cách tiếp cận dưới đây đều tạo ra các pixel giống nhau. đã thể hiện sai.
Phương pháp 1: FFmpeg, tham số theo tham số
Lệnh chuẩn rất ngắn:
ffmpeg -i input.mp4 -vf fps=1 -q:v 2 frame_%04d.jpg
Mỗi khung hình được mã hóa. một phần quan trọng:
-i input.mp4— tệp nguồn. FFmpeg đọc một lần, bắt đầu kết thúc; nó không tìm kiếm từng dấu thời gian riêng lẻ.-vf fps=1— bộ lọc video thực hiện công việc thực tế.fps=1có nghĩa là một khung hình đầu ra mỗi giây trong thời gian phát lại, bất kể tốc độ khung hình nguồn. sử dụngfps=1/5cho một khung hình cứ sau 5 giây hoặcfps=2cho hai khung hình mỗi giây. Đây là giá trị đọc tại thời điểm phát lại.-q:v 2— Chất lượng JPEG, ở thang đo đảo ngược trong đó 2 gần như không mất dữ liệu và 31 được nén nhiều. Bỏ qua nó và bạn nhận được mặc định của FFmpeg, mềm hơn đáng kể so với hầu hết mọi người mong đợi. Nếu bạn muốn đầu ra không bị mất dữ liệu, hãy viếtframe_%04d.pngthay vào đó, bỏ hoàn toàn cờ này.frame_%04d.jpg— mẫu đầu ra.%04dkhông đệm bộ đếm đến bốn chữ số:frame_0001.jpg,frame_0002.jpg. Lớp đệm không mang tính thẩm mỹ; xem vấn đề đánh số dưới đây.
Nếu bạn muốn đọc nội dung khác — mọi Nkhung được mã hóa thứ thay vì mọi khung N giây — bộ lọc thay đổi:
ffmpeg -i input.mp4 -vf "select=not(mod(n\,10))" -vsync vfr frame_%04d.png
Điều này giữ cho các khung có chỉ mục khung n có thể chia hết cho 10 và -vsync vfr ngăn FFmpeg sao chép các khung để tạo ra tốc độ đầu ra không đổi. Hãy tắt cờ đó và bạn sẽ nhận được nhiều tệp hơn mức bạn yêu cầu, đây là kết quả đầu tiên phổ biến và khó hiểu.
Để giới hạn công việc trong một phân đoạn, hãy đặt -ss trước khi -i vì vậy FFmpeg tìm kiếm trước khi giải mã thay vì giải mã và loại bỏ:
ffmpeg -ss 00:01:30 -to 00:02:15 -i input.mp4 -vf fps=1 frame_%04d.png
Phương pháp 2: Công việc tương tự trong trình duyệt
trình trích xuất khung trên trang web này ánh xạ tới hai chỉ số giống nhau, với sự mơ hồ được thể hiện rõ ràng trong giao diện thay vì ẩn trong chuỗi bộ lọc.
- Thả tệp vào. Nó được đọc trực tiếp từ đĩa vào trình duyệt bộ nhớ — không có nội dung tải lên nên nguồn 3 GB bắt đầu xử lý ngay lập tức thay vì sau khi truyền.
- Chọn phương pháp trích xuất. "Khoảng thời gian" tương đương với
fps=1/N— bạn nhập khoảng trống sau vài giây. "Tốc độ khung hình (FPS)" tương đương vớiselect/modbộ lọc — bạn nhập N để giữ mọi Nkhung hình. - Đọc gợi ý về số lượng khung hình trước khi trích xuất. Đây là phần tiết kiệm thời gian nhất. Giao diện hiển thị số lượng hình ảnh mà cài đặt hiện tại của bạn sẽ tạo ra trước khi mọi thứ đều chạy nên lỗi 4.000 tệp sẽ trở thành một con số mà bạn thấy thay vì một thư mục mà bạn khám phá.
- Đặt định dạng và chất lượng. PNG cho lossless, JPG hoặc WebP với thanh trượt 10–100% khi kích thước quan trọng. Vị trí thanh trượt tương ứng với
-q:vđiều khiển, thể hiện cách mà hầu hết mọi người nghĩ về nó. - Cắt bớt phạm vi nếu cần. Thanh trượt tay cầm kép là
-ss/-totương đương, với dấu thời gian hiển thị khi bạn kéo. - Xuất. Khung hình xuất hiện trong lưới xem trước; nhấp vào một cái để lưu riêng hoặc lấy toàn bộ dưới dạng một ZIP.
Quy tắc chung để chọn khoảng thời gian: đối với đầu nói chuyện hoặc bản ghi màn hình, 1 khung hình cứ sau 2–5 giây sẽ ghi lại mọi thay đổi trạng thái có ý nghĩa. Đối với thể thao hoặc bất cứ thứ gì có chuyển động nhanh, 2–5 khung hình mỗi giây. Dành riêng "mọi khung hình" để phân tích chính xác khung hình — một phút 60 khung hình/giây là 3.600 hình ảnh và vài gigabyte PNG.
Ba vấn đề thực sự khiến mọi người tốn thời gian
1. Đầu ra là hàng nghìn khung hình gần giống nhau
Hầu như luôn luôn là sự trộn lẫn các đơn vị: ý bạn là "mỗi khung hình thứ 10" và viết fps=10, có nghĩa là mười khung hình mỗi giây — trên nguồn 30 khung hình/giây có số hình ảnh nhiều hơn gấp 3 lần so với mong đợi ban đầu chứ không phải ít hơn 3×.
Trước khi chạy bất cứ thứ gì, hãy thực hiện phép tính. Chế độ thời gian phát lại: duration ÷ interval. Chế độ chỉ mục khung: duration × source_fps ÷ N. Một clip dài 10 phút 30 khung hình/giây ở "mỗi khung hình thứ 10" là 600 × 30 10 = 1.800 hình ảnh. Nếu con số đó làm bạn ngạc nhiên, hãy điều chỉnh trước khi bắt đầu thay vì sau đó. Trong công cụ trình duyệt, hình tương tự sẽ tự động xuất hiện trong trường khoảng thời gian.
2. Quá trình trích xuất bị đình trệ giữa một đoạn video dài
Các nguyên nhân khác nhau ở mỗi bên nên cách khắc phục cũng khác nhau.
Với FFmpeg, tình trạng ngừng hoạt động thường liên quan đến ổ đĩa — hàng nghìn PNG nằm trong một thư mục và hệ thống tập tin, chứ không phải bộ giải mã, sẽ trở thành nút cổ chai. Ghi vào một thư mục trống mới, ưu tiên JPG khi bạn không cần lossless và chia các nguồn rất dài thành các phân đoạn với -ss/-to.
Trong trình duyệt, giới hạn là RAM: mọi khung hình được trích xuất sẽ được giữ trong bộ nhớ cho đến khi bạn tải xuống ZIP. Vài trăm 4K PNG là vài gigabyte và một tab có thể bị hủy vì nó. Mẫu đáng tin cậy là làm việc theo từng phần — sử dụng thanh trượt phạm vi thời gian để lấy 0:00–2:00, tải xuống ZIP đó, sau đó di chuyển phạm vi sang 2:00–4:00. Việc đóng các tab khác trước khi thực hiện một tác vụ lớn thực sự hữu ích và JPG ở chất lượng 85–90% giúp giảm áp lực bộ nhớ gấp nhiều lần mà không có sự khác biệt rõ ràng đối với hầu hết các mục đích sử dụng.
3. Đánh số khung phá vỡ thứ tự nhập
Cái này hoạt động ổn định sau khi xuất. Các công cụ sắp xếp tên tệp dưới dạng văn bản — và hầu hết đều thực hiện — sắp xếp frame_10.png trước khi frame_2.png, vì "1" sắp xếp trước "2" theo từng ký tự. Trình tự của bạn phát lại bị xáo trộn và không rõ tại sao.
Cách khắc phục là không có phần đệm, đủ rộng cho số lượng lớn nhất mà bạn từng tạo ra. Đó là điều %04d dành cho; sử dụng %05d nếu bạn có thể vượt quá 9.999 khung hình. Công cụ trình duyệt tự động đệm, đó là lý do chính khiến đầu ra của nó có xu hướng rơi thẳng vào trình nhập chuỗi hình ảnh mà không đổi tên.
Khi FFmpeg vẫn là lựa chọn phù hợp
Rất nhiều lần. Đây không phải là trường hợp trình duyệt giành chiến thắng trên mọi phương diện:
- Bất kỳ điều gì được lập kịch bản hoặc lên lịch. Một công việc định kỳ, một bước CI, một quy trình phía máy chủ - một trình duyệt hoàn toàn không thể tham gia vào những công việc đó.
- Tập hợp trên nhiều lô file. Một vòng lặp shell trên 200 clip là chuyện bình thường trong FFmpeg và tẻ nhạt ở bất kỳ nơi nào khác.
- Codec mà trình duyệt sẽ không giải mã. ProRes, DNxHD, định dạng máy ảnh thô, vùng chứa bất thường. Nếu trình duyệt không thể phát nó, nó sẽ không thể trích xuất nó. FFmpeg xử lý hầu hết mọi thứ.
- Lọc trong quá trình trích xuất. Khử xen kẽ, chia tỷ lệ, chuyển đổi không gian màu, cắt xén, phát hiện thay đổi cảnh — tất cả đều có sẵn dưới dạng bộ lọc trong cùng một lượt.
- Khả năng tái tạo. Một lệnh trong README là chính xác. "Đặt thanh trượt về đây" thì không.
Công cụ trình duyệt phù hợp hơn cho các công việc diễn ra một lần, cho bất kỳ ai không muốn cài đặt và duy trì chuỗi công cụ cho một nhiệm vụ không thường xuyên, khi nguồn đủ bí mật nên việc xử lý chỉ cục bộ là quan trọng và khi bạn muốn xem các khung trước khi thực hiện xuất. Đó thực sự là những tình huống khác nhau, không phải là xếp hạng.
Tham khảo nhanh
| Những gì bạn muốn | FFmpeg | Công cụ trình duyệt |
|---|---|---|
| Một khung hình mỗi giây | -vf fps=1 |
Khoảng thời gian = 1 |
| Một khung hình cứ sau 5 giây | -vf fps=1/5 |
Khoảng thời gian = 5 |
| Mỗi khung hình được mã hóa thứ 10 | -vf "select=not(mod(n\,10))" -vsync vfr |
Chế độ Tốc độ khung hình, N = 10 |
| Chỉ 1:30 đến 2:15 | -ss 00:01:30 -to 00:02:15 |
Thanh trượt phạm vi thời gian |
| Đầu ra không mất dữ liệu | .png mẫu đầu ra |
Định dạng = PNG |
| Các tệp nhỏ hơn | -q:v 5 với .jpg |
JPG + thanh trượt chất lượng |
| Xem số lượng trước khi chạy | Tính toán thủ công | Hiển thị trong trường khoảng thời gian |
| Xem trước trước khi lưu | Mở thư mục đầu ra | Lưới xem trước tích hợp sẵn |
| Tự động hóa / lô | Shell loop, cron, CI | Không thể |
| ProRes, DNxHD, raw | Được hỗ trợ | Chỉ những gì trình duyệt giải mã |
Cho dù bạn đi theo lộ trình nào thì quyết định khoảng thời gian sẽ đến trước và công cụ sẽ là thứ hai. Hãy tính xem bạn thực sự cần bao nhiêu khung hình, xác nhận số lượng trước khi bắt đầu và phần còn lại là máy móc.