Java 实现大文件(视频)的高效下载,并让前端播放,有什么思路吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Triump
V2EX    程序员

Java 实现大文件(视频)的高效下载,并让前端播放,有什么思路吗?

  •  
  •   Triump 2023-02-16 11:12:57 +08:00 5804 次点击
    这是一个创建于 969 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求背景:

    要在网页上播放视频,视频是存储在文件系统( minIO )上,现在的做法是,前端请求后台的文件下载接口,将整个文件下载后返回给前端进行播放。但是这个视频大概有 140M ,整个过程耗时大概 1 分钟了。用户体验很差。

    我的思路:

    后端提供一个支持文件分片下载的方法,前端通过请求头设置 Range 参数传入指定的范围。比如一个 100M 的文件,每次请求 10M, 但是我不确定前端拿到这 10M 文件后,是否能够播放。。。 如果这个思路可行的话,前端需要用到哪些技术呢?

    有没有大佬能够提供一下思路啊?

    38 条回复    2023-02-17 17:52:00 +08:00
    fiveStarLaoliang
        1
    fiveStarLaoliang  
       2023-02-16 11:17:00 +08:00
    走 nginx 转发不就行了,顶多加个鉴权,不需要自己去写切片播放
    weixiaoyun
        2
    weixiaoyun  
       2023-02-16 11:17:04 +08:00
    不用下载,minio 支持视频拉流的,给个视频预览源地址给前端播放器调用就好了
    Triump
        3
    Triump  
    OP
       2023-02-16 11:22:35 +08:00
    @weixiaoyun 就是让前端直接去访问 minio 吗?这样的话要把 桶的权限设置为公开,会不会很危险,因为这个项目要支持外网访问的。
    tool2d
        4
    tool2d  
       2023-02-16 11:28:39 +08:00
    "但是我不确定前端拿到这 10M 文件后,是否能够播放"

    本来就无法确定。

    MP4 有两种格式,头格式和尾格式。头格式把具体播放信息都放在头部,可以流式播放。尾格式是把详细信息都放在文件末尾,你比如下载视频 BT ,必须把整个文件拖下来后,才能播放。

    当然有工具可以在这两种格式之间切换。
    MoonWalker
        5
    MoonWalker  
       2023-02-16 11:29:48 +08:00
    返回 206 状态码然后按 Range 解析字节范围就好了吧?
    MoYi123
        6
    MoYi123  
       2023-02-16 11:30:10 +08:00
    @Triump 用 presignedGetObjectUrl
    registerrr
        7
    registerrr  
       2023-02-16 11:31:00 +08:00
    @Triump
    不用,把桶权限设置成 download (共有读私有写)就行了

    返回视频流时候你有业务要处理么?没有就是直接访问啊,前端只写个 video 标签都可以了
    registerrr
        8
    registerrr  
       2023-02-16 11:34:28 +08:00
    要是访问也需要授权就用 6#的这个方法
    duckyrain
        9
    duckyrain  
       2023-02-16 11:35:29 +08:00
    走公有云 CDN ?
    边下边播是视频格式决定的,和下载服务没关系。
    Triump
        10
    Triump  
    OP
       2023-02-16 11:37:26 +08:00
    @MoonWalker 我现在的思路就是这样,和前端小哥沟通了一下,他还不知道这种方式要怎么处理,所以不知道前端能不能去这个实现。
    Triump
        11
    Triump  
    OP
       2023-02-16 11:38:41 +08:00
    @registerrr 感谢,这个思路也可以。
    okakuyang
        12
    okakuyang  
       2023-02-16 11:59:15 +08:00
    边下边播要 Range 支持,不然苹果系可能播放不了。
    niushuai
        13
    niushuai  
       2023-02-16 13:31:03 +08:00
    还是做切片比较合适
    rqxiao
        14
    rqxiao  
       2023-02-16 13:39:41 +08:00
    m3u8 文件
    opengg
        15
    opengg  
       2023-02-16 13:44:47 +08:00
    luob
        16
    luob  
       2023-02-16 13:46:17 +08:00
    后端调用 ffmpeg 切成 dash ,然后前端直接 plyr 播放器,都是成熟方案不用自己写什么
    luob
        17
    luob  
       2023-02-16 13:48:16 +08:00   1
    唯一缺点是担心客户看到 plyr 播放器的界面会不有什么奇怪的反应(
    spike76
        18
    spike76  
       2023-02-16 13:50:43 +08:00
    用 ffmpeg 将 mp4 转成流格式
    ffmpeg -i #{video_path} -codec: copy -start_number 0 -hls_time 16 -hls_list_size 0 -f hls #{hls_index_path}
    每个小块文件只有 16 秒内容,前端下载应该足够快了
    wxd21020
        19
    wxd21020  
       2023-02-16 13:53:35 +08:00
    学习学习,看大佬们有啥解决方案
    cheng6563
        20
    cheng6563  
       2023-02-16 14:16:33 +08:00
    前端播放很难说的,你别看这些文件都是.mp4 ,其实内部差异大得很。
    有必要的话还是要上 ffmpeg 重新封包(不是转码)
    mmdsun
        21
    mmdsun  
       2023-02-16 14:32:46 +08:00
    你是不是用 Java 先 download 文件,然后再 Response 写返回给页面的?
    你应该用 gateway 代理直接转发给页面,这样后端你就需要先下载了
    mmdsun
        22
    mmdsun  
       2023-02-16 14:37:17 +08:00
    var file = downloadFile("http://xxxxxxxxxx");
    Response.write(file);

    上面这种换成:

    /gateway/download/xxxxxxxxxx => http://file.download/xxxxxxxxxx

    要是云存储那边要鉴权加什么请求头的,你网关直接给加上就好。
    zzl22100048
        23
    zzl22100048  
       2023-02-16 15:11:35 +08:00
    能用 m3u8 是最好
    最省事就 presignedGetObjectUrl 期限设置一天
    mouyong
        24
    mouyong  
       2023-02-16 15:20:14 +08:00
    我有解决方案,可付费提供,见下方图。本地大文件视频在线播放。
    1. 大文件视频在线播放不卡顿
    2. 大文件视频本地存储,不用担心昂贵的云存储费用

    mouyong
        25
    mouyong  
       2023-02-16 15:22:39 +08:00
    在线预览与管理管理本地文件、视频。

    renmu
        26
    renmu  
       2023-02-16 15:23:38 +08:00 via Android
    走 m3u8 ,很成熟了
    qfdk
        27
    qfdk  
    PRO
       2023-02-16 15:24:31 +08:00
    m3u8 吧 多简单 流方案.
    m3u8 视频格式原理:将完整的视频拆分成多个.ts 视频碎片,.m3u8 文件详细记录每个视频片段的地址。 视频播放时,会先读取.m3u8 文件,再逐个下载播放.ts 视频片段
    HTML001
        28
    HTML001  
       2023-02-16 17:16:25 +08:00
    后端将视频转 m3u8, 前端用 hls.js 或者 video.js 播放应该就可以满足
    wqhui
        29
    wqhui  
       2023-02-16 17:31:26 +08:00
    m3u8 ,大的在线视频网站都这样玩
    HtPM
        30
    HtPM  
       2023-02-16 18:00:02 +08:00
    #16 楼是正规方案,现在基本上都是用 MPEG-DASH 方案,Youtube 采用的这种
    123zouwen
        31
    123zouwen  
       2023-02-16 19:04:53 +08:00
    前段时间刚做了类似需求, 简单做法就是后端返回给前端 mp4 的视频链接(如果桶不是 public 的话, 后端调用 minio 生成一个临时访问链接), 前端拿到链接即可播放视频, 快进等功能正常
    xylxAdai
        32
    xylxAdai  
       2023-02-16 19:10:09 +08:00
    m3u8 啊。切成流格式,直接播放。
    ryanbuu
        33
    ryanbuu  
       2023-02-17 00:24:03 +08:00
    转 dash + 1
    ryanbuu
        34
    ryanbuu  
       2023-02-17 00:24:16 +08:00
    @q1angch0u 转完存一下,下次接着播
    cephei
        35
    cephei  
       2023-02-17 10:49:38 +08:00
    可以在后台做一层代理,把前端的 Http Range 请求转发到 MinIO
    Sum0l
        36
    Sum0l  
       2023-02-17 13:25:32 +08:00
    推荐一个 java 版的 ffmpeg https://github.com/bytedeco/javacv
    dudubaba
        37
    dudubaba  
       2023-02-17 14:53:08 +08:00
    好像除了直接访问,没有一劳永逸的方法,得后端改造一下。
    lbunderway
        38
    lbunderway  
       2023-02-17 17:52:00 +08:00
    ffmpeg 这个靠谱
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1012 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 18:10 PVG 02:10 LAX 11:10 JFK 14:10
    Do have faith in what you're doing.
    ubao 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