zoukankan      html  css  js  c++  java
  • 关于大视频video播放的问题以及解决方案(m3u8的播放)

    在HTML5里,提供了<video> 标签,可以直接播放视频,video的使用很简单:

    <video width="320" height="240" controls>
      <source src="movie.mp4" type="video/mp4"> 
    </video>

    这基本上能满足大部分用户的需求,但是还是有几个问题需要解决:

    (1)大视频的问题。

    (2)字幕的问题

    (3)清晰度的问题

    (4)视频保密问题。

    本文将简单的探讨上面几个问题并给出简单的解决方案。

    备注:这些问题也是我在制作启明星视频系统时遇到的(演示  http://demo.dotnetcms.org/video ),所以,如果你在开发视频播放,那么本文应该对你有用。

    1.大视频问题

    当使用video播放视频时,对于大视频最好是分片存储,例如一个500M的视频,以10M为一个视频段,那么可以分为50个片段。播放时,按需加载所需要的视频片段(例如用户拖动滚动条直接到一个部分)。

    这里又遇到2个问题:

    1.1大文件的上传

    大文件上传,这里使用的百度的 WebUploader,百度很好的一个上传组件,可惜已经不再维护,当然国外也有很多开源的大文件上传组件,所以,这个问题不大。

    大文件上传的原理也比较简单:HTML5里提供了JS 的 FileReader 类,Blob类,利用这个类可以在本地直接读取视频的大小,例如要上传500M的视频,以10M为一个分块,把视频分割为一个为50份,对于每一份利用JQuery的AJAX分别上传到服务器上,等50份上传完后,服务器再把这50分视频合并成一个大文件即可。

    在上传时通常需要给每个视频一个编号,例如 file0,file1,file2... file49, 上传完毕后,利用.NET提供的System.IO.File.ReadAllBytes读取这些文件然后合并起来。

                        foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write
                            {
                                var bytes = System.IO.File.ReadAllBytes(part);
                                fs.Write(bytes, 0, bytes.Length);
                                bytes = null;
                                System.IO.File.Delete(part);//删除分块
                            }

    这样,就把本地的500M视频,原封不动的加速上传到服务器暂且命名为 video1.mp4。

    1.2大文件分割

    当视频播放时,利用的是m3u8进行列表播放(下述),在这里使用了ffmpeg.exe组件,ffmpeg提供了如下命令:

    ffmpeg.exe -i a.mp4 -hls_time 30 -hls_list_size 0 -f hls  a.m3u8;

    上面代码段里, -i 表示输入(input)  a.mp4,   -hls_time 30 表示每个分块断是30秒, hls_list_size 表示序号是从0开始。  a.m3u8 表示最终生成的文件名。

    上面代表的是意思是:用ffmpeg把a.mp4进行分割,每个分段长为30秒,并把分割后的信息存放在a.m3u8里。

    执行上述命令后,就可以得到 一些列的 *.ts 文件和一个a.m3u8文件

    利用.NET可以通过服务器执行合并操作。

    1.3 m3u8

     m3u8用来存储视频播放的列表,他的内容类似如下:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-MEDIA-SEQUENCE:35232
    #EXT-X-TARGETDURATION:10
    #EXTINF:10.000,
    cctv6hd-1549272376000.ts
    #EXTINF:10.000,
    cctv6hd-1549272386000.ts
    #EXTINF:10.000,
    cctv6hd-1549272396000.ts
    #EXTINF:10.000,
    cctv6hd-1549272406000.ts
    #EXTINF:10.000,
    cctv6hd-1549272416000.ts
    #EXTINF:10.000,
    cctv6hd-1549272426000.ts

    简单的说,m3u8存放的是播放列表,视频以.ts格式存储, ts即"Transport Stream"的缩写。 全称为MPEG2-TS,MPEG2-TS,格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。

    不用mp4是因为,如果用mp4,那么在2个分块直接播放时,会出现卡顿。而ts格式可以无缝对接。

    你甚至可以设定客户端存储的数量,例如设置为3,当使用手机看到5.ts时,手机开始缓存6.ts ,7.ts, 8.ts, 只有这3个都下载完毕后,才播放,而不用等到整个下完才播放,这样增加了播放的流畅度。(有时候我们看视频时,卡顿时,手机会显示一直在缓冲中,来缓存片段。。。)

    m3u8不是<video> 标签的支持的标准格式。换句话说,你使用如下代码是无法播放的

    <video width="320" height="240" controls>
      <source src="a.m3u8"  type=application/x-mpegURL> 
    </video>

    目前国内的有 腾讯的 tcplayerlite 和百度的cyberplayer 可以播放m3u8,不过,他们其实都使用videojs这个开源内容,外加一层皮肤。

    在我自己开发里,因为不想引入太多的JS,所以直接使用 HLS.JS (HTTP Live Streaming )

    当引入hls后,播放视频变的非常简单:

                      
          <video          width="100%"      id="video2"     >     </video> 
    
                    <script>
                        if (Hls.isSupported()) {
                            var video2 = document.getElementById('video2');
                            var hls = new Hls();
                            hls.loadSource('a.m3u8'); 
                            hls.attachMedia(video2);
                            hls.on(Hls.Events.MANIFEST_PARSED, function () {
                                video2.play();
                            });
                        }
            </script>

    直接使用       hls.loadSource('a.m3u8');  即可加载播放列表。

    1.4 播放清晰度

    m3u8指向的是播放列表,他本身不提供多清晰度的问题,通常,你需要利用 ffmpeg.exe 生成不同的清晰度,例如

    对于video1.mp3, 你可以生成 video-360.mp4, video-720.mp4和 video-1080.mp4 并生产 多个m3u8

     video-360.m3u8
     video-720.m3u8
     video-1080.m3u8

    当视频播放时,如果用户选择不同的清晰度,加载不同的m3u8.

    你也可以根据用户的网速,加载不同的m3u8.

    2.字幕问题

     (以下内容主要来自张鑫旭的文章)HTML5 Video视频支持支持外挂字幕,文件后缀名是.vtt,称为WebVTT格式,专门的web字幕格式。使用很简单,用一个<track>元素即可,例如:

    <video id="video">
    <source src="example.mp4" type="video/mp4">
    <track src="example.vtt" default>
    </video>

    只要src属性地址OK,同时有default属性,字幕就会生效。

    字幕格式是纯文本格式

    WEBVTT
    00:00:00.001 --> 00:00:01.000
    请把你的锅
    
    00:00:01.001 --> 00:00:03.500
    带回你的虾
    
    00:00:03.501 --> 00:00:07.000
    请把你的微笑留下……
    
    00:00:07.501 --> 00:00:10.000
    请把你的锅
    
    00:00:10.001 --> 00:00:12.000
    带回你的虾
    
    00:00:12.001 --> 00:00:15.000
    请把你的微笑留下

    <video>标签外挂<track>

    <track src="example.vtt" kind="subtitles" label="中文字幕" srclang="zh" default>

    而track支持多个字幕,例如:

    <track src="example.vtt" kind="subtitles" label="中文字幕" srclang="zh" default>
    <track src="example2.vtt" kind="subtitles" label="中文字幕(修正)" srclang="zh">

    如果你的视频希望提供中文/英文/日文等多语言版本,利用这个方法,可以解决视频字幕多语言版本的问题。

    在youtube上,我们有时候会看到一个视频会提供很多语言版本,如上所述,vtt是一个纯文本格式,利用机器翻译,例如百度翻译,把 vtt翻译上百个版本,挂在在track上,这样

    瞬间,让你的视频支持几百个语言,立刻就会高大上。

    最后,说一下视频加密,无论你用何种技术,视频最终是要在用户端显示的,所以,视频本身是无法加密的,而作为简单加密主要有2个方法:

    (1)createObjectURL

    当我们查看部分网站得出视频或者部分图片时,你会发现网址网址是用blob:src开头,这其实是 createObjectURL搞的鬼

    有兴趣的朋友可以看看其文档介绍,简单说,他就是把真实的地址隐藏了,当你看video的src看到的是一个虚拟地址。

    (3)m3u8 加密

    如上所述,m3u8里存放的是一个个 *.ts,对于普通用户来说,就算看到*.ts文件,让他一个个下载ts,估计想死的心都有。所以,我们保护m3u8最核心的是防止工具下载。

    一个简单的解决方法是:m3u8加参数或者利用session,例如  a.m3u8?key=xxxxx-xxx-xxx

    当使用工具下载视频时,工具因为无法获取key参数,那么就无法获取到a.m3u8。

    当然,如果真正想下载m3u8也不是完全没办法,

    ffmpeg.exe 这个工具既然提供了video分割为ts功能,自然也提供ts合并为一个完整的video功能。只是对普通人来说比较繁琐罢了。

    当然,如果你不想搞这么复杂,使用下面代码就可以了, controlslist="nodownload" 让视频不出现下载,而contextmenu不允许使用右键播放,这应付一般的小白应该足够了。

                
          <video    
             id="video2"   
             controlslist="nodownload" 
            >   
             </video>
      
          
          <script>
              $('#video').bind('contextmenu',function() { return false; });
          </script>

    最后说一下视频播放的问题,虽然HTML5里使用 autoplay 就可以制动播放,但是谷歌的chrome在新版本里,已经禁止自动播放了,谷歌给的解释:很多用户利用autoplay这个属性投放大量广告,让用户不堪其扰。因此,如果要autoplay必须配合muted(静音),也就是只有静音后自动播放才能生效,否则需要用户手动点击“播放”。

    当然谷歌也给出另外一个解决方案:就是不静音的自动播放,需要这个网址在安全性名单里,因此,我们看youtube是可以自动播放的,但是,很多网站是不能自动播放 。

    以上内容是我做启明星视频遇到的,你可以查看demo当然还有很多细节要考虑,但是大部分问题都已经解决。

  • 相关阅读:
    .Net常识之 浅析as和is操作符
    使用com object 控制outlook
    override 和 new 关键字的总结
    interface Virtual and abstract
    SQL Server 索引结构及其使用(四)
    ASP。NET的设计思想
    系统性能的提升之二"聚集索引"的建立
    SQL Server 索引结构及其使用(一)
    form 中加上target
    创建多维ArrayList的方法
  • 原文地址:https://www.cnblogs.com/mqingqing123/p/14127924.html
Copyright © 2011-2022 走看看