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

为什么 ffmpeg 的体积会这么大?多复杂的算法编译后也不会有几十 MB 吧?

  •  
  •   LLaMA · 2023-03-25 18:49:12 +08:00 · 8602 次点击
    这是一个创建于 369 天前的主题,其中的信息可能已经有所发展或是发生改变。
    46 条回复    2023-03-27 14:11:25 +08:00
    FozillaMox
        1
    FozillaMox  
       2023-03-25 19:44:24 +08:00   ❤️ 12
    为什么「多复杂的算法编译后也不会有几十 MB 」?
    weijancc
        2
    weijancc  
       2023-03-25 20:11:18 +08:00
    常见和不常见的视频格式 ffmpeg 都能转码, 你至少先了解下他的功能再说话吧?
    LLaMA
        3
    LLaMA  
    OP
       2023-03-25 21:19:11 +08:00
    @weijancc #2 我当然非常熟悉它的功能,但也不至于体积这么大吧
    placeholder
        4
    placeholder  
       2023-03-25 21:47:26 +08:00   ❤️ 3
    源码就在那儿,嫌大自己优化一下呗
    tuwulin365
        5
    tuwulin365  
       2023-03-25 22:16:36 +08:00
    不是静态链接?
    TJT
        6
    TJT  
       2023-03-25 22:21:19 +08:00   ❤️ 2
    将近 150 万行代码,凭什么不能有几十 MB ?
    learningman
        7
    learningman  
       2023-03-25 22:32:21 +08:00 via Android
    说明你对体积没概念呗。
    自己编译个带符号表的版本,扫一遍每个符号多大不就知道都是啥占体积了
    learningman
        8
    learningman  
       2023-03-25 22:32:48 +08:00 via Android   ❤️ 1
    你要是能给他优化一下,保持现有功能的同时两三兆,几十万人感谢你应该还是有的
    0o0O0o0O0o
        9
    0o0O0o0O0o  
       2023-03-25 22:32:55 +08:00
    https://github.com/FFmpeg/FFmpeg/blob/master/configure

    配合这些 --enable-* 和 --disable-*
    yanzhiling2001
        10
    yanzhiling2001  
       2023-03-25 22:35:09 +08:00
    @learningman #8 是几十亿人,ffmpeg 无处不在,每个人手机里或多或少 都有 app 的视频编码引用了 ffmpeg
    learningman
        11
    learningman  
       2023-03-25 22:40:24 +08:00 via Android   ❤️ 1
    @yanzhiling2001 用了而已,用户不知道,只有开发者会感谢他
    MrKrabs
        12
    MrKrabs  
       2023-03-25 22:40:55 +08:00
    你说的也没问题,但是 ffmpeg 带了多种编解码器
    yuzo555
        13
    yuzo555  
       2023-03-25 22:48:04 +08:00
    运行一下:
    ffmpeg -encoders
    ffmpeg -decoders

    然后再想想标题的问题
    1423
        14
    1423  
       2023-03-25 22:49:11 +08:00   ❤️ 6
    https://ffmpeg.org/pipermail/ffmpeg-user/2013-February/013313.html
    https://stackoverflow.com/questions/22898112/why-my-ffmpeg-libs-are-so-large

    好问题果然是早就有人问过的
    可以按上面的自己编译试试

    不知道 28 原理是否适用,20%用不到的功能站了 80%的空间
    kenvix
        15
    kenvix  
       2023-03-25 22:49:19 +08:00
    因为 ffmpeg 确实有很多屎山,建议你去重构它
    yfwo
        16
    yfwo  
       2023-03-26 01:24:42 +08:00
    --disable-debug
    dobelee
        17
    dobelee  
       2023-03-26 01:40:26 +08:00
    几十 MB 很大?
    jevonszmx
        18
    jevonszmx  
       2023-03-26 01:54:28 +08:00
    @dobelee 赞同你,现在随便打开一个手机 app 都是百兆上 G 的,QQ 为了 qq 秀都是上 G 往里塞,结果大家反而为了几十 MB 折腾自己人,关键你辛辛苦苦搞了很久,别人甚至都感觉不到。
    yfwo
        19
    yfwo  
       2023-03-26 02:05:42 +08:00
    @jevonszmx 嗯嗯,国内有 qq ,国外有 Gmail ,一个邮箱 app 没啥功能就 447 MB ( iOS App Store ),简直无厘头。
    em70
        20
    em70  
       2023-03-26 03:48:37 +08:00
    大是因为编译时候带了太多功能,比如 png,aac,h265 等等,你可以根据自己业务编译一个不到 2M 的啊
    talkischeap567
        21
    talkischeap567  
       2023-03-26 05:10:08 +08:00
    反串?
    talkischeap567
        22
    talkischeap567  
       2023-03-26 05:12:22 +08:00
    为什么 windows 的体积会这么大?多复杂的系统编译后也不会有几十个 G 吧?
    为什么 ios 的体积会这么大?多复杂的手机系统编译后也不会有 10 个 G 吧?
    billccn
        23
    billccn  
       2023-03-26 05:18:12 +08:00   ❤️ 5
    用静态语言编写的追求高性能的代码编译结果大是很正常的,因为最基本的优化方向就是针对不同的情况有专门的代码。比如:

    * 针对不同的指令集(各种版本的 SIMD)分别生成代码
    * 针对某些数据类型进行特定的优化
    * 依赖查表而不是运算
    * 循环 unrolling
    * 为了减少跳转而把越来越多的函数 inline
    * 利用条件运算减少分支

    这些叠加在一起还会形成 combinatorial explosion.

    说笼统一点就是空间换时间的思路。
    msg7086
        24
    msg7086  
       2023-03-26 07:10:04 +08:00
    但凡你知道很多代码为不同指令集分别做了优化并且运行时自动选择最优路径导致编译出来的二进制体积成倍增长也不至于嫌他大(

    一般人用 ffmpeg 完全可以裁剪出自己需要的功能。比如我之前发布的一个软件,用到了 m2ts 解包功能,ffmpeg 裁剪到只需要支持 file protocol 和 mpegts demuxer ,出来只有几百 KB 。
    msg7086
        25
    msg7086  
       2023-03-26 07:15:17 +08:00
    运行一下下面这些命令再看看你觉得多大容量比较合适。

    ffmpeg -codecs
    ffmpeg -formats
    ffmpeg -muxers
    ffmpeg -demuxers
    ffmpeg -protocols
    ffmpeg -filters
    msg7086
        26
    msg7086  
       2023-03-26 07:19:23 +08:00
    另外再说说规模问题。

    ffmpeg 里用到的 x265 ,他里面源码中最核心的那些汇编文件,光 x86 指令集,就有 20 多万行。这没算其他的指令集,没算外围的那些代码,没算 ffmpeg 里其他的大项目。就这一个目录就 20 万行。

    不要小看大型项目的规模啊……
    whi147
        27
    whi147  
       2023-03-26 08:00:58 +08:00 via iPhone
    自己裁剪,我裁剪后就两三兆
    paranoiagu
        28
    paranoiagu  
       2023-03-26 08:40:04 +08:00 via Android
    应该是静态编译才这么大吧。
    secondwtq
        29
    secondwtq  
       2023-03-26 09:29:40 +08:00   ❤️ 29
    这是个有趣的问题。实际上如果只是想把一个东西做得体积很大很简单,一个真实的故事:
    一个算法有 2 个较为固定的参数,每个参数有 5 种可能性,那么如果我把这些参数静态编译进去就是 25 种可能性,如果再考虑到在 5 种不同硬件上的组合,那就是 125 种。如果假设每种的代码有 1KB 大,再有三四十个类似的算法,光这玩意就能整出 4MB 来。

    类似地,如果工程中涉及到根据外部数据文件生成可执行代码,如 RPC 协议通信等,随着数据越来越多,附加的代码也会越来越多。

    另外,编译器优化也可能导致代码体积的指数增长,常见地例如:
    * 如果一个函数里面出现了对其他函数的多次独立调用,而这些函数又被 inline 。该函数实际生成的代码会包含子函数代码的多个拷贝。如果多个函数 inline 了同一个函数,该子函数代码会被在不同函数中多次拷贝。
    * 如果一个函数被多次调用,并且调用时使用了常量参数,该函数的代码可能会被拷贝多份,并将常量参数代入其中单独优化。
    * 循环的 unroll 会将循环体代码拷贝多份(虽然一般会有一定的长度限制)。
    * 循环的向量化会将循环体代码拷贝多份(不同于 unroll ,这个是向量化逻辑所必须的,因此一般不会限制)。

    我这有个对比的例子是 GTK3 。目前我这的 GTK3 包一共 49MB ,不过里面有一堆 GTK 元数据和 locale 之类的东西。只看最关键的 libgtk-3.so ,这玩意一共 7.8 MB ,其中 .text 大概有 3.7MB ,由 500 多个 .o 链接而成,这些 .o 的 .text 大小相加和 libgtk-3.so 的 .text 差不多。.text 最大的前 10% 的 .o ,.text 大小加起来大概 1.6MB 。这些 .o 对应的源码大小加起来大概 7.6MB 。总的源码大小是 17MB (只算 .c ,不算 header )。把 .o 的 .text 大小,和对应 .c 文件的大小画个图,可以很清楚地发现 .c 文件的大小大概是 .text 大小的 4-6 倍,平均值是 5 倍左右。

    ffmpeg 包一共 37MB ,其中最大的是 libavcodec.so ,15MB 。.text 有 10MB 。大概有 1100 个 .o (我去除了一部分直接汇编出的 .o ,这些 .o 的 .text 加起来大概 1MB )。.text 最大的前 10% 的 .o ,.text 大小加起来大概 5.3MB 。这些 .o 对应的源码大小加起来大概 5.6MB ,总的源码大小是 19MB 。部分 .o 依然满足 4-6 倍的规律,但是整体的分布分散了许多。很多头部的 .o ,其 .c 文件大小是 .text 文件大小的两倍,一倍,甚至零点几倍。总的来说相比 GTK3 ,ffmpeg 编译生成的 .text 要更大。
    进一步研究源码发现:
    * libavcodec 源码中有很多以 _template.c 结尾的文件,加起来 1MB 左右,这些文件并不会直接编译出 .o (因此并不会计算在上面的 .c 大小上),而主要是被以不同的参数(如位深度)等多次 include 到不同的 .c 中,其实类似于模拟 C++ 的 non-type template parameter 。这些文件中的代码自然也会被拷贝多份。
    * 部分源码大量使用了定义宏再多次以不同参数使用宏的技巧,这个还是类似于 non-type template parameter ,同样会导致同样的代码被拷贝多份。
    * .o 中的代码存在大量 inline 的痕迹。也出现了一些 constprop 函数。源码中大量函数标记了 always_inline 。

    #14 的链接中指出使用 --enable-small 选项(即指示编译器优先优化代码体积)可以数倍降低 libavcodec.so 的大小。暗示编译器优化是巨大体积的重要因素。不过我实测的效果并没有那么吼,.text 大概降低了 40% 左右。相对地,libgtk-3.so 降低了不到 20%。不过确实可以看到很多的 .o 文件 .text 大小成倍地缩小。GTK3 则鲜有缩小超过 30% 的 .o 。
    liberize
        30
    liberize  
       2023-03-26 09:33:10 +08:00
    chrome 一个 dll 已经超过 200MB 了
    sl0000
        31
    sl0000  
       2023-03-26 10:26:52 +08:00
    一个模板函数就能编译出几十个 G 的执行文件, 和代码行数有关系吗?
    Kisesy
        32
    Kisesy  
       2023-03-26 13:38:53 +08:00
    可能是因为高度优化,导致内联过多,或者循环展开等原因吧
    bruce0
        33
    bruce0  
       2023-03-26 14:28:13 +08:00
    pika,一个基于 rocksdb 开发的类似 Redis 的数据库, 以前用手写 MakeFile 组织代码编译,最近开始使用 cmake 重新组织代码编译. 除了几个系统库全部使用静态链接. 在下不才,cmake 默认编译方式那部分是我写的
    如果使用 `DCMAKE_BUILD_TYPE=Debug`,这样编译出来的是带调试符号的,最终的可执行文件是 230M,
    如果使用 `DCMAKE_BUILD_TYPE=Release` pika 部分代码使用 -O2 优化,依赖库都使用 release 编译, 去掉调试信息 最终的可执行文件是 25M

    最后说一下我的结论啊, 编译时加不加调试信息,对最后的二进制体积影响非常大; 有时候可能就是一堆逻辑,没有任何 gui,图片等等资源,编译出来就是几十 M 了,
    sharpy
        34
    sharpy  
       2023-03-26 14:40:57 +08:00
    一般自己裁剪吧,disable-everything ,然后看着需求开
    fy
        35
    fy  
       2023-03-26 15:35:52 +08:00
    +1 同样疑问,不知道 github 上有没有公开的带 action 的裁剪编译,只需要少数几个编码转换到 silk
    SekiBetu
        36
    SekiBetu  
       2023-03-26 18:07:35 +08:00
    代码体积就有好几个 G 了,编译算是削减了体积
    herozzm
        37
    herozzm  
       2023-03-26 18:09:20 +08:00
    能到这么小很不容易了,它能转码几乎所有视频编码的视频
    009694
        38
    009694  
       2023-03-26 20:07:51 +08:00 via iPhone
    楼主只是疑问为什么 ffmpeg 编译出来体积怎么这么大。 为啥这么多人回复这么充满攻击性和蔑视? 甚至还有 “嫌大你自己写” 这种毫无帮助甚至涉嫌引战的回复
    ch2
        39
    ch2  
       2023-03-26 22:33:09 +08:00
    因为去掉简单,但是你永远不知道哪个人因为你去掉了什么他的代码就运行不起来,所以就维持在一个兼容性较好的子集里
    yolee599
        40
    yolee599  
       2023-03-27 09:08:40 +08:00 via Android
    @009694 主要是最后面一句,多复杂的算法编译出来都不会有几十 MB ?
    standchan
        41
    standchan  
       2023-03-27 10:56:09 +08:00
    @tuwulin365
    @learningman 啥也别说了,保持现有功能同时 2 、3m ,我当面给楼主磕头。比下个月清明节还响的那种
    cyningxu
        42
    cyningxu  
       2023-03-27 11:23:41 +08:00
    多复杂的算法编译出来都不会有几十 MB ?这句话一看就不是正常程序员能说出来的
    fresco
        43
    fresco  
       2023-03-27 11:43:09 +08:00
    我觉得你要用心研究一下就知道它为啥这么“大”了
    noreplay
        44
    noreplay  
       2023-03-27 12:19:12 +08:00 via Android
    晋惠帝只是疑问 何不食肉糜。为啥这么多人对他充满了鄙视和厌恶?甚至还时不时拖来鞭尸?
    mayli
        45
    mayli  
       2023-03-27 14:07:37 +08:00 via Android
    核心是静态链接一堆库加上自己的库。
    类似的有 Linux kernel, 你把所有的驱动都放进去 也能编译出巨大的文件
    mayli
        46
    mayli  
       2023-03-27 14:11:25 +08:00
    例如,ffmpeg 本体只有
    Size 266.55 kB Installed size 688 kB

    但是库就多了
    比如
    ffmpeg-libavcodec: Size 6.48 MB Installed size 14.49 MB
    x265-libs: Size 3.16 MB Installed size 18.61 MB

    想要支持各种格式,同时又兼容小白用静态链接 all in one ,只好这么大了。

    https://pkgs.alpinelinux.org/package/edge/community/x86_64/ffmpeg
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3181 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 12:28 · PVG 20:28 · LAX 05:28 · JFK 08:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.