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

ffmpeg 如何加快解码速度?算力不变的情况下,不在乎解码质量

  •  
  •   1054850490 · 320 天前 · 5357 次点击
    这是一个创建于 320 天前的主题,其中的信息可能已经有所发展或是发生改变。
    `ffmpeg -stats -hwaccel none -i "1.mp4" -map v -fps_mode cfr -stats_period 0.04 -f null -
    `
    如上述代码所示,如何在同等算力条件下,加快“解码”速度,注意,这里不是编码,是解码,而且据我测试,12490F 对比 3080 的解码器也快不过 CPU ,这是因为视频文件需要在显存和内存之间频繁交换,反而导致解码变慢了。虽然在 av01 以及 8K 的情况下比不过显卡的解码,但是 6 核的 12490f 已经是比 3080 的解码器快了,(虽然 3080 支持双路,单路性能限制一半,暂且按下不表),所以让我换显卡解码加快这个提议已经 pass 了

    我为什么要这样做是因为,我需要一帧一帧拆开看看视频有没有损坏,因为我用下载器下载的视频合成的时候总是出现破损的视频文件,而用重封装查损并不适用于大多场景,所以还是回到最稳的一帧一帧的拆包看,可是这个方案还是太慢了,如果升级机器也不太现实,只能是寻求歪路子,我看到某些解码器可以通过降低解码质量从而让低配机器也可以流畅播放高质量视频的时候就在想,我是否也可以按照这个方法来?我问过 GPT ,但是 GPT 给出的答案是让我降低分辨率,也就是-s 1280p-720p 选项,但是这样其实更慢了,我觉得更像是重编码了一样,虽然降低了分辨率,可是中间一定是有一个再转码的过程导致吃的损耗更多了
    54 条回复    2023-06-20 11:43:32 +08:00
    xeathen
        1
    xeathen  
       320 天前
    不太了解但想知道答案
    hello2090
        2
    hello2090  
       320 天前
    很久没做这个了,你用下载器下载再合成?合成以后出现问题?那你查查合成哪里出问题不就行了,解决了以后就不会有问题了,不需要每个文件都这么搞一次啊

    不知道你要求的要多快,光解码不播放挺快的吧,ffmpeg 提供选项每帧输出到一张图片,或者你试试能不能隔几帧生成一张?
    wy315700
        3
    wy315700  
       320 天前
    >某些解码器可以通过降低解码质量从而让低配机器也可以流畅播放高质量视频

    应该用的方法是丢帧
    sunxiaping521
        4
    sunxiaping521  
       320 天前
    你需要这个项目 https://github.com/ZLMediaKit/ZLMediaKit ,如果不想开发,可以调用对应的 REST API 接口,超级方便省事。
    SenseHu
        5
    SenseHu  
       320 天前
    -hwaccel 试下 qsv, d3d11va, dxva2, linux 的话试下 vaapi
    参考 https://ffmpeg.org/ffmpeg.html
    lisxour
        6
    lisxour  
       320 天前
    @hello2090 确实解决的思路就走歪了,每一帧每一帧查完全不现实,我要是下载了一个很大很长的 4k 视频,这么搞那不完犊子了。而且怎么定义一帧有没有损坏?有黑块?有雪花?还是解码报错才算?
    newmlp
        7
    newmlp  
       320 天前
    @wy315700 丢帧并不能加快解码速度
    wy315700
        8
    wy315700  
       320 天前
    @newmlp

    丢帧为啥不能加快解码速度,把 B 帧都丢了速度能快不少吧
    OblivionStaff
        9
    OblivionStaff  
       320 天前
    @wy315700 我咋记得解码 b 帧也必须依赖前一帧
    OblivionStaff
        10
    OblivionStaff  
       320 天前
    我知道的唯一快速解码的方式是抽取 i 帧,但这样 i 帧之间的图像全没了
    SenseHu
        11
    SenseHu  
       320 天前
    感觉思路歪了,
    > 下载器下载的视频合成的时候总是出现破损的视频文件
    应该要定位这个过程中哪里出了问题,
    给个实际的案例看下是哪个操作步骤导致的破损,不一定原视频就有问题
    minami
        12
    minami  
       320 天前
    瓶颈在磁盘,上内存盘吧
    MarginK
        13
    MarginK  
       320 天前
    解码的本质就是解压缩,这似乎无关你的解码质量,而验证每一帧的完整性也是需要解码来验证的,否则其他一切都只是表面级别的验证,所以我觉得好像无解。
    1054850490
        14
    1054850490  
    OP
       320 天前
    @SenseHu 11#
    @hello2090 2#
    @lisxour 6#
    思路没有歪,这并不是下载阶段可以避免的,首先第一个就是无法避免的就是服务器端提供的源文件就破损的,但是换一个分辨率就没事,这存在于 youtube 上,视频在某个分辨率无论你下载多少遍,就算在源页面播放都是破损的,但是换一个分辨率就正常了,其次,并不一定的花瓶,而是某个片段丢失,列如丢失片段在 1.30 秒到 1.35 秒处,播放到这里就会花屏,过了这个时间段才正常,为什么会出现这个问题呢?这也是多线程下载的缺点,源服务器并没有提供校验,所以我下载也并不能校验文件完整性,源视频是 100%有问题的,在我之前就发过帖子了,不会是我解码的问题,对于这个问题我不想过多的展开,因为我已经有相当多的案例了,已经确认视频确实是有问题,如果想在下载端解决这个问题,不显示,你哪怕跟我说以后下载都不怕没事了,我也得全部拆开看看是不是真的无损了
    imoru
        15
    imoru  
       320 天前
    借楼问个问题,有办法提高 ffmpeg 生成 sprites 的速度吗?我试过无论用不用硬件加速,调小 fps 数值或者 scale 数值,消耗的时间几乎是固定的,很奇怪
    ffmpeg -hwaccel auto -i demo.mp4 -vf "fps=1,scale=320:180,tile=15x15" demo-%02d.jpg -y
    1054850490
        16
    1054850490  
    OP
       320 天前
    @minami 12# 瓶颈不在于磁盘,我解码的时候读取硬盘才不到 50MB 每秒,远不如机械硬盘的 180MB 每秒( 8T 以上的硬盘读取是有这么高的)
    1054850490
        17
    1054850490  
    OP
       320 天前
    @MarginK 13# 我刚开始也这么想的,可是当我看到某些解码器可以通过降低质量来让低配置机器也可以播放 hevc 的时候,我就想,我是不是也可以这样,所以才来问问
    1054850490
        18
    1054850490  
    OP
       320 天前
    @hello2090 2# 你对于我视频的数量量级可能没什么概念,我现在收集的视频已经有 8W 多部了,视频大小高达 45TB
    zsxzy
        19
    zsxzy  
       320 天前
    降低解码质量, 一般的做法就是丢掉 B 帧, 比如 ijkplayer 在低配手机就这样做
    1054850490
        20
    1054850490  
    OP
       320 天前
    @SenseHu 11# https://www.v2ex.com/t/919129#reply13
    你可以看一下我这个帖子,里面详细说明了视频的情况
    1054850490
        21
    1054850490  
    OP
       320 天前
    @zsxzy 19# 我尝试一下
    1054850490
        22
    1054850490  
    OP
       320 天前
    @SenseHu 5# 这个也试过,但是对于我来说,还是软解最快,ffmpeg 技术文档里面也解释了,硬解由于需要频繁和 GPU 显存交换,所以在某种时刻会更慢,比如对于低分辨率的情况下, 通常都是 CPU 赢,但是对于 8K av1 就吃力了,这方面得硬解
    ttvast
        23
    ttvast  
       320 天前
    为啥不用 intel 核显,不比 3080 快多了?
    hello2090
        24
    hello2090  
       320 天前 via iPhone
    @lisxour 为啥不能试试?如果下载是好的问题在合成阶段,运气好第一分钟就能看到坏的帧呢?你非要找个适合几百 T 文件的方法就为了解决也许很快能解决的问题?
    hello2090
        25
    hello2090  
       320 天前 via iPhone
    @lisxour 有没有损坏问楼主啊又不是我的问题
    JeromeCui
        26
    JeromeCui  
       320 天前
    拆成很多段,然后并发用 aws 的 lambda 来做解码校验
    Jimmyisme
        27
    Jimmyisme  
       320 天前
    不是很懂,但是想知道为什么任何关于视频编解码的任务都是用 ffmpeg ?感觉网上有什么视频音频开源项目都绕不开
    1054850490
        28
    1054850490  
    OP
       320 天前
    @hello2090 24# 既然你追问,那我就说一下吧,这过程中不只是合成阶段,也发生在下载阶段,也出现在源服务器提供的源就有问题的,
    1:合成阶段的情况大多是在移动的时候出现了错误,比如我合成完成后,自动移动到另一个盘的时候,发生了宕机,或者资源管理器停摆,导致文件破损,这种情况下产生的破损文件通常是头部没问题,但是尾部有问题
    2:下载阶段的情况,由于的 aria2 多线程下载,我也采用了“等待次数过长不要丢弃片段”的选项,但是依旧不能阻止破损的发生,我也阅读了技术文档采用了各种方法,但是产生破损的文件是超级多原因的,我不能一并概述,
    3:youtube 的源服务器提供的文件有损坏,有部分视频文件只要换一个分辨率就正常了,或者换一个编码(目前 youtube 有三个编码,avc vp9 av01 ),我筛查出来再重新替换就好了,这部分是无法避免的。

    这些文可能有点混乱,主要还是我不太想描述太详细,太费脑子了,因为我说得再详细也并没有什么帮助,这些问题并不是从根源能解决的
    1054850490
        29
    1054850490  
    OP
       320 天前
    @ttvast 23# 硬解并没有快很多,如果你面对的是几十 T 级别的视频,你就不会觉得这点算力够用了,而且论解码器,那还得是 nvidia 的牛逼,intel 的只能说是解码全,这个全,并不是相对 nvidia 来说,只是很多的意思
    ljsh093
        30
    ljsh093  
       320 天前
    不懂视频的问一嘴没有专门校验错误的指令或者程序吗?
    hikigaya58
        31
    hikigaya58  
       320 天前 via Android   ❤️ 1
    YouTube 源文件有损坏?是指在网页播放视频就有问题吗?能不能给个例子?第一次听说这种情况。
    laqow
        32
    laqow  
       320 天前
    如果存在问题合成的时候 ffmpeg 就会报错吧,它只是默认 skip warning ,可能是加-xerror 能让它遇到错误退出。如果有合成前的文件只重下片段不是方便的多。
    如果只需要软解那就并行一下,有多少线程并行多少 ffmpeg ?
    sl0000
        33
    sl0000  
       320 天前
    换硬件治本
    SenseHu
        34
    SenseHu  
       320 天前
    1. `ffmpeg 通常需要将解码后的帧从 GPU 内存复制到系统内存中`. 纯命令不知道有没有办法跳过这个复制过程,c++ 的 api 是有一个明确的复制函数调用的, 我写硬解的 demo 时用过.
    2. 考虑一种充分利用资源的编排方式。一部分 cuda 解码, 一部分 intel qsv 解码, 一部分 d3d11va 解码, 一部分 CPU 解码
    SenseHu
        35
    SenseHu  
       320 天前
    > '合成阶段的情况大多是在移动的时候出现了错误'
    给合成好的文件就地生成个 md5, 移动的时候带着一起 ?
    sl0000
        36
    sl0000  
       320 天前
    可以试试 8 通道内存工作站 ECC DDR4 3200:25.6 GB/s*8 即 200GB/s
    JusticeLanding
        37
    JusticeLanding  
       320 天前
    我们做的播放器,有改造 ffmpeg ,解码过程中把错误帧、坏帧发现不送去渲染,达到丢帧显示不花屏的效果。
    JusticeLanding
        38
    JusticeLanding  
       320 天前
    另外在研究解码效率,正在做降采样解码,一种是解码完的 YUV 降采样,另外一种是 DCT 降采样。
    Jakarta
        39
    Jakarta  
       320 天前
    既然 gpu 硬件做不到加速解码,那干脆以后“硬件加速”改名叫“硬件减速”好了。

    我的建议是检查确认自己使用的 gpu 加速命令是否有误。
    Jakarta
        40
    Jakarta  
       320 天前   ❤️ 2
    没有经过充分测试,但我用-hwaccel cuda -hwaccel_output_format cuda 代替你的指令中的-hwaccel none ,使用显卡加速后,同一个视频的解码速度从 15x 提高到了 50x 。
    alz5113
        41
    alz5113  
       320 天前
    如果是纯软解的话 可靠考虑自己重新编译 ffmpeg 针对当前 cpu 环境的选项都开上 ,优化选项开-O3 加上运行时 profile 优化
    MrKrabs
        42
    MrKrabs  
       320 天前
    我也有点这个需求
    我的命令是
    ["-loglevel", "+level+warning", "-hide_banner", "-nostdin", "-i", "VOL_1.mkv", "-map", "0:v?", "-map", "0:a?", "-f", "null", "-"]
    MrKrabs
        43
    MrKrabs  
       320 天前
    硬解速度不如 cpu 解码结果也不靠谱也不知道会不会真的报错,我是不用的
    zmcity
        44
    zmcity  
       320 天前
    凭我的经验,软解不太可能在 12490F 上比 3080 的 nvcodec 快。
    解码可调参数很少,纯软解的优化我能想到就是上面说的 dct 降采样,yuv2rgb 降采样,或者直接输出灰度视频。
    然后就是直接调 api 提高一点性能,提高点灵活性,比如做个边下边解。
    进一步判断是不是下载 /封装问题的话不需要解码,先读一下流,如果流有问题就不用解码了。
    1054850490
        45
    1054850490  
    OP
       320 天前
    @hikigaya58 31#
    在上面这个视频里,破损发生在 4k 分辨率,vp9 编码的,9.43 分处,这就是源就有问题的视频,更换一个分辨率就正常了,虽然只是缺了几秒
    1054850490
        46
    1054850490  
    OP
       320 天前
    @zmcity 44#我虽然没有 3080 ,但是我花钱让另一个拥有 3080 的人和我去解码同一批视频测试了解码速度,结果显示在低分辨率情况下是可以吊打 GPU 解码的,也就是 4k 以下的分辨率,8k vp9 以及 8K av1 就显得乏力了
    1054850490
        47
    1054850490  
    OP
       320 天前
    @zmcity 44# 另外,我不止是在下载阶段发生破损,还有很多其他方面发生破损,所以让我去解决下载以及合成这个阶段发生的破损并不适用于所有场景
    1054850490
        48
    1054850490  
    OP
       320 天前
    @Jakarta 39# 40# 我不知道你是什么 CPU ,但是我花钱让一个拥有 3080 的人去跟我测试同一批视频了,命令只是单独添加了-hwaccel cuda ,结果显示 4K 以下的分辨率是 CPU 胜出,而 8k vp9 av01 被摁着打,3080 解码 8k AV1 速率只是 1.45x ,而我 CPU 只是刚好徘徊在 1X ,而且 3080 这时候的解码占用也只有 60%,我查了一下,这是因为 3080 支持双路 8K AV1 ,所以并没有把解码吃光,而 3070 以下的卡并不支持双路 8k AV1
    1054850490
        49
    1054850490  
    OP
       320 天前
    @laqow 32# 这不失为一种方法,只是我遇到的破损并不只是下载合成阶段产生的,所以我需要寻找一个可靠的能够找出视频破损的招
    ameizing
        50
    ameizing  
       320 天前
    @1054850490 谷歌转码成 vp9 的时候,编码出错了吧。ffmpeg 是能识别出这种错误的。
    bitdepth
        51
    bitdepth  
       319 天前
    FFmpeg 的 DMA buffer 支援有問題,還有是單一輕量行程的。用 Gstreamer 吧
    kice
        52
    kice  
       319 天前 via Android
    我感觉怎么解决视频合成会出现坏帧的问题收益更大。不过不清楚你坏帧是怎么坏。

    或者就是你 GPU 解码然后 GPU 上查,这样就只是要折腾一波 GPU 程序。
    1054850490
        53
    1054850490  
    OP
       319 天前
    @kice 52# 因为我不只是一个下载器,网盘下载的呢?要知道百度网盘到现在都没有下载校检,这种闭源的我又该如何解决呢?我需求的是一整套的查损流程,而不是对下载进行纠错,因为有些下载器并不是我能够修改的
    tangtang369
        54
    tangtang369  
       312 天前
    没有用过显卡的解码 你这个用的是带不带核显的 cpu 我试过 ffmpeg 用 intel 的核显大概能以 4 ~ 10 倍的速度解码视频文件 当然我在其他 arm 平台的 ai 盒子上也测出过 1080P 1000fps 没秒的解码
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2836 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 15:10 · PVG 23:10 · LAX 08:10 · JFK 11:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.