ezuikit.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /**
  2. * ezui 1.4
  3. */
  4. ( function( global, factory ) {
  5. "use strict";
  6. if ( typeof module === "object" && typeof module.exports === "object" ) {
  7. module.exports = global.document ?
  8. factory( global, true ) :
  9. function( w ) {
  10. if ( !w.document ) {
  11. throw new Error( "EZUIPlayer requires a window with a document" );
  12. }
  13. return factory( w );
  14. };
  15. } else {
  16. factory( global );
  17. }
  18. // Pass this if window is not defined yet
  19. } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ){
  20. /**
  21. * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
  22. */
  23. !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);
  24. /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
  25. if("document" in self){if(!("classList" in document.createElement("_"))){(function(j){"use strict";if(!("Element" in j)){return}var a="classList",f="prototype",m=j.Element[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p<o;p++){if(p in this&&this[p]===q){return p}}return -1},n=function(o,p){this.name=o;this.code=DOMException[o];this.message=p},g=function(p,o){if(o===""){throw new n("SYNTAX_ERR","An invalid or illegal string was specified")}if(/\s/.test(o)){throw new n("INVALID_CHARACTER_ERR","String contains an invalid character")}return c.call(p,o)},d=function(s){var r=k.call(s.getAttribute("class")||""),q=r?r.split(/\s+/):[],p=0,o=q.length;for(;p<o;p++){this.push(q[p])}this._updateClassName=function(){s.setAttribute("class",this.toString())}},e=d[f]=[],i=function(){return new d(this)};n[f]=Error[f];e.item=function(o){return this[o]||null};e.contains=function(o){o+="";return g(this,o)!==-1};e.add=function(){var s=arguments,r=0,p=s.length,q,o=false;do{q=s[r]+"";if(g(this,q)===-1){this.push(q);o=true}}while(++r<p);if(o){this._updateClassName()}};e.remove=function(){var t=arguments,s=0,p=t.length,r,o=false,q;do{r=t[s]+"";q=g(this,r);while(q!==-1){this.splice(q,1);o=true;q=g(this,r)}}while(++s<p);if(o){this._updateClassName()}};e.toggle=function(p,q){p+="";var o=this.contains(p),r=o?q!==true&&"remove":q!==false&&"add";if(r){this[r](p)}if(q===true||q===false){return q}else{return !o}};e.toString=function(){return this.join(" ")};if(b.defineProperty){var l={get:i,enumerable:true,configurable:true};try{b.defineProperty(m,a,l)}catch(h){if(h.number===-2146823252){l.enumerable=false;b.defineProperty(m,a,l)}}}else{if(b[f].__defineGetter__){m.__defineGetter__(a,i)}}}(self))}else{(function(){var b=document.createElement("_");b.classList.add("c1","c2");if(!b.classList.contains("c2")){var c=function(e){var d=DOMTokenList.prototype[e];DOMTokenList.prototype[e]=function(h){var g,f=arguments.length;for(g=0;g<f;g++){h=arguments[g];d.call(this,h)}}};c("add");c("remove")}b.classList.toggle("c3",false);if(b.classList.contains("c3")){var a=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(d,e){if(1 in arguments&&!this.contains(d)===!e){return e}else{return a.call(this,d)}}}b=null}())}};
  26. Date.prototype.Format = function (fmt) { //author: meizz
  27. var o = {
  28. "M+": this.getMonth() + 1, //月份
  29. "d+": this.getDate(), //日
  30. "h+": this.getHours(), //小时
  31. "m+": this.getMinutes(), //分
  32. "s+": this.getSeconds(), //秒
  33. "q+": Math.floor((this.getMonth() + 3) / 3), //季度
  34. "S": this.getMilliseconds() //毫秒
  35. };
  36. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  37. for (var k in o)
  38. if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  39. return fmt;
  40. };
  41. // var Domain = 'https://open.ys7.com';
  42. var Domain = '';
  43. var logDomain = 'https://log.ys7.com/statistics.do';
  44. // var ckplayerJS = './ckplayer/ckplayer.js';
  45. // var ckplayerSWF = './ckplayer/ckplayer.swf';
  46. // var m3u8SWF = './ckplayer/m3u8.swf';
  47. // var hlsJS ='./hls.min.js';
  48. var mpegJS = Domain + 'js/jsmpeg.min.js';
  49. var ckplayerJS = Domain + 'js/ckplayer.js';
  50. var ckplayerSWF = Domain + 'js/ckplayer.swf';
  51. var m3u8SWF = Domain + 'js/m3u8.swf';
  52. var hlsJS = 'js/hls.min.js';
  53. // 当前页面是否是https协议
  54. var isHttps = window.location.protocol === 'https:' ? true : false;
  55. // 是否为移动端
  56. var isMobile = !!navigator.userAgent.match(/(iPhone|iPod|iPad|Android|ios|SymbianOS)/i);
  57. var testVideo = document.createElement('video');
  58. // 是否支持video标签和addEventListener方法(主要为了区别ie8)
  59. var isModernBrowser = !!testVideo.canPlayType && !!window.addEventListener;
  60. // 是否能使用video原生播放hls,目前只有safari可以支持原生video播放。
  61. var isNativeSupportHls = isModernBrowser && testVideo.canPlayType('application/vnd.apple.mpegURL');
  62. // 是否能使用hls.js播放
  63. var isSupportHls = false;
  64. // 是否使用flash
  65. var useFlash = false;
  66. // 本地信息上报
  67. var LOCALINFO = 'open_netstream_localinfo';
  68. // 预览主表上报
  69. var PLAY_MAIN = 'open_netstream_play_main';
  70. function dclog(obj){
  71. var logObj = {
  72. Ver: 'v.1.4.0',
  73. PlatAddr: 'open.ys7.com',
  74. ExterVer: 'Ez.1.4.0',
  75. CltType: 102,
  76. StartTime: (new Date()).Format('yyyy-MM-dd hh:mm:ss.S'), // 每个日志包含当前的时间
  77. OS: navigator.platform
  78. }
  79. for(var i in obj){
  80. logObj[i] = obj[i];
  81. }
  82. var tempArray = [];
  83. for(var j in logObj){
  84. tempArray.push(j + '=' + logObj[j]);
  85. }
  86. var params = '?' + tempArray.join('&');
  87. // 上报一次本地统计信息
  88. var img = new Image();
  89. img.src = logDomain + params;
  90. }
  91. // 上报一次本地信息
  92. // dclog({
  93. // systemName: LOCALINFO
  94. // });
  95. var RTMP_REG = /^rtmp/;
  96. var HLS_REG = /\.m3u8/;
  97. // 获取元素样式
  98. function getStyle(el){
  99. return window.getComputedStyle
  100. ? window.getComputedStyle(el, null)
  101. : el.currentStyle;
  102. }
  103. // 加载js
  104. function addJs(filename, callback){
  105. var oJs = document.createElement("script");
  106. oJs.setAttribute("src", filename);
  107. oJs.onload = callback;
  108. document.getElementsByTagName("head")[0].appendChild(oJs);
  109. }
  110. var EZUIPlayer = function(videoId){
  111. if(!isModernBrowser){
  112. throw new Error('不支持ie8等低版本浏览器');
  113. return;
  114. }
  115. if(typeof videoId !== 'string'){
  116. throw new Error('EZUIPlayer requires parameter videoId');
  117. }
  118. this.videoId = videoId;
  119. this.video = document.getElementById(videoId);
  120. if(!this.video){
  121. throw new Error('EZUIPlayer requires parameter videoId');
  122. }
  123. this.opt = {};
  124. this.opt.sources = [];
  125. var sources = this.video.getElementsByTagName('source');
  126. // 转为数组对象,不受removeChild影响
  127. sources = Array.prototype.slice.call(sources, 0);
  128. if(this.video.src){
  129. // 移动端删除rtmp地址
  130. if(isMobile && RTMP_REG.test(this.video.src)){
  131. this.video.removeAttribute('src');
  132. this.video.load();
  133. }else{
  134. this.opt.sources.push(this.video.src);
  135. }
  136. }
  137. var l = sources.length;
  138. if(l > 0){
  139. for(var i = 0; i < l; i++){
  140. // 移动端删除rtmp地址
  141. if(isMobile && RTMP_REG.test(sources[i].src)){
  142. this.video.removeChild(sources[i]);
  143. }else{
  144. this.opt.sources.push(sources[i].src);
  145. }
  146. }
  147. }
  148. if(this.opt.sources.length < 1){
  149. throw new Error('no source found in video tag.');
  150. }
  151. this.opt.cur = 0;
  152. // 事件存储
  153. this.handlers = {};
  154. this.opt.poster = this.video.poster;
  155. var videoStyle = getStyle(this.video);
  156. var width = this.video.width;
  157. var height = this.video.height;
  158. if(width){
  159. this.opt.width = width;
  160. if(height){
  161. this.opt.height = height;
  162. }else{
  163. this.opt.height = 'auto';
  164. }
  165. this.log('video width:' + this.opt.width + ' height:' + this.opt.height);
  166. }else{
  167. this.opt.width = videoStyle.width;
  168. this.opt.height = videoStyle.height;
  169. this.log('videoStyle.width:' + videoStyle.width + ' wideoStyle.height:' + videoStyle.height);
  170. }
  171. this.opt.parentId = videoId;
  172. this.opt.autoplay = this.video.autoplay ? true : false;
  173. this.log('autoplay:' + this.video.autoplay);
  174. this.tryPlay();
  175. this.initTime = (new Date()).getTime();
  176. this.on('play', function(){
  177. // 上报播放成功信息
  178. // dclog({
  179. // systemName: PLAY_MAIN,
  180. // playurl: this.opt.currentSource,
  181. // Time: (new Date()).Format('yyyy-MM-dd hh:mm:ss.S'),
  182. // Enc: 0, // 0 不加密 1 加密
  183. // PlTp: 1, // 1 直播 2 回放
  184. // Via: 2, // 2 服务端取流
  185. // ErrCd: 0,
  186. // Cost: (new Date()).getTime() - this.initTime // 毫秒数
  187. // });
  188. });
  189. this.retry = 2;
  190. this.on('error', function(){
  191. // dclog({
  192. // systemName: PLAY_MAIN,
  193. // playurl: this.opt.currentSource,
  194. // cost: -1,
  195. // ErrCd: -1
  196. // });
  197. });
  198. };
  199. // 事件监听
  200. EZUIPlayer.prototype.on = function(eventName, callback){
  201. if(typeof eventName !== 'string' || typeof callback !== 'function'){
  202. return;
  203. }
  204. if(typeof this.handlers[eventName] === 'undefined'){
  205. this.handlers[eventName] = [];
  206. }
  207. this.handlers[eventName].push(callback);
  208. };
  209. // 事件触发
  210. EZUIPlayer.prototype.emit = function(){
  211. if(this.handlers[arguments[0]] instanceof Array){
  212. var handlers = this.handlers[arguments[0]];
  213. var l = handlers.length;
  214. for(var i = 0; i < l; i++){
  215. handlers[i].apply(this, Array.prototype.slice.call(arguments, 1));
  216. }
  217. }
  218. };
  219. // 尝试播放
  220. EZUIPlayer.prototype.tryPlay = function(){
  221. this.opt.currentSource = this.opt.sources[this.opt.cur];
  222. if(!this.opt.currentSource){
  223. this.log('未找到合适的播放URL');
  224. return;
  225. }
  226. var me = this;
  227. // 如果是HLS地址
  228. if(/\.m3u8/.test(this.opt.currentSource)){
  229. // 如果是手机浏览器环境,或者原生支持HLS播放的,直接使用video标签播放
  230. // 否则尝试使用hls.js播放,
  231. // 最后使用flash
  232. if(isMobile || isNativeSupportHls){
  233. this.log('使用原生video');
  234. this.video.style.heght = this.opt.height = Number(this.opt.width.replace(/px$/g, '')) * 9 / 16 + 'px';
  235. this.initVideoEvent();
  236. }else{
  237. if(isHttps){
  238. addJs(ckplayerJS, function(){
  239. me.initCKPlayer();
  240. });
  241. }else{
  242. addJs(hlsJS, function(){
  243. isSupportHls = Hls.isSupported();
  244. if(isSupportHls){
  245. me.log('使用hls.js');
  246. me.initHLS();
  247. }else{
  248. useFlash = true;
  249. me.log('2 使用flash');
  250. addJs(ckplayerJS, function(){
  251. me.initCKPlayer();
  252. });
  253. }
  254. });
  255. }
  256. }
  257. }else if(/^rtmp:/.test(this.opt.currentSource)){
  258. if(isMobile){
  259. this.opt.cur++;
  260. this.tryPlay();
  261. return;
  262. }else{
  263. addJs(ckplayerJS, function(){ console.log("initCKPlayer")
  264. me.initCKPlayer();
  265. });
  266. }
  267. }else if(/^wss:|^ws:/.test(this.opt.currentSource)){
  268. /*
  269. * WS协议的JSMpeg的不支持IE11以下的版本
  270. * 开放平台官网不支持IE8打开,所以官网上面不兼容两个人版本IE9 ,和IE10
  271. *
  272. * */
  273. if (!ltIE11()) {
  274. addJs(mpegJS, function(){
  275. me.initJSmpeg();
  276. });
  277. } else {
  278. alert('WS协议不支持Ie11以下的浏览器!请使用IE11,或者更高版本的浏览器');
  279. return;
  280. }
  281. }
  282. };
  283. // 初始化hls.js
  284. EZUIPlayer.prototype.initHLS = function(){
  285. var me = this;
  286. var hls = new Hls({defaultAudioCodec: 'mp4a.40.2'}); // 萤石设备默认使用 AAC LC 音频编码
  287. hls.loadSource(this.opt.currentSource);
  288. hls.attachMedia(this.video);
  289. hls.on(Hls.Events.MANIFEST_PARSED, function(){
  290. if(me.opt.autoplay){
  291. me.video.play();
  292. }
  293. me.initVideoEvent();
  294. });
  295. hls.on(Hls.Events.ERROR, function (event, data) {
  296. if (data.fatal) {
  297. switch(data.type) {
  298. case Hls.ErrorTypes.NETWORK_ERROR:
  299. // try to recover network error
  300. console.log("fatal network error encountered, try to recover");
  301. hls.startLoad();
  302. break;
  303. case Hls.ErrorTypes.MEDIA_ERROR:
  304. console.log("fatal media error encountered, try to recover");
  305. hls.recoverMediaError();
  306. break;
  307. default:
  308. // cannot recover
  309. hls.destroy();
  310. break;
  311. }
  312. }
  313. });
  314. this.hls = hls;
  315. };
  316. // 日志
  317. EZUIPlayer.prototype.log = function(msg){
  318. this.emit('log', msg);
  319. };
  320. // 初始化ckplayer
  321. EZUIPlayer.prototype.initCKPlayer = function(){
  322. this.log('ckplayer初始化');
  323. var me = this;
  324. var events = {
  325. 'play': function(){me.emit('play')},
  326. 'pause': function(){me.emit('pause')},
  327. 'error': function(){me.emit('error')}
  328. };
  329. window.ckplayer_status = function(){
  330. me.log(arguments);
  331. events[arguments[0]] && events[arguments[0]]();
  332. };
  333. // 新增相同id的div标签,然后删除video标签
  334. this.videoFlash = document.createElement('DIV');
  335. this.video.parentNode.replaceChild(this.videoFlash, this.video);
  336. this.video = this.videoFlash;
  337. this.videoFlash.id = this.opt.parentId;
  338. var flashvars = null;
  339. // 如果rtmp服务器环境设置了视频暂停则断开链接
  340. // 需要修改ckplayer.js setup参数第30个值
  341. // 在播放暂停后点击播放是否采用重新链接的方式
  342. if(/^rtmp/.test(this.opt.currentSource)){
  343. flashvars = {
  344. f: this.opt.currentSource,
  345. c: 0,
  346. p: this.opt.autoplay ? 1 : 0,
  347. i: this.opt.poster,
  348. lv: 1,
  349. loaded: 'loadHandler'
  350. };
  351. }else if(/\.m3u8/.test(this.opt.currentSource)){
  352. flashvars = {
  353. s:4, // 4-使用swf视频流插件播放
  354. f:m3u8SWF,
  355. a: this.opt.currentSource,
  356. c: 0, // 0-使用ckplayer.js的配置 1-使用ckplayer.xml的配置
  357. lv:1, // 1-直播 0-普通方式
  358. p: this.opt.autoplay ? 1 : 0, // 1-默认播放 0-默认暂停
  359. i: this.opt.poster,
  360. loaded: 'loadHandler'
  361. };
  362. }else{
  363. flashvars = {
  364. f: this.opt.currentSource,
  365. c: 0,
  366. p: 1,
  367. loaded: 'loadHandler'
  368. };
  369. }
  370. var params={bgcolor:'#FFF',allowFullScreen:true,allowScriptAccess:'always',wmode:'transparent'};
  371. this.flashId = this.opt.parentId + 'flashId';
  372. window.CKobject.embedSWF(ckplayerSWF,this.opt.parentId,this.flashId,this.opt.width,this.opt.height,flashvars,params);
  373. };
  374. EZUIPlayer.prototype.initVideoEvent = function(){
  375. var me = this;
  376. var EVENT = {
  377. 'loadstart': function(e){
  378. me.log('loadstart...当浏览器开始查找音频/视频时...');
  379. me.emit('loadstart', e);
  380. },
  381. 'durationchange': function(e){
  382. me.log('durationchange...当音频/视频的时长已更改时...');
  383. me.emit('durationchange', e);
  384. },
  385. 'loadedmetadata': function(e){
  386. me.log('loadedmetadata...当浏览器已加载音频/视频的元数据时...');
  387. me.emit('loadedmetadata', e);
  388. },
  389. 'loadeddata': function(e){
  390. me.log('loadeddata...当浏览器已加载音频/视频的当前帧时...');
  391. me.emit('loadeddata', e);
  392. },
  393. 'progress': function(e){
  394. me.log('progress...当浏览器正在下载音频/视频时...');
  395. me.emit('progress', e);
  396. },
  397. 'canplay': function(e){
  398. me.log('canplay...当浏览器可以播放音频/视频时...');
  399. me.emit('canplay', e);
  400. },
  401. 'canplaythrough': function(e){
  402. me.log('canplaythrough...当浏览器可在不因缓冲而停顿的情况下进行播放时...');
  403. me.emit('canplaythrough', e);
  404. },
  405. 'abort': function(e){
  406. me.log('abort...当音频/视频的加载已放弃时...');
  407. me.emit('abort', e);
  408. },
  409. 'emptied': function(e){
  410. me.log('emptied...当目前的播放列表为空时...');
  411. me.emit('emptied', e);
  412. },
  413. 'ended': function(e){
  414. me.log('ended...当目前的播放列表已结束时...');
  415. me.emit('ended', e);
  416. },
  417. 'pause': function(e){
  418. me.log('pause...当音频/视频已暂停时...');
  419. me.emit('pause', e);
  420. },
  421. 'play': function(e){
  422. me.log('play...当音频/视频已开始或不再暂停时...');
  423. me.emit('play', e);
  424. },
  425. 'playing': function(e){
  426. me.log('playing...当音频/视频在已因缓冲而暂停或停止后已就绪时...');
  427. me.emit('playing', e);
  428. },
  429. 'ratechange': function(e){
  430. me.log('ratechange...当音频/视频的播放速度已更改时...');
  431. me.emit('ratechange', e);
  432. },
  433. 'seeked': function(e){
  434. me.log('seeked...当用户已移动/跳跃到音频/视频中的新位置时...');
  435. me.emit('seeked', e);
  436. },
  437. 'seeking': function(e){
  438. me.log('seeking...当用户开始移动/跳跃到音频/视频中的新位置时...');
  439. me.emit('seeking', e);
  440. },
  441. 'stalled': function(e){
  442. me.log('stalled...当浏览器尝试获取媒体数据,但数据不可用时...');
  443. me.emit('stalled', e);
  444. },
  445. 'suspend': function(e){
  446. me.log('suspend...当浏览器刻意不获取媒体数据时...');
  447. me.emit('suspend', e);
  448. if(me.opt.autoplay){
  449. me.video.play();
  450. }
  451. },
  452. 'timeupdate': function(e){
  453. //me.log('timeupdate...当目前的播放位置已更改时...');
  454. me.emit('timeupdate', e);
  455. },
  456. 'volumechange': function(e){
  457. me.log('volumechange...当音量已更改时...');
  458. me.emit('volumechange', e);
  459. },
  460. 'waiting': function(e){
  461. me.log('waiting...当视频由于需要缓冲下一帧而停止...');
  462. me.emit('waiting', e);
  463. },
  464. 'error': function(e){
  465. me.log('error...当在音频/视频加载期间发生错误时...');
  466. me.emit('error', e);
  467. }
  468. };
  469. for(var i in EVENT){
  470. this.video.addEventListener( i, EVENT[i], false);
  471. }
  472. ios11Hack(this.video);
  473. };
  474. EZUIPlayer.prototype.initJSmpeg = function () {
  475. this.canvasEle = document.createElement('canvas');
  476. this.canvasEle.style.width = this.opt.width;
  477. this.canvasEle.style.height = this.opt.height;
  478. this.video.parentNode.replaceChild(this.canvasEle,this.video);
  479. this.canvasEle.id = this.opt.parentId;
  480. var player;
  481. if(player && player.destroy){
  482. player.destroy();
  483. }
  484. player = new JSMpeg.Player(this.opt.currentSource, {canvas: this.canvasEle});
  485. }
  486. EZUIPlayer.prototype.play = function(){
  487. this.opt.autoplay = true;
  488. if(!!window['CKobject']){
  489. CKobject.getObjectById(this.flashId).videoPlay();
  490. }else if(!!this.video){
  491. this.video.play();
  492. }
  493. };
  494. EZUIPlayer.prototype.pause = function(){
  495. this.opt.autoplay = false;
  496. if(!!window['CKobject']){
  497. CKobject.getObjectById(this.flashId).videoPause();
  498. }else if(!!this.video){
  499. this.video.pause();
  500. }
  501. };
  502. EZUIPlayer.prototype.stop = function () {
  503. // 执行停止
  504. this.opt.autoplay = false;
  505. if (!!window['CKobject']) {
  506. CKobject.getObjectById(this.flashId).videoClear();
  507. } else if (!!this.video) {
  508. if (!!this.hls) { // hls停止依赖this.hls
  509. // 通过暂停停止播放
  510. this.video.pause();
  511. // 停止取流
  512. this.hls.stopLoad();
  513. } else if (!!this.flv) {
  514. this.flv.pause();
  515. this.flv.unload();
  516. this.flv.detachMediaElement();
  517. this.flv.destroy();
  518. this.flv = null;
  519. } else if(!!this.JSmpeg) {
  520. this.JSmpeg.stop();
  521. // this.JSmpeg.destroy();
  522. }
  523. }
  524. };
  525. EZUIPlayer.prototype.load = function(){
  526. if(!!window['CKobject']){
  527. // flash load
  528. }else if(!!this.video){
  529. this.video.load();
  530. }
  531. };
  532. //
  533. // EZUIPlayer.prototype.remove = function(){
  534. //
  535. // };
  536. //
  537. // EZUIPlayer.prototype.clear = function(){
  538. //
  539. // };
  540. //
  541. // // 修改播放地址
  542. // EZUIPlayer.prototype.changeSource = function(source){
  543. //
  544. // };
  545. // iOS11手机HLS直播在m3u8响应时间过长后不继续请求的hack
  546. function ios11Hack(video){
  547. var isloadeddata = false;
  548. var isPlaying = false;
  549. var stalledCount = 0;
  550. video.addEventListener('loadeddata', function(){
  551. isloadeddata = true;
  552. }, false);
  553. video.addEventListener('stalled', function(){
  554. stalledCount++;
  555. if(!isPlaying){
  556. if(stalledCount >= 2 && !isloadeddata){
  557. video.load();
  558. video.play();
  559. isloadeddata = false;
  560. isPlaying = false;
  561. stalledCount = 0;
  562. }
  563. }
  564. }, false);
  565. video.addEventListener('playing', function(){
  566. isPlaying = true;
  567. });
  568. }
  569. /*
  570. *
  571. * 值 值类型 值说明
  572. -1 Number 不是ie浏览器
  573. 6 Number ie版本<=6
  574. 7 Number ie7
  575. 8 Number ie8
  576. 9 Number ie9
  577. 10 Number ie10
  578. 11 Number ie11
  579. 'edge' String ie的edge浏览器
  580. * */
  581. function IEVersion() {
  582. var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
  583. var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
  584. var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
  585. var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
  586. if(isIE) {
  587. var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
  588. reIE.test(userAgent);
  589. var fIEVersion = parseFloat(RegExp["$1"]);
  590. if(fIEVersion == 7) {
  591. return 7;
  592. } else if(fIEVersion == 8) {
  593. return 8;
  594. } else if(fIEVersion == 9) {
  595. return 9;
  596. } else if(fIEVersion == 10) {
  597. return 10;
  598. } else {
  599. return 6;//IE版本<=7
  600. }
  601. } else if(isEdge) {
  602. return 'edge';//edge
  603. } else if(isIE11) {
  604. return 11; //IE11
  605. }else{
  606. return -1;//不是ie浏览器
  607. }
  608. }
  609. function ltIE11() {
  610. var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
  611. var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
  612. if (isIE) {
  613. return true;
  614. } else {
  615. return false;
  616. }
  617. }
  618. if ( !noGlobal ) {
  619. window.EZUIPlayer = EZUIPlayer;
  620. }
  621. return EZUIPlayer;
  622. });