PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 4.5.11.2
WpStream – Live Streaming, Video on Demand, Pay Per View v4.5.11.2
4.14.1 4.14.0 4.13.2 4.13.1 4.13 4.12.5 4.12.4 4.12.3 4.12.2 4.12.1 4.12 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5 4.5.1 4.5.11 4.5.11.1 4.5.11.2 4.5.11.4 4.5.11.5 4.5.11.6 All 181 releases
wpstream / public / js / wpstream-player.js

wpstream-player.js in WpStream – Live Streaming, Video on Demand, Pay Per View 4.5.11.2, at public/js/wpstream-player.js

832 lines 25.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 * player,'.$live_event_uri_final.','.$live_conect_views.'
6 */
7
8 window.WebSocket = window.WebSocket || window.MozWebSocket;
9 if (!window.WebSocket) {
10 console.log("Sorry, but your browser does not support WebSockets");
11 }
12
13 function wpstream_player_initialize(settings){
14 const player = new WpstreamPlayer(settings);
15 }
16
17 class WpstreamPlayer {
18 // id;
19 // trailerUrl;
20 // contentUrl;
21 // statsUri;
22 // autoplay;
23 // ruler = 0; //0 - basic; 1 - ajax; 2 - ws
24 // state = -1;
25 //-1 - unknown
26 // 0 - stopped
27 // 1 - notstarted
28 // 2 - started
29 // 4 - init
30 // 5 - paused
31 // 6 - startup
32 // 7 - onair
33 // 9 - ended
34 // 10 - finished
35
36 // liveConnect;
37 // wrapper;
38 // counter;
39 // chat;
40
41 constructor(settings){
42 console.log("[]WpstreamPlayer: ", settings);
43 this.id = settings.videoElementId;
44 this.trailerUrl = settings.trailerUrl;
45 this.contentUrl = settings.contentUrl;
46 this.statsUri = settings.statsUri;
47 this.autoplay = settings.autoplay;
48 this.playTrailerButton = jQuery(`#${settings.playTrailerButtonElementId}`);
49 console.log("playTrailerButton: ", this.playTrailerButton);
50 this.liveConnect = new LiveConnect(this);
51 this.wrapper = jQuery('#wpstream_live_player_wrapper' + this.id);
52 console.log("wrapper: ", this.wrapper)
53 this.channelId = this.wrapper.attr('data-product-id');
54 console.log("channelId: ", this.channelId)
55 this.playback = new WpstreamPlayback(this, this.id, this.autoplay);
56 this.counter = new LiveCounter(this.wrapper, this.id);
57 this.liveMessage = new WpstreamLiveMessage(this.wrapper, this.id);
58 this.chat = new WpstreamChat();
59 this.setRuler(1);
60
61 if (settings.trailerUrl) {
62 const owner = this;
63 this.playTrailerButton.on('click',function(){
64 console.log("playTrailer()");
65 owner.playTrailerButton.hide();
66 owner.playback.playTrailer(owner.trailerUrl, true);
67 });
68 }
69 this.playTrailerButton.hide();
70 }
71
72 setRuler(ruler){
73 console.log("setRuler: " + ruler);
74 let oldRuler = this.ruler;
75 console.log("oldRuler: ", oldRuler);
76 this.ruler = ruler;
77 switch (ruler){
78 case 1:
79 if (oldRuler != 1){
80 this.getDynamicSettings();
81 }
82 clearTimeout(this.retrieveDynamicSettingsTimeout);
83 let self = this;
84 this.retrieveDynamicSettingsTimeout = setTimeout(() => self.getDynamicSettings(), 30 * 1000)
85 break;
86 case 2:
87 clearTimeout(this.retrieveDynamicSettingsTimeout);
88 break;
89 }
90 }
91
92 getDynamicSettings(){
93 console.log("getDynamicSettings()");
94 let ajaxurl = wpstream_player_vars.admin_url + 'admin-ajax.php';
95 let owner = this;
96 jQuery.ajax({
97 type: 'POST',
98 url: ajaxurl,
99 dataType: 'json',
100 data: {
101 'action' : 'wpstream_player_check_status',
102 'channel_id' : this.channelId
103 },
104 success: function (data) {
105
106 console.log("dynamicSettings: ", data);
107 if (data == 0){
108 owner.setState('stopped');
109 }
110 else if (data.started == "no"){
111 owner.setState('notstarted');
112 owner.chat.disconnect();
113
114 }
115 else if (data.started == "yes"){
116 let liveConnectUri = data.live_conect_views;
117 owner.liveConnect.setup(liveConnectUri);
118 let contentUrl = data.event_uri;
119 owner.setState('started');
120 owner.setContentSrc(contentUrl);
121 owner.chat.connect(data.chat_url);
122 }
123 },
124 error: function (error) {
125 console.log("dynamicSettingsError: ", error)
126 }
127 });
128 if (this.ruler <= 1){
129 this.setRuler(1);
130 }
131 }
132
133 setContentSrc(uri){
134 this.playback.setContentSrc(uri);
135 }
136
137 setState(state){
138 console.log("setState: ", state);
139 const oldState = this.state;
140 console.log("oldState: ", oldState);
141 this.state = state;
142
143 if (this.trailerUrl && state != 'onair' && state != 'started' && state != 'startup'){
144 this.playback.playTrailer(this.trailerUrl);
145 }
146
147 switch(state){
148 case 'stopped':
149 case 'notstarted':
150 case 'starting':
151 this.liveMessage.showOriginalMessage();
152 this.playback.pauseContent();
153 break;
154 case 'started':
155 this.liveMessage.hide();
156 break;
157 case 'init':
158 case 'paused':
159 this.liveMessage.showMessage(state);
160 this.playback.pauseContent();
161 break;
162 case 'ended':
163 this.liveMessage.showMessage(state);
164 this.playback.pauseContent(true);
165 break;
166 case 'startup':
167 this.liveMessage.showMessage(state);
168 if (oldState != 'onair'){
169 this.playback.pauseContent();
170 }
171 break;
172 case 'onair':
173 this.liveMessage.hide();
174 this.playback.playContent();
175 break;
176 }
177 }
178
179 onLiveConnectActive(isActive){
180 console.log("onLiveConnectActive: ", isActive);
181 this.setRuler(isActive ? 2 : 1);
182 if (!isActive){
183 this.counter.hide();
184 }
185 }
186
187 updateViewerCount(count){
188 console.log("updateViewerCount: ", count)
189 this.counter.show();
190 this.counter.setCount(count);
191 }
192 }
193
194 class WpstreamPlayback {
195 // player;
196 // timeQueue = [];
197 // master;
198 // paused = false;
199 // played = false;
200
201
202 constructor(master, id, autoplay){
203 this.timeQueue = [];
204 this.paused = false;
205 this.played = false;
206 this.contentSrc = null;
207 this.trailerState = 'notstarted';
208 this.playingTrailer = false;
209 this.master = master;
210 this.setupBasePlayer(id, autoplay);
211 this.runWatchdog();
212 }
213
214 setupBasePlayer(id, autoplay){
215 console.log("setupBasePlayer: ", id, autoplay);
216 let contentUrl = this.master.contentUrl;
217 console.log("contentUrl: ", contentUrl);
218 let llhls = isLlHls(contentUrl);
219 console.log("llhls: ", llhls);
220 this.player = videojs('wpstream-video' + id, {
221 html5: {
222 vhs: {
223 useBandwidthFromLocalStorage: true,
224 limitRenditionByPlayerDimensions: false,
225 useDevicePixelRatio: true,
226 overrideNative: !videojs.browser.IS_SAFARI,
227 cacheEncryptionKeys: true,
228 llhls
229 }
230 },
231 errorDisplay: false,
232 autoplay:autoplay,
233 preload:"auto",
234 // muted : true
235 });
236 // this.player.controls(false);
237 this.player.bigPlayButton.hide();
238 // player.controlBar.progressControl.hide();
239 const owner = this;
240 this.player.on('play', function(event) {
241 console.log("Play");
242 owner.played = true;
243 console.log("src: ", owner.player.currentSrc());
244 console.log("playingTrailer: ", owner.playingTrailer);
245 if (owner.playingTrailer){
246 console.log("trailerState: ", owner.trailerState);
247 if (owner.trailerState == 'attempted'){
248 owner.trailerState = 'playing';
249 owner.master.liveMessage.setupAsSubtitle(true);
250 }
251 }
252 owner.master.playTrailerButton.hide();
253 });
254 this.player.on('pause', function(event) {
255 console.log("Pause");
256 });
257 this.player.on('ended', () => {
258 console.log("Ended");
259 console.log("playingTrailer: ", this.playingTrailer);
260 if (this.playingTrailer){
261 owner.stopTrailer();
262 }
263 else {
264 console.log("content ended");
265 this.player.controls(false);
266 this.player.hasStarted(false);
267 }
268 });
269 this.player.on("durationchange", () => {
270 const duration = this.player.duration();
271 console.log('durationchange: ', duration);
272 if (duration > 0 && duration < Infinity){
273 this.player.controls(false);
274 }
275 });
276 this.player.on("error", (error) => {
277 console.log('error: ', error);
278 });
279 console.log("src: ", this.player.currentSrc());
280 // setTimeout(() => {
281 // this.player.bigPlayButton.show();
282 // }, 2000);
283 }
284
285 playTrailer(src, click){
286 console.log("### playTrailer: ", src, click);
287 console.log("trailerState: ", this.trailerState);
288 // if (this.trailerState == 'notstarted' || this.trailerState == 'attempted'){
289
290 if (this.trailerState == 'notstarted' && !click){
291 this.master.playTrailerButton.show();
292 }
293
294 if (this.trailerState == 'notstarted' || click){
295 this.playingTrailer = true;
296 const player = this.player;
297 player.controls(false);
298 player.src({src});
299 if (click){
300 player.play();
301 }
302 this.trailerState = 'attempted';
303 }
304 }
305
306 stopTrailer(){
307 console.log("stopTrailer()");
308 console.log("trailerState: ", this.trailerState);
309 if (this.trailerState == 'playing'){
310 console.log('trailer has ended');
311 this.trailerState = 'ended';
312 this.master.liveMessage.setupAsSubtitle(false);
313 this.player.hasStarted(false);
314 }
315 }
316
317 setContentSrc(src, force){
318 console.log("### setContentSrc: ", src, force);
319 console.log("currentSrc: ", this.player.currentSrc());
320 console.log("paused: ", this.player.paused());
321 console.log("currentTime: ", this.player.currentTime());
322 this.playingTrailer = false;
323 this.contentSrc = src;
324
325 const owner = this;
326 clearTimeout(this.setSrcTimeout);
327 this.setSrcTimeout = setTimeout(() => {
328 console.log("setting src...");
329 // src = src != null ? src : owner.player.currentSrc()
330 // owner.player.src({
331 // src,
332 // type: "application/x-mpegURL",
333 // llhls: isLlHls(src)
334 // });
335 owner.playContent(force);
336 }, force ? 1 : 2000);
337
338 // this.player.controlBar.show();
339 // this.player.loadingSpinner.show();
340 this.player.controls(true);
341 // this.player.muted(true);
342 // this.player.play();
343 }
344
345 playContent(forced){
346 console.log("playContent() ", forced);
347 this.paused = false;
348 this.stopTrailer();
349 this.playingTrailer = false;
350 this.master.playTrailerButton.hide();
351 this.player.bigPlayButton.show();
352 clearTimeout(this.setSrcTimeout);
353 console.log("player.paused: ", this.player.paused());
354 console.log("currentTime: ", this.player.currentTime());
355 console.log("objectivelyPlaying: ", this.objectivelyPlaying);
356
357 // if (this.player.paused() || forced || this.player.currentTime() === 0){
358 if (!this.objectivelyPlaying || forced){
359 this.player.src({
360 src: this.contentSrc,
361 type: "application/x-mpegURL",
362 llhls: isLlHls(this.contentSrc)
363 });
364 console.log("autoplay: ", this.player.autoplay());
365 // this.player.currentTime(0);
366 console.log("played: ", this.played);
367 if (this.played){
368 var promise = this.player.play();
369 // console.log("promise: ", promise);
370 let player = this.player;
371 if (promise !== undefined) {
372 promise.then(function() {
373 console.log("Autoplay started ;)");
374 }).catch(function(error) {
375 console.log("Autoplay did not work ", error);
376 });
377 }
378 console.log("no promise")
379 }
380 }
381 this.player.controlBar.show();
382 this.player.loadingSpinner.show();
383 this.player.controls(true);
384 }
385
386 pauseContent(stop){
387 console.log("pauseContent()");
388 this.paused = true;
389 clearTimeout(this.setSrcTimeout);
390 console.log("playingTrailer: ", this.playingTrailer);
391 if (!this.playingTrailer){
392 console.log("paused: ", this.player.paused());
393 this.player.pause();
394 console.log("currentTime: ", this.player.currentTime());
395 this.player.controlBar.hide();
396 this.player.loadingSpinner.hide();
397 this.player.controls(false);
398 if (stop){
399 this.player.hasStarted(false);
400 }
401 }
402 }
403
404 runWatchdog(){
405 //console.log("runWatchdog()");
406 const currentTime = this.player.currentTime();
407 this.timeQueue.push(currentTime);
408
409 var objectivelyPlaying = false;
410 if (currentTime > 0){
411 const queueLength = this.timeQueue.length;
412 if (queueLength > 1){
413 if (this.timeQueue[queueLength - 1] > this.timeQueue[queueLength - 2]){
414 objectivelyPlaying = true;
415 }
416 }
417 }
418 this.objectivelyPlaying = objectivelyPlaying;
419
420 if (this.timeQueue.length > 25){
421 this.timeQueue.shift();
422 if (this.timeQueue[0] === this.timeQueue[this.timeQueue.length -1]){
423 console.log("queue: ", this.timeQueue[0], this.timeQueue[this.timeQueue.length -1]);
424 console.log("paused: ", this.paused);
425 console.log("ruler: ", this.master.ruler);
426 console.log("state: ", this.master.state);
427 console.log("player paused: ", this.player.paused());
428 console.log("currentTime: ", this.player.currentTime());
429
430 if (this.master.ruler == 2){
431 if (!this.player.paused()){
432 this.playContent(true);
433 }
434 }
435 else if (this.master.state > 1) {
436 if (!this.player.paused() || this.player.currentTime() === 0){
437 this.playContent(true);
438 }
439 }
440 this.timeQueue = [];
441 }
442 }
443 let self = this;
444 setTimeout(() => self.runWatchdog(), 1 * 1000)
445 }
446 }
447
448 class WpstreamChat {
449 // connected = '';
450
451 constructor(){
452 this.connected = '';
453 }
454
455 connect(url){
456 this.connected = 'yes';
457 if(typeof(connect)==='function' ){
458 connect(url);
459 }
460 }
461
462 disconnect(){
463 if( typeof(showChat) === 'function' && this.connected === 'yes' ){
464 showChat('info', null, wpstream_player_vars.chat_not_connected);
465 this.connected='no';
466 }
467 }
468 }
469
470 class WpstreamLiveMessage {
471
472
473 // element;
474 // msg;
475 // originalMessage;
476 // customMessage;
477 // state = -1; // -1 - unknown; 0 - hidden; 1 - showing original msg; 3 - showing paused msg; 5 - showing custom msg
478 static customMessageStates = ['init', 'paused', 'startup', 'ended'];
479
480 constructor(wrapper, id){
481 this.state = -1;
482 this.element = wrapper.find('.wpstream_not_live_mess');
483 this.msg = wrapper.find('.wpstream_not_live_mess_mess');
484 this.originalMessage = this.msg.text();
485 console.log("originalMessage: ", this.originalMessage);
486 var playerElement = jQuery('#wpstream-video' + id);
487 this.element.appendTo(playerElement);
488 }
489
490 setCustomMessage(msg){
491 this.customMessage = msg;
492 if (WpstreamLiveMessage.customMessageStates.includes(this.state)){
493 this.showMessage(this.state);
494 }
495 }
496
497 showMessage(state){
498 // console.log("showMessage: ", state);
499 var label;
500 if (this.customMessage && WpstreamLiveMessage.customMessageStates.includes(state)){
501 label = this.customMessage;
502 }
503 else {
504 label = wpstream_player_vars[`wpstream_player_state_${state}_msg`];
505 }
506 this.msg.text(label);
507 // don't show if label is empty or spaces
508 if (!/^\s*$/.test(label))
509 this.show();
510 else
511 this.hide();
512 this.state = state;
513 }
514
515 showOriginalMessage(){
516 this.msg.text(this.originalMessage)
517 this.show();
518 this.state = 1;
519 }
520
521 setupAsSubtitle(set){
522 console.log("element: ", this.element);
523 this.element[0].style.top = set ? '80%' : '31%';
524 }
525
526 //public
527 hide(){
528 this.element.hide();
529 this.state = 0;
530 }
531
532 //private
533 show(){
534 this.element.show();
535 }
536
537
538 }
539
540 class LiveCounter {
541 // element;
542 constructor(wrapper, id){
543 console.log("[]LiveCounter: ", wrapper, id);
544 this.element = wrapper.find('.wpestream_live_counting');
545 this.element.css("background-color","rgb(174 69 69 / 90%)");
546 //var playerElement = wrapper.find('.wpstream-video' + id);
547 var playerElement = jQuery('#wpstream-video' + id);
548 console.log("playerElement: ", playerElement);
549 this.element.appendTo(playerElement);
550 this.hide();
551 }
552
553 show(){
554 this.element.show();
555 }
556
557 hide(){
558 this.element.hide();
559 }
560 setCount(count){
561 this.element.html( count + " Viewers");
562 }
563 }
564
565 class LiveConnect {
566 // master;
567 // wsUri;
568 // ws;
569 // connectCount = 0;
570 // connected = false;
571 // pendingConnect = false;
572
573 constructor(master){
574 this.connectCount = 0;
575 this.connected = false;
576 this.pendingConnect = false;
577 this.master = master;
578 }
579
580 setup(wsUri){
581 console.log("setup: ", wsUri);
582 this.close();
583 this.wsUri = wsUri;
584 this.connect();
585 }
586
587 close(){
588 if (this.ws != null){
589 this.ws.close();
590 }
591 this.ws = null;
592 }
593
594 connect(){
595 let connectAttempt = ++ this.connectCount;
596 console.log("connect() ", connectAttempt);
597 this.pendingConnect = true;
598 try {
599 this.ws = new WebSocket(this.wsUri);
600 let owner = this;
601 this.ws.onopen = function () {
602 console.log("connected. ", connectAttempt);
603 owner.pendingConnect = false;
604 owner.master.onLiveConnectActive(true);
605 //socket_connection.send(`{"type":"register","data":"${now}"}`);
606 };
607 this.ws.onclose = function(){
608 console.log("onclose.. ", connectAttempt);
609 owner.master.onLiveConnectActive(false);
610 }
611 this.ws.onerror = function (error) {
612 console.log("onerror: ", connectAttempt, error);
613 owner.master.onLiveConnectActive(false);
614 };
615 this.ws.onmessage = function (message) {
616 console.log("onmessage: ", connectAttempt, message.data);
617 owner.processMessage(message.data);
618 }
619 }
620 catch (error){
621 console.log(error);
622 this.master.onLiveConnectActive(false);
623 }
624 }
625
626 processMessage(msg){
627 console.log("processMessage: ", msg);
628 var json;
629 try {
630 json = JSON.parse(msg);
631 } catch (e) {
632 console.log("Invalid JSON: ", msg);
633 return;
634 }
635 if (json.type){
636 switch(json.type){
637 case "viewerCount":
638 this.master.updateViewerCount(json.data);
639 break;
640 case "onair":
641 if (json.info){
642 this.master.setState(json.info.broadcasting);
643 }
644 else {
645 this.master.setState(json.data ? 'onair' : 'paused');
646 }
647 break;
648 case "status":
649 this.master.liveMessage.setCustomMessage(json.data);
650 break;
651 default:
652 console.log("invalid type: ", json.type);
653 }
654 }
655 }
656 }
657
658 function wpstream_read_websocket_info(event_id,player, player_wrapper, socket_wss_live_conect_views_uri, event_uri){
659 console.log("wpstream_read_websocket_info: ", event_id, player, player_wrapper, socket_wss_live_conect_views_uri, event_uri);
660 console.log("sldpPlayer: ", sldpPlayer);
661 if (sldpPlayer != null){
662 var chat = new WpstreamChat();
663 chat.connect(socket_wss_live_conect_views_uri);
664 }
665 }
666
667 jQuery(document).ready(function ($) {
668 console.log("ready!")
669 var event_id;
670 var player_wrapper;
671 jQuery('.wpstream_live_player_wrapper').each(function(){
672 console.log("wrapper: ", this, $(this));
673 if($(this).hasClass('wpstream_low_latency')){
674 return;
675 }
676 event_id = jQuery(this).attr('data-product-id');
677 player_wrapper = jQuery(this);
678
679 //wpstream_check_player_status_ticker(player_wrapper,event_id);
680 });
681
682 });
683
684
685
686 var sldpPlayer;
687
688 function initPlayer(playerID,low_latency_uri,muted,autoplay){
689 console.log("initPlayer: ", low_latency_uri)
690 var is_muted = false;
691 var is_autoplay = true;
692 if(muted === 'muted'){
693 is_muted=true;
694 }
695
696 if(autoplay !== 'autoplay'){
697 is_autoplay=false;
698 }
699
700 console.log('is_muted '+is_muted + '/ '+is_autoplay);
701
702 let player = OvenPlayer.create(playerID, {
703 "autoStart": is_autoplay,
704 "autoFallback": false,
705 "mute": is_muted,
706 "sources": [{
707 "type": "webrtc",
708 "file": low_latency_uri
709 }],
710 "hlsConfig": {
711 "liveSyncDuration": 1.5,
712 "liveMaxLatencyDuration": 3,
713 "maxLiveSyncPlaybackRate": 1.5
714 },
715 "webrtcConfig": {
716 "timeoutMaxRetry": 100,
717 "connectionTimeout": 10000
718 }
719 });
720
721
722 };
723
724 function removePlayer(){
725 sldpPlayer.destroy();
726 }
727
728 // {
729 // videoElementId
730 // trailerUrl
731 // videoUrl
732 // autoplay
733 // muted
734 // playTrailerButtonElementId
735 // playVideoButtonElementId
736 // }
737 function wpstream_player_initialize_vod(settings){
738
739 console.log('wpstream_player_initialize_vod: ', settings);
740 var playing = settings.trailerUrl ? 'trailer' : 'content';
741
742 const playTrailerButton = jQuery(`#${settings.playTrailerButtonElementId}`)
743 const playVideoButton = jQuery(`#${settings.playVideoButtonElementId}`);
744
745 if (!settings.trailerUrl) {
746 playTrailerButton.hide();
747 }
748 if (!settings.videoUrl){
749 playVideoButton.hide();
750 }
751
752 const initialSrc = settings.trailerUrl ? getSrc(settings.trailerUrl) : getSrc(settings.videoUrl);
753 console.log("initialSrc: ", initialSrc);
754
755 const player = videojs(settings.videoElementId);
756 player.preload('auto');
757 player.playsinline(true);
758 player.controls(!settings.trailerUrl);
759 player.autoplay(settings.autoplay);
760 player.muted(settings.muted);
761
762 player.src({...initialSrc, autoplay:true, muted: true});
763
764 player.on("play", () => {
765 console.log('play()');
766 playTrailerButton.hide();
767 console.log("playing: ", playing);
768 if (playing != 'trailer'){
769 playVideoButton.hide();
770 }
771 });
772
773 player.on('ended', () => {
774 console.log("ended")
775 if (playing == 'trailer'){
776 console.log('trailer has ended');
777 if (settings.videoUrl){
778 playing = 'content';
779 player.controls(true);
780 player.autoplay(false);
781 player.src(getSrc(settings.videoUrl))
782 }
783 else {
784 player.hasStarted(false);
785 }
786 }
787 else {
788 console.log('video has ended');
789 }
790 });
791
792 player.on("error", () => {
793 console.log('error()');
794 if (playing == 'trailer'){
795 console.log('trailer failed');
796 playTrailerButton.hide();
797 if (videoUrl){
798 playing = 'content';
799 player.controls(true);
800 player.src(getSrc(settings.videoUrl))
801 }
802 }
803 });
804
805 playTrailerButton.on('click',function(){
806 console.log("playTrailer()")
807 player.play();
808 });
809
810 playVideoButton.on('click',function(){
811 console.log("playVideo")
812 if (!settings.videoUrl)
813 return;
814 if (playing == 'trailer'){
815 playing = 'content';
816 player.controls(true);
817 player.src(getSrc(settings.videoUrl));
818 }
819 player.play();
820 });
821 }
822
823 function getSrc(url) {
824 return {
825 src: url,
826 type: url.endsWith('.m3u8') ? 'application/x-mpegURL' : null
827 }
828 }
829
830 function isLlHls(url){
831 return /ll[a-z]+\.m3u8/.test(url);
832 }