关于大视频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>
以上内容是我做启明星视频遇到的,你可以查看demo当然还有很多细节要考虑,但是大部分问题都已经解决。
关于大视频video播放的问题以及解决方案(m3u8的播放)的更多相关文章
- 手机浏览器自动播放视频video(设置autoplay无效)的解决方案
1.问题的提出 某一天接了个需求,需要在手机的H5页面内加入视频,我开开心心做完,准备交付的时候,问题来了,PM想要用户一进入页面,视频就开始播放,不需要用户手动点击. 2.尝试解决 加autopla ...
- video视频在本地可以播放,在服务器上不可以播放
今天遇到一个比较坑的问题,视频在本地可以播放,然后放到服务器上面就播放不了,原因是因为服务器上面不支持mp4的播放,下面看解决办法.1.首先进入IIS(Internet Information Ser ...
- html5--移动端视频video的android兼容,去除播放控件、全屏等
html5 中的video 在手机浏览器中的总结所有页面播放时, 如果选择全屏播放, 播放画面将浮动到屏幕的最上层 IOS 手机 自动播放 播放界面浮动文字 播放时是否自动全屏 能否嵌入在页面中播 ...
- html5之音频、视频(video&audio)
音频&视频 本篇为本人的学习笔记. 在Html5之前,浏览器对于视频和音频的处理并没有一个标准.因此在网页中看到的视频,都是通过第三插件的方式嵌入的,如:QuickTime.RealPlaye ...
- HTML5视频Video 音频Audio
视频协议 视频格式 Flash HTML5 HTTP flv HTTP f4v HTTP mp4 HTTP m3u8 HTTP webm HTTP ogg RTMP flv RTMP f4v RTMP ...
- 如何使用油猴脚本不要vip就能观看各大视频网站如腾讯,爱奇艺等的vip视频
如何使用油猴脚本不要vip就能观看各大视频网站如腾讯,爱奇艺等的vip视频 首先打开谷歌商店(这里需要fq,如不能fq的小伙伴请看上面写的Chrome怎么访问外网) 搜索Tampermonkey,点击 ...
- html5视频video积累
又是好几个月没有写东西,还是太懒散了~必须要教育下自己罗~ 这次做了个播放视频的移动H5,之前没有仔细玩过,好好记录下基本知识,还有遇到的一些坑,方便之后再次遇见后进行解决 一.基本 video标签在 ...
- popcorn-js视频Video框架简单用法
<div> <video class="video" id="ourvideobig" preload="auto" co ...
- IOS(苹果手机)使用video播放HLS流,实现在内部播放及全屏播放(即非全屏和全屏播放)。
需求: 实现PC及移动端播放HLS流,并且可以自动播放,在页面内部播放及全屏播放功能. 初步:PC及安卓机使用hls.js实现hls流自动播放及全屏非全屏播放 首先使用了hls.js插件,可以实现在P ...
随机推荐
- C#高级编程之泛型一(泛型的引入、泛型的使用、何为泛型)
为何引入泛型 当我们要对不同类型的参数执行类似的方法时:如下所示功能打印传入参数的相关信息. class CommonMethdod { /// <summary> /// show in ...
- xss攻击与防范
xss攻击方式以及防范 通常来说,网站一般都是有着,用户注册,用户登录,实名认证等等这些需要用户把信息录入数据库的接口 xss找的就是这种接口,他们可以在传递数据的时候,传递恶意的 script ...
- 学习django笔记一:在urls.py中导入sign应用views文件的问题
>python-admin startproject guest #创建guest项目 >python3 manage.py startapp sign #在guest项目中创建 ...
- centos8 yum 升级nginx
原文地址:https://blog.csdn.net/lpwmm/article/details/105627476 CentOS8的Yum仓库中内置的nginx版本是1.14.1,最近漏扫提示需要升 ...
- nginx负载均衡配置详解
已经了解了负载均衡的常用算法:轮询,加权轮询,热备等... 接下来就看看具体怎么配置. upstream配置是写一组被代理的服务器地址,然后配置负载均衡的算法. upstream mysvr{ ser ...
- C++基础知识篇:C++ 存储类
存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期.这些说明符放置在它们所修饰的类型之前.下面列出 C++ 程序中可用的存储类: auto register static extern m ...
- Python实现树莓派摄像头持续录像并传送到主机
关于树莓派,想必从事嵌入式开发的开发者都有听过,树莓派原名为Raspberry Pi,也就是它的英文读法,树莓派诞生于英国,由"Raspberry Pi 基金会"这个慈善组织注册开 ...
- 深度学习(一):Python神经网络——手写数字识别
声明:本文章为阅读书籍<Python神经网络编程>而来,代码与书中略有差异,书籍封面: 源码 若要本地运行,请更改源码中图片与数据集的位置,环境为 Python3.6x. 1 import ...
- UML第二次作业(代码互评)
博客班级 https://edu.cnblogs.com/campus/fzzcxy/2018SE2/ 作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018S ...
- JZOJ 2020.10.7 提高B组反思
JZOJ 2020.10.7 提高B组反思 T1 比较简单的一道题 跑\(k\)遍\(SPFA\) 然后全排列顺序枚举求解 TLE 60 双向存边数组没开两倍-- T2 搞出分母 分子不会求 \(n^ ...