使用的场景:欲做一个直播间,并且拉流地址支持 .flv、.m3u8、mp4。同时播放控件需要自定义,支持直播回放、直播时移、微窗显示。
其次,捎带记录一下讨论区功能。
期间使用了 video-player (.flv 格式的直播暂时不支持播放)
aliplayer (这个忘记是什么原因了总之也没用成)
xgplayer(本次介绍就是使用的这个组件)
主动献上他的官网地址: https://v2.h5player.bytedance.com/api/
一、安装
# 最新稳定版 $ npm install xgplayer
二、使用
import 'xgplayer'; import FlvPlayer from 'xgplayer-flv'; import HlsPlayer from 'xgplayer-hls.js'; import Mp4Player from 'xgplayer-mp4'; // 下面引入的插件需要的引入不需要也可以不引入 import Player from 'xgplayer/dist/core_player'; import play from 'xgplayer/dist/controls/play'; import fullscreen from 'xgplayer/dist/controls/fullscreen'; import progress from 'xgplayer/dist/controls/progress'; import volume from 'xgplayer/dist/controls/volume'; import pip from 'xgplayer/dist/controls/pip'; import flex from 'xgplayer/dist/controls/flex'; /* * 这里注意 别再created里面实例化 最好是在mounted里面实例化 */ mounted() { // 三种格式使用 // 1、 this.player = new FlvPlayer({ id: 'videoPlayer', url: this.roomAddress, poster: this.roomAddress.replaceAll('.flv', '.png'), isLive: true, preloadTime: 30, minCachedTime: 5, cors: true, // fluid: true,//设置为流式布局,可使播放器宽度跟随父元素的宽度大小变化 autoplayMuted: true, controlPlugins: [ flex ], }) // 2、 this.player = new HlsPlayer({ id: 'videoPlayer', // url: this.roomAddress.replaceAll('app.livestream.bksti.com', '192.168.2.100:12002'), url: this.roomAddress, poster: this.roomAddress.replaceAll('.m3u8', '.png'), controlPlugins: [ flex ], // fluid: true,//设置为流式布局,可使播放器宽度跟随父元素的宽度大小变化 autoplayMuted: true, useHls: true }) // 3、 this.player = new Mp4Player({ id: 'videoPlayer', url: roomPlayback, playNext: function(){ if (videoArr.length > 0) { return { urlList: videoArr } } }(), // fluid: true,//设置为流式布局,可使播放器宽度跟随父元素的宽度大小变化 autoplayMuted: true, loop: true,//是否循环播放 volume: 1, controlPlugins: [ flex ], autoplay: true, maxBufferLength: 20 // 设置最大缓冲区时长,默认5秒 }) //以下举例示例里面的属性,需要哪个就用哪个。 //el: document.getElementById('mse'), id: 'videoPlayer', //height:300, url: 'http://211.943/268769823.mp4', // fluid: true,//设置为流式布局,可使播放器宽度跟随父元素的宽度大小变化 //volume: 0.6,//开发者可以为播放器预设音量大小 参考值0~1 autoplay:false,//是否自动播放, muted:true, autoplayMuted: true, loop: true,//是否循环播放 poster:'../assets/move2.png', playbackRate: [0.5, 0.75, 1, 1.5, 2], defaultPlaybackRate: 1, lastPlayTime: 70, //视频起播时间(单位:秒) lastPlayTimeHideDelay: 3, //提示文字展示时长(单位:秒) rotate: { //视频旋转按钮配置项 innerRotate: true, //只旋转内部video clockwise: false // 旋转方向是否为顺时针 }, playNext: { urlList: [ 'http://211.88//8898.MP4', 'http://211.88//8898.MP', 'http://211.88//8898.MP4' ], }, download: true, //设置download控件显示 danmu: { comments: [ //弹幕数组 { duration: 15000, //弹幕持续显示时间,毫秒(最低为5000毫秒) id: '1', //弹幕id,需唯一 start: 3000, //弹幕出现时间,毫秒 prior: true, //该条弹幕优先显示,默认false color: true, //该条弹幕为彩色弹幕,默认false txt: '长弹幕长弹幕长弹幕长弹幕长弹幕长弹幕长弹幕长弹幕长弹幕长弹幕', //弹幕文字内容 style: { //弹幕自定义样式 color: '#ff9500', fontSize: '20px', border: 'solid 1px #ff9500', borderRadius: '50px', padding: '5px 11px', backgroundColor: 'rgba(255, 255, 255, 0.1)' }, mode: 'top',//显示模式,top顶部居中,bottom底部居中,scroll滚动,默认为scroll } ], panel: true, //弹幕面板 area: { //弹幕显示区域 start: 0, //区域顶部到播放器顶部所占播放器高度的比例 end: 1 //区域底部到播放器顶部所占播放器高度的比例 }, closeDefaultBtn: false, //开启此项后不使用默认提供的弹幕开关,默认使用西瓜播放器提供的开关 defaultOff: false //开启此项后弹幕不会初始化,默认初始化弹幕 }, // 标记点所对应的播放时间 progressDot: [ { time: 2000, //展示标记的时间 text: '他死了', //鼠标hover在标记时展示的文字 // duration: 8, //标记段长度(以时长计算) style: { //标记样式 background: 'red' } }, { time: 1500, text: '他才是凶手?' }, { time: 2600, text: '又是谁杀了她?', // duration: 8, }, { time: 3800, text: '怎么回事?', // duration: 8, } ] } // 如果需要切换下一个视频需要做一下操作 this.player = new Mp4Player({ id: 'videoPlayer', url: roomPlayback, playNext: function(){ if (videoArr.length > 0) { return { urlList: videoArr } } }(), volume: 1, controlPlugins: [ flex ], autoplay: true, maxBufferLength: 20 // 设置最大缓冲区时长,默认5秒 }) this.player.on('ended', () =>{ console.log('播放结束,即将播放下一个') this.player.emit('playNextBtnClick') }) // player.emit('playNextBtnClick') 这个在源码里可以找到
//配置
// 1、去掉播放视频中的loading 在ignores中配置loading
简单说下讨论区的实现 ,这里也是使用第三方的 。websocket已经被封装好的包括心跳、重连之类的。
import SockJS from 'sockjs-client'; import EventBus from '@vertx/eventbus-bridge-client.js' data() { return { assetsUrl: assetsUrl, ws: new EventBus(liveWs + '/im/message/send', { vertxbus_reconnect_attempts_max: Infinity, // Max reconnect attempts vertxbus_reconnect_delay_min: 1000, // Initial delay (in ms) before first reconnect attempt vertxbus_reconnect_delay_max: 5000, // Max delay (in ms) between reconnect attempts vertxbus_reconnect_exponent: 2, // Exponential backoff factor vertxbus_randomization_factor: 0.5 // Randomization factor between 0 and 1 }), } } created() { this.ws.enableReconnect(true); this.ws.onerror = err => {} }, mounted() { this.ws.onopen = () => { this.ws.registerHandler('12345:message:'+this.roomData.roomId, (error, message) => { // 收到聊天室消息 console.log('received a appid:message: ', message.body); this.commentList.push({ type: message.body.type, user: '观众', content: message.body.text, userName: message.body.userName, userId: message.body.userId, }) this.$nextTick(() => { // console.log(this.$refs) this.$refs.comment.$el.scrollTop = this.$refs.comment.$el.scrollHeight }) }); } }
捎带在附加一个第三方复制插件 Clipboard
// 主要用到的是 class="share" @click.native.prevent="copy('.share')" :data-clipboard-text="" <image src="/static/icon-fenxiang.png" mode="" class="share" @click.native.prevent="copy('.share')" :data-clipboard-text="roomData.roomAddress"></image> // 复制 copy(name) { let clipboard = new Clipboard(name); //单页面引用 clipboard.on("success", (e) => { // 释放内存 clipboard.destroy(); this.$cnt.okmsg("复制成功!") }); clipboard.on("error", (e) => { // 不支持复制 this.$cnt.errmsg("复制失败!") // 释放内存 clipboard.destroy(); }); },