[FFmpeg Tutorial] Lấy thông tin video bằng FFmpeg

Posted on October 14th, 2018

Lấy thông tin video bằng FFmpeg như thế nào và lấy để làm gì?

Do là gần đây có nhiều bạn hỏi mình về việc cắt ghép video. Mà bạn ấy hay bị lỗi khi ghép nhiều video với nhau.

Nguyên nhân gây lỗi là do các file video đó không tương đồng nhau (về định dạng, framerate, bitrate,...). Mà chuyện tương đồng là cần thiết nếu bạn muốn ghép chúng lại thành một.

Vì vậy, việc lấy thông tin của video trước khi ghép là vô cùng cần thiết. Qua đó, bạn sẽ biết mình phải xử lý video như thế nào trước khi ghép chúng lại với nhau.

Để lấy thông tin video bằng FFmpeg có hai cách là: sử dụng ffmpeg.exe và sử dụng ffprobe.exe (đây là 2 trong 3 công cụ có được sau khi cài đặt FFmpeg).

Lấy thông tin video sử dụng ffmpeg

Câu lệnh

Để lấy được thông tin video bằng ffmpeg bạn có thể sử dụng câu lệnh sau:

ffmpeg -i input.mp4 -hide_banner

Trong đó:

  • -i là cờ dùng để xác định file input, sau đó là tên của file đầu vào (input.mp4)
  • -hide_banner là cờ dùng để bỏ qua thông tin liên quan đến phiên bản, các thư viện mà FFmpeg sử dụng,...

Phân tích kết quả

Ví dụ khi mình lấy thông tin của video bằng FFmpeg như sau:

Lấy thông tin của video sử dụng ffmpeg.exe

Bạn có thể thấy video mà mình thử nghiệm ở đây có thời lượng (duration) là 00:21:38.21 (tức ~ 21 phút 38 giây) và bitrate là 1123kb/s.

Ngoài ra, bạn cũng thấy rằng file này có 2 stream (hay gọi là 2 kênh cho dễ hiểu). Kênh 1 ứng với Stream #0:0 và kênh 2 ứng với Stream #0: 1.

Trong đó:

  • Kênh 1 (video) được encode theo chuẩn h264 với profile level là Main; mỗi frame ảnh có định dạng yuv420p; kích thước video là 854x480 (với width=854 và height=480); bitrate của kênh video là 990 kb/s (dĩ nhiên sẽ nhỏ hơn bitrate tổng của cả video); tỉ lệ framerate là 23.98 fps;
  • Kênh 2 (audio) có chuẩn aac; sample rate là 44100 Hz; âm thanh dạng stereo; bitrate là 127 kb/s.

Đây là những thông tin của video mà bạn cần phải biết. Ngoài ra, nếu muốn biết thêm nhiều thông tin hơn nữa thì bạn có thể sử dụng công cụ ffprobe.exe như sau.

Lấy thông tin video sử dụng ffprobe.exe

Câu lệnh cơ bản

Câu lệnh cơ bản sử dụng ffprobe.exe để lấy thông tin video là:

ffprobe -v error -show_format -show_streams input.mp4

Kết quả hiển thị khá dài:

[STREAM]
    index=0
    codec_name=h264
    codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
    profile=Main
    codec_type=video
    codec_time_base=38946407/1867560000
    codec_tag_string=avc1
    codec_tag=0x31637661
    width=854
    height=480
    coded_width=854
    coded_height=480
    has_b_frames=2
    sample_aspect_ratio=0:1
    display_aspect_ratio=0:1
    pix_fmt=yuv420p
    level=30
    color_range=tv
    color_space=bt709
    color_transfer=bt709
    color_primaries=bt709
    chroma_location=left
    field_order=unknown
    timecode=N/A
    refs=1
    is_avc=true
    nal_length_size=4
    id=N/A
    r_frame_rate=24000/1001
    avg_frame_rate=933780000/38946407
    time_base=1/90000
    start_pts=0
    start_time=0.000000
    duration_ts=116839221
    duration=1298.213567
    bit_rate=990486
    max_bit_rate=N/A
    bits_per_raw_sample=8
    nb_frames=31126
    nb_read_frames=N/A
    nb_read_packets=N/A
    DISPOSITION:default=1
    DISPOSITION:dub=0
    DISPOSITION:original=0
    DISPOSITION:comment=0
    DISPOSITION:lyrics=0
    DISPOSITION:karaoke=0
    DISPOSITION:forced=0
    DISPOSITION:hearing_impaired=0
    DISPOSITION:visual_impaired=0
    DISPOSITION:clean_effects=0
    DISPOSITION:attached_pic=0
    DISPOSITION:timed_thumbnails=0
    TAG:creation_time=2013-03-21T04:50:31.000000Z
    TAG:language=und
    TAG:encoder=JVT/AVC Coding
    [/STREAM]
    [STREAM]
    index=1
    codec_name=aac
    codec_long_name=AAC (Advanced Audio Coding)
    profile=LC
    codec_type=audio
    codec_time_base=1/44100
    codec_tag_string=mp4a
    codec_tag=0x6134706d
    sample_fmt=fltp
    sample_rate=44100
    channels=2
    channel_layout=stereo
    bits_per_sample=0
    id=N/A
    r_frame_rate=0/0
    avg_frame_rate=0/0
    time_base=1/44100
    start_pts=0
    start_time=0.000000
    duration_ts=57250816
    duration=1298.204444
    bit_rate=127986
    max_bit_rate=185256
    bits_per_raw_sample=N/A
    nb_frames=55909
    nb_read_frames=N/A
    nb_read_packets=N/A
    DISPOSITION:default=1
    DISPOSITION:dub=0
    DISPOSITION:original=0
    DISPOSITION:comment=0
    DISPOSITION:lyrics=0
    DISPOSITION:karaoke=0
    DISPOSITION:forced=0
    DISPOSITION:hearing_impaired=0
    DISPOSITION:visual_impaired=0
    DISPOSITION:clean_effects=0
    DISPOSITION:attached_pic=0
    DISPOSITION:timed_thumbnails=0
    TAG:creation_time=2013-03-21T04:50:31.000000Z
    TAG:language=eng
    [/STREAM]
    [FORMAT]
    filename=input.mp4
    nb_streams=2
    nb_programs=0
    format_name=mov,mp4,m4a,3gp,3g2,mj2
    format_long_name=QuickTime / MOV
    start_time=0.000000
    duration=1298.213567
    size=182308296
    bit_rate=1123441
    probe_score=100
    TAG:major_brand=mp42
    TAG:minor_version=0
    TAG:compatible_brands=mp42isomavc1
    TAG:creation_time=2013-03-21T04:50:31.000000Z
    TAG:encoder=HandBrake rev4860 2012121899
    [/FORMAT]

Có khá nhiều thông tin ở đây mà mình nghĩ là rất khó để thể giải thích hết ở đây được (bạn thông cảm nhé).

Dĩ nhiên, với yêu cầu sử dụng FFmpeg cơ bản thì mình nghĩ rằng bạn không cần thiết phải biết hết những thông tin này.

Cái nào cần thì mình tra thôi. Nhưng, biết đâu đấy, sau này cần phải dùng thì sao nhỉ?

À mà ffprobe.exe còn hỗ trợ việc lấy ra thông tin video dạng JSON hoặc XML. Khi đó, bạn có thể sử dụng kết quả ở nhiều nơi khác nữa (khi lập trình hoặc viết script chạy tự động,...).

Lấy thông tin video dạng JSON

Để thực hiện việc này bạn chỉ cần thêm cờ  -print_format với giá trị json.

Khi đó, câu lệnh trên trở thành:

ffprobe -v error -print_format json -show_format -show_streams input.mp4

Kết quả dạng JSON:

{
        "streams": [
            {
                "index": 0,
                "codec_name": "h264",
                "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
                "profile": "Main",
                "codec_type": "video",
                "codec_time_base": "38946407/1867560000",
                "codec_tag_string": "avc1",
                "codec_tag": "0x31637661",
                "width": 854,
                "height": 480,
                "coded_width": 854,
                "coded_height": 480,
                "has_b_frames": 2,
                "sample_aspect_ratio": "0:1",
                "display_aspect_ratio": "0:1",
                "pix_fmt": "yuv420p",
                "level": 30,
                "color_range": "tv",
                "color_space": "bt709",
                "color_transfer": "bt709",
                "color_primaries": "bt709",
                "chroma_location": "left",
                "refs": 1,
                "is_avc": "true",
                "nal_length_size": "4",
                "r_frame_rate": "24000/1001",
                "avg_frame_rate": "933780000/38946407",
                "time_base": "1/90000",
                "start_pts": 0,
                "start_time": "0.000000",
                "duration_ts": 116839221,
                "duration": "1298.213567",
                "bit_rate": "990486",
                "bits_per_raw_sample": "8",
                "nb_frames": "31126",
                "disposition": {
                    "default": 1,
                    "dub": 0,
                    "original": 0,
                    "comment": 0,
                    "lyrics": 0,
                    "karaoke": 0,
                    "forced": 0,
                    "hearing_impaired": 0,
                    "visual_impaired": 0,
                    "clean_effects": 0,
                    "attached_pic": 0,
                    "timed_thumbnails": 0
                },
                "tags": {
                    "creation_time": "2013-03-21T04:50:31.000000Z",
                    "language": "und",
                    "encoder": "JVT/AVC Coding"
                }
            },
            {
                "index": 1,
                "codec_name": "aac",
                "codec_long_name": "AAC (Advanced Audio Coding)",
                "profile": "LC",
                "codec_type": "audio",
                "codec_time_base": "1/44100",
                "codec_tag_string": "mp4a",
                "codec_tag": "0x6134706d",
                "sample_fmt": "fltp",
                "sample_rate": "44100",
                "channels": 2,
                "channel_layout": "stereo",
                "bits_per_sample": 0,
                "r_frame_rate": "0/0",
                "avg_frame_rate": "0/0",
                "time_base": "1/44100",
                "start_pts": 0,
                "start_time": "0.000000",
                "duration_ts": 57250816,
                "duration": "1298.204444",
                "bit_rate": "127986",
                "max_bit_rate": "185256",
                "nb_frames": "55909",
                "disposition": {
                    "default": 1,
                    "dub": 0,
                    "original": 0,
                    "comment": 0,
                    "lyrics": 0,
                    "karaoke": 0,
                    "forced": 0,
                    "hearing_impaired": 0,
                    "visual_impaired": 0,
                    "clean_effects": 0,
                    "attached_pic": 0,
                    "timed_thumbnails": 0
                },
                "tags": {
                    "creation_time": "2013-03-21T04:50:31.000000Z",
                    "language": "eng"
                }
            }
        ],
        "format": {
            "filename": "input.mp4",
            "nb_streams": 2,
            "nb_programs": 0,
            "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
            "format_long_name": "QuickTime / MOV",
            "start_time": "0.000000",
            "duration": "1298.213567",
            "size": "182308296",
            "bit_rate": "1123441",
            "probe_score": 100,
            "tags": {
                "major_brand": "mp42",
                "minor_version": "0",
                "compatible_brands": "mp42isomavc1",
                "creation_time": "2013-03-21T04:50:31.000000Z",
                "encoder": "HandBrake rev4860 2012121899"
            }
        }
    }

Lấy thông tin video dạng XML

Tương tự, để lấy thông tin video dạng XML, bạn chỉ cần thêm cờ -print_format với giá trị là xml.

Khi đó, câu lệnh trên trở thành:

ffprobe -v error -print_format xml -show_format -show_streams input.mp4

Kết quả dạng XML:

<?xml version="1.0" encoding="UTF-8"?>
    <ffprobe>
        <streams>
            <stream index="0" codec_name="h264" codec_long_name="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10" profile="Main" codec_type="video" codec_time_base="38946407/1867560000" codec_tag_string="avc1" codec_tag="0x31637661" width="854" height="480" coded_width="854" coded_height="480" has_b_frames="2" sample_aspect_ratio="0:1" display_aspect_ratio="0:1" pix_fmt="yuv420p" level="30" color_range="tv" color_space="bt709" color_transfer="bt709" color_primaries="bt709" chroma_location="left" refs="1" is_avc="true" nal_length_size="4" r_frame_rate="24000/1001" avg_frame_rate="933780000/38946407" time_base="1/90000" start_pts="0" start_time="0.000000" duration_ts="116839221" duration="1298.213567" bit_rate="990486" bits_per_raw_sample="8" nb_frames="31126">
                <disposition default="1" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0" timed_thumbnails="0"/>
                <tag key="creation_time" value="2013-03-21T04:50:31.000000Z"/>
                <tag key="language" value="und"/>
                <tag key="encoder" value="JVT/AVC Coding"/>
            </stream>
            <stream index="1" codec_name="aac" codec_long_name="AAC (Advanced Audio Coding)" profile="LC" codec_type="audio" codec_time_base="1/44100" codec_tag_string="mp4a" codec_tag="0x6134706d" sample_fmt="fltp" sample_rate="44100" channels="2" channel_layout="stereo" bits_per_sample="0" r_frame_rate="0/0" avg_frame_rate="0/0" time_base="1/44100" start_pts="0" start_time="0.000000" duration_ts="57250816" duration="1298.204444" bit_rate="127986" max_bit_rate="185256" nb_frames="55909">
                <disposition default="1" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0" timed_thumbnails="0"/>
                <tag key="creation_time" value="2013-03-21T04:50:31.000000Z"/>
                <tag key="language" value="eng"/>
            </stream>
        </streams>

        <format filename="input.mp4" nb_streams="2" nb_programs="0" format_name="mov,mp4,m4a,3gp,3g2,mj2" format_long_name="QuickTime / MOV" start_time="0.000000" duration="1298.213567" size="182308296" bit_rate="1123441" probe_score="100">
            <tag key="major_brand" value="mp42"/>
            <tag key="minor_version" value="0"/>
            <tag key="compatible_brands" value="mp42isomavc1"/>
            <tag key="creation_time" value="2013-03-21T04:50:31.000000Z"/>
            <tag key="encoder" value="HandBrake rev4860 2012121899"/>
        </format>
    </ffprobe>

Lời kết

Trên đây là 2 cách để lấy thông tin video bằng FFmpeg. Nếu có gì sai sót, bạn vui lòng góp ý cho mình biết trong phần bình luận phía dưới nhé!

Xin chào và hẹn gặp lại, thân ái!

Tham khảo:


★ Nếu bạn thấy bài viết này hay thì hãy theo dõi mình trên Facebook để nhận được thông báo khi có bài viết mới nhất nhé: