各位大佬,如何实现一个 avi 格式的视频播放平台,并且视频帧有关联信息的。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
CorgiDuu

各位大佬,如何实现一个 avi 格式的视频播放平台,并且视频帧有关联信息的。

  •  1
     
  •   CorgiDuu 2024 年 3 月 2 日 1830 次点击
    这是一个创建于 785 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:业务上有一个需求,可以对特定事件进行回放,回放的内容包括有视频信息( 20s-几分钟不等),以及视频每一帧对应的业务参数等。数据源位于腾讯 COS 对象存储中,一个原始视频大约 5 分钟,但是一个视频包含若干事件,也就是说一个事件只占原始视频的其中 20 秒左右,用户点击每一条事件时,后端会返回上述的业务参数,用于前端和视频帧匹配,视频经常变化,每天都会有新的大量视频上传到对象存储中,大概就是这种。

    需求点:

    1. 视频格式为 avi
    2. 点击每一条事件时,事件所在的视频片段可以快速加载(比如说在 1-2 秒内快速加载 5 分钟视频中的指定 20 秒)
    3. 事件会跨视频,也就是说会存在一个事件需要播放两段视频的情况,比如说第一个 5 分钟结尾的 10 秒,到第二个 5 分钟开始的 10 秒
    4. 需要同屏能够展示 4 个视频播放器,但是共享同一个进度条,拖动进度条,同时操控 4 个视频
    5. 前端需要能够获取到视频帧信息,比如说进度条拖动到某点时,能够知道当前是具体帧索引,比如说第 300 帧,用于匹配业务参数(目前,后端点击事件信息时会返回)

    技术栈:Go + vue3

    小弟之前未接触过视频播放的实现,一头雾水,想请教一下有什么成熟的方案可以解决吗?搜了一圈,大多数都是在提 m3u8 、videojs 、flvjs 、http range 之类的。不知道具体要实现上面的 5 点需求,需要有哪些技术点组合。

    希望有经验的前辈指点迷津,比如说是否需要后端把 COS 中的视频先拉取到本地,然后切片成 m3u8 存储?还是说直接可以读取 COS 中的视频?再比如说后端会记录这条事件在原视频中的位置,比如说第 400 帧到 1000 帧之间,那怎么和切片或者 range 搭配使用呢?

    或许以上就是很简单的视频播放需求,但是没接触过这方面的架构设计,所以一时找不到方向,希望 v 佬们指点下~

    10 条回复    2024-03-04 17:54:41 +08:00
    CorgiDuu
        1
    CorgiDuu  
    OP
       2024 年 3 月 2 日
    上面提到的事件是一个业务概念,就类似于一个列表中每一条记录,后面关联的有每一帧的业务参数信息(非视频的参数,例如信号,配置参数等),在拖动视频进度条的时候,信号曲线也会跟着变化,类似于股票走势那种,所以想比较视频播放网站,这里还需要知道视频当前播放的帧序号,用于展示信号信息
    busier
        2
    busier  
       2024 年 3 月 2 日 via iPhone
    avi 只是封装容器 不是格式 并且非常古老
    CorgiDuu
        3
    CorgiDuu  
    OP
       2024 年 3 月 2 日
    @busier 哦哦,学到了,那我表述有问题,我想说的就是是 .avi 结尾的视频文件,如果想实现切片和播放之类的,是不是要转为 mp4 之类的呢?
    CorgiDuu
        4
    CorgiDuu  
    OP
       2024 年 3 月 2 日
    补充一点:现在的实现方式很笨重,说出来怕大家笑话,我们根据用户的点击行为把 cos 视频拉下来,然后调用 opencv 库切成一帧帧的图片,然后根据事件所在索引,把具体的帧图片 base64 推给前端,前端解码展示图片,然后图片轮替,实现播放。。。。。。现在项目要重构了,想把这段逻辑给优化一下,希望能够做到不占用本地空间(如果可行,不行的话也可以接受),主要是可以优化体验,快速响应
    hello2090
        5
    hello2090  
       2024 年 3 月 2 日 via iPhone
    没仔细看你的描述,太复杂了,你如果是需要用户点击的时间的视频帧,这就是一个类似于视频播放器 seek 的功能啊。

    得到用户点击的 timestamp,ffmpeg 打开文件,调 API seek 到那个位置,再从那个位置开始解码图片不就行了。当然一个细节是 ffmpeg seek 返回的是最接近用户点击位置的 I frame, 可能比用户需要的 timestamp 早一点,解码图片的时候你不需要返回那些太早的图片
    CorgiDuu
        6
    CorgiDuu  
    OP
       2024 年 3 月 2 日
    @hello2090 有可能我说复杂了,就是想实现一个视频播放功能,只不过在播放的时候前端能获取到播放的详细进度,另外想问的是 COS 中的视频能不能直接播放
    ntedshen
        7
    ntedshen  
       2024 年 3 月 3 日
    avi 基本没救吧,绑 windows 的古董。。。
    如果转码你需要用 mp4 封装 h264/h265(hevc)/av1 编码集,mkv 部分浏览器也可以。。。

    加载感觉主要是网速问题,浏览器和后端自己会处理 206 Partial Content 。。。
    至少我 20m 的 frp 看个 nas 的视频跳到中间加载也就两秒,5m 就龟速了。。。

    跨视频那不如就别分段。。。

    拖一个进度条操作四个这个你写一个事件里就行,这个没啥问题。。。

    为啥要用帧定位。。。好奇怪的需求。。。
    计算到对应时间在前端展示不行嘛?
    jim9606
        8
    jim9606  
       2024 年 3 月 3 日
    输入 avi 的话转码这一步是无可避免的,需要转成 AVC MEPG-TS 切片,建议预先切好,这个我觉得 ffmpeg 手撸都行。
    我建议是预先按照事件切分点将每个事件转码切成 ts 片段,连续播放用 hls (也就是 m3u8 ),可能直接使用<video>标签就能实现快速跳转。
    转码使用恒定帧率应该能满足时间-帧计数的正比关系。

    不切片的方法需要你理解视频 I 帧/GOP 的概念,对视频进行转码时事件切分点为 I 帧(最终效果约等于先按上面切好然后 ffmpeg concat copy 拼回去),还要服务器支持 HTTP Range 访问,所以我觉得还不如上面那种,要求少点还好理解。
    CorgiDuu
        9
    CorgiDuu  
    OP
       2024 年 3 月 3 日
    @jim9606 感谢大佬回复,比如说前端用 hls.js 播放的时候,需要什么额外的操作读取 ts 文件吗?还是说直接就读取 m3u8 文件,hls 封装好了,会自动的顺序播放呢
    jim9606
        10
    jim9606  
       2024 年 3 月 4 日
    我不是搞前端的不清楚,你自己看文档和做测试吧。
    一般来说不需要直接处理 ts 读取的,可能需要在 m3u8 包含时间信息
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2463 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 57ms UTC 16:00 PVG 00:00 LAX 09:00 JFK 12:00
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86