直播原理就是一个推流和拉取流的过程;
直播端将直播流推送至服务器,用户端发起请求从服务器拉取直播流然后解码播放
第一部分就是视频直播端的操作:视频采集处理后推流到流媒体服务器。
第二部分就是流媒体服务器:负责把从第一部分接收到的流进行处理并分发给用户。
流媒体服务器的主要功能是对流媒体内容进行采集(接收推流)、缓存、调度和传输播放(以流式协议实现用户分发)。
第三部分就是用户端:只需要拥有支持对应流媒体传输协议的播放器即可。
这一部分其实就是我们前端需要实现的,如何在移动端的内嵌h5页面中实现直播流的播放。所以我们只需要关注后端是通过什么协议给我们返回直播流以及我们如何有效的播放就可以了~
协议比较全能,既可以用来推送,又可以用来直播。其核心理念是将大块的视频帧和音频帧“剁碎”,然后以小数据包的形式在互联网上进行传输,且支持加密,因此隐私性相对比较理想,但拆包组包的过程比较复杂,所以在海量并发时容易出现一些不可预期的稳定性问题。
苹果推出的解决方案,将视频分成 5-10 秒的视频小分片,然后用 M3U8 索引表进行管理。由于客户端下载到的视频都是 5-10 秒的完整数据,故视频的流畅性很好,但也同样引入了很大的延迟(HLS 的一般延迟在 10-30s 左右)。相比于 FLV,HLS 在iPhone 和大部分 Android 手机浏览器上的支持非常给力,所以常用于 QQ 和微信朋友圈的 URL 分享。
由 Adobe 公司主推,格式极其简单,只是在大块的视频帧和音视频头部加入一些标记头信息,由于这种极致的简洁,在延迟表现和大规模并发方面都很成熟。唯一的不足就是在手机浏览器上的支持非常有限,但是用作手机端 APP 直播协议却异常合适。
RTMP、HLS、HTTP-FLV 协议对比如下图所示:
1、技术选型:
2、vue-video-player安装与引入:
<link rel="stylesheet" href="path/to/video.js/dist/video-js.css"/><script type="text/javascript" src="path/to/video.min.js"></script><script type="text/javascript" src="path/to/vue.min.js"></script><script type="text/javascript" src="path/to/dist/vue-video-player.js"></script><script type="text/javascript"> Vue.use(window.VueVideoPlayer)</script>
全局引入
import Vue from 'vue'import VueVideoPlayer from 'vue-video-player'// 引入videojs样式import 'video.js/dist/video-js.css'// 自定义样式引入,并为<video-player>添加对应类名即可,例如vjs-custom-skin// import 'vue-video-player/src/custom-theme.css'Vue.use(VueVideoPlayer, /* { options: 全局默认配置, events: 全局videojs事件} */)
按需引入
// 引入videojs样式import 'video.js/dist/video-js.css'import { videoPlayer } from 'vue-video-player'export default { components: { videoPlayer }}
3、video.js插件扩展: 当已有插件无法满足需求时可对已有插件进行扩展或自行开发video.js插件
import videojs from 'video.js'// videojs pluginconst Plugin = videojs.getPlugin('plugin')class ExamplePlugin extends Plugin { // something...}videojs.registerPlugin('examplePlugin', ExamplePlugin)// videojs languagevideojs.addLanguage('es', { Pause: 'Pausa', // something...})// more videojs api...// vue component...
4、视频直播关键代码:
options:video.js options
playsinline:设置播放器在移动设备上不全屏[ Boolean, default: false ]
customEventName:自定义状态变更时的事件名[ String, default: 'statechanged' ]
<template> <video-player class="video-player-box" ref="videoPlayer" :options="playerOptions" :playsinline="true" customEventName="customstatechangedeventname" @play="onPlayerPlay($event)" @pause="onPlayerPause($event)" @ended="onPlayerEnded($event)" @waiting="onPlayerWaiting($event)" @playing="onPlayerPlaying($event)" @loadeddata="onPlayerLoadeddata($event)" @timeupdate="onPlayerTimeupdate($event)" @canplay="onPlayerCanplay($event)" @canplaythrough="onPlayerCanplaythrough($event)" @statechanged="playerStateChanged($event)" @ready="playerReadied"> </video-player></template>
export default { data() { return { playerOptions: { // 是否关闭音频 muted: true, // 初始语言,默认为英语,code参见:https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry language: 'zh-CN', // 播放速度,指定后Video.js将显示一个控件(vjs-playback-rate类的控件),允许用户从选项数组中选择播放速度 playbackRates: [0.5, 1.0, 1.5, 2.0], // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值,表示长宽比例 aspectRatio: '4:3', // 等同于原生<video>标签中的一组<source>子标签,可实现优雅降级;type 属性规定媒体资源的 MIME 类型,标准类型可参见:https://www.iana.org/assignments/media-types/media-types.xhtml; sources: [{ type: "rtmp/flv", src: "rtmp://58.200.131.2:1935/livetv/hunantv" }, { type: "application/x-mpegURL", src: "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8" }], // 兼容顺序,默认值是['html5'],这意味着html5技术是首选,其他已注册的技术将按其注册的顺序在该技术之后添加。 techOrder: ['flash'], // 在视频开始播放之前显示的图像的URL(封面),这通常是一个视频帧或自定义标题屏幕,一旦用户点击“播放”,图像就会消失。 poster: require('../assets/test.jpg'), } } }, mounted() { console.log('this is current player instance object', this.player) }, computed: { player() { return this.$refs.videoPlayer.player } }, methods: { // 各个事件监听 onPlayerPlay(player) { // console.log('播放器播放!', player) }, onPlayerPause(player) { // console.log('播放器暂停!', player) }, // ...(此处省略多个事件监听函数) // 状态监听 playerStateChanged(playerCurrentState) { // console.log('播放器当前状态更新', playerCurrentState) }, // 监听播放器是否就绪 playerReadied(player) { console.log('播放器已就绪', player) // 就绪后就可以调用播放器的一些方法 } } }
踩坑小tips:
播放 HLS 协议流,需要videojs-contrib-hls插件,但是直接引用即可,因为在安装vue-video-player插件时,videojs-contrib-hls是一并安装的;如果需要播放RTMP协议流,需要videojs-flash插件,也是直接引用就可以了(flash插件需要在hls之前引用)
import 'videojs-flash'import 'videojs-contrib-hls'