SkeyeWebPlayer.js H5播放器开发之播放器video动态创建(三)

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播放功能就已经实现

	 // videoEl
    this.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;
	    }
	
	    // videoEl
	    this.videoElement = new Element(this, this.boxDom, {
	      height: height,
	      isFill: showMode
	    });
	    this.h5Video = this.videoEl = this.videoElement.videoEl;
	    // canvas
	    this.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()) {
	        //仅为内部判断是否启用音频进行remux
	        common.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;
	  }
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值