背景:业务上有一个需求,可以对特定事件进行回放,回放的内容包括有视频信息( 20s-几分钟不等),以及视频每一帧对应的业务参数等。数据源位于腾讯 COS 对象存储中,一个原始视频大约 5 分钟,但是一个视频包含若干事件,也就是说一个事件只占原始视频的其中 20 秒左右,用户点击每一条事件时,后端会返回上述的业务参数,用于前端和视频帧匹配,视频经常变化,每天都会有新的大量视频上传到对象存储中,大概就是这种。
需求点:
技术栈:Go + vue3
小弟之前未接触过视频播放的实现,一头雾水,想请教一下有什么成熟的方案可以解决吗?搜了一圈,大多数都是在提 m3u8 、videojs 、flvjs 、http range 之类的。不知道具体要实现上面的 5 点需求,需要有哪些技术点组合。
希望有经验的前辈指点迷津,比如说是否需要后端把 COS 中的视频先拉取到本地,然后切片成 m3u8 存储?还是说直接可以读取 COS 中的视频?再比如说后端会记录这条事件在原视频中的位置,比如说第 400 帧到 1000 帧之间,那怎么和切片或者 range 搭配使用呢?
或许以上就是很简单的视频播放需求,但是没接触过这方面的架构设计,所以一时找不到方向,希望 v 佬们指点下~
1
CorgiDuu OP 上面提到的事件是一个业务概念,就类似于一个列表中每一条记录,后面关联的有每一帧的业务参数信息(非视频的参数,例如信号,配置参数等),在拖动视频进度条的时候,信号曲线也会跟着变化,类似于股票走势那种,所以想比较视频播放网站,这里还需要知道视频当前播放的帧序号,用于展示信号信息
|
2
busier 264 天前 via iPhone
avi 只是封装容器 不是格式 并且非常古老
|
4
CorgiDuu OP 补充一点:现在的实现方式很笨重,说出来怕大家笑话,我们根据用户的点击行为把 cos 视频拉下来,然后调用 opencv 库切成一帧帧的图片,然后根据事件所在索引,把具体的帧图片 base64 推给前端,前端解码展示图片,然后图片轮替,实现播放。。。。。。现在项目要重构了,想把这段逻辑给优化一下,希望能够做到不占用本地空间(如果可行,不行的话也可以接受),主要是可以优化体验,快速响应
|
5
hello2090 264 天前 via iPhone
没仔细看你的描述,太复杂了,你如果是需要用户点击的时间的视频帧,这就是一个类似于视频播放器 seek 的功能啊。
得到用户点击的 timestamp,ffmpeg 打开文件,调 API seek 到那个位置,再从那个位置开始解码图片不就行了。当然一个细节是 ffmpeg seek 返回的是最接近用户点击位置的 I frame, 可能比用户需要的 timestamp 早一点,解码图片的时候你不需要返回那些太早的图片 |
6
CorgiDuu OP @hello2090 有可能我说复杂了,就是想实现一个视频播放功能,只不过在播放的时候前端能获取到播放的详细进度,另外想问的是 COS 中的视频能不能直接播放
|
7
ntedshen 263 天前
avi 基本没救吧,绑 windows 的古董。。。
如果转码你需要用 mp4 封装 h264/h265(hevc)/av1 编码集,mkv 部分浏览器也可以。。。 加载感觉主要是网速问题,浏览器和后端自己会处理 206 Partial Content 。。。 至少我 20m 的 frp 看个 nas 的视频跳到中间加载也就两秒,5m 就龟速了。。。 跨视频那不如就别分段。。。 拖一个进度条操作四个这个你写一个事件里就行,这个没啥问题。。。 为啥要用帧定位。。。好奇怪的需求。。。 计算到对应时间在前端展示不行嘛? |
8
jim9606 263 天前
输入 avi 的话转码这一步是无可避免的,需要转成 AVC MEPG-TS 切片,建议预先切好,这个我觉得 ffmpeg 手撸都行。
我建议是预先按照事件切分点将每个事件转码切成 ts 片段,连续播放用 hls (也就是 m3u8 ),可能直接使用<video>标签就能实现快速跳转。 转码使用恒定帧率应该能满足时间-帧计数的正比关系。 不切片的方法需要你理解视频 I 帧/GOP 的概念,对视频进行转码时事件切分点为 I 帧(最终效果约等于先按上面切好然后 ffmpeg concat copy 拼回去),还要服务器支持 HTTP Range 访问,所以我觉得还不如上面那种,要求少点还好理解。 |
9
CorgiDuu OP @jim9606 感谢大佬回复,比如说前端用 hls.js 播放的时候,需要什么额外的操作读取 ts 文件吗?还是说直接就读取 m3u8 文件,hls 封装好了,会自动的顺序播放呢
|
10
jim9606 262 天前
我不是搞前端的不清楚,你自己看文档和做测试吧。
一般来说不需要直接处理 ts 读取的,可能需要在 m3u8 包含时间信息 |