- Trình bày cấu trúc và cách sử dụng của framework FFmpeg để mã hóa, giải mã, chuyển mã và phát trực tuyến âm thanh và video
- Giải thích cụ thể vai trò của các công cụ dòng lệnh như ffmpeg, ffplay, ffprobe và các thư viện cốt lõi như libavcodec, libavformat, libavfilter
- Triển khai từng bước quy trình phân tích luồng và giải mã xoay quanh AVFormatContext, AVCodecContext, AVPacket, AVFrame
- Sử dụng hệ thống build meson/ninja để tự động tải xuống và biên dịch mã ví dụ, đồng thời phân tích các tệp media mẫu và in kết quả
- Có thể dùng như tài liệu nhập môn thiên về thực hành để hiểu nguyên lý hoạt động bên trong và pipeline giải mã của FFmpeg
Cấu thành gói FFmpeg
- FFmpeg là bộ công cụ và thư viện có thể mã hóa, giải mã, chuyển mã nhiều định dạng âm thanh·video khác nhau và phát trực tuyến qua mạng
-
Công cụ FFmpeg
- ffmpeg: công cụ chuyển đổi định dạng multimedia dựa trên dòng lệnh
- ffplay: trình phát media đơn giản dựa trên SDL và các thư viện FFmpeg
- ffprobe: công cụ phân tích luồng multimedia
-
Thư viện FFmpeg
- libavformat: cung cấp chức năng nhập/xuất và muxing/demuxing
- libavcodec: cung cấp chức năng mã hóa/giải mã
- libavfilter: xử lý media thô thông qua bộ lọc dựa trên đồ thị
- libavdevice: hỗ trợ thiết bị nhập/xuất
- libavutil: cung cấp các tiện ích multimedia dùng chung
- libswresample: hỗ trợ resampling âm thanh, chuyển đổi định dạng mẫu và trộn âm thanh
- libswscale: chức năng chuyển đổi màu sắc và scale hình ảnh
- libpostproc: chức năng hậu xử lý video (deblocking, bộ lọc nhiễu, v.v.)
Trình phát FFmpeg đơn giản
- Cách sử dụng FFmpeg cơ bản là demux luồng multimedia để tách thành luồng âm thanh và video, sau đó giải mã thành dữ liệu âm thanh/video thô
-
Các cấu trúc chính
- AVFormatContext: cấu trúc cấp cao quản lý đồng bộ hóa luồng, metadata và muxing
- AVStream: luồng âm thanh hoặc video liên tục
- AVCodec: định nghĩa phương thức mã hóa và giải mã dữ liệu
- AVPacket: dữ liệu đã mã hóa trong luồng
- AVFrame: khung hình video thô hoặc mẫu âm thanh đã giải mã
-
Quy trình phân tích luồng và demux
- Cấp phát bộ nhớ cho AVFormatContext bằng
avformat_alloc_context()
- Mở tệp multimedia bằng
avformat_open_input()
- Phân tích thông tin luồng trong tệp bằng
avformat_find_stream_info()
- In ra time base, frame rate, thời gian bắt đầu, độ dài, loại, mã FourCC của từng luồng
- Đóng tệp và giải phóng bộ nhớ bằng
avformat_close_input()
-
Tìm codec và khởi tạo
- Tìm decoder phù hợp với codec ID của AVStream bằng
avcodec_find_decoder()
- Với luồng video thì in độ phân giải (width, height), với luồng âm thanh thì in số kênh và sample rate
- Tạo AVCodecContext bằng
avcodec_alloc_context3()
- Áp dụng tham số codec của luồng vào decoder context bằng
avcodec_parameters_to_context()
- Mở decoder bằng
avcodec_open2()
-
Đọc packet và giải mã
- Cấp phát các cấu trúc
AVPacket và AVFrame lần lượt để lưu packet đã mã hóa và frame đã giải mã
- Đọc tuần tự packet từ tệp đầu vào bằng
av_read_frame()
- Xác định packet đến từ luồng nào thông qua stream_index của packet
- Chỉ gửi các packet của luồng video được chọn (
first_video_stream_index) tới decoder
- Chuyển packet tới decoder bằng
avcodec_send_packet()
- Nhận lặp lại các frame đã giải mã bằng
avcodec_receive_frame()
- In ra số thứ tự, loại (I/P/B), định dạng, PTS, có phải keyframe hay không của từng frame
- Tái sử dụng bộ nhớ packet bằng
av_packet_unref()
- Khi hoàn tất mọi xử lý, giải phóng bộ nhớ bằng
av_packet_free(), av_frame_free(), avcodec_free_context(), avformat_close_input()
-
Ví dụ chạy và kết quả
- Mã ví dụ được cung cấp trong kho lưu trữ GitHub
- Có thể build bằng meson và ninja (
pip3 install meson ninja)
- Chạy
meson setup build để FFmpeg tự động được tải xuống và cấu hình
- Sau khi build bằng
ninja -C build, chạy bằng ./build/ffmpeg-101 sample.mp4
- Kết quả chạy sẽ in ra định dạng tệp, thông tin luồng (video/audio), codec, độ phân giải, sample rate, PTS của từng packet và thông tin frame đã giải mã
-
Tóm tắt ví dụ đầu ra
- Luồng video: H.264 (avc1), độ phân giải 206x80, frame rate 30fps
- Luồng âm thanh: AAC (mp4a), 2 kênh, 44.1kHz
- PTS và loại frame (I/P) của từng packet được hiển thị tuần tự, và quá trình giải mã được in ra trên console
Môi trường build và chạy
- Công cụ cần thiết: Python, pip, meson, ninja
- Lệnh cài đặt:
pip3 install meson ninja
-
Quy trình build
- Giải nén tệp ví dụ vào thư mục
ffmpeg-101
- Chạy
meson setup build
- Build bằng
ninja -C build
- Chạy bằng
./build/ffmpeg-101 sample.mp4
- Nếu FFmpeg chưa được cài đặt trên hệ thống, nó sẽ tự động được tải xuống và cấu hình
1 bình luận
Ý kiến trên Hacker News
Rất khuyến nghị tutorial của Leandro Moreira cho những ai muốn hiểu sâu cách FFmpeg và libav hoạt động bên trong
Cá nhân mình thấy đây là phần giải thích đầy đủ và rõ ràng nhất từng đọc cho đến nay
Link tutorial FFmpeg-libav
Thật ngạc nhiên khi đã là ffmpeg 101 rồi. Cảm giác như ffmpeg 8 mới ra mắt ngày hôm qua
Chia sẻ thêm một hướng dẫn khác
Link hướng dẫn liên quan trên HN
FFmpeg đúng là một công cụ mình rất yêu thích
Đây là tài liệu nhập môn ffmpeg rất tuyệt. Cảm ơn
ffmpeg đúng là một siêu năng lực
Mình luôn dùng nó khi cần ghép nhiều đoạn video thành một dạng có thể phát được