SkeyeWebPlayer.js H5播放器是由成都视开信息科技开发和维护的一个完善的RTSP、FLV、HLS等多种流媒体协议播放,视频编码支持H.264,H.265,音频支持AAC,支持TCP/UDP协议,是一套极佳的且适合用于综合安防视频云服务播放组件,已经非常稳定、完整。功能包括:直播、录像、抓图,目前在功能性、稳定性、可扩展性和完整性极强的一款H5播放器!
上一节加到编译flvjs播放器,实现基础的播放器功能,本节将实现自定义动态创建video标签渲染。如下图:
首先为了方便开发,需要将项目的目录结构做以下调整
-
新建flv目录,将之前的flvjs代码放到这个目录内,
-
新建一个element 目录下新建index.js,具体代码:放在下面,
-
首先创建一个 class 类,Element 接受self:(调用this),dom:(播放器容器:由初始化传入ID去获取:document.getElementById(ID))options:{height},当然如果有需要其他参数也可以传入,根据自己的需求来即可,
-
首先判断有没dom (播放器容器)
-
height:是否继承外部容器的高度 Boolean值 ,false:动态设置播放器容器 56.25% 也就是默认值 16:9,
-
createElement js动态创建video标签,设置宽高为容器的宽高
export default class Element {constructor(self, dom, {height}) {if (!dom) {return '';}if (height) {dom.style.position = 'relative';dom.style.backgroundColor = '#000000';dom.style.overflow = 'hidden';} else {dom.style.position = 'relative';dom.style.backgroundColor = '#000000';dom.style.width = '100%';dom.style.height = '100%';dom.style.paddingTop = '56.25%';dom.style.overflow = 'hidden';}this.elDom = dom;this.videoEl = document.createElement('video');this.videoEl.style.width = '100%';this.videoEl.style.height = '100%';this.videoEl.style.position = 'absolute';this.videoEl.style.top = '0';this.videoEl.style.left = '0';this.videoEl.style.background = '#000000';this.videoEl.style.background = '#000000';this.elDom.appendChild(this.videoEl);// this.videoEl.setAttribute('webkit-playsinline', 'true');// this.videoEl.setAttribute('playsinline', 'true');}}
在播放器初始化的时候将创建出来video添加到页面
- 在src 目录下index.js 完整代码放在最后面
- import Element from ‘./element’;
- this.videoElement = new Element(this, this.boxDom, { height: height });
至此SkeyeWebPlayer播放器之flv播放功能就已经实现
// videoElthis.videoElement = new Element(this, this.boxDom, {height: height,isFill: showMode});import Features from './flv/core/features.js';import ScreenCanvas from './element/off-screen-canvas';import Element from './element';import BigPlayButton from './element/big-play-button';import Emitter from './utils/emitter';import {isNum, parseLocation} from './utils';import './font/iconfont.css';import './styles/index.css';import './styles/range.css';import WebFlvPlayer from './player/webFlvPlayer.js';export default class WebMediaPlayer extends Emitter {constructor(url, ID, cbFunc, data = {}) {super();let {cbUserPtr, decodeType, openAudio, bigPlay = false, height = false, showMode = false, playbackRecord} = data;this.player = null;this.url = url;this.callbackFunc = cbFunc || function () {};this.callbackUserPtr = cbUserPtr;this.height = height;this.bigPlay = bigPlay;this.decodeType = 'auto';this.version = __VERSION__;this.isPlaying = false;if (decodeType === 'auto' || decodeType === 'soft') {this.decodeType = decodeType;}if (!Features.supportMSEH264Playback()) {this.decodeType = 'soft';}//此处应为true, 则在所有平台上功能表现正常, 如为false,在苹果上则不能自动播放声音, 现应用在win chrome上,暂置为false;this.internalTriggerPlay = true;this.showMode = showMode;this.playbackRecord = playbackRecord;this.VideoCodec = '';this.VideoWidth = 0;this.VideoHeight = 0;this.showTimeLabel = false;this.seeking = false;this.callbackEnd = false;this.initH5Flag = false;this.currentH5Status = false;this.seekTimeSecs = 0;this.fullScreenFlag = false;if (!ID) {return false;}// 声音this.defaultAudioStatus = !!openAudio;this.enableAudio = !!openAudio;this.boxDom = document.getElementById(ID);if (!this.boxDom) {return false;}// videoElthis.videoElement = new Element(this, this.boxDom, {height: height,isFill: showMode});this.h5Video = this.videoEl = this.videoElement.videoEl;// canvasthis.screenCanvas = new ScreenCanvas(this, this.boxDom);// 中间大播放按钮this.bigPlayButton = new BigPlayButton(this, this.boxDom, bigPlay);this.on('streamType', this._onChangeTypeCallback.bind(this));if (url) {this.play(url, true);}}/*** 播放 play* @param url* @param autoPlay* @param time* @returns {boolean|void}*/play(url, autoPlay = true, time = 0) {if (!url) {url = this.url;}if (!this.boxDom) {return false;} else if (!url) {return console.log('播放地址不能为空');} else if (!autoPlay) {return false;} else if (!isNum(time)) {return console.log('time 必须传数字类型');}let locationObj = parseLocation(url);if (!['rtsp:', 'http:', 'https:', 'ws:', 'wss:'].some(item => item === locationObj.protocol)) {console.log('不支持 stream: ' + url);}this.url = url;this.emit('play');this.callbackFunc('play');this.seekTimeSecs = time;// 关闭加载动画this._onConnectStatus(this, 99);// 后缀let postfix = url.split('.').pop().toLowerCase();if (this.player) {// 暂停之后继续播放this.player.play(this.url, 0);} else if (/flv$/.test(postfix)) {// FLV流 (http-flv 、 ws-flv)this.player = new WebFlvPlayer(this, {type: 'flv',isLive: true,url: url,videoDom: this.videoEl,canvasDom: this.screenCanvas.canvas,decodeType: this.decodeType,}, {onGetVideoInfo: this.onVideoInfo,self: this});}}stop() {if (!this.boxDom) return;this.callbackFunc('stop');this.callbackEnd = false;this._onConnectStatus(this, 99); // 关闭加载动画if (this.playerInstance) {this.closeAudio();this.playerInstance.stop();this.showTimeLabel = false;return true;}return false;}pause() {this.player.pause();}removeAllChilds(p) {for (var i = p.childNodes.length - 1; i >= 0; i--) {this.removeAllChilds(p.childNodes[i]);p.removeChild(p.childNodes[i]);}}destroy() {this.stop();if (this.boxDom) {this.removeAllChilds(this.boxDom);}if (this.playerInstance) {this.playerInstance.stop();this.playerInstance.destroy();delete this.playerInstance;this.playerInstance = null;}}changeToH5Video(b) {if (!this.initH5Flag) {this.initH5Flag = true;} else {if (b === this.currentH5Status) {return;}}this.currentH5Status = b;if (b) {if (this.screenCanvas.canvas) {this.boxDom.removeChild(this.screenCanvas.canvas);}} else {if (this.h5Video) {this.boxDom.removeChild(this.h5Video);}}}// 连接状态回调_onConnectStatus(_this, status) {_this.emit('status', status);}//流类型回调_onChangeTypeCallback(streamType, isWasm) {this.changeToH5Video(!isWasm);}/*** 获取视频编码信息* @param _this* @param _videoCodec* @param _width* @param _height* @private*/onVideoInfo(_this, _videoCodec, _width, _height) {_this.VideoCodec = _videoCodec;_this.VideoWidth = _width;_this.VideoHeight = _height;_this.emit('resolutionRatio', {code: _videoCodec, width: _width, height: _height});_this._onConnectStatus(_this, 100);}rtspScale(scaleValue, ptsInterval) {if (this.playerInstance) {this.playerInstance.rtspScale(scaleValue, ptsInterval);}}//外部调用(秒)seekToSecs(seekValue) {console.log('seekValue', seekValue);if (this.playerInstance) {this.playerInstance.seek(seekValue, 0);}}//百分比seekToPercent(seekValue) {if (this.playerInstance) {this.playerInstance.seek(seekValue, 1);}}// 设置滚动条和时间标签setTrack(timeTrack, timeLabel) {if (this.playerInstance) {this.playerInstance.setTrack(timeTrack, timeLabel);}}openAudio() {this.callbackFunc('openAudio');if (this.playerInstance) {if (this.playerInstance.openAudio()) {//仅为内部判断是否启用音频进行remuxcommon.SetEnableAudio(true);this.enableAudio = true;} else {this.enableAudio = false;}}this.emit('audio', this.enableAudio);return this.enableAudio;}closeAudio() {this.callbackFunc('closeAudio');if (this.playerInstance) {if (!this.enableAudio) {return true;}if (this.playerInstance.closeAudio()) {this.enableAudio = false;} else {this.enableAudio = true;}}this.emit('audio', this.enableAudio);return !this.enableAudio;}showStaticsInfo(enable) {if (this.playerInstance == null) {return false;}if (enable) {return this.playerInstance.openStatinfo();} else {return this.playerInstance.closeStatinfo();}return false;}}
o’, this.enableAudio);
return !this.enableAudio;
}
showStaticsInfo(enable) {if (this.playerInstance == null) {return false;}if (enable) {return this.playerInstance.openStatinfo();} else {return this.playerInstance.closeStatinfo();}return false;}}