当前位置:   article > 正文

腾讯云 Web 超级播放器开发实战

腾讯云 Web 超级播放器开发实战

目录

关于超级播放器

范例运行环境

开发前准备

设计与实现

初始化播放器

播放器重要属性设置

播放器实用事件

 一些兼容性判断

浏览器支持

关于华为手机

 实现代码

小结


关于超级播放器

腾讯云 Web 超级播放器 TCPlayer 可实现在手机浏览器和 PC 浏览器上播放音视频流的问题,功能强劲,兼容性好,可以不依赖用户安装 App,就能进行播放。

在实际的应用中,我们仍然根据需求直接改造了混淆代码,主要解决了以下问题:

1、增加、集成了播放快进组件

2、更改了一些样式

3、增强了一些旧版手机的兼容性

范例运行环境

操作系统: Windows Server 2019 DataCenter

.net版本: .netFramework4.0 或以上

开发工具:VS2019  C# 

浏览器需要支持 H5 技术。

开发前准备

(1)我们需要引入腾讯云 Web 超级播放器的 JS 库,以下是我改造后的资源,可点击如下链接进行下载:

https://download.csdn.net/download/michaelline/89367455

(2)前端布局,下载我的资源后,假设放在当前应用目录下,首先我们需要引入样式单,如下代码:

<link rel="stylesheet" href="tcplayer2021.css" />

 其次,引入核心库,如下代码:

  1. <script type="text/javascript" src="hls.min.0.12.4.js"> </script>
  2. <script type="text/javascript" src="tcplayer.v4.min.js"> </script>

(3)需要引入 Jquery,以下是一组基于Jquery的自定义开发的扩展应用库,请下载我的资源:

https://download.csdn.net/download/michaelline/88615565

进行引用,本库用于调用服务器静态方法等功能使用。

设计与实现

初始化播放器

播放器需要引入与结合 H5 的 Video 控件,假设有如下引用:

  1. <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;">
  2. <video id="realcoplayer" autoplay="autoplay" controls="controls" webkit-playsinline playsinline x5-playsinline x-webkit-airplay="allow" runat="server" ></video>
  3. <a id="b_rate" onclick="rate(this);" style=" float:right; line-height:25px; margin-right:10px; color:#fff;display:none;">1x</a>
  4. </div>

其中

1、coplayer 为外围容器层,控制一些样式和位置输出  

2、realcoplayer 为 h5 video 控件,用于结合腾讯 web 超级播放器使用

其关键属性说明如下:

序号属性与设置说明
1autoplay="autoplay" 设置是否自动播放,在移动端或IOS系统可能无法实现
2controls="controls"是否显示控制工具栏,这里设置为需要显示
3webkit-playsinline playsinline

兼容性属性:webkit-playsinline使ios 10中设置可以让视频在小窗内播放,即不全屏播放。  playsinline 可使用IOS/微信浏览器支持小窗内播放

4x5-playsinlineH5 移动是否禁用全屏,这里为允许,为空则不允许
5x-webkit-airplay="allow"使此视频支持ios的AirPlay(隔空播放)功能,隔空播放能将各种 Apple 设备中的音乐流传输到家中的多个扬声器上,并让这些扬声器中播放的旋律始终保持合拍, 让音乐荡漾在每个房间。

3、b_rate 为用于改造及引入超级播放器的快进组件,配合其使用。

客户端播放器的初始化代码如下:

  1. var player = new TCPlayer('realcoplayer', {
  2. fileID: 111,
  3. appID: '125407',
  4. playbackRates: [0.5, 1, 1.25, 1.5, 2],
  5. autoplay: false,
  6. live: false,
  7. x5_player: true,
  8. volume: 0.5,
  9. flash: true,
  10. x5_player: true,
  11. systemFullscreen: false,
  12. playsinline: true,
  13. x5_orientation: 0,
  14. x5_type: 'h5',
  15. allowFullScreen: false,
  16. width:_w,
  17. height:_h,
  18. });

播放器重要属性设置

在实际使用中,为保证良好的可用性和兼容性,还需要设置如下属性,说明见下表:

序号参数类型说明
1fileID string云点播平台可播放视频文件的 fileID
2appIDstring云点播平台申请的 appID
3playbackRatesfloat[]快进倍速设置,如此数组 [0.5, 1, 1.25, 1.5, 2]
4autoplaybool是否设置为自动播放,false 为不自动
5livebool是否直播功能,默认为 false
6x5_playerbool设为 true 。是否启用 TBS 的播放 flv 或 hls 。启用时播放器将在 TBS 模式下(例如 Android 的微信、QQ 浏览器),将 flv 或 hls 播放地址直接赋给 <video> 播放。
7volumefloat默认音量,0-1,0.5为居中
8flashbool一个兼容的重要属性,设为 true
9systemFullscreenbool开启后(true),在不支持 Fullscreen API 的浏览器环境下,尝试使用浏览器提供的 webkitEnterFullScreen 方法进行全屏,如果支持,将进入系统全屏,控件为系统控件
10playsinlinebool兼容性属性,设为 true
11x5_orientationint

通过 video 属性 “x5-video-orientation” 声明 TBS 播放器支持的方向,可选值:

0:landscape 横屏

1:portraint 竖屏

2:landscape | portrait 跟随手机自动旋转。

(备注:该属性为 TBS 内核实验性属性,非 TBS 内核不支持)

12x5_typestring通过 video 属性 “x5-video-player-type” 声明启用同层 H5 播放器,支持的值:h5-page (该属性为 TBS 内核实验性属性,非 TBS 内核不支持)
13allowFullScreenbool兼容性写法,是否允许全屏播放
14widthint设置播放器宽度,单位为像素。
15heightint设置播放器高度,单位为像素。

播放器实用事件

通过跟踪超级播放器提供的监听事件,实现我们的开发需求,其关键事件说明如下:

序号事件说明
1timeupdate

播放时间更新事件,可记录播放时间,其结构体如下:

player.on('timeupdate',function(){  }) 

2play

开始播放时事件,其结构体如下:

player.on('play',function(){ })

3fullscreenchange

切换全屏状态事件,其结构体如下:

player.on('fullscreenchange',function(){    })

4seeked

拖动播放进度结束事件,其结构体如下:

player.on('seeked',function(){    })

5pause

播放暂停时事件,其结构体如下:

player.on('pause',function(){    })

6ended

播放结束时事件,其结构体如下:

player.on('ended',function(){    })

7canplay

播放能力执行成功事件,其结构体如下:

player.on('canplay',function(){    })

8loadeddata

音视频数据加载完毕时事件,其结构体如下:

player.on('loadeddata',function(){    })

9ratechange

改变快进倍速完成时事件,其结构体如下:

player.on('ratechange',function(){    })

类实现代码如下:

  1. public class QR_LIMIT_STR_SCENE
  2. {
  3. public string AccessToken { get; set; }
  4. public string ticket { get; set; }
  5. public string url { get; set; }
  6. public string ResultJson = "";
  7. public QR_LIMIT_STR_SCENE()
  8. {
  9. }
  10. public string getUrl(string scene_str)
  11. {
  12. string PostJson = "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"" + scene_str + "\"}}}";
  13. String action = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + AccessToken;
  14. WebService ws = new WebService();
  15. string rs = ws.GetResponseResult(action, Encoding.UTF8, "POST", PostJson);
  16. Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(rs);
  17. ticket = jsonObj["ticket"] != null ? jsonObj["ticket"].ToString() : "";
  18. url = jsonObj["url"] != null ? jsonObj["url"].ToString() : "";
  19. ResultJson = rs;
  20. return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket;
  21. }
  22. }

 一些兼容性判断

浏览器支持

编写浏览器是否支持终端H5播放的判断,实现代码如下:

  1. function checkVideo() {
  2. if (!!document.createElement('video').canPlayType) {
  3. var vidTest = document.createElement("video");
  4. oggTest = vidTest.canPlayType('video/ogg; codecs="theora, vorbis"');
  5. if (!oggTest) {
  6. h264Test = vidTest.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
  7. if (!h264Test) {
  8. return false;
  9. }
  10. else {
  11. if (h264Test == "probably") {
  12. return true;
  13. }
  14. else {
  15. return false;
  16. }
  17. }
  18. }
  19. else {
  20. if (oggTest == "probably") {
  21. return true;
  22. }
  23. else {
  24. return false;
  25. }
  26. }
  27. }
  28. else {
  29. return false;
  30. }
  31. return true;
  32. }
  33. if (!checkVideo()) {
  34. alert('您的浏览器不支持Video播放,请使用支持H5技术的浏览器!');
  35. }
关于华为手机

在某些华为手机我们发现倍速快进组件样式显示异常,因此引入 JS 函数,对机型增加了一些判断 ,代码如下:

  1. function judgeBrand(sUserAgent) {
  2. var isIphone = sUserAgent.match(/iphone/i) == "iphone";
  3. var isHuawei = sUserAgent.match(/huawei/i) == "huawei";
  4. var isHonor = sUserAgent.match(/honor/i) == "honor";
  5. var isOppo = sUserAgent.match(/oppo/i) == "oppo";
  6. var isOppoR15 = sUserAgent.match(/pacm00/i) == "pacm00";
  7. var isVivo = sUserAgent.match(/vivo/i) == "vivo";
  8. var isXiaomi = sUserAgent.match(/mi\s/i) == "mi ";
  9. var isXiaomi2s = sUserAgent.match(/mix\s/i) == "mix ";
  10. var isRedmi = sUserAgent.match(/redmi/i) == "redmi";
  11. var isSamsung = sUserAgent.match(/sm-/i) == "sm-";
  12. if (isIphone) {
  13. return 'iphone';
  14. } else if (isHuawei || isHonor) {
  15. return 'huawei';
  16. } else if (isOppo || isOppoR15) {
  17. return 'oppo';
  18. } else if (isVivo) {
  19. return 'vivo';
  20. } else if (isXiaomi || isRedmi || isXiaomi2s) {
  21. return 'xiaomi';
  22. } else if (isSamsung) {
  23. return 'samsung';
  24. } else {
  25. return 'default';
  26. }
  27. }

对华为手机的判断处理代码如下:

  1. if(judgeBrand(navigator.userAgent.toLowerCase())=='huawei'){
  2. $("#b_rate").html="1x";
  3. $("#b_rate").css("display","");
  4. }else{
  5. $("#b_rate").css("display","none");
  6. }

 实现代码

相对完整的实现代码(包括样式引入、前端控件和JS控制)如下:

  1. <link rel="stylesheet" href="tcplayer2021.css" />
  2. <asp:TextBox ID="x_roomid" checkSchema="" runat="server" style="display:none"></asp:TextBox>
  3. <script type="text/javascript" src="hls.min.0.12.4.js"> </script>
  4. <script type="text/javascript" src="tcplayer.v4.min.js"> </script>
  5. <script type="text/javascript" language="javascript" src="jquery.js" ></script>
  6. <div id="h5panel" runat="server" >
  7. <asp:TextBox ID="x_fileid" style="display:none;" runat="server"></asp:TextBox>
  8. <asp:TextBox ID="current" Text="0" style="display:none;" runat="server"></asp:TextBox>
  9. <asp:TextBox ID="duration" Text="0" style="display:none;" runat="server"></asp:TextBox>
  10. <asp:TextBox ID="mname" style="display:none;" runat="server"></asp:TextBox>
  11. <asp:TextBox ID="x_mp4url" style="display:none;" runat="server"></asp:TextBox>
  12. <asp:TextBox ID="x_CoverUrl" style="display:none;" runat="server"></asp:TextBox>
  13. <asp:TextBox ID="x_playMark" style="display:none;" runat="server"></asp:TextBox>
  14. <asp:TextBox ID="x_lasttime" style="display:none;" runat="server"></asp:TextBox>
  15. <asp:TextBox ID="confirmflag" Text="0" runat="server" style="display:none;" ></asp:TextBox>
  16. <asp:TextBox ID="playMarkflag" Text="0" runat="server" style="display:none;" ></asp:TextBox>
  17. <asp:TextBox ID="x_videocount" Text="0" style="display:none;" runat="server"></asp:TextBox>
  18. <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;">
  19. <video id="realcoplayer" autoplay="autoplay" controls="controls" webkit-playsinline playsinline x5-playsinline x-webkit-airplay="allow" runat="server" ></video>
  20. <a id="b_rate" onclick="rate(this);" style=" float:right; line-height:25px; margin-right:10px; color:#fff;display:none;">1x</a>
  21. </div>
  22. <script language="javascript">
  23. var windowheight=$(window).height();
  24. form = document.forms[0];
  25. function checkVideo() {
  26. if (!!document.createElement('video').canPlayType) {
  27. var vidTest = document.createElement("video");
  28. oggTest = vidTest.canPlayType('video/ogg; codecs="theora, vorbis"');
  29. if (!oggTest) {
  30. h264Test = vidTest.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
  31. if (!h264Test) {
  32. return false;
  33. }
  34. else {
  35. if (h264Test == "probably") {
  36. return true;
  37. }
  38. else {
  39. return false;
  40. }
  41. }
  42. }
  43. else {
  44. if (oggTest == "probably") {
  45. return true;
  46. }
  47. else {
  48. return false;
  49. }
  50. }
  51. }
  52. else {
  53. return false;
  54. }
  55. return true;
  56. }
  57. if (!checkVideo()) {
  58. alert('您的浏览器不支持Video播放,请使用支持H5技术的浏览器!');
  59. }
  60. var timer=null;
  61. var curtime=0;
  62. function stimer(){
  63. timer=window.setInterval("setpmark()",1000);
  64. }
  65. function etimer(){
  66. window.clearInterval(timer);
  67. }
  68. function secondToDate(result) {
  69. var h = Math.floor(result / 3600) < 10 ? '0'+Math.floor(result / 3600) : Math.floor(result / 3600);
  70. var m = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60));
  71. var s = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60));
  72. if(h=="00"){
  73. return result = m + ":" + s;
  74. }else{
  75. return result = h + ":" + m + ":" + s;
  76. }
  77. }
  78. var _w = $(document).width();
  79. if(_w>=1200){
  80. _w=640;
  81. }
  82. _h=_w/16*9;
  83. function resizeAll(){
  84. var _w = $(document).width();
  85. if(_w>=1200){
  86. _w=640;
  87. }
  88. _h=_w/16*9;
  89. if(player.isFullscreen()==true){
  90. }
  91. document.getElementById('coplayer').style.left=($(document).width()-_w)/2+'px';
  92. document.getElementById('coplayer').style.width=_w+'px';
  93. document.getElementById('coplayer').style.height=_h+'px';
  94. function aiplaymark(curtime){
  95. player.currentTime(curtime);
  96. player.play();
  97. }
  98. var debug=document.getElementById('debug');
  99. var curtime=0;
  100. var seeked=false;
  101. var player = new TCPlayer('realcoplayer', { fileID: document.getElementById('x_fileid').value, appID: '12540',
  102. playbackRates: [0.5, 1, 1.25, 1.5, 2],
  103. autoplay: false,
  104. live: false,
  105. x5_player: true,
  106. volume: 0.5,
  107. flash: true,
  108. x5_player: true,
  109. systemFullscreen: false,
  110. playsinline: true,
  111. x5_orientation: 0,
  112. x5_type: 'h5',
  113. allowFullScreen: false,
  114. width:_w,
  115. height:_h,
  116. });
  117. player.on('timeupdate',function(){
  118. document.getElementById("current").value=player.currentTime();
  119. })
  120. player.on('play',function(){
  121. stimer();
  122. updcountinfo('play',0);
  123. })
  124. player.on('fullscreenchange',function(){
  125. })
  126. player.on('seeked',function(){
  127. })
  128. player.on('pause',function(){
  129. etimer();
  130. })
  131. player.on('ended',function(){
  132. etimer();
  133. })
  134. player.on('canplay',function(){
  135. })
  136. player.on('loadeddata',function(){
  137. player.poster(document.getElementById('x_CoverUrl').value);
  138. if(judgeBrand(navigator.userAgent.toLowerCase())=='huawei'){
  139. $("#b_rate").html="1x";
  140. $("#b_rate").css("display","");
  141. }else{
  142. $("#b_rate").css("display","none");
  143. }
  144. this.currentTime(document.getElementById("current").value);
  145. })
  146. player.on('ratechange',function(){
  147. $('#b_rate').html($('.vjs-playback-rate-value').html());
  148. })
  149. function rate(o) {
  150. document.querySelectorAll('.vjs-playback-rate')[1].click();
  151. }
  152. function judgeBrand(sUserAgent) {
  153. var isIphone = sUserAgent.match(/iphone/i) == "iphone";
  154. var isHuawei = sUserAgent.match(/huawei/i) == "huawei";
  155. var isHonor = sUserAgent.match(/honor/i) == "honor";
  156. var isOppo = sUserAgent.match(/oppo/i) == "oppo";
  157. var isOppoR15 = sUserAgent.match(/pacm00/i) == "pacm00";
  158. var isVivo = sUserAgent.match(/vivo/i) == "vivo";
  159. var isXiaomi = sUserAgent.match(/mi\s/i) == "mi ";
  160. var isXiaomi2s = sUserAgent.match(/mix\s/i) == "mix ";
  161. var isRedmi = sUserAgent.match(/redmi/i) == "redmi";
  162. var isSamsung = sUserAgent.match(/sm-/i) == "sm-";
  163. if (isIphone) {
  164. return 'iphone';
  165. } else if (isHuawei || isHonor) {
  166. return 'huawei';
  167. } else if (isOppo || isOppoR15) {
  168. return 'oppo';
  169. } else if (isVivo) {
  170. return 'vivo';
  171. } else if (isXiaomi || isRedmi || isXiaomi2s) {
  172. return 'xiaomi';
  173. } else if (isSamsung) {
  174. return 'samsung';
  175. } else {
  176. return 'default';
  177. }
  178. }
  179. function updcountinfo(ctype,counts){
  180. if(ctype=='play'){
  181. if(document.getElementById('x_videocount').value=='0'){
  182. document.getElementById('x_videocount').value='1';
  183. }else{
  184. return;
  185. }
  186. }
  187. callServerFunction("", "updateCountInfo","{cid:'"+$("#x_cid").val()+"',ctype:'"+ctype+"',counts:'"+counts+"'}", sscount);
  188. }
  189. function setpmark(){
  190. curtime++;
  191. callServerFunction("", "updatePersonLearnInfo","{cid:'"+$("#x_cid").val()+"',uid:'"+$("#x_uid").val()+"',pid:'"+$("#x_pid").val()+"',playmark:'"+$('#current').val()+"',steptime:'1'}", ss);
  192. }
  193. var sTime;
  194. </script>

小结

(1)关于更多的超级播放器 SDK 开发介绍,请参照如下链接:

https://cloud.tencent.com/document/product/881/30818

(2)实现代码中事件代码仅供参考,对于服务器静态方法实现需要根据我们实际的应用需求进行开发。

(3)实现代码中的前端控件,只为演示实例使用,可根据需要改造符合自己的开发规范。

感谢您的阅读,希望本文能够对您有所帮助。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/642486
推荐阅读
相关标签
  

闽ICP备14008679号