Học FFmpeg qua ví dụ
(ffmpegbyexample.com)- Các tác vụ FFmpeg thường dễ trở nên phức tạp do phải kết hợp nhiều tùy chọn, và FFmpeg By Example là một trang tài liệu giúp nhanh chóng tìm được cách xử lý media cần thiết thông qua các ví dụ lệnh thực tế
- Trang cung cấp cả kho GitHub, cộng đồng Discord và trang đóng góp để người dùng có thể trực tiếp gửi các ý tưởng ứng dụng FFmpeg mới
- Giống như ví dụ về bộ lọc
testsrc, trang hiển thị nguồn đầu vào, độ phân giải, tốc độ khung hình và tệp đầu ra trong một lệnh duy nhất để có thể làm theo nguyên cấu trúc lệnh - Các ví dụ bao quát toàn bộ các tác vụ xử lý media như tính bitrate, thay đổi kích thước ảnh, giảm nhiễu âm thanh, hiệu ứng chuyển cảnh, ánh xạ stream, tăng tốc phần cứng và xử lý metadata
- Mỗi ví dụ được chia theo thẻ và trang riêng, nên rất dễ duyệt các lệnh FFmpeg cần thiết dựa trên bộ lọc cụ thể hoặc mục đích chuyển đổi
Trang tài liệu FFmpeg tập trung vào ví dụ
- FFmpeg By Example là một website tổng hợp nhiều cách sử dụng FFmpeg theo từng ví dụ cụ thể
- Trang cũng cung cấp các liên kết để tham gia cộng đồng và đóng góp
Ví dụ tạo video kiểm thử bằng testsrc
- Generate test video color pattern with 'testsrc' filter là ví dụ tạo video mẫu màu để kiểm thử bằng bộ lọc
testsrc - Lệnh này tạo video 10 giây, 1280x720, 30fps thành
testsrc.mpgbằng đầu vào lavfi
ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 testsrc.mpg
Mã hóa, chuyển đổi và tăng tốc phần cứng
- Bao gồm các ví dụ liên quan đến mã hóa video và chuyển đổi định dạng
- Recode Your Video With a Modern Codec, Often Saving Space: ví dụ về mã hóa H.265
- Convert Video to Telegram Video Sticker Format (512px Max, 256KB Limit): ví dụ chuyển sang định dạng sticker video Telegram
- Use Intel QuickSync Video Hardware Acceleration for Transcoding Video: ví dụ transcoding có tăng tốc phần cứng Intel QuickSync Video
Xử lý âm thanh
- Có thể xem các ví dụ về tác vụ âm thanh thường dùng như khử nhiễu, chuẩn hóa, chuyển đổi và trích xuất
- Audio Noise Reduction Using Arnndn: giảm nhiễu âm thanh bằng
arnndn - Normalize Audio to EBU R128 Loudness Standard (-23 LUFS): chuẩn hóa theo chuẩn EBU R128 ở
-23 LUFS - Convert Wav to Mp3 File: chuyển WAV sang MP3
- Extract an AAC Audio Track From a Video File: trích xuất track âm thanh AAC từ tệp video
- Audio Noise Reduction Using Arnndn: giảm nhiễu âm thanh bằng
Hình ảnh và hoạt ảnh
- Trang cũng bao quát các workflow dựa trên hình ảnh, từ xử lý ảnh tĩnh đến tạo hoạt ảnh WebP
- Resize PNG Images While Preserving Transparency and Aspect Ratio: thay đổi kích thước PNG mà vẫn giữ độ trong suốt và tỷ lệ khung hình
- Generate Looping WebP Animation From Image Sequence With Variable Quality: tạo hoạt ảnh WebP lặp từ chuỗi ảnh với chất lượng thay đổi
- Slow Animated WebP Image Sequence (Carousel): ví dụ chuỗi ảnh WebP hoạt ảnh chậm
Bộ lọc và hiệu ứng hình ảnh
- Các ví dụ về hoạt ảnh, chuyển cảnh và hiệu ứng chữ bằng bộ lọc FFmpeg được sắp xếp gọn gàng
- Animate an Image Using Zoompan Filter: tạo hoạt ảnh cho ảnh bằng bộ lọc
zoompan - XFade Video Transitions Examples: hiệu ứng chuyển cảnh dựa trên
xfade - Video Echo Effect With Delay and Hue Using Lagfun: hiệu ứng echo video có độ trễ và thay đổi sắc độ bằng
lagfun - Fade in and Out Text Using the 'Drawtext' Filter: fade in/out văn bản bằng bộ lọc
drawtext - "Drawtext" and "Drawbox" Using "Sendcmd" Manifest: dùng
drawtextvàdrawboxvới manifestsendcmd
- Animate an Image Using Zoompan Filter: tạo hoạt ảnh cho ảnh bằng bộ lọc
Trích xuất, phân tích và metadata
- Cũng bao gồm các tác vụ lấy stream cần thiết từ tệp hoặc phân tích khung hình và metadata
- Extract Audio From Video Files With Stream Mapping: trích xuất âm thanh từ tệp video bằng stream mapping
- Extract Multiple Video Clips From Single Input With Precise Timestamps: trích xuất nhiều clip từ một đầu vào với timestamp chính xác
- Analyze Video Frames, Timecode and Metadata With Showinfo Filter: phân tích khung hình, timecode và metadata bằng bộ lọc
showinfo - Getting Streams Information of a Video File: xem thông tin stream của tệp video
- Copy Metadata From One Mp3 to Another: sao chép metadata giữa các tệp MP3
Nguồn sinh và pipe đầu ra
- Trang cũng cung cấp các ví dụ hữu ích cho tự động hóa hoặc gỡ lỗi như tạo nguồn kiểm thử, ghi từng khung hình riêng lẻ và xuất ra STDOUT
- Generate Solid Color Video With Custom Hex Color Code: tạo video một màu bằng mã màu Hex tùy chỉnh
- Create SMPTE Color Bars With Centered Text Overlay: tạo thanh màu SMPTE với lớp phủ văn bản ở giữa
- Generate "Game of Life" Video Using Lavfi Video Source: tạo video Game of Life bằng nguồn video
lavfi - Print a Data Channel to STDOUT Using Ffmpeg: in một kênh dữ liệu ra STDOUT
- Record a Video From Individual Frames: ghi video từ các khung hình riêng lẻ
1 bình luận
Các ý kiến trên Hacker News
Niềm vui khi dùng ffmpeg đã tăng ít nhất 1000%
Trước đây tôi phải chán chường Google để tìm các câu trả lời trên Stack Overflow rồi ghép lại thành lệnh, còn giờ ChatGPT viết lệnh thay tôi nên tiện hơn nhiều
Nhờ LLM mà tôi dùng ffmpeg nhiều lần mỗi tuần
Đây là ứng dụng tốt nhất cho công cụ
llm cmdcủa tôi:uv tool install llmllm install llm-cmdllm cmd use ffmpeg to extract audio from myfile.mov and save that as mp3https://github.com/simonw/llm-cmd
Từ lâu tôi đã xếp ffmpeg vào cùng một hộp với regex: cảm giác “mình thật sự nên học, nhưng chắc sẽ cực kỳ ghét nó”
Rồi ChatGPT xuất hiện và giải quyết cả hai
Tôi cũng vậy. Những việc kiểu này AI đã hoàn toàn đảm nhận, còn tôi chỉ là người trung gian sao chép và dán phần truy vết lỗi
Cũng đã có nhiều công cụ khác xuất hiện, nhưng tôi vừa viết một script giúp đơn giản hóa khá nhiều các chuỗi lệnh kiểu này: llmpeg https://github.com/jjcm/llmpeg
Nếu đã cài ffmpeg và đặt khóa API trong biến môi trường OpenAI thì nó sẽ chạy ngay
Demo: https://image.non.io/1c7a92ef-0917-49ef-9460-6298c7a9116c.we...
Sau khi học cách bộ lọc phức hợp hoạt động, trải nghiệm dùng ffmpeg của tôi đã tốt hơn
Tôi chợt nghĩ mình nên viết và công khai cách biến các băng video gia đình đã số hóa thành clip bằng phát hiện cảnh
Biết đâu có ai đó tìm kiếm, nên tôi để lại gist từng hoạt động khá tốt [0]. Tuy nhiên đôi khi nó bị đánh lừa bởi đèn flash máy ảnh hoặc rung lắc, nên tôi phải cung cấp riêng các file bắt đầu/kết thúc rồi nối lại bằng ffmpeg [1]
Điều kỳ lạ là trên bản cập nhật Mac mới nhất, hiệu năng lại tốt hơn khi không dùng
-c:v h264_videotoolbox. Có thể là hồi quy hiệu năng của Sequoia, nhưng tôi không chắc. Cờ tương ứng trên máy Windows có GPU Nvidia là-c:v h264_nvenc. Tôi thắc mắc vì sao ffmpeg không tự phát hiện. Nhờ cái này tôi đạt được mức tăng hiệu năng khoảng 8 lầnKhoảnh khắc duy nhất tôi thật sự xứng đáng với đồng lương ở công ty là khi phát hiện bản ffmpeg đã cài được biên dịch mà không có tăng tốc GPU, ngay trước lúc chúng tôi định chi thêm nhiều tiền cho máy chủ cloud có GPU để xử lý video
[0] https://gist.githubusercontent.com/nielsbom/c86c504fa5fd61ae...
[1] https://gist.githubusercontent.com/jazzyjackson/bf9282df0a40...
Vấn đề của CPU trên cloud là chúng không có bộ mã hóa video phần cứng như trong CPU tiêu dùng, nên phải chuyển sang máy GPU đắt hơn nhiều
Thành thật mà nói tôi chưa thật sự so sánh giá đúng cách khi dùng tăng tốc phần cứng trên cloud, nên tôi tò mò liệu ý bạn có phải là bạn đã thử và thấy chi phí/hiệu quả ổn không
Tôi từng dùng ffmpeg để phát hiện cảnh trống
Tôi có một camera hướng về đường bay SFO, và sau khi loại bỏ mọi khung hình không có chuyển động, chỉ còn lại một đoạn video liên tục các máy bay đi qua mà không có những đoạn nhàm chán
-c:v h264_nvenchữu ích cho mã hóa hàng loạt khi mã hóa nhiều video cùng lúc, vì nó có thể tăng thông lượng mã hóaTuy nhiên trong các thử nghiệm hạn chế trước đây của tôi, chất lượng đầu ra hơi kém hơn libx264. Tôi không biết có cách nào xử lý không, nhưng không chỉ mình tôi gặp chuyện này
Lý do ffmpeg không tự phát hiện điều này là mã hóa phần cứng thường có phạm vi cấu hình hẹp, phải đánh đổi nhiều hơn so với codec phần mềm tinh vi, và ngay cả với cùng tham số cũng không cho ra kết quả chính xác giống nhau
Hơn nữa, trên một hệ thống thường có thể có nhiều API phần cứng để lựa chọn, và tính năng của chúng cũng khác nhau
FFmpeg là một công cụ dòng lệnh phức tạp, nhắm tới người dùng sẵn sàng học các chi tiết, nên tôi không chắc việc đặt giá trị mặc định dựa trên giả định có phải là đúng hay không
Nhìn vào snippet thì có vẻ bạn không khử xen kẽ
Nếu clip trước khi số hóa đã được khử xen kẽ thì không sao, nhưng nếu chưa thì bạn đang làm hỏng chất lượng khi mã hóa tư liệu interlaced thành progressive. Nên thử thêm bộ lọc
bwdifđể nội dung 30i được mã hóa thành 60p. Nó sẽ trông gần với băng video gốc hơnTheo thời gian tôi đã khá quen với nhiều phần của ffmpeg. CLI của nó có logic riêng và phụ thuộc vào thứ tự. Không phải mọi CLI Unix đều như vậy
Gần đây tôi đang thử một số tính năng khó hiểu hơn. Ví dụ như lưu trực tiếp video thô từ camera trên một máy khá chậm. Tôi đã làm một kính hiển vi và đọc các khung hình ở định dạng video thô (YUYV 1280x720) từ camera ở 120FPS; nếu lưu nguyên như vậy xuống đĩa thì dung lượng tăng theo đơn vị gigabyte mỗi phút. Đĩa thì rẻ, nhưng có vẻ lãng phí, nên tôi đã xem xét các kỹ thuật gần như lossless có thể nén và lưu ảnh chính xác thật nhanh
Tôi phát hiện việc chuyển đổi RGB24 trong ffmpeg rất chậm, nên sau khi mày mò các dòng lệnh, tôi chốt ở lệnh sau:
ffmpeg -f rawvideo -pix_fmt yuyv422 -s 1280x720 -i test.raw -vcodec libx264 -pix_fmt yuv420p movie.mp4 -crf 13 -yVideo thô không có container nên không có metadata như “định dạng pixel” hay “kích thước ảnh”, vì vậy phải cung cấp trực tiếp. Nó phụ thuộc vào thứ tự: mọi thứ trước
-i test.rawdùng để giải mã đầu vào, còn mọi thứ sau đó dùng để ghi đầu ra. Chỉ thực hiện một phép chuyển đổi định dạng pixel rất nhỏ (ffmpeg có thể xử lý rất nhanh), rồi ghi dữ liệu sang một định dạng gần như lossless có container. Trong hầu hết trường hợp, container.mkvlà tốt nhấtVì không thích dòng lệnh nên cuối cùng tôi dùng ffmpeg-python, và để nó ghép dòng lệnh từ đoạn mã sau:
self.process = (ffmpeg.input("pipe:",format="rawvideo",pix_fmt="yuyv422",s="{}x{}".format(1280, 720),threads=8).output(fname, pix_fmt="yuv422p", vcodec="libx264", crf=13).overwrite_output().global_args("-threads", "8").run_async(pipe_stdin=True))Và thực tế là tôi
write()các frame vào stdin của process đó. Máy có 12 core và việc điều khiển kính hiển vi luôn dùng ít nhất 2 core, nên tôi phải giới hạn số luồngTôi vẫn đang tìm một cách mã hóa YUV lossless tốt hơn và nhanh hơn
Việc phụ thuộc vào thứ tự là hợp lý. Pipeline Unix cũng phụ thuộc vào thứ tự các thành phần, và các lệnh FFMpeg phức tạp cũng làm việc tương tự
Nhiều người thích tính thẩm mỹ của “fluent interface” như
ffmpeg-python, nhưng trong Python nó thường bị xem là không giống phong cách Python. Theo tôi hiểu, ffmpeg-python được thiết kế để phản ánh sát thứ tự dòng lệnhSở thích được củng cố bởi thiết kế của thư viện chuẩn và các kiểu tích hợp là https://en.wikipedia.org/wiki/Command%E2%80%93query_separati... mạnh mẽ. Theo nguyên tắc này thì đại khái sẽ trông như sau:
ffmpeg(global_args=..., overwrite_output=True).process_async(piped_input(...), output(...))Nếu biến đầu vào thành một quá trình cấu hình riêng, ta sẽ có một kiểu runtime khác, và cũng có thể báo cho mã xử lý rằng nó cần đọc từ stdin
Không cần tìm thêm nữa: FFV1 https://trac.ffmpeg.org/wiki/Encode/FFV1
Tôi chỉ muốn gợi ý một từ: RAM disk
Nếu có tệp dùng cho bước xử lý trung gian nhưng không muốn lưu giữ, hãy dùng RAM disk. Thực sự rất tốt
Tôi tưởng đây sẽ là một website tập hợp và quản lý kiến thức mà các cao thủ FFmpeg đã tích lũy, nhưng ngay ví dụ đầu tiên tôi bấm vào đã khiến tôi thất vọng
https://www.ffmpegbyexample.com/examples/l1bilxyl/get_the_du...
Không nên gọi thêm đến hai công cụ chỉ để xử lý chuỗi. Chỉ riêng FFprobe cũng có thể trả trực tiếp thời lượng hoặc giá trị mong muốn:
ffprobe -loglevel quiet -output_format csv=p=0 -show_entries format=duration video.mp4Đừng dừng lại ở thứ đầu tiên chạy được; sau khi nó chạy, hãy nghĩ xem có cách nào cải thiện hơn không
Dù vậy tôi thích giải pháp bạn đưa ra hơn
Hay đấy. Nó làm tôi nhớ đến cheatsheet ffmpeg tôi dùng. Tôi nghĩ ai thường dùng ffmpeg cũng có một bộ ghi chú tương tự
https://github.com/fastily/cheatsheet/blob/master/ffmpeg.md
https://github.com/ericfortis/quick-reference/blob/main/ffmp...
FFmpeg là một trong những công cụ mà tôi dùng quá thỉnh thoảng nên cú pháp chính xác không bao giờ đọng lại trong đầu. Cuối cùng tôi để LLM đưa cho mình dòng lệnh cần dùng
Công cụ duy nhất từng khiến tôi khổ sở tương tự là MegaCLI kiểu thập niên 1990 của LSI Logic. Nó cũng gần như mỗi năm mới dùng một lần, nhưng lại là loại phải dùng chính xác trong lúc chịu áp lực
Tôi đã dùng FFMPEG hơn 15 năm mà vẫn gần như không nhớ nổi lệnh nào. Dù vậy, khi dùng FFMPEG thì LLM thực sự tuyệt vời
Nếu nói với ChatGPT và Claude rằng “remux video sang mkv, nhúng subtitle.srt vào tệp, và tôi chỉ muốn đoạn từ 0:00:05 đến 0:01:00”, chúng xử lý rất tốt. Nếu bạn tò mò thì kết quả là:
ffmpeg -i input.mp4 -i subtitle.srt -ss 00:00:05 -to 00:01:00 -map 0 -map 1 -c copy -c:s mov_text output.mkvTôi tự hỏi nếu mục tiêu chỉ là sinh lệnh ffmpeg thì có thể làm một LLM nhỏ đến mức nào. Biết đâu nó có thể nhỏ đủ để đưa lên một trang web tĩnh và chạy cục bộ?
Suốt 15 năm nay tôi duy trì một tài liệu ghi chú cá nhân chứa cú pháp mình hay dùng. Nếu vẫn không được thì tôi
greplịch sử bashTôi cũng vậy. Thứ còn đọng lại trong đầu chỉ là đổi từ định dạng X sang
.mp4. Phần còn lại lần nào cũng phải tra lạiXKCD liên quan https://xkcd.com/1168/
Vài ngày trước tôi nửa đùa nửa thật rằng, nếu LLM chỉ cần cho tôi biết các flag ffmpeg tôi muốn, thì có lẽ đốt sạch rừng nhiệt đới cũng đáng giá
Đừng quên là còn có GStreamer. Vì dựa trên pipeline nên dòng lệnh và tài liệu dễ hiểu hơn ffmpeg một chút, cách kết hợp cũng có phần hợp lý hơn
Với các tác vụ video nặng, tôi đã bỏ hẳn ffmpeg và chỉ dùng GStreamer
Nhưng với các tác vụ dùng một lần, ffmpeg có vẻ thân thiện hơn nhiều. Ví dụ ffmpeg có các giá trị mặc định x264 hợp lý, còn với
gst-launchthì để mã hóa x264 chất lượng tốt, bạn thật sự phải biết mình đang làm gìCó thể cấu thành các graph phức tạp gồm source, sink và filter chuyển đổi
Có một kho GitHub về sách ffmpeg có thể bổ sung tốt cho trang này:
https://github.com/jdriselvato/FFmpeg-For-Beginners-Ebook
ffmpeg luôn cho tôi cảm giác như một ứng dụng GUI bị nhồi nhét gượng ép vào dạng TUI
Tôi cũng từng phải dùng C API vài lần khá khó chịu; về nhiều mặt thì nó trực quan, nhưng quá dễ biểu diễn các trạng thái sai. Ước gì có một framework mã hóa AV1 thời gian thực “cứ thế là chạy”
Về cơ bản, đây gần như là công cụ duy nhất khiến tôi tìm đến HandBrake, công cụ thay thế dạng GUI, trước tiên. Ngoại lệ chỉ là khi xử lý hàng loạt
Cũng có vài GUI thuần cho ffmpeg. Có điều gì đó ở công việc video khiến dòng lệnh không khớp với cách tôi xử lý trong đầu
Nếu dùng qua API thì tôi có thể khuyên dùng GStreamer. Tôi dùng Rust binding nên không quá quen với C API, nhưng thấy nó có vẻ tốt
Có những phần trở nên dài dòng vì GObject, nhưng khi đã hiểu thì bạn có thể tương tác nhất quán với mọi đối tượng trong API. Có rất nhiều độ phức tạp cần thiết (video khó mà), nhưng thiết kế, triển khai và tài liệu đều khá tốt
Với các use case thông thường, Bins (
decodebin,transcodebin,playbin) giúp làm khá dễ. Ngay cả các use case phức tạp hơn cũng làm được nhờ tính linh hoạt của thiết kếTôi thích nhận định này, nhưng TUI là thứ có tính đồ họa, còn ffmpeg chỉ là CLI
Nếu có một công cụ TUI thì sẽ rất hay. Kiểu như https://github.com/Twinklebear/fbed, nhưng ở dạng hoàn thiện tính năng hơn
Trên hệ thống Linux, tôi thích build tĩnh ffmpeg. Lý do là phiên bản trong distro đôi khi quá cũ hoặc thiếu các module tôi muốn
Phiên bản container hóa này rất hữu ích: https://github.com/wader/static-ffmpeg