V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xlsepiphone
V2EX  ›  程序员

H.264 编码的视频能同时被 mov 和 mp4 进行封装?

  •  
  •   xlsepiphone · 2021-09-13 11:45:14 +08:00 · 4072 次点击
    这是一个创建于 1167 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在上一个帖子『Golang 的 http.DetectContentType 有更好的替代实现吗?』求问了 Golang 下面对于不同文件头识别的开源库,有 V 友回复了filetype这个库,但是我最后使用了mimetype这个库的解决方案。

    mimetype能够正确把视频的 mimetype 识别成 video/mp4,但是filetype这个库却识别出来的是 video/quicktime 。

    然后我在上面的帖子也 append 了一下让我困惑的问题,就是我接着用 ffprobe 查看视频的编码信息,输出的是 H.264 ,封装格式如下:

    format_name=mov,mp4,m4a,3gp,3g2,mj2
    format_long_name=QuickTime / MOV
    

    最后我用 Mac 的 Finder 查看,显示的又是 MPEG-4 影片,完全糊涂了,这意味着这个视频是先用用 mov 封装,再用 mp4 进行封装的吗?

    本人对视频编解码相关知识的了解非常基础,基本处于懵懵懂懂的状态,Google 了好久都没有找到对于 format_name 这个字段的多个值的具体解释。

    求 V 友解惑。

    26 条回复    2021-09-14 10:30:01 +08:00
    wy315700
        1
    wy315700  
       2021-09-13 11:49:09 +08:00   ❤️ 1
    H.264 是视频编码,类似的还有 h265 。

    mov 和 mp4 是视频文件格式,类似的还有 mkv,flv 。

    一个视频文件里可以包含多个 H.264 视频和多个音频数据。。


    mov 和 mp4 其实是一种东西,格式都一样的。。
    ysc3839
        2
    ysc3839  
       2021-09-13 11:50:21 +08:00   ❤️ 1
    > The MP4 container is derived from Apple QuickTime (MOV).
    https://www.quora.com/What-is-the-main-difference-between-MOV-and-MP4-files
    seki
        3
    seki  
       2021-09-13 11:52:12 +08:00   ❤️ 1
    因为 mov 与 mp4 容器的渊源比较深吧
    https://en.wikipedia.org/wiki/QuickTime_File_Format

    可以试试用 Mediainfo 查看具体是什么容器
    JerryCha
        4
    JerryCha  
       2021-09-13 11:56:34 +08:00
    你去看 flv 的也是 H.264
    ts 和 m2ts 里面也有 H.264
    惊不惊喜 意不意外?
    xlsepiphone
        5
    xlsepiphone  
    OP
       2021-09-13 11:59:36 +08:00
    @wy315700 #1
    @ysc3839 #2
    @seki #3
    @JerryCha #4
    所以到底怎么判断容器的格式呢?
    xlsepiphone
        6
    xlsepiphone  
    OP
       2021-09-13 12:05:02 +08:00
    mediainfo 输出如下
    ```
    General
    Complete name : /Users/言叶之庭.mp4
    Format : MPEG-4
    Format profile : Base Media
    Codec ID : isom (isom)
    File size : 1.01 GiB
    Duration : 46 min 3 s
    Overall bit rate mode : Variable
    Overall bit rate : 3 130 kb/s
    Encoded date : UTC 2018-11-17 15:06:54
    Tagged date : UTC 2018-11-17 15:06:54

    Video
    ID : 1
    Format : AVC
    Format/Info : Advanced Video Codec
    Format profile : High@L4
    Format settings : CABAC / 4 Ref Frames
    Format settings, CABAC : Yes
    Format settings, Reference frames : 4 frames
    Codec ID : avc1
    Codec ID/Info : Advanced Video Coding
    Duration : 46 min 3 s
    Bit rate : 3 000 kb/s
    Maximum bit rate : 20.6 Mb/s
    Width : 1 920 pixels
    Height : 1 080 pixels
    Display aspect ratio : 16:9
    Frame rate mode : Variable
    Frame rate : 23.976 FPS
    Minimum frame rate : 23.810 FPS
    Maximum frame rate : 24.390 FPS
    Color space : YUV
    Chroma subsampling : 4:2:0
    Bit depth : 8 bits
    Scan type : Progressive
    Bits/(Pixel*Frame) : 0.060
    Stream size : 989 MiB (96%)
    Writing library : x264 core 148 r2597+52 4ed4a81 xiaowan [8-bit@all X86_64]
    Encoding settings : cabac=1 / ref=4 / deblock=1:1:1 / analyse=0x3:0x133 / me=umh / subme=10 / psy=1 / fade_compensate=0.00 / psy_rd=0.30:0.00 / mixed_ref=1 / me_range=24 / chroma_me=1 / trellis=2 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=12 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / fgo=0 / bframes=3 / b_pyramid=2 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=240 / keyint_min=1 / scenecut=60 / intra_refresh=0 / rc_lookahead=60 / rc=2pass / mbtree=1 / bitrate=3000 / ratetol=1.0 / qcomp=0.50 / qpmin=0:0:0 / qpmax=69:69:69 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.40 / aq=2:0.80 / aq-sensitivity=10.00 / aq-factor=1.00:1.00:1.00 / aq2=0 / aq3=0
    Encoded date : UTC 2018-11-17 14:02:01
    Tagged date : UTC 2018-11-17 15:07:04
    Color range : Limited
    Matrix coefficients : BT.709
    Codec configuration box : avcC

    Audio
    ID : 2
    Format : AAC LC
    Format/Info : Advanced Audio Codec Low Complexity
    Codec ID : mp4a-40-2
    Duration : 46 min 3 s
    Bit rate mode : Variable
    Bit rate : 125 kb/s
    Maximum bit rate : 262 kb/s
    Channel(s) : 6 channels
    Channel layout : C L R Ls Rs LFE
    Sampling rate : 48.0 kHz
    Frame rate : 46.875 FPS (1024 SPF)
    Compression mode : Lossy
    Stream size : 41.0 MiB (4%)
    Encoded date : UTC 2018-11-17 13:37:54
    Tagged date : UTC 2018-11-17 15:07:04
    ```
    xylophone21
        7
    xylophone21  
       2021-09-13 12:05:31 +08:00
    ffmpeg
    siguretto
        8
    siguretto  
       2021-09-13 12:07:13 +08:00
    最简单的方法是判断头部字节 ftyp,mov 是 ftypqt,mp4 是 ftypmp4 。
    xlsepiphone
        9
    xlsepiphone  
    OP
       2021-09-13 12:08:37 +08:00
    @siguretto #8

    xxd /Users/言叶之庭.mp4 | head
    00000000: 0000 0014 6674 7970 6973 6f6d 0000 0001 ....ftypisom....
    00000010: 6973 6f6d 001b 04be 6d6f 6f76 0000 006c isom....moov...l
    00000020: 6d76 6864 0000 0000 d815 df0e d815 df0e mvhd............
    00000030: 0000 0258 0019 4dc0 0001 0000 0100 0000 ...X..M.........
    00000040: 0000 0000 0000 0000 0001 0000 0000 0000 ................
    00000050: 0000 0000 0000 0000 0001 0000 0000 0000 ................
    00000060: 0000 0000 0000 0000 4000 0000 0000 0000 ........@.......
    00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
    00000080: 0000 0000 0000 0003 0000 0015 696f 6473 ............iods
    00000090: 0000 0000 1007 004f ffff 2a15 ff00 11d3 .......O..*.....
    xlsepiphone
        10
    xlsepiphone  
    OP
       2021-09-13 12:09:10 +08:00
    @siguretto #8 fty pisom 是什么鬼。。。
    siguretto
        11
    siguretto  
       2021-09-13 12:09:20 +08:00
    在我理解,mov 是兼容 mp4 的,所里两个库得到的 mimetype 不一样也很正常。video/mp4 是从兼容性考虑,video/quicktime 则是更加准确。
    siguretto
        12
    siguretto  
       2021-09-13 12:14:44 +08:00   ❤️ 1
    关于 iso,可以看看 wiki: https://en.wikipedia.org/wiki/ISO/IEC_base_media_file_format

    可以这么想,iso 把 mov 标准化了,mp4 又采纳了 iso 标准,所以就是 mov -> iso -> mp4
    mikewang
        13
    mikewang  
       2021-09-13 12:17:44 +08:00 via iPhone   ❤️ 1
    mov 是 Apple 的定标准,mp4 来自于 mov,用是 ISO 的标准。它们的格式类似。就像 webm 来自于 mkv,格式类似但有着不同的标准。

    大多数情况播放器 mov 和 mp4 可以互相兼容,视频编码一样的话。mimetype 不一致关系也不大。

    使用 ffprobe 来看,mov 格式的 major_brand 是 qt ( QuickTime )
    lostvincent
        14
    lostvincent  
       2021-09-13 14:01:41 +08:00   ❤️ 4
    首先,你要区分视频流和封装
    h.264 是视频流的格式
    mp4 是封装格式
    这两个是可以同时存在的,简单来说就是一个是外包装,一个是内容

    其次,你要明确下你需要的是视频流还是封装的格式。
    看帖子内容,我假设你需要的是:封装格式
    在没有具体文件的情况下,你描述的情况是可能存在的

    类比现实情况,就是你拿到了一个水果礼物盒( mp4 ),里面装着一个柑橘( h.264 )
    mimetype 检测之后,告诉你这是一个水果礼物盒( video/mp4 )
    filetype 检测后,告诉你这是一个橘子礼物盒( video/quicktime )
    ffprobe 告诉你这是一个柑橘( h.264 )

    一些关于 isom 的东西
    Some references:
    https://forum.doom9.org/showthread.php?p=1664561#post1664561
    https://forum.doom9.org/showthread.php?p=1827483#post1827483

    相关行业标准文档:
    Document:
    ISO/IEC 14496-12

    太长不看版:
    都说的没错,只不过对象和详细程度不同
    expy
        15
    expy  
       2021-09-13 14:15:47 +08:00
    容器跟编码的区别,H264/MPEG4/AVC 是同一个编码。

    MP4 是容器,可以封装各种编码的视频流和音频流(H.264/H.265/AV1/AAC/FLAC/MP3/Opus)。
    tsanie
        16
    tsanie  
       2021-09-13 14:50:41 +08:00
    抛开标题,我觉得这个文件比较奇怪。'ftypisom'为什么会被 ffprobe 和 filetype 库识别成 QuickTime File,果子的 QuickTime 格式规范上写的 major_brand 不是一定要'qt '么……
    huangmingyou
        17
    huangmingyou  
       2021-09-13 14:55:17 +08:00
    封装和内容编码是两个独立概念。 内容编码可以比喻成英语书或者中文书,封装可以理解成顺风或者邮政快递。可以随便组合啊。
    CEBBCAT
        18
    CEBBCAT  
       2021-09-13 16:00:50 +08:00 via Android   ❤️ 1
    mikewang
        19
    mikewang  
       2021-09-13 16:59:24 +08:00   ❤️ 1
    #14 @lostvincent
    水果礼物盒和橘子礼物盒的比喻可能不太准确,mov 和 mp4 应该是平级的,他们之间还存在一些微小的差别。
    例如:
       video/quicktime 支持封装 ALAC 无损音频,video/mp4 不能。
       video/mp4 支持封装 AV1 编码的视频,video/quicktime 不能。

    上面都在讨论视频编码的问题,我觉得这个问题重点不在这里。
    macOS 文件简介显示的「 MPEG-4 影片」指的是「 MPEG-4 Part 14 」定义的容器格式,不是指「 MPEG-4 Part 2 」定义的 MPEG-4 编码。
    可以查看一个封装 HEVC 的 mp4 文件,简介依然为「 MPEG-4 影片」。

    严格意义上讲,只有 major_brand 为 qt 时,文件才是 video/quicktime 。
    filetype 库,将 #9 的文件识别为 video/quicktime 是有问题的,这显然是个 video/mp4 文件。

    这个问题已经有人提过了,同一个文件多次执行,得到结果不一样 XD
    https://github.com/h2non/filetype/issues/64

    ![]( https://ae01.alicdn.com/kf/Hdd619c78118648b1a0d5550c16c80aa3x.png)
    xlsepiphone
        20
    xlsepiphone  
    OP
       2021-09-13 17:10:53 +08:00
    @mikewang #19

    ```
    Metadata:
    major_brand : isom
    minor_version : 1
    compatible_brands: isom
    creation_time : 2018-11-17T15:06:54.000000Z
    ```
    major_brand 是 isom,看完你们的回复,懵了,感觉视频编码与封装这块,太不直白了,这么多历史渊源。
    lostvincent
        21
    lostvincent  
       2021-09-13 17:28:39 +08:00
    @mikewang 多谢指正,quicktime 这部分不是了解太多,对表达失误带来的误解,表示抱歉
    关于 ISO/IEC 14496-12 是因为我手边之前研究的是这份,也只看过这份,所以想了下,没删掉-12

    @xlsepiphone 你要了解的话,看下 mp4 的 ftyp 这个东西就够了
    litesoar
        22
    litesoar  
       2021-09-13 17:48:36 +08:00
    应该可以吧。

    h.264 是视频编码格式
    mp4 和 mov 是视频封装格式,都能采用 h264 编码。
    xylophone21
        23
    xylophone21  
       2021-09-13 18:20:57 +08:00
    score 越大,可能性越高

    ```c
    static int mov_probe(const AVProbeData *p)
    {
    int64_t offset;
    uint32_t tag;
    int score = 0;
    int moov_offset = -1;

    /* check file header */
    offset = 0;
    for (;;) {
    int64_t size;
    int minsize = 8;
    /* ignore invalid offset */
    if ((offset + 8ULL) > (unsigned int)p->buf_size)
    break;
    size = AV_RB32(p->buf + offset);
    if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
    size = AV_RB64(p->buf+offset + 8);
    minsize = 16;
    } else if (size == 0) {
    size = p->buf_size - offset;
    }
    if (size < minsize) {
    offset += 4;
    continue;
    }
    tag = AV_RL32(p->buf + offset + 4);
    switch(tag) {
    /* check for obvious tags */
    case MKTAG('m','o','o','v'):
    moov_offset = offset + 4;
    case MKTAG('m','d','a','t'):
    case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
    case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
    case MKTAG('f','t','y','p'):
    if (tag == MKTAG('f','t','y','p') &&
    ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ')
    || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ')
    )) {
    score = FFMAX(score, 5);
    } else {
    score = AVPROBE_SCORE_MAX;
    }
    break;
    /* those are more common words, so rate then a bit less */
    case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
    case MKTAG('w','i','d','e'):
    case MKTAG('f','r','e','e'):
    case MKTAG('j','u','n','k'):
    case MKTAG('p','i','c','t'):
    score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
    break;
    case MKTAG(0x82,0x82,0x7f,0x7d):
    case MKTAG('s','k','i','p'):
    case MKTAG('u','u','i','d'):
    case MKTAG('p','r','f','l'):
    /* if we only find those cause probedata is too small at least rate them */
    score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
    break;
    }
    if (size > INT64_MAX - offset)
    break;
    offset += size;
    }
    if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
    /* moov atom in the header - we should make sure that this is not a
    * MOV-packed MPEG-PS */
    offset = moov_offset;

    while (offset < (p->buf_size - 16)) { /* Sufficient space */
    /* We found an actual hdlr atom */
    if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') &&
    AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') &&
    AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) {
    av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n");
    /* We found a media handler reference atom describing an
    * MPEG-PS-in-MOV, return a
    * low score to force expanding the probe window until
    * mpegps_probe finds what it needs */
    return 5;
    } else {
    /* Keep looking */
    offset += 2;
    }
    }
    }

    return score;
    }
    ```
    msg7086
        24
    msg7086  
       2021-09-13 18:50:06 +08:00 via Android   ❤️ 1
    Mp4 isom mov 本来就是一家人。
    顺便提一个有趣的小知识,avi 和 wav 也是一家人,都是基于 riff 。
    视频音频方面的水本来就很深,一大堆公司在搞,各种组织在定自己的标准,然后各种标准又在借鉴别的标准。
    然后甚至有时候还会出现软件输出的文件不那么标准的情况,然后软件也要一步步迭代完善。
    很多格式还在不停发展变化,比如说 opus 或 flac in MP4 还没完全搞明白,各家软件还没支持,标准也还在草案阶段一点点推进,等哪天定稿了再逐步给各大工具平台推,再一点点开始普及,等等。
    本来已经成熟的格式也在不停变化,比如前段时间 NHK 搞了 24 声道的 AAC,一直无人支持,后来有一天我去问了,然后给了个音轨样本以后他们才一点点开始实现功能。
    这方面的浑水要趟的话得要有一些心理准备的。
    thunderw
        25
    thunderw  
       2021-09-14 08:58:58 +08:00
    https://blog.csdn.net/pirateleo/article/details/7583321
    这里面说的好像比较清楚。可以指定一种主格式,另外声明还兼容哪些格式。
    所以你这个具体的文件就是 isom 兼容 moov 。约等于既是 mp4 又是 mov 。
    参阅: http://www.ftyps.com
    tsanie
        26
    tsanie  
       2021-09-14 10:30:01 +08:00
    @thunderw 那倒不是,他这个文件第一个 atom 是 0x14 个字节,major_brand 是 isom,compatible_brands 只有 4 字节也是 isom,moov 是另一个 atom,里面存视频时长之类的信息的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2374 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:09 · PVG 00:09 · LAX 08:09 · JFK 11:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.