目录
关于超级播放器
腾讯云 web 超级播放器 tcplayer 可实现在手机浏览器和 pc 浏览器上播放音视频流的问题,功能强劲,兼容性好,可以不依赖用户安装 app,就能进行播放。
在实际的应用中,我们仍然根据需求直接改造了混淆代码,主要解决了以下问题:
1、增加、集成了播放快进组件
2、更改了一些样式
3、增强了一些旧版手机的兼容性
范例运行环境
操作系统: windows server 2019 datacenter
.net版本: .netframework4.0 或以上
开发工具:vs2019 c#
浏览器需要支持 h5 技术。
开发前准备
(1)我们需要引入腾讯云 web 超级播放器的 js 库,以下是我改造后的资源,可点击如下链接进行下载:
(2)前端布局,下载我的资源后,假设放在当前应用目录下,首先我们需要引入样式单,如下代码:
<link rel="stylesheet" href="tcplayer2021.css" />
其次,引入核心库,如下代码:
<script type="text/javascript" src="hls.min.0.12.4.js"> </script>
<script type="text/javascript" src="tcplayer.v4.min.js"> </script>
(3)需要引入 jquery,以下是一组基于jquery的自定义开发的扩展应用库,请下载我的资源:
进行引用,本库用于调用服务器静态方法等功能使用。
设计与实现
初始化播放器
播放器需要引入与结合 h5 的 video 控件,假设有如下引用:
<div id="coplayer" style="box-shadow:2px 0px 35px #000; -webkit-box-shadow:2px 0px 35px #000; background-color:rgb(69,69,69); position:fixed;top:40px;left:0px;width:80%;height:100px; margin: 0px auto;">
<video id="realcoplayer" autoplay="autoplay" controls="controls" webkit-playsinline playsinline x5-playsinline x-webkit-airplay="allow" runat="server" ></video>
<a id="b_rate" onclick="rate(this);" style=" float:right; line-height:25px; margin-right:10px; color:#fff;display:none;">1x</a>
</div>
其中
1、coplayer 为外围容器层,控制一些样式和位置输出
2、realcoplayer 为 h5 video 控件,用于结合腾讯 web 超级播放器使用
其关键属性说明如下:
序号 | 属性与设置 | 说明 |
---|---|---|
1 | autoplay="autoplay" | 设置是否自动播放,在移动端或ios系统可能无法实现 |
2 | controls="controls" | 是否显示控制工具栏,这里设置为需要显示 |
3 | webkit-playsinline playsinline | 兼容性属性:webkit-playsinline使ios 10中设置可以让视频在小窗内播放,即不全屏播放。 playsinline 可使用ios/微信浏览器支持小窗内播放 |
4 | x5-playsinline | h5 移动是否禁用全屏,这里为允许,为空则不允许 |
5 | x-webkit-airplay="allow" | 使此视频支持ios的airplay(隔空播放)功能,隔空播放能将各种 apple 设备中的音乐流传输到家中的多个扬声器上,并让这些扬声器中播放的旋律始终保持合拍, 让音乐荡漾在每个房间。 |
3、b_rate 为用于改造及引入超级播放器的快进组件,配合其使用。
客户端播放器的初始化代码如下:
var player = new tcplayer('realcoplayer', {
fileid: 111,
appid: '125407',
playbackrates: [0.5, 1, 1.25, 1.5, 2],
autoplay: false,
live: false,
x5_player: true,
volume: 0.5,
flash: true,
x5_player: true,
systemfullscreen: false,
playsinline: true,
x5_orientation: 0,
x5_type: 'h5',
allowfullscreen: false,
width:_w,
height:_h,
});
播放器重要属性设置
在实际使用中,为保证良好的可用性和兼容性,还需要设置如下属性,说明见下表:
序号 | 参数 | 类型 | 说明 |
---|---|---|---|
1 | fileid | string | 云点播平台可播放视频文件的 fileid |
2 | appid | string | 云点播平台申请的 appid |
3 | playbackrates | float[] | 快进倍速设置,如此数组 [0.5, 1, 1.25, 1.5, 2] |
4 | autoplay | bool | 是否设置为自动播放,false 为不自动 |
5 | live | bool | 是否直播功能,默认为 false |
6 | x5_player | bool | 设为 true 。是否启用 tbs 的播放 flv 或 hls 。启用时播放器将在 tbs 模式下(例如 android 的微信、qq 浏览器),将 flv 或 hls 播放地址直接赋给 <video> 播放。 |
7 | volume | float | 默认音量,0-1,0.5为居中 |
8 | flash | bool | 一个兼容的重要属性,设为 true |
9 | systemfullscreen | bool | 开启后(true),在不支持 fullscreen api 的浏览器环境下,尝试使用浏览器提供的 webkitenterfullscreen 方法进行全屏,如果支持,将进入系统全屏,控件为系统控件 |
10 | playsinline | bool | 兼容性属性,设为 true |
11 | x5_orientation | int | 通过 video 属性 “x5-video-orientation” 声明 tbs 播放器支持的方向,可选值: 0:landscape 横屏 1:portraint 竖屏 2:landscape | portrait 跟随手机自动旋转。 (备注:该属性为 tbs 内核实验性属性,非 tbs 内核不支持) |
12 | x5_type | string | 通过 video 属性 “x5-video-player-type” 声明启用同层 h5 播放器,支持的值:h5-page (该属性为 tbs 内核实验性属性,非 tbs 内核不支持) |
13 | allowfullscreen | bool | 兼容性写法,是否允许全屏播放 |
14 | width | int | 设置播放器宽度,单位为像素。 |
15 | height | int | 设置播放器高度,单位为像素。 |
播放器实用事件
通过跟踪超级播放器提供的监听事件,实现我们的开发需求,其关键事件说明如下:
序号 | 事件 | 说明 |
---|---|---|
1 | timeupdate | 播放时间更新事件,可记录播放时间,其结构体如下: player.on('timeupdate',function(){ }) |
2 | play | 开始播放时事件,其结构体如下: player.on('play',function(){ }) |
3 | fullscreenchange | 切换全屏状态事件,其结构体如下: player.on('fullscreenchange',function(){ }) |
4 | seeked | 拖动播放进度结束事件,其结构体如下: player.on('seeked',function(){ }) |
5 | pause | 播放暂停时事件,其结构体如下: player.on('pause',function(){ }) |
6 | ended | 播放结束时事件,其结构体如下: player.on('ended',function(){ }) |
7 | canplay | 播放能力执行成功事件,其结构体如下: player.on('canplay',function(){ }) |
8 | loadeddata | 音视频数据加载完毕时事件,其结构体如下: player.on('loadeddata',function(){ }) |
9 | ratechange | 改变快进倍速完成时事件,其结构体如下: player.on('ratechange',function(){ }) |
类实现代码如下:
public class qr_limit_str_scene
{
public string accesstoken { get; set; }
public string ticket { get; set; }
public string url { get; set; }
public string resultjson = "";
public qr_limit_str_scene()
{
}
public string geturl(string scene_str)
{
string postjson = "{\"action_name\": \"qr_limit_str_scene\", \"action_info\": {\"scene\": {\"scene_str\": \"" + scene_str + "\"}}}";
string action = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accesstoken;
webservice ws = new webservice();
string rs = ws.getresponseresult(action, encoding.utf8, "post", postjson);
newtonsoft.json.linq.jobject jsonobj = newtonsoft.json.linq.jobject.parse(rs);
ticket = jsonobj["ticket"] != null ? jsonobj["ticket"].tostring() : "";
url = jsonobj["url"] != null ? jsonobj["url"].tostring() : "";
resultjson = rs;
return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket;
}
}
一些兼容性判断
浏览器支持
编写浏览器是否支持终端h5播放的判断,实现代码如下:
function checkvideo() {
if (!!document.createelement('video').canplaytype) {
var vidtest = document.createelement("video");
oggtest = vidtest.canplaytype('video/ogg; codecs="theora, vorbis"');
if (!oggtest) {
h264test = vidtest.canplaytype('video/mp4; codecs="avc1.42e01e, mp4a.40.2"');
if (!h264test) {
return false;
}
else {
if (h264test == "probably") {
return true;
}
else {
return false;
}
}
}
else {
if (oggtest == "probably") {
return true;
}
else {
return false;
}
}
}
else {
return false;
}
return true;
}
if (!checkvideo()) {
alert('您的浏览器不支持video播放,请使用支持h5技术的浏览器!');
}
关于华为手机
在某些华为手机我们发现倍速快进组件样式显示异常,因此引入 js 函数,对机型增加了一些判断 ,代码如下:
function judgebrand(suseragent) {
var isiphone = suseragent.match(/iphone/i) == "iphone";
var ishuawei = suseragent.match(/huawei/i) == "huawei";
var ishonor = suseragent.match(/honor/i) == "honor";
var isoppo = suseragent.match(/oppo/i) == "oppo";
var isoppor15 = suseragent.match(/pacm00/i) == "pacm00";
var isvivo = suseragent.match(/vivo/i) == "vivo";
var isxiaomi = suseragent.match(/mi\s/i) == "mi ";
var isxiaomi2s = suseragent.match(/mix\s/i) == "mix ";
var isredmi = suseragent.match(/redmi/i) == "redmi";
var issamsung = suseragent.match(/sm-/i) == "sm-";
if (isiphone) {
return 'iphone';
} else if (ishuawei || ishonor) {
return 'huawei';
} else if (isoppo || isoppor15) {
return 'oppo';
} else if (isvivo) {
return 'vivo';
} else if (isxiaomi || isredmi || isxiaomi2s) {
return 'xiaomi';
} else if (issamsung) {
return 'samsung';
} else {
return 'default';
}
}
对华为手机的判断处理代码如下:
if(judgebrand(navigator.useragent.tolowercase())=='huawei'){
$("#b_rate").html="1x";
$("#b_rate").css("display","");
}else{
$("#b_rate").css("display","none");
}
实现代码
相对完整的实现代码(包括样式引入、前端控件和js控制)如下:
<link rel="stylesheet" href="tcplayer2021.css" />
<asp:textbox id="x_roomid" checkschema="" runat="server" style="display:none"></asp:textbox>
<script type="text/javascript" src="hls.min.0.12.4.js"> </script>
<script type="text/javascript" src="tcplayer.v4.min.js"> </script>
<script type="text/javascript" language="javascript" src="jquery.js" ></script>
<div id="h5panel" runat="server" >
<asp:textbox id="x_fileid" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="current" text="0" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="duration" text="0" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="mname" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="x_mp4url" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="x_coverurl" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="x_playmark" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="x_lasttime" style="display:none;" runat="server"></asp:textbox>
<asp:textbox id="confirmflag" text="0" runat="server" style="display:none;" ></asp:textbox>
<asp:textbox id="playmarkflag" text="0" runat="server" style="display:none;" ></asp:textbox>
<asp:textbox id="x_videocount" text="0" style="display:none;" runat="server"></asp:textbox>
<div id="coplayer" style="box-shadow:2px 0px 35px #000; -webkit-box-shadow:2px 0px 35px #000; background-color:rgb(69,69,69); position:fixed;top:40px;left:0px;width:80%;height:100px; margin: 0px auto;">
<video id="realcoplayer" autoplay="autoplay" controls="controls" webkit-playsinline playsinline x5-playsinline x-webkit-airplay="allow" runat="server" ></video>
<a id="b_rate" onclick="rate(this);" style=" float:right; line-height:25px; margin-right:10px; color:#fff;display:none;">1x</a>
</div>
<script language="javascript">
var windowheight=$(window).height();
form = document.forms[0];
function checkvideo() {
if (!!document.createelement('video').canplaytype) {
var vidtest = document.createelement("video");
oggtest = vidtest.canplaytype('video/ogg; codecs="theora, vorbis"');
if (!oggtest) {
h264test = vidtest.canplaytype('video/mp4; codecs="avc1.42e01e, mp4a.40.2"');
if (!h264test) {
return false;
}
else {
if (h264test == "probably") {
return true;
}
else {
return false;
}
}
}
else {
if (oggtest == "probably") {
return true;
}
else {
return false;
}
}
}
else {
return false;
}
return true;
}
if (!checkvideo()) {
alert('您的浏览器不支持video播放,请使用支持h5技术的浏览器!');
}
var timer=null;
var curtime=0;
function stimer(){
timer=window.setinterval("setpmark()",1000);
}
function etimer(){
window.clearinterval(timer);
}
function secondtodate(result) {
var h = math.floor(result / 3600) < 10 ? '0'+math.floor(result / 3600) : math.floor(result / 3600);
var m = math.floor((result / 60 % 60)) < 10 ? '0' + math.floor((result / 60 % 60)) : math.floor((result / 60 % 60));
var s = math.floor((result % 60)) < 10 ? '0' + math.floor((result % 60)) : math.floor((result % 60));
if(h=="00"){
return result = m + ":" + s;
}else{
return result = h + ":" + m + ":" + s;
}
}
var _w = $(document).width();
if(_w>=1200){
_w=640;
}
_h=_w/16*9;
function resizeall(){
var _w = $(document).width();
if(_w>=1200){
_w=640;
}
_h=_w/16*9;
if(player.isfullscreen()==true){
}
document.getelementbyid('coplayer').style.left=($(document).width()-_w)/2+'px';
document.getelementbyid('coplayer').style.width=_w+'px';
document.getelementbyid('coplayer').style.height=_h+'px';
function aiplaymark(curtime){
player.currenttime(curtime);
player.play();
}
var debug=document.getelementbyid('debug');
var curtime=0;
var seeked=false;
var player = new tcplayer('realcoplayer', { fileid: document.getelementbyid('x_fileid').value, appid: '12540',
playbackrates: [0.5, 1, 1.25, 1.5, 2],
autoplay: false,
live: false,
x5_player: true,
volume: 0.5,
flash: true,
x5_player: true,
systemfullscreen: false,
playsinline: true,
x5_orientation: 0,
x5_type: 'h5',
allowfullscreen: false,
width:_w,
height:_h,
});
player.on('timeupdate',function(){
document.getelementbyid("current").value=player.currenttime();
})
player.on('play',function(){
stimer();
updcountinfo('play',0);
})
player.on('fullscreenchange',function(){
})
player.on('seeked',function(){
})
player.on('pause',function(){
etimer();
})
player.on('ended',function(){
etimer();
})
player.on('canplay',function(){
})
player.on('loadeddata',function(){
player.poster(document.getelementbyid('x_coverurl').value);
if(judgebrand(navigator.useragent.tolowercase())=='huawei'){
$("#b_rate").html="1x";
$("#b_rate").css("display","");
}else{
$("#b_rate").css("display","none");
}
this.currenttime(document.getelementbyid("current").value);
})
player.on('ratechange',function(){
$('#b_rate').html($('.vjs-playback-rate-value').html());
})
function rate(o) {
document.queryselectorall('.vjs-playback-rate')[1].click();
}
function judgebrand(suseragent) {
var isiphone = suseragent.match(/iphone/i) == "iphone";
var ishuawei = suseragent.match(/huawei/i) == "huawei";
var ishonor = suseragent.match(/honor/i) == "honor";
var isoppo = suseragent.match(/oppo/i) == "oppo";
var isoppor15 = suseragent.match(/pacm00/i) == "pacm00";
var isvivo = suseragent.match(/vivo/i) == "vivo";
var isxiaomi = suseragent.match(/mi\s/i) == "mi ";
var isxiaomi2s = suseragent.match(/mix\s/i) == "mix ";
var isredmi = suseragent.match(/redmi/i) == "redmi";
var issamsung = suseragent.match(/sm-/i) == "sm-";
if (isiphone) {
return 'iphone';
} else if (ishuawei || ishonor) {
return 'huawei';
} else if (isoppo || isoppor15) {
return 'oppo';
} else if (isvivo) {
return 'vivo';
} else if (isxiaomi || isredmi || isxiaomi2s) {
return 'xiaomi';
} else if (issamsung) {
return 'samsung';
} else {
return 'default';
}
}
function updcountinfo(ctype,counts){
if(ctype=='play'){
if(document.getelementbyid('x_videocount').value=='0'){
document.getelementbyid('x_videocount').value='1';
}else{
return;
}
}
callserverfunction("", "updatecountinfo","{cid:'"+$("#x_cid").val()+"',ctype:'"+ctype+"',counts:'"+counts+"'}", sscount);
}
function setpmark(){
curtime++;
callserverfunction("", "updatepersonlearninfo","{cid:'"+$("#x_cid").val()+"',uid:'"+$("#x_uid").val()+"',pid:'"+$("#x_pid").val()+"',playmark:'"+$('#current').val()+"',steptime:'1'}", ss);
}
var stime;
</script>
小结
(1)关于更多的超级播放器 sdk 开发介绍,请参照如下链接:
https://cloud.tencent.com/document/product/881/30818
(2)实现代码中事件代码仅供参考,对于服务器静态方法实现需要根据我们实际的应用需求进行开发。
(3)实现代码中的前端控件,只为演示实例使用,可根据需要改造符合自己的开发规范。
感谢您的阅读,希望本文能够对您有所帮助。
发表评论