😎 知识点概览
为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。
本章节为【学成在线】项目的 day13
的内容
-
FFmpeg
的基本使用 - 使用
m3u8
和video.js
技术实现视频的在线播放 - 搭建媒资服务工程实现文件的分块储存
目录
内容会比较多,小伙伴们可以根据目录进行按需查阅。
一、在线学习需求分析
0x01 需求描述
学成在线作为在线教育网站,提供多种学习形式,包括:录播、直播、图文、社群等,学生登录进入学习中心即可
在线学习,本章节将开发录播课程的在线学习功能,需求如下:
1、学生可以在 windows
浏览器上在线观看视频。
2、播放器具有快进、快退、暂停等基本功能。
3、学生可以方便切换章节进行学习。
什么是录播课程?
录播课程就是提供录制好课程视频,供用户在线点播,反复学习。
课程视频如何管理?
媒资管理系统专门来管理课程视频,用户视频文件上传到媒资系统,并对视频进行编码处理。
0x02 视频点播解决方案
流媒体方案
详细参考:https://baike.baidu.com/item/%E6%B5%81%E5%AA%92%E4%BD%93/98740?fr=aladdin
概括理解:流媒体就是将视频文件分成许多小块儿,将这些小块儿作为数据包通过网络发送出去,实现一边传输视
频 数据 包一边观看视频。
-
流式传输
在网络上传输音、视频信息有两个方式:下载 和 流式传输。
下载:就是把音、视频文件完全下载到本机后开始播放,它的特点是必须等到视频文件下载完成方可播放,播放等待时间较长,无法去播放还未下载的部分视频。
流式传输:就是客户端通过链接视频服务器实时传输音、视频信息,实现 “边下载边播放”。
流式传输包括如下两种方式:
-
1) 顺序流式传输
即顺序下载音、视频文件,可以实现边下载边播放,不过,用户只能观看已下载的视频内容,无法快进到未下载的视频部分,顺序流式传输可以使用
Http
服务器来实现,比如Nginx
、Apache
等。 -
2)实时流式传输
实时流式传输可以解决顺序流式传输无法快进的问题,它与Http流式传输不同,它必须使用流媒体服务器并且使用流媒体协议来传输视频,它比
Http
流式传输复杂。常见的实时流式传输协议有RTSP
、RTMP
、RSVP
等。
-
-
流媒体系统的概要结构
通过流媒体系统的概要结构,学习流媒体系统的基本业务流程。
1、将原始的视频文件通过编码器转换为适合网络传输的流格式,编码后的视频直接输送给媒体服务器。
原始的视频文件通常是事先录制好的视频,比如通过摄像机、摄像头等录像、录音设备采集到的音视频文
件,体积较大,要想在网络上传输需要经过压缩处理,即通过编码器进行编码 。
2、媒体服务获取到编码好的视频文件,对外提供流媒体数据传输接口,接口协议包括 :HTTP
、RTSP
、RTMP
等 。
3、播放器通过流媒体协议与媒体服务器通信,获取视频数据,播放视频。
点播方案
本项目包括点播和直播两种方式,我们先调研一下几个点播的方案,如下:
-
播放器通过
http
协议从http
服务器上下载视频文件进行播放问题:必须等到视频下载完才可以播放,不支持快进到某个时间点进行播放
-
播放器通过
rtmp
协议连接媒体服务器以实时流方式播放视频使用rtmp协议需要架设媒体服务器,造价高,对于直播多采用此方案。
-
播放器使用
HLS
协议连接http
服务器(Nginx
、Apache
等)实现近实时流方式播放视频HLS协议规定:基于
Http
协议,视频封装格式为ts
,视频的编码格式为H264
,音频编码格式为MP3
、AAC
或者AC-3
。
那么 HLS
是什么?
HLS
的工作方式是:将视频拆分成若干 ts
格式的小文件,通过 m3u8
格式的索引文件对这些 ts
小文件建立索引。一般 10
秒一个 ts
文件,播放器连接 m3u8
文件播放,当快进时通过 m3u8
即可找到对应的索引文件,并去下载对应的 ts
文件,从而实现快进、快退以近实时的方式播放视频。
IOS、Android 设备、及各大浏览器都支持 HLS
协议。
详细参考:https://baike.baidu.com/item/HLS/8328931?fr=aladdin
采用 HLS
方案即可实现边下载边播放,并可不用使用 rtmp
等流媒体协议,不用构建专用的媒体服务器,节省成本。所以本项目点播方案确定为方案 3
。
二、视频编码
0x01 视频编码格式
先来看一下百度百科中的简介
详情参考 :https://baike.baidu.com/item/%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81/839038
首先我们要分清文件格式和编码格式:
文件格式:是指 .mp4
、.avi
、.rmvb
等 这些不同扩展名的视频文件的文件格式 ,视频文件的内容主要包括视频和音频,其文件格式是按照一 定的编码格式去编码,并且按照该文件所规定的封装格式将视频、音频、字幕等信息封装在一起,播放器会根据它们的封装格式去提取出编码,然后由播放器解码,最终播放音视频。
音视频编码格式:通过音视频的压缩技术,将视频格式转换成另一种视频格式,通过视频编码实现流媒体的传输。
比如:一个 .avi
的视频文件原来的编码是 a
,通过编码后编码格式变为 b
,音频原来为 c
,通过编码后变为d
。
0x02 FFmpeg 的基本使用
我们将视频录制完成后,使用视频编码软件对视频进行编码,本项目 使用 FFmpeg
对视频进行编码。
FFmpeg
被许多开源项目采用,QQ影音、暴风影音、VLC 等。
下载:FFmpeg https://www.ffmpeg.org/download.html#build-windows
下载完成后,将 ffmpeg
解压到磁盘下,设置环境变量 FFMPEG_HOME
的值为 ffmpeg
的安装目录
将 %FFMPEG_HOME%/bin
添加到环境变量Path
中
0x03 生成 m3u8/ts 文件
使用 ffmpeg
生成 m3u8
的步骤如下:
第一步:先将 avi
视频转成 mp4
ffmpeg.exe -i lucene.avi -c:v libx264 -s 1280x720 -pix_fmt yuv420p -b:a 63k -b:v 753k -r 18 lucene.mp4
下面把各参数意思大概讲讲,大概了解意思即可,不再此展开流媒体专业知识的讲解。
-
-c:v
视频编码为x264
,x264
编码是H264
的一种开源编码格式。 -
-s
设置分辨率 -
-pix_fmt yuv420p
:设置像素采样方式,主流的采样方式有三种,YUV4:4:4
,YUV4:2:2
,YUV4:2:0
,它的作用是根据采样方式来从码流中还原每个像素点的YUV(亮度信息与色彩信息)值。 -
-b
设置码率,-b:a
和-b:v
分别表示音频的码率和视频的码率,-b
表示音频加视频的总码率。码率对一个视频质量有很大的作用,后边会介绍。 -
-r
:帧率,表示每秒更新图像画面的次数,通常大于24
肉眼就没有连贯与停顿的感觉了。
第二步:将 mp4
生成 m3u8
mkdir hls
ffmpeg -i lucene.mp4 -hls_time 10 -hls_list_size 0 -hls_segment_filename ./hls/lucene_%05d.ts ./hls/lucene.m3u8
-
-hls_time
设置每片的长度,单位为秒 -
-hls_list_size n
: 保存的分片的数量,设置为0
表示保存所有分片 -
-hls_segment_filename
:段文件的名称,%05d
表示5
位数字生成的效果是:将
lucene.mp4
视频文件每10
秒生成一个ts
文件,最后生成一个m3u8
文件,m3u8
文件是ts
的索引文件。
使用 VLC
打开 m3u8
文件,测试播放效果,VLC
是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD
、音频 CD
、VCD
及各类流媒体协议。(http://www.videolan.org/)
如果这里出现无法播放的情况,请将
FFmpeg
和VLC
播放器更新到最新版本。
码率的设置
码率又叫比特率即每秒传输的 bit
数,单位为 bps(Bit Per Second)
,码率越大传送数据的速度越快。
码率的计算公式是:文件大小(转成 bit)/ 时长(秒)/1024 = kbps
即每秒传输千位数
例如一个 1M
的视频,它的时长是 10s
,它的码率等于 1*1024*1024*8/10/1024 = 819Kbps
码率设置到多少才能达到最好,通过根据个人的经验或参考一些视频网台给出的参考,下图是优酷对码率的要求:
如果要将视频上传到优酷则必须按照上面的要求,如果是自己搭建视频服务器,码率设置不易过大,最终达到的视频清晰度满足业务需求即可。
三、播放器
0x01 技术选型
视频编码后要使用播放器对其进行解码、播放视频内容。在 web
应用中常用的播放器有 flash
播放器、H5
播放器或浏览器插件播放器,其中以 flash
和 H5
播放器最常见。
flash 播放器:缺点是需要在客户机安装 Adobe Flash Player
播放器,优点是 flash
播放器已经很成熟了,并且浏览器对 flash
支持也很好。
H5播放器:基于 h5
自带 video
标签进行构建,优点是大部分浏览器支持 H5
,不用再安装第三方的flash
播放器,并且随着前端技术的发展,h5
技术会越来越成熟。
本项目采用H5播放器,使用 Video.js
开源播放器。
Video.js
是一款基于 HTML5
世界的网络视频播放器。它支持 HTML5
和 Flash
视频,它支持在台式机和移动设备上播放视频。这个项目于 2010
年中开始,目前已在 40
万网站使用。
官方地址:http://videojs.com/
0x02 下载 video.js
Video.js: https://github.com/videojs/video.js
videojs-contrib-hls: https://github.com/videojs/videojs-contrib-hls#installation(videojs-contrib-hls是播放 hls
的一个插件)
使用文档:http://docs.videojs.com/tutorial-videojs_.html
本教程使用 video.js 6.7.3
版本,videojs-contrib-hls 5.14.1
版本。
下载上边两个文件,为了测试需求将其放在门户工程的 plugins
目录中。
0x03 搭建媒体播放器
正常使用 video.js
播放视频是通过一个网页,用户通过浏览器打开网页去播放视频,网页和视频都从web服务器请求,通常视频的 url
地址使用单独的域名。
配置 Nginx媒体服务器
HLS 协议基于 Http
协议,本项目使用 Nginx
作为视频服务器。下图是 Nginx
媒体服务器的配置流程图:
1、用户打开www.xuecheng.com上边的 video.html
网页 ,在此网页中引入视频链接,视频地址指向video.xuecheng.com
2、video.xuecheng.com 进行负载均衡处理,将视频请求转发到媒体服务器
根据上边的流程,我们在媒体服务器上安装 Nginx
,并配置如下:
#学成网媒体服务
server {
listen 90;
server_name localhost;
#视频目录
location /video/ {
alias F:/develop/video/;
}
}
配置媒体服务器代理
媒体服务器不止一台,通过代理实现负载均衡功能,使用 Nginx
作为媒体服务器的代理,此代理服务器作为 video.xuecheng.com
域名服务器。
配置 video.xuecheng.com
虚拟主机:
注意:这里我们开发环境中代理服务器和媒体服务器在同一台服务器,使用同一个Nginx
。
#学成网媒体服务代理
map $http_origin $origin_list{
default http://www.xuecheng.com;
"~http://www.xuecheng.com" http://www.xuecheng.com;
"~http://ucenter.xuecheng.com" http://ucenter.xuecheng.com;
}
#学成网媒体服务代理
server {
listen 80;
server_name video.xuecheng.com;
location /video {
proxy_pass http://video_server_pool;
add_header Access-Control-Allow-Origin $origin_list;
#add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET;
}
}
cors跨域参数:
-
Access-Control-Allow-Origin:允许跨域访问的外域地址
-
Access-Control-Allow-Credentials: 允许客户端携带证书访问
-
Access-Control-Allow-Methods:允许客户端跨域访问的方法
通常允许跨域访问的站点不是一个,所以这里用 map
定义了多个站点。
如果允许任何站点跨域访问则设置为 *,通常这是不建议的。
video_server_pool
的配置如下:
#媒体服务
upstream video_server_pool{
server 127.0.0.1:90 weight=10;
}
配置 hosts
文件,本教程开发环境使用 Windows10
,修改 hosts
文件,路径为 C:\Windows\System32\drivers\etc\hosts
127.0.0.1 video.xuecheng.com
0x04 测试 video.js
参考文档如下:
https://github.com/videojs/videojs-contrib-hls#installation
http://jsbin.com/vokipos/8/edit?html,output
1、编写测试页面 video.html
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>视频播放</title>
<link href="/plugins/videojs/video-js.css" rel="stylesheet">
</head>
<body>
<video id=example-video width=800 height=600 class="video-js vjs-default-skin vjs-big-play-
centered" controls poster="http://127.0.0.1:90/video/add.jpg">
<source
src="http://video.xuecheng.com/video/hls/lucene.m3u8"
type="application/x-mpegURL">
</video>
<input type="button" onClick="switchvideo()" value="switch"/>
<script src="/plugins/videojs/video.js"></script>
<script src="/plugins/videojs/videojs-contrib-hls.js"></script>
<script>
var player = videojs('example-video');
//player.play();
//切换视频
function switchvideo(){
player.src({
src: 'http://video.xuecheng.com/video/hls/lucene.m3u8',
type: 'application/x-mpegURL',
withCredentials: true
});
player.play();
}
</script>
</body>
</html>
2、测试
点击 switch
测试切换视频功能。
四、搭建学习中心前端
0x01 界面原型
先看一下界面原型,如下图,最终的目标是在此页面使用 video.js
播放视频。
0x02 创建学习中心工程
学习中心的用户是学生,为了便于系统维护和扩展,单独创建学习中心工程:
1、从资料目录拷贝 xc-ui-pc-leanring.zip
并解压到 xc-ui-pc-leanring
目录。
2、使用 webstorm
创建打开 xc-ui-pc-leanring
目录
3、进入 xc-ui-pc-leanring
目录,执行 cnpm install
,将根据 package.json
的依赖配置远程下载依赖的 js
包。
创建完成,xc-ui-pc-leanring
工程如下:
配置域名
学习中心的二级域名为 ucenter.xuecheng.com
,我们在 nginx
中配置 ucenter
虚拟主机。
#学成网用户中心
server {
listen 80;
server_name ucenter.xuecheng.com;
#个人中心
location / {
proxy_pass http://ucenter_server_pool;
}
}
#前端ucenter
upstream ucenter_server_pool{
#server 127.0.0.1:7081 weight=10;
server 127.0.0.1:13000 weight=10;
}
在根服务下添加一个 /plugins/
站点
# 根服务
server{
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
location /plugins/ {
# 跨域参数
alias E:/Project/XueChengOnline/xcEduUI01/xc-ui-pc-static-portal/plugins/;
add_header Access-Control-Allow-Origin http://ucenter.xuecheng.com;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods GET;
}
.....
}
访问测试
启动工程,看到下边的界面说明本工程创建完成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AtcW0UdA-1595567116697)(https://qnoss.codeyee.com/20200704_13/image16)]
0x03 调试视频播放页面
使用 vue-video-player
组件将 video.js
集成到 vue.js
中,本项目使用 vue-video-player
实现video.js
播放。
组件地址:https://github.com/surmon-china/vue-video-player
上面的 xc-ui-pc-learning
工程已经添加 vue-video-player
组件,我们在 vue
页面直接使用即可。
前边我们已经测试通过 video.js
,下面我们直接在 vue
页面中使用 vue-video-player
完成视频播放。
导入 learning_video.vue
页面到 course
模块下。
配置路由
import learning_video from '@/module/course/page/learning_video.vue';
{
path: '/learning/:courseId/:chapter',
component: learning_video,
name: '录播视频学习',
hidden: false,
iconCls: 'el‐icon‐document'
}
预览效果
请求:http://ucenter.xuecheng.com/#/learning/1/2
第一个参数:courseId
,课程id,这里是测试页面效果随便输入一个 ID
即可,这里输入1
第二个参数:chapter
,课程计划id,这里是测试页面效果随便输入一个 ID
即可,这里输入2
五、媒资管理
前边章节完成在线视频播放,如何实现点击课程计划播放视频呢,课程视频如何管理呢?
本节开始将对课程视频进行管理。
0x01 需求分析
媒资管理系统是每个在线教育平台所必须具备的,百度百科对它的定义如下:
每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。
目前媒资管理的主要管理对象是课程录播视频,包括:媒资文件的查询、视频上传、视频删除、视频处理等。
-
媒资查询:教学机构查询自己所拥有的媒体文件。
-
视频上传:将用户线下录制的教学视频上传到媒资系统。
-
视频处理:视频上传成功,系统自动对视频进行编码处理。
-
视频删除 :如果该视频已不再使用,可以从媒资系统删除。
下边是媒资系统与其它系统的交互情况:
1、上传媒资文件
前端/客户端请求媒资系统上传文件。
文件上传成功将文件存储到媒资服务器,将文件信息存储到数据库。
2、使用媒资
课程管理请求媒资系统查询媒资信息,将课程计划与媒资信息对应、存储。
3、视频播放
用户进入学习中心请求学习服务学习在线播放视频。
学习服务校验用户资格通过后请求媒资系统获取视频地址。
0x02 开发环境搭建
创建媒资数据库
1、媒资文件信息
package com.xuecheng.framework.domain.media;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;
@Data
@ToString
@Document(collection = "media_file")
public class MediaFile {
/*
文件id、名称、大小、文件类型、文件状态(未上传、上传完成、上传失败)、上传时间、视频处理方式、视频处理状态、hls_m3u8,hls_ts_list、课程视频信息(课程id、章节id)
*/
@Id
//文件id
private String fileId;
//文件名称
private String fileName;
//文件原始名称
private String fileOriginalName;
//文件路径
private String filePath;
//文件url
private String fileUrl;
//文件类型
private String fileType;
//mimetype
private String mimeType;
//文件大小
private Long fileSize;
//文件状态
private String fileStatus;
//上传时间
private Date uploadTime;
//处理状态
private String processStatus;
//hls处理
private MediaFileProcess_m3u8 mediaFileProcess_m3u8;
//tag标签用于查询
private String tag;
}
2、创建 xc_media
数据库
媒资系统使用 mongodb
数据库存储媒资信息,再创建集合 media_file
创建媒资服务工程
媒资管理的相关功能单独在媒资服务中开发,下边创建媒资服务工程(xc-service-manage-media
)。
媒资服务的配置与 cms
类似,导入 资料/xc-service-manage-media
工程,工程结构如下:
0x03 上传文件
断点续传解决方案
通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件
的上传要求。http
协议本身对上传文件大小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了,电断了没有上传完成,需要客户重新上传,这是致命的,所以对于大文件上传的要求最基本的是断点续传。
什么是断点续传?
引用百度百科:断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载,断点续传可以提高节省操作时间,提高用户体验性。
如下图:
上传流程如下:
1、上传前先把文件分成块
2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传
3、各分块上传完成最后合并文件
文件下载则同理。
文件分块与合并
为了更好的理解文件分块上传的原理,下边用java代码测试文件的分块与合并。
1、分块
文件分块的流程如下:
1、获取源文件长度
2、根据设定的分块文件的大小计算出块数
3、从源文件读数据,再依次向每一个块文件写入数据。
单元测试代码如下
/**
* 测试文件分块
*/
@Test
public void testChunk() throws IOException