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

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

  •  1
     
  •   CorgiDuu · 263 天前 · 1136 次点击
    这是一个创建于 263 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

    不切片的方法需要你理解视频 I 帧/GOP 的概念,对视频进行转码时事件切分点为 I 帧(最终效果约等于先按上面切好然后 ffmpeg concat copy 拼回去),还要服务器支持 HTTP Range 访问,所以我觉得还不如上面那种,要求少点还好理解。
    CorgiDuu
        9
    CorgiDuu  
    OP
       262 天前
    @jim9606 感谢大佬回复,比如说前端用 hls.js 播放的时候,需要什么额外的操作读取 ts 文件吗?还是说直接就读取 m3u8 文件,hls 封装好了,会自动的顺序播放呢
    jim9606
        10
    jim9606  
       261 天前
    我不是搞前端的不清楚,你自己看文档和做测试吧。
    一般来说不需要直接处理 ts 读取的,可能需要在 m3u8 包含时间信息
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2847 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:18 · PVG 23:18 · LAX 07:18 · JFK 10:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.