前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案。
发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端目前以 HLS 为主(HLS存在延迟性问题,也可以借助 video.js 采用RTMP),PC端则以 RTMP 为主实时性较好,接下来将围绕这两种视频流协议来展开H5直播主题分享。
1. HTTP Live Streaming
HTTP Live Streaming(简称 HLS)是一个基于 HTTP 的视频流协议,由 Apple 公司实现,Mac OS 上的 QuickTime、Safari 以及 iOS 上的 Safari 都能很好的支持 HLS,高版本 Android 也增加了对 HLS 的支持。一些常见的客户端如:MPlayerX、VLC 也都支持 HLS 协议。
HLS 协议基于 HTTP,而一个提供 HLS 的服务器需要做两件事:
编码:以 H.263 格式对图像进行编码,以 MP3 或者 HE-AAC 对声音进行编码,最终打包到 MPEG-2 TS(Transport Stream)容器之中;分割:把编码好的 TS 文件等长切分成后缀为 ts 的小文件,并生成一个 .m3u8 的纯文本索引文件;浏览器使用的是 m3u8 文件。m3u8 跟音频列表格式 m3u 很像,可以简单的认为 m3u8 就是包含多个 ts 文件的播放列表。播放器按顺序逐个播放,全部放完再请求一下 m3u8 文件,获得包含最新 ts 文件的播放列表继续播,周而复始。整个直播过程就是依靠一个不断更新的 m3u8 和一堆小的 ts 文件组成,m3u8 必须动态更新,ts 可以走 CDN。一个典型的 m3u8 文件格式如下:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=200000
gear1/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=311111
gear2/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=484444
gear3/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=737777
gear4/prog_index.m3u8
可以看到 HLS 协议本质还是一个个的 HTTP 请求 / 响应,所以适应性很好,不会受到防火墙影响。但它也有一个致命的弱点:延迟现象非常明显。如果每个 ts 按照 5 秒来切分,一个 m3u8 放 6 个 ts 索引,那么至少就会带来 30 秒的延迟。如果减少每个 ts 的长度,减少 m3u8 中的索引数,延时确实会减少,但会带来更频繁的缓冲,对服务端的请求压力也会成倍增加。所以只能根据实际情况找到一个折中的点。
对于支持 HLS 的浏览器来说,直接这样写就能播放了:
<video src=”./bipbopall.m3u8″ height=”300″ width=”400″ preload=”auto” autoplay=”autoplay” loop=”loop” webkit-playsinline=”true”></video>
注意:HLS 在 PC 端仅支持safari浏览器,类似chrome浏览器使用HTML5 video
标签无法播放 m3u8 格式,可直接采用网上一些比较成熟的方案,如:sewise-player、MediaElement、videojs-contrib-hls、jwplayer。
程序猿的生活:web前端全栈资料粉丝福利(面试题、视频、资料笔记,进阶路线)zhuanlan.zhihu.com/p/136454207
2. Real Time Messaging Protocol
Real Time Messaging Protocol(简称 RTMP)是 Macromedia 开发的一套视频直播协议,现在属于 Adobe。这套方案需要搭建专门的 RTMP 流媒体服务如 Adobe Media Server,并且在浏览器中只能使用 Flash 实现播放器。它的实时性非常好,延迟很小,但无法支持移动端 WEB 播放是它的硬伤。
虽然无法在iOS的H5页面播放,但是对于iOS原生应用是可以自己写解码去解析的, RTMP 延迟低、实时性较好。浏览器端,HTML5 video
标签无法播放 RTMP 协议的视频,可以通过 video.js 来实现。
<link href=“http://vjs.zencdn.net/5.8.8/video-js.css” rel=“stylesheet”>
<video id=“example_video_1″ class=“video-js vjs-default-skin” controls preload=“auto” width=“640” height=“264” loop=“loop” webkit-playsinline>
<source src=“rtmp://10.14.221.17:1935/rtmplive/home” type=‘rtmp/flv’>
</video>
<script src=“http://vjs.zencdn.net/5.8.8/video.js”></script>
<script>
videojs.options.flash.swf = ‘video.swf’;
videojs(‘example_video_1′).ready(function() {
this.play();
});
</script>
3. 视频流协议HLS与RTMP对比
目前直播展示形式,通常以YY直播、映客直播这种页面居多,可以看到其结构可以分成三层:
① 背景视频层
② 关注、评论模块
③ 点赞动画
而现行H5类似直播页面,实现技术难点不大,其可以通过实现方式分为:
① 底部视频背景使用video视频标签实现播放
② 关注、评论模块利用 WebScoket 来实时发送和接收新的消息通过DOM 和 CSS3 实现
③ 点赞利用 CSS3 动画
了解完直播形式之后,接下来整体了解直播流程。
相关学习资料推荐,点击下方链接免费报名,先码住不迷路~】
音视频免费学习地址:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~
直播整体流程大致可分为:
视频采集端:可以是电脑上的音视频输入设备、或手机端的摄像头、或麦克风,目前以移动端手机视频为主。
直播流视频服务端:一台Nginx服务器,采集视频录制端传输的视频流(H264/ACC编码),由服务器端进行解析编码,推送RTMP/HLS格式视频流至视频播放端。
视频播放端:可以是电脑上的播放器(QuickTime Player、VLC),手机端的native播放器,还有就是 H5 的video标签等,目前还是以手机端的native播放器为主。
(web前端学习交流群:328058344 禁止闲聊,非喜勿进!)
对于H5视频录制,可以使用强大的 webRTC (Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的技术,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。
使用 webRTC 录制视频基本流程
① 调用 window.navigator.webkitGetUserMedia()
获取用户的PC摄像头视频数据。
② 将获取到视频流数据转换成 window.webkitRTCPeerConnection
(一种视频流数据格式)。
③ 利用 WebScoket
将视频流数据传输到服务端。
注意:
虽然Google一直在推WebRTC,目前已有不少成型的产品出现,但是大部分移动端的浏览器还不支持 webRTC(最新iOS 10.0也不支持),所以真正的视频录制还是要靠客户端(iOS,Android)来实现,效果会好一些。
WebRTC支持度
WebRTC支持度
iOS原生应用调用摄像头录制视频流程
① 音视频的采集,利用AVCaptureSession和AVCaptureDevice可以采集到原始的音视频数据流。
② 对视频进行H264编码,对音频进行AAC编码,在iOS中分别有已经封装好的编码库(x264编码、faac编码、ffmpeg编码)来实现对音视频的编码。
③ 对编码后的音、视频数据进行组装封包。
④ 建立RTMP连接并上推到服务端。
安装nginx、nginx-rtmp-module
① 先clone nginx项目到本地:
brew tap homebrew/nginx
② 执行安装nginx-rtmp-module
brew install nginx-full –with-rtmp-module
2. nginx.conf配置文件,配置RTMP、HLS
查找到nginx.conf配置文件(路径/usr/local/etc/nginx/nginx.conf),配置RTMP、HLS。
① 在http节点之前添加 rtmp 的配置内容:
② 在http中添加 hls 的配置
3. 重启nginx服务
重启nginx服务,浏览器中输入 http://localhost:8080,是否出现欢迎界面确定nginx重启成功。
nginx -s reload
当服务器端接收到采集视频录制端传输过来的视频流时,需要对其进行解析编码,推送RTMP/HLS格式视频流至视频播放端。通常使用的常见编码库方案,如x264编码、faac编码、ffmpeg编码等。鉴于 FFmpeg 工具集合了多种音频、视频格式编码,我们可以优先选用FFmpeg进行转换格式、编码推流。
1.安装 FFmpeg 工具
brew install ffmpeg
2.推流MP4文件
视频文件地址:/Users/gao/Desktop/video/test.mp4
推流拉流地址:rtmp://localhost:1935/rtmplive/home,rtmp://localhost:1935/rtmplive/home
//RTMP 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -acodec aac -f flv rtmp://10.14.221.17:1935/rtmplive/home
//HLS 协议流
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://10.14.221.17:1935/hls/test
注意:
当我们进行推流之后,可以安装VLC、ffplay(支持rtmp协议的视频播放器)本地拉流进行演示
3.FFmpeg推流命令
① 视频文件进行直播
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://192.168.1.101:1935/hls/test
ffmpeg -re -i /Users/gao/Desktop/video/test.mp4 -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -q 10 rtmp://10.14.221.17:1935/hls/test
② 推流摄像头+桌面+麦克风录制进行直播
ffmpeg -f avfoundation -framerate 30 -i “1:0″ \-f avfoundation -framerate 30 -video_size 640x480 -i “0” \-c:v libx264 -preset ultrafast \-filter_complex ‘overlay=main_w-overlay_w-10:main_h-overlay_h-10′ -acodec libmp3lame -ar 44100 -ac 1 -f flv rtmp://192.168.1.101:1935/hls/test
更多命令,请参考:
FFmpeg处理RTMP流媒体的命令大全
FFmpeg常用推流命令
移动端iOS和 Android 都天然支持HLS协议,做好视频采集端、视频流推流服务之后,便可以直接在H5页面配置 video 标签播放直播视频。
<video controls preload=“auto” autoplay=“autoplay” loop=“loop” webkit-playsinline>
<source src=“http://10.14.221.8/hls/test.m3u8″ type=“application/vnd.apple.mpegurl” />
<p class=“warning”>Your browser does not support HTML5 video.</p>
</video>
本文从视频采集上传,服务器处理视频推流,以及H5页面播放直播视频一整套流程,具体阐述了直播实现原理,实现过程中会遇到很多性能优化问题。
① H5 HLS 限制必须是H264+AAC编码。
② H5 HLS 播放卡顿问题,server 端可以做好分片策略,将 ts 文件放在 CDN 上,前端可尽量做到 DNS 缓存等。
③ H5 直播为了达到更好的实时互动,也可以采用RTMP协议,通过video.js 实现播放。
原文 https://zhuanlan.zhihu.com/p/146323842
<!DOCTYPE html>
<html>
<head>
<title>hello</title>
</head>
<body bgcolor="grey">
<p>HELLO,everyone.This is my first page!</p>
</body>
</html>
我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取。
第2章 文章段落
2.1 文档声明和META标签
<html>,<body>,<head>标签是html文档结构标签,<!DOCTYPE HTML>不属于html标签,它用于定义文档类型
网页中不能正常显示中文,出现乱码现象,使用meta标签设置编码格式:<meta charset="utf-8">
<!DOCTYPE html>
<html>
<head>
<title>第一个网页</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
大家好,一起来学习html标记语言
</body>
</html>
3.如果想在html页面中显示空格,使用
4.
标题标签:<h1></h1>~<h6></h6>
段落标签:<p></p>
align对齐属性值:
left:左对齐内容
right:右对齐内容
center:居中对齐内容
justify:对行进行延申,这样每行都可以有相等的长度
换行标签<br/>
5.一个<p></p>标签代表一个段落,两个<p>标签中的文本内容不在同一行,在<p>标签中,使用<br/>文本内容的位置只是换行,其实还是一个段落
6.<pre></pre>标签用于预定义格式显示文本,即文本在浏览器中显示时遵循在HTML原文档中定义的格式
<!DOCTYPE html>
<html>
<head>
<title>练习1</title>
<meta http-equiv="Content-Type" content="text/http;charset=utf-8"/>
</head>
<body>
<h3 align="center">《早发白帝城》</h3>
<p align="center">朝辞白帝彩云间,千里江陵一日还。</p>
<p align="center">两岸猿声啼不住,轻舟已过万重山。</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>练习2</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<h1>敕勒歌</h1>
<h2>朝代:南北朝</h2>
<h3>作者:佚名</h3>
<p> 敕勒川,<br/>
阴山下,<br/>
天似穹庐,<br/>
</p>
<pre>
笼盖四野,
天苍苍,
野茫茫,
风吹草低见牛羊。
</pre>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>任务</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<p align="center">关于我们 | 招聘信息 | 联系我们 | 意见反馈</p>
<hr/>
<p align="center">Copyright © 2016 imooc.com All Rights Reserved</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>任务</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<p>公式:x<sup>2</sup>+x=0 解:x<sub>1</sub>=0;x<sub>2</sub>=-1</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>3</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<ul type="disc">
<li>朝辞白帝彩云间,</li>
<li>千里江陵一日还,</li>
<li>两岸猿声啼不住,</li>
<li>轻舟已过万重山,</li>
</ul>
<ul type="square">
<li>朝辞白帝彩云间,</li>
<li>千里江陵一日还,</li>
<li>两岸猿声啼不住,</li>
<li>轻舟已过万重山,</li>
</ul>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>3</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<ol type="a">
<li>朝辞白帝彩云间,</li>
<li>千里江陵一日还,</li>
<li>两岸猿声啼不住,</li>
<li>轻舟已过万重山,</li>
</ol>
<ol type="i">
<li>朝辞白帝彩云间,</li>
<li>千里江陵一日还,</li>
<li>两岸猿声啼不住,</li>
<li>轻舟已过万重山,</li>
</ol>
</body>
</html>
<dt><dd>是同级标签
绝对路径:
相对路径:
效果图
<!DOCTYPE html>
<html>
<head>
<title>3</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<p>一幅图像:<img src="http://climg.mukewang.com/58c112ed0001370f03000300.jpg" width="30%"></p>
<p>一幅动画图像:<img src="http://climg.mukewang.com/58c11324000144f703550220.jpg" height="50px" width="50px"></p>
</body>
</html>
超链接标签
空链接:<a href="#"> </a>
任务:
<!DOCTYPE html>
<html>
<head>
<title>3</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<p><a name="dingbu">这里是顶部</p>
<p><a href="#shuiguo">水果</p>
<p><a href="#shucai">蔬菜</p>
<p><a href="#yundong">运动</a></p>
<h3><a name="shuiguo">水果</a></h3>
<ul>
<li>香蕉</li>
<li>苹果</li>
<li>葡萄</li>
<li>梨</li>
<li>西瓜</li>
<li>樱桃</li>
<li>菠萝</li>
<li>橙子</li>
<li>柚子</li>
<li>芒果</li>
</ul>
<p><a href="#dingbu">返回顶部</a></p>
<h3><a name="shucai">蔬菜</a></h3>
<ul>
<li>西红柿</li>
<li>黄瓜</li>
<li>土豆</li>
<li>芹菜</li>
<li>蒜苔</li>
<li>西葫芦</li>
<li>香菇</li>
<li>菠菜</li>
<li>豆角</li>
<li>油菜</li>
</ul>
<a name="yundong"></a>
<p><a href="#dingbu">返回顶部</a></p>
</body>
</html>
1. 电子邮件链接
2.文件下载
<!DOCTYPE html>
<html>
<head>
<title>3</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<a href="mailto:2539391306@qq.com.cn">邮箱链接</a>
<a href="58ca5b6700018dfc02400135.zip">文件下载</a>
</body>
</html>
原文链接:https://blog.csdn.net/qq_43405634/article/details/103789819
用 CSS 最困难的部分之一是处理CSS的权重值,它可以决定到底哪条规则会最终被应用,尤其是如果你想在 Bootstrap 这样的框架中覆盖其已有样式,更加显得麻烦。不过随着 CSS 层的引入,这一切都发生了变化。 这个新功能允许您创建自己的自定义 CSS 层,这是有史以来第一次确定所有 CSS 代码权重的层次结构。 在本文中,我将剖析这对您意味着什么,它是如何工作的,以及您今天如何开始使用它。
什么是层(Layers)
创建您自己的自定义图层是 CSS 的新功能,但图层从一开始就存在于 CSS 中。 CSS 中有 3 个不同的层来管理所有样式的工作方式。
浏览器(也称为用户代理)样式 - user agent style
用户样式 - User Styles
作者样式 - Author Styles
浏览器样式是应用于浏览器的默认样式。这就是为什么 Chrome 和 Safari 中的按钮看起来不同的原因。在浏览器层中找到的样式在浏览器之间是不同的,并且给每个浏览器一个独特的外观。
下一层是用户样式,这并不是您真正需要担心的事情。这些通常是用户可以编写并注入浏览器的自定义样式,但浏览器不再真正支持这些样式。用户可能会更改一些浏览器设置,这些设置会向该图层添加样式,但在大多数情况下,可以完全忽略该层。
最后,我们来到作者层。这是您最熟悉的层,因为您编写的每一段 CSS 代码都属于这一层。
这些层分开的原因是因为它可以很容易地覆盖浏览器样式和用户样式中定义的代码,因为层定义了自己的层次结构,完全忽略了权重的影响。
这 3 个 CSS 层是有序的(浏览器样式、用户样式、然后是作者样式),后面层中的每个样式都将覆盖前一层的任何样式。这意味着即使浏览器样式定义了一个超级特定的选择器,例如#button.btn.super-specific,并且您的作者样式定义了一个超级通用的选择器,例如按钮,您的作者样式仍然会覆盖浏览器样式。
这实际上已经是您可能一直在使用而没有意识到的东西。
* {
box-sizing: border-box;
}
上面的选择器没有权重,因为 * 符号对权重没有贡献。 这意味着例如使用 p 作为选择器的 p 标签的浏览器样式在技术上比 * 选择器更具体,权重更高。 但是,这一切并不重要,因为作者样式位于比浏览器样式层晚的层中,因此您的代码将始终覆盖浏览器样式。
理解这一点至关重要,因为使用这个新的图层 API,您可以在作者图层中创建自己的图层,从而更轻松地处理特定性。
如何创建你自己的层
下面来看个例子:
很明显,这是我们正常理解的CSS, ID设置的颜色权重更高,所以按钮显示为红色。让我们使用@layer给它们加上两个层,看看是什么效果:
按钮变成蓝色。为什么会这样?
我们给两条CSS分别建立了base和utilities层,很明显,后面创建的层的样式覆盖了前面层的样式,尽管前面层的样式有更高的权重。这就是层的默认工作原理。当然层的顺序是可以指定的,
@layer utilities, base;
@layer utilities, base;
您需要做的就是编写@layer 关键字,后跟以逗号分隔的层列表。 这将按从左到右的顺序定义所有层,其中列出的第一层到最后一层的权重是依次增加的。 然后,您可以稍后使用普通的@layer 语法向每个层添加代码,而不必担心定义层的顺序,因为它们都在这一行中定义。 需要注意的是,这行代码必须在定义任何层之前出现,所以我通常将它作为我的 CSS 文件中的第一行。如上图,通过指定层的顺序,我们让base层应用在utilities层之后,所以按钮又显示为红色。
导入层
上面这两种方式都是导入bootstrap框架的CSS,并且把他们放在framework层中,这样你如果想要覆盖它已有的样式,只需要新建一个自己的层,放置在framework层后面就行。像下面这样。
匿名层
匿名层不常用,但它写在后面可以覆盖其他层的样式,像下面可以把按钮设为橙色。
不在层里的样式
不在层里的样式会有更高的权重,下面这个列表会让你看得更清楚覆盖是怎么发生的
层还可以重叠设置,不过很少用。具体的用法可以查阅相关文档。
浏览器支持
自从IE死了以后,所有主流浏览器都已支持这一特性。大家请放心使用。
*请认真填写需求信息,我们会在24小时内与您取得联系。