UNPKG

ngx-video-list-player

Version:

A simple Angular video player with video list. No dependecies. Only custom controls, css, ts and svgs. Youtube support

1 lines 83.7 kB
{"version":3,"file":"ngx-video-list-player.mjs","sources":["../../../projects/ngx-video-list-player/src/lib/Models/video-event-types.model.ts","../../../projects/ngx-video-list-player/src/lib/Constants/youtube-state.constant.ts","../../../projects/ngx-video-list-player/src/lib/Directives/stop-propagation.directive.ts","../../../projects/ngx-video-list-player/src/lib/Components/ngx-video-list-player.component.ts","../../../projects/ngx-video-list-player/src/lib/Components/ngx-video-list-player.component.html","../../../projects/ngx-video-list-player/src/lib/ngx-video-list-player.module.ts","../../../projects/ngx-video-list-player/src/public-api.ts","../../../projects/ngx-video-list-player/src/ngx-video-list-player.ts"],"sourcesContent":["export class VideoEventTypes {\r\n public static readonly TimeUpdate = \"timeupdate\" \r\n public static readonly LoadedMetadata = \"loadedmetadata\" \r\n public static readonly FullScreenChange = \"fullscreenchange\"\r\n public static readonly Ended = \"ended\"\r\n public static readonly LeavePictureInPicture = \"leavepictureinpicture\"\r\n public static readonly EnterPictureInPicture = \"enterpictureinpicture\"\r\n public static readonly Pause = \"pause\"\r\n public static readonly Play = \"play\"\r\n public static readonly CanPlay = \"canplay\"\r\n public static readonly Error = \"error\"\r\n}","export class YoutubeStateConstant {\r\n static Unstarted: number = -1;\r\n static Ended: number = 0;\r\n static Playing: number = 1;\r\n static Paused: number = 2;\r\n static Buffering: number = 3;\r\n static VideoCued: number = 5;\r\n}","import { Directive, HostListener } from '@angular/core';\r\n\r\n@Directive({\r\n selector: '[stopPropagation]'\r\n})\r\nexport class StopPropagationDirective {\r\n\r\n @HostListener(\"click\", ['$event']) onClick(event: Event) {\r\n if (event.stopPropagation) {\r\n event.stopPropagation();\r\n }\r\n else if (window.event) {\r\n window.event.cancelBubble = true;\r\n }\r\n }\r\n}\r\n","import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, HostListener, Input, OnDestroy, OnInit, Output, QueryList, Renderer2, ViewChild, ViewChildren } from '@angular/core';\r\nimport { VideoEventTypes } from '../Models/video-event-types.model';\r\nimport { } from '../Models/global.model';\r\nimport { IVideoConfig, IVideoSource } from '../Models/ngx-video-list-player.config';\r\nimport { YoutubeStateConstant } from '../Constants/youtube-state.constant';\r\nimport { IExtendedVideoSubtitle } from '../Models/custom.config';\r\nimport { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';\r\nimport { EventEmitter } from '@angular/core';\r\nimport { YouTubePlayer } from '@angular/youtube-player';\r\n\r\n@Component({\r\n selector: 'ngx-video-list-player',\r\n templateUrl: 'ngx-video-list-player.component.html',\r\n styleUrls: ['ngx-video-list-player.component.scss']\r\n})\r\nexport class NgxVideoListPlayerComponent implements AfterViewInit, OnInit, OnDestroy {\r\n\r\n videoElement: HTMLVideoElement;\r\n private mediaControlElement: HTMLElement;\r\n actualVideo: IVideoSource;\r\n\r\n @ViewChild('mediaVideo') video: ElementRef;\r\n @ViewChild('mediaVideoSource') videoSource: ElementRef;\r\n @ViewChild(\"progressContainer\") progressContainer: ElementRef;\r\n @ViewChild(\"progressContainerHover\") progressContainerHover: ElementRef;\r\n @ViewChildren(\"from_pause_to_play\") fromPauseToPlay: QueryList<ElementRef>;\r\n @ViewChildren(\"from_play_to_pause\") fromPlayToPause: QueryList<ElementRef>;\r\n @ViewChild(\"mediaPlayer\") mediaPlayer: ElementRef;\r\n @ViewChild(\"mediaControlContainer\") mediaControlContainer: ElementRef;\r\n @ViewChild(\"meter\") meterContainer: ElementRef;\r\n @ViewChild(\"progressSlider\") progressSlider: ElementRef;\r\n @ViewChild(\"videoTitleContainer\") videoTitleContainer: ElementRef;\r\n @ViewChild(\"dropUpContent\") dropUpContent: ElementRef;\r\n @ViewChild(\"videoListContainer\") videoListContainer: ElementRef;\r\n @ViewChildren(\"videoListElement\") videoListElements: QueryList<ElementRef>;\r\n @ViewChild(\"mobileDeviceMainPprContainer\") mobileDeviceMainPprContainer: ElementRef;\r\n @ViewChild(\"subtitleModal\") subtitleModal: ElementRef;\r\n @ViewChild('youtubePlayer', {static: true}) youtubePlayer: YT.Player;\r\n\r\n @Input() config: IVideoConfig;\r\n @Output() onTimeUpdate = new EventEmitter();\r\n @Output() onCanPlay = new EventEmitter();\r\n @Output() onLoadedMetadata = new EventEmitter();\r\n \r\n private visibleMobileDeviceMainPprContainer: boolean = false;\r\n private disableControlHide: boolean = false;\r\n private displayControlsTimeout: NodeJS.Timeout;\r\n private countDownCircleTimeout: NodeJS.Timeout;\r\n private youtubeCurrentTimeInterval: NodeJS.Timeout;\r\n private mediaPlayerIsFocused: boolean = false;\r\n private actualVideoIndex: number = 0;\r\n private firstSourceLoad: boolean = false;\r\n private firstVideoLoad: boolean = true;\r\n private pauseKeyboardCodes: string[] = [\"Space\"];\r\n\r\n subtitles: IExtendedVideoSubtitle[];\r\n videoName: string;\r\n currentTime: string = \"0:00\";\r\n duration: string = \"0:00\";\r\n isFullScreen: boolean = false;\r\n volumePercent: number = 100;\r\n muted: boolean = false;\r\n progressSliderMaxValue: number = 100000;\r\n progressSliderValue: number = 0;\r\n pipIsActive: boolean = false;\r\n supportPictureInPicture = 'pictureInPictureEnabled' in document && document.pictureInPictureEnabled;\r\n supportFullScreen = 'fullscreenEnabled' in document && document.fullscreenEnabled;\r\n canPlay?: boolean;\r\n videoType: string;\r\n actualSubtitleId: string;\r\n isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\r\n youtubeIsPaused: boolean = false;\r\n youtubeIsEnded: boolean = false;\r\n\r\n //Safari does not trigger CanPlay event\r\n isSafariBrowser: boolean = navigator.userAgent.toLowerCase().indexOf(\"safari\") != -1 && navigator.userAgent.toLowerCase().indexOf(\"chrome\") == -1;\r\n\r\n constructor(private renderer: Renderer2, \r\n private breakpointObserver: BreakpointObserver,\r\n private changeDetectorRef: ChangeDetectorRef) {\r\n \r\n }\r\n\r\n ngOnInit():void { \r\n if(!this.config.isAutoPlay)\r\n this.config.isAutoPlay = false;\r\n\r\n if(!this.config.isFirstVideoAutoPlay)\r\n this.config.isFirstVideoAutoPlay = false;\r\n\r\n if(this.config.volumeCookieName) {\r\n const volumeCookieValue = document.cookie\r\n .split('; ')\r\n .find(row => row.startsWith(`${this.config.volumeCookieName}=`));\r\n\r\n if(volumeCookieValue) {\r\n this.volumePercent = parseInt(volumeCookieValue.split('=')[1]);\r\n if(this.volumePercent < 0)\r\n this.volumePercent = 0;\r\n else if(this.volumePercent > 100)\r\n this.volumePercent = 100;\r\n }\r\n }\r\n\r\n if(this.config.videoIndexCookieName) {\r\n const videoIndexCookieValue = document.cookie\r\n .split('; ')\r\n .find(row => row.startsWith(`${this.config.videoIndexCookieName}=`));\r\n \r\n if(videoIndexCookieValue)\r\n this.actualVideoIndex = parseInt(videoIndexCookieValue.split('=')[1]);\r\n }\r\n }\r\n\r\n ngAfterViewInit():void {\r\n this.videoElement = this.video.nativeElement as HTMLVideoElement;\r\n\r\n if(isNaN(this.actualVideoIndex) || this.actualVideoIndex > this.config.sources.length - 1 || this.actualVideoIndex < 0)\r\n this.actualVideoIndex = 0;\r\n \r\n this.setVideoIndexCookie();\r\n\r\n this.loadVideo();\r\n this.changeDetectorRef.detectChanges();\r\n\r\n this.videoElement.controls = false;\r\n this.videoElement.ontimeupdate = (this.videoEventHandler.bind(this));\r\n this.videoElement.onloadedmetadata = (this.videoEventHandler.bind(this));\r\n this.videoElement.onended = this.videoEventHandler.bind(this);\r\n this.videoElement.onleavepictureinpicture = this.videoEventHandler.bind(this);\r\n this.videoElement.onenterpictureinpicture = this.videoEventHandler.bind(this);\r\n this.videoElement.onpause = this.videoEventHandler.bind(this);\r\n this.videoElement.onplay = this.videoEventHandler.bind(this);\r\n this.videoElement.oncanplay = this.videoEventHandler.bind(this);\r\n this.videoElement.onerror = this.videoEventHandler.bind(this);\r\n (this.videoSource.nativeElement as HTMLSourceElement).onerror = this.videoEventHandler.bind(this);\r\n this.mediaControlElement = this.mediaPlayer.nativeElement as HTMLElement;\r\n this.mediaControlElement.onfullscreenchange = this.videoEventHandler.bind(this);\r\n this.setVolumeValue(this.volumePercent);\r\n\r\n this.breakpointObserver.observe([Breakpoints.XSmall, Breakpoints.Small]).subscribe(result => {\r\n if(this.config.videoListDisplayMode) {\r\n switch(this.config.videoListDisplayMode) {\r\n case \"inline\": \r\n this.renderer.addClass(this.mediaPlayer.nativeElement, \"custom-col-8\");\r\n this.renderer.addClass(this.videoListContainer.nativeElement, \"custom-col-4\");\r\n this.renderer.removeClass(this.mediaPlayer.nativeElement, \"custom-col-12\");\r\n this.renderer.removeClass(this.videoListContainer.nativeElement, \"custom-col-12\");\r\n break;\r\n case \"block\":\r\n this.renderer.addClass(this.mediaPlayer.nativeElement, \"custom-col-12\");\r\n this.renderer.addClass(this.videoListContainer.nativeElement, \"custom-col-12\");\r\n this.renderer.removeClass(this.mediaPlayer.nativeElement, \"custom-col-8\");\r\n this.renderer.removeClass(this.videoListContainer.nativeElement, \"custom-col-4\");\r\n break;\r\n case \"none\": \r\n this.renderer.setStyle(this.videoListContainer.nativeElement, \"display\", \"none\");\r\n this.renderer.removeClass(this.mediaPlayer.nativeElement, \"custom-col-8\");\r\n this.renderer.addClass(this.mediaPlayer.nativeElement, \"custom-col-12\");\r\n break;\r\n }\r\n return;\r\n }\r\n if (result.matches) {\r\n this.renderer.removeClass(this.mediaPlayer.nativeElement, \"custom-col-8\");\r\n this.renderer.removeClass(this.videoListContainer.nativeElement, \"custom-col-4\");\r\n this.renderer.addClass(this.mediaPlayer.nativeElement, \"custom-col-12\");\r\n this.renderer.addClass(this.videoListContainer.nativeElement, \"custom-col-12\");\r\n } else {\r\n this.renderer.addClass(this.mediaPlayer.nativeElement, \"custom-col-8\");\r\n this.renderer.addClass(this.videoListContainer.nativeElement, \"custom-col-4\");\r\n this.renderer.removeClass(this.mediaPlayer.nativeElement, \"custom-col-12\");\r\n this.renderer.removeClass(this.videoListContainer.nativeElement, \"custom-col-12\");\r\n }\r\n this.resizeVideoListContainer();\r\n })\r\n }\r\n\r\n videoEventHandler(ev: Event):void {\r\n if(this.actualVideo.isYoutubeVideo && ev.type != VideoEventTypes.FullScreenChange)\r\n return;\r\n \r\n switch(ev.type){\r\n case VideoEventTypes.TimeUpdate: \r\n if(!this.videoElement.duration)\r\n {\r\n this.onTimeUpdate.emit();\r\n return;\r\n }\r\n \r\n this.timeUpdateEvent();\r\n break;\r\n case VideoEventTypes.LoadedMetadata: \r\n this.loadMetadataEvent();\r\n break;\r\n case VideoEventTypes.FullScreenChange:\r\n this.isFullScreen = !!document.fullscreenElement;\r\n break;\r\n case VideoEventTypes.Ended: \r\n this.endEvent(true);\r\n break;\r\n case VideoEventTypes.LeavePictureInPicture:\r\n this.pipIsActive = false;\r\n this.mediaPlayerMouseLeave();\r\n //Not refresh pip Svg automatic after close in pause state\r\n this.changeDetectorRef.detectChanges();\r\n //setTimeout is beacuse of exitPiP pause\r\n setTimeout(() => {\r\n if (this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getPlayerState() == YoutubeStateConstant.Ended : this.videoElement.ended) {\r\n this.endEvent(false);\r\n }\r\n }, 1);\r\n break;\r\n case VideoEventTypes.EnterPictureInPicture: \r\n this.pipIsActive = true;\r\n this.mediaPlayerMouseMove();\r\n this.clearMobileDeviceMainPprContainerStyles();\r\n break;\r\n case VideoEventTypes.Play: \r\n this.playEvent();\r\n break;\r\n case VideoEventTypes.Pause: \r\n this.pauseEvent();\r\n break;\r\n case VideoEventTypes.CanPlay: \r\n this.canPlayEvent();\r\n this.onCanPlay.emit();\r\n break;\r\n case VideoEventTypes.Error: \r\n this.videoLoadErrorHandling();\r\n break;\r\n }\r\n } \r\n\r\n private videoLoadErrorHandling() {\r\n this.resizeVideoListContainer();\r\n this.canPlay = false;\r\n this.firstSourceLoad = false;\r\n this.firstVideoLoad = false;\r\n if(this.isNextVideo()) {\r\n this.clearCountDownCircleTimeout();\r\n this.countDownCircleTimeout = setTimeout(() => {\r\n this.next();\r\n }, 5000);\r\n }\r\n }\r\n\r\n private canPlayEvent() {\r\n this.resizeVideoListContainer();\r\n this.canPlay = true; \r\n if(this.firstVideoLoad && this.config.isFirstVideoAutoPlay) {\r\n this.mute();\r\n this.playPause();\r\n } \r\n else if(!this.firstVideoLoad && this.firstSourceLoad && this.config.isAutoPlay) {\r\n this.playPause();\r\n }\r\n this.firstSourceLoad = false;\r\n this.firstVideoLoad = false;\r\n }\r\n\r\n private endEvent(isNextEvent: boolean): void{\r\n if(isNextEvent) {\r\n if(this.isNextVideo() && this.config.isAutoPlay) {\r\n this.clearCountDownCircleTimeout();\r\n this.countDownCircleTimeout = setTimeout(() => {\r\n this.next();\r\n }, 5000);\r\n }\r\n }\r\n this.fromPlayToPause.forEach(element => {\r\n element.nativeElement.beginElement(); \r\n });\r\n\r\n if(this.actualVideo != null && this.actualVideo.isYoutubeVideo)\r\n this.youtubeIsEnded = true;\r\n }\r\n\r\n async pipEnter():Promise<void> {\r\n if(!this.canPlay)\r\n return;\r\n\r\n await this.videoElement.requestPictureInPicture();\r\n }\r\n\r\n async pipExit():Promise<void> {\r\n await document.exitPictureInPicture();\r\n }\r\n\r\n private playEvent():void {\r\n this.fromPauseToPlay.forEach(element => {\r\n element.nativeElement.beginElement(); \r\n });\r\n this.mediaPlayerMouseLeave(); \r\n if(this.actualVideo != null && this.actualVideo.isYoutubeVideo)\r\n this.youtubeIsPaused = false;\r\n }\r\n\r\n private pauseEvent():void {\r\n this.fromPlayToPause.forEach(element => {\r\n element.nativeElement.beginElement(); \r\n });\r\n this.mediaPlayerMouseMove();\r\n this.clearMobileDeviceMainPprContainerStyles();\r\n if(this.actualVideo != null && this.actualVideo.isYoutubeVideo)\r\n this.youtubeIsPaused = true;\r\n }\r\n \r\n private clearMobileDeviceMainPprContainerStyles() {\r\n if(this.mobileDeviceMainPprContainer) {\r\n this.visibleMobileDeviceMainPprContainer = true;\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"visibility\");\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"opacity\");\r\n }\r\n }\r\n\r\n playPause():void { \r\n if(!this.canPlay)\r\n return;\r\n \r\n this.clearCountDownCircleTimeout();\r\n\r\n if(this.actualVideo.isYoutubeVideo) {\r\n var youtubeState = this.youtubePlayer.getPlayerState();\r\n this.youtubeIsEnded = false;\r\n if(youtubeState != YoutubeStateConstant.Playing)\r\n {\r\n this.youtubePlayer.playVideo();\r\n this.youtubeIsPaused = false;\r\n }\r\n else\r\n {\r\n this.youtubePlayer.pauseVideo();\r\n this.youtubeIsPaused = true;\r\n }\r\n }\r\n else {\r\n if(this.videoElement.paused || this.videoElement.ended) {\r\n this.videoElement.play();\r\n }\r\n else{\r\n this.videoElement.pause(); \r\n }\r\n }\r\n \r\n }\r\n\r\n fullScreen():void {\r\n if (this.mediaControlElement.requestFullscreen) {\r\n this.mediaControlElement.requestFullscreen();\r\n } else if (this.mediaControlElement.webkitRequestFullscreen) { /* Safari */\r\n this.mediaControlElement.webkitRequestFullscreen();\r\n } else if (this.mediaControlElement.msRequestFullscreen) { /* IE11 */ \r\n this.mediaControlElement.msRequestFullscreen();\r\n } else if (this.mediaControlElement.mozRequestFullscreen) {\r\n this.mediaControlElement.mozRequestFullscreen();\r\n } else if(this.videoElement.webkitEnterFullscreen)\r\n this.videoElement.webkitEnterFullscreen();\r\n\r\n if(this.actualVideo.isYoutubeVideo)\r\n this.isFullScreen = true;\r\n }\r\n\r\n exitFullScreen():void {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if (document.webkitExitFullscreen) { /* Safari */\r\n document.webkitExitFullscreen();\r\n } else if (document.msExitFullscreen) { /* IE11 */\r\n document.msExitFullscreen();\r\n } else if (document.mozCancelFullScreen) {\r\n document.mozCancelFullScreen();\r\n }\r\n\r\n if(this.actualVideo.isYoutubeVideo)\r\n this.isFullScreen = false;\r\n }\r\n\r\n isNextVideo(): boolean {\r\n return this.actualVideoIndex < this.config.sources.length - 1;\r\n }\r\n\r\n \r\n next(): void {\r\n this.actualVideoIndex += 1;\r\n this.loadVideo();\r\n }\r\n\r\n prev(): void {\r\n if(this.actualVideoIndex == 0) {\r\n this.clearCountDownCircleTimeout();\r\n\r\n this.videoElement.currentTime = 0;\r\n if(!this.videoElement.paused)\r\n this.playPause();\r\n }\r\n else {\r\n this.actualVideoIndex -= 1;\r\n this.loadVideo();\r\n }\r\n }\r\n\r\n private loadMetadataEvent() {\r\n const duration = this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getDuration() : this.videoElement.duration;\r\n if(duration == 0)\r\n this.duration = \"0:00\"\r\n else\r\n this.duration = `${Math.floor(duration / 60)}:${Math.floor(duration % 60).toLocaleString(\"en-US\", { minimumIntegerDigits: 2 })}`;\r\n\r\n this.firstSourceLoad = true;\r\n this.supportFullScreen ||= this.videoElement.webkitSupportsFullscreen;\r\n if(this.isSafariBrowser)\r\n {\r\n this.canPlayEvent();\r\n this.onCanPlay.emit();\r\n }\r\n\r\n this.onLoadedMetadata.emit();\r\n }\r\n\r\n private timeUpdateEvent() {\r\n try {\r\n const duration = this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getDuration() : this.videoElement.duration;\r\n let currentTime = this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getCurrentTime() : this.videoElement.currentTime;\r\n if(!currentTime)\r\n currentTime = 0;\r\n \r\n let percentage = (100 / duration) * currentTime;\r\n if(isNaN(percentage))\r\n percentage = 0;\r\n\r\n this.renderer.setStyle(this.progressContainer.nativeElement, \"width\", `${percentage}%`);\r\n if(currentTime == 0)\r\n this.currentTime = `0:00`;\r\n else\r\n this.currentTime = `${Math.floor(currentTime / 60)}:${Math.floor(currentTime % 60).toLocaleString(\"en-US\", { minimumIntegerDigits: 2 })}`;\r\n \r\n this.progressSliderValue = percentage * (this.progressSliderMaxValue / 100);\r\n this.onTimeUpdate.emit();\r\n }\r\n catch { \r\n const percentage = 0;\r\n this.renderer.setStyle(this.progressContainer.nativeElement, \"width\", `${percentage}%`);\r\n this.currentTime = `0:00`;\r\n this.progressSliderValue = percentage * (this.progressSliderMaxValue / 100);\r\n this.onTimeUpdate.emit();\r\n }\r\n }\r\n\r\n private onReadyYoutubeVideo() {\r\n if(!this.actualVideo.isYoutubeVideo)\r\n return;\r\n\r\n this.setVolumeValue(this.volumePercent);\r\n this.loadMetadataEvent();\r\n this.canPlayEvent();\r\n this.onCanPlay.emit();\r\n }\r\n\r\n private onStateChangeYoutubeVideo(event) {\r\n if(!this.actualVideo.isYoutubeVideo)\r\n return;\r\n\r\n switch (event.data) {\r\n case YoutubeStateConstant.Ended: \r\n this.endEvent(true); \r\n this.clearYoutubeCurrentTimeInterval();\r\n break;\r\n case YoutubeStateConstant.Playing: \r\n this.playEvent(); \r\n this.loadMetadataEvent(); \r\n this.clearYoutubeCurrentTimeInterval();\r\n this.youtubeCurrentTimeInterval = setInterval(() => {\r\n this.timeUpdateEvent();\r\n }, 100);\r\n break;\r\n case YoutubeStateConstant.Paused: \r\n this.pauseEvent(); \r\n this.clearYoutubeCurrentTimeInterval();\r\n break;\r\n case YoutubeStateConstant.VideoCued: \r\n this.onReadyYoutubeVideo();\r\n break;\r\n }\r\n\r\n }\r\n\r\n private async loadVideo(index?: number, tryNumber: number = 1): Promise<void> {\r\n if(index >= 0)\r\n this.actualVideoIndex = index;\r\n\r\n const videoElement = this.videoListElements.find((element, index) => index == this.actualVideoIndex);\r\n this.videoListContainer.nativeElement.scroll({\r\n top: videoElement.nativeElement.offsetTop - this.videoListContainer.nativeElement.offsetTop - videoElement.nativeElement.offsetHeight,\r\n left: 0,\r\n behavior: 'smooth'\r\n });\r\n\r\n this.clearCountDownCircleTimeout();\r\n\r\n this.setVideoIndexCookie();\r\n\r\n this.pauseEvent();\r\n \r\n this.canPlay = null;\r\n this.videoElement.currentTime = 0;\r\n this.progressSliderValue = 0;\r\n this.renderer.setStyle(this.progressContainerHover.nativeElement, \"width\", `0%`);\r\n this.renderer.setStyle(this.progressContainer.nativeElement, \"width\", `0%`);\r\n this.currentTime = \"0:00\"\r\n\r\n this.actualVideo = this.config.sources[this.actualVideoIndex];\r\n this.clearYoutubeCurrentTimeInterval();\r\n\r\n if(this.actualVideo.isYoutubeVideo) {\r\n if(this.pipIsActive)\r\n await document.exitPictureInPicture();\r\n\r\n if(this.youtubePlayer instanceof YouTubePlayer) {\r\n try {\r\n this.youtubePlayer = new YT.Player('youtubePlayer', {\r\n videoId: this.actualVideo.src,\r\n height: \"100%\",\r\n width: \"100%\",\r\n playerVars: { 'autoplay': 0, 'controls': 0, 'autohide': 1, 'disablekb': 1, 'showinfo': 0, 'iv_load_policy': 3, 'loop': 1, 'modestbranding': 1, 'playsinline': 0, 'rel': 0 },\r\n events: {\r\n 'onReady': this.onReadyYoutubeVideo.bind(this),\r\n 'onStateChange': this.onStateChangeYoutubeVideo.bind(this),\r\n 'onError': (e) => { \r\n if(tryNumber >= 4)\r\n {\r\n this.videoLoadErrorHandling.bind(this)();\r\n }\r\n else {\r\n setTimeout(() => { \r\n this.loadVideo(index, ++tryNumber);\r\n }, 1000);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n catch {\r\n if(tryNumber >= 4)\r\n this.videoLoadErrorHandling()\r\n else {\r\n setTimeout(() => { \r\n this.loadVideo(index, ++tryNumber);\r\n }, 1000);\r\n return;\r\n }\r\n }\r\n }\r\n else {\r\n this.youtubePlayer.loadVideoById(this.actualVideo.src, 0);\r\n this.youtubePlayer.stopVideo();\r\n }\r\n this.subtitles = [];\r\n this.videoElement.pause();\r\n\r\n setTimeout(() => { \r\n this.youtubeIsEnded = false;\r\n this.youtubeIsPaused = false;\r\n }, 150);\r\n }\r\n else {\r\n if(!(this.youtubePlayer instanceof YouTubePlayer))\r\n {\r\n this.youtubePlayer.stopVideo();\r\n }\r\n\r\n this.videoName = this.actualVideo.videoName;\r\n this.videoElement.src = this.actualVideo.src;\r\n this.videoType = this.actualVideo.type;\r\n this.subtitles = [];\r\n \r\n if(this.actualVideo.subtitles) {\r\n this.subtitles = this.actualVideo.subtitles.map(item => ({\r\n src: item.src,\r\n name: item.name,\r\n default: item.default,\r\n id: `video_vtt_${this.actualVideo.subtitles.indexOf(item)}`\r\n }));\r\n }\r\n \r\n var defaultSubtitle = this.subtitles.find(item => item.default);\r\n if(defaultSubtitle)\r\n this.actualSubtitleId = defaultSubtitle.id;\r\n else\r\n this.actualSubtitleId = null;\r\n }\r\n }\r\n\r\n private clearYoutubeCurrentTimeInterval(): void {\r\n if(this.youtubeCurrentTimeInterval)\r\n clearInterval(this.youtubeCurrentTimeInterval);\r\n }\r\n\r\n private clearCountDownCircleTimeout():void { \r\n if(this.countDownCircleTimeout)\r\n clearTimeout(this.countDownCircleTimeout);\r\n }\r\n\r\n mute():void {\r\n if(this.actualVideo.isYoutubeVideo) {\r\n this.youtubePlayer.isMuted() ? this.youtubePlayer.unMute() : this.youtubePlayer.mute();\r\n }\r\n else {\r\n this.videoElement.muted = !this.videoElement.muted;\r\n }\r\n\r\n this.muted = !this.muted;\r\n\r\n if(this.muted){\r\n this.volumePercent = 0;\r\n }\r\n else{\r\n this.volumePercent = this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getVolume() : this.videoElement.volume * 100;\r\n }\r\n }\r\n\r\n setVolume(event: Event):void {\r\n if(this.actualVideo.isYoutubeVideo) {\r\n this.youtubePlayer.unMute();\r\n }\r\n else {\r\n this.videoElement.muted = false;\r\n }\r\n\r\n this.muted = false;\r\n const percentage = parseInt((event.target as HTMLInputElement).value);\r\n\r\n if(this.config.volumeCookieName)\r\n document.cookie = `${this.config.volumeCookieName}=${percentage}`;\r\n\r\n this.setVolumeValue(percentage);\r\n this.volumePercent = percentage;\r\n }\r\n\r\n private setVolumeValue(percentage):void {\r\n try {\r\n if(this.actualVideo.isYoutubeVideo)\r\n this.youtubePlayer.setVolume(percentage);\r\n else\r\n this.videoElement.volume = percentage / 100;\r\n }\r\n catch {}\r\n }\r\n\r\n private setVideoIndexCookie():void {\r\n if(this.config.videoIndexCookieName)\r\n document.cookie = `${this.config.videoIndexCookieName}=${this.actualVideoIndex}`;\r\n }\r\n\r\n progressHelperMouseMove(event):void {\r\n if(!this.canPlay)\r\n return;\r\n\r\n const hoverPercent = event.offsetX / event.srcElement.offsetWidth * 100;\r\n this.renderer.setStyle(this.progressContainerHover.nativeElement, \"width\", `${hoverPercent}%`);\r\n this.renderer.setStyle(this.mediaControlContainer.nativeElement, \"height\", \"50px\");\r\n this.renderer.setStyle(this.meterContainer.nativeElement, \"height\", \"6px\");\r\n this.renderer.setStyle(this.progressSlider.nativeElement, \"display\", \"inline-block\");\r\n }\r\n\r\n mediaPlayerMouseMove():void {\r\n if(!this.canPlay)\r\n return;\r\n\r\n if(this.videoTitleContainer)\r\n this.renderer.removeStyle(this.videoTitleContainer.nativeElement, \"opacity\")\r\n\r\n this.renderer.removeStyle(this.mediaControlContainer.nativeElement, \"opacity\")\r\n this.renderer.removeStyle(this.mediaControlContainer.nativeElement, \"visibility\")\r\n this.renderer.removeStyle(this.meterContainer.nativeElement, \"opacity\")\r\n this.renderer.removeStyle(this.mediaPlayer.nativeElement, \"cursor\") \r\n if(this.mobileDeviceMainPprContainer) {\r\n this.visibleMobileDeviceMainPprContainer = true;\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"visibility\");\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"opacity\");\r\n }\r\n\r\n if((!this.actualVideo.isYoutubeVideo && !this.videoElement.paused && !this.videoElement.ended || this.actualVideo.isYoutubeVideo && !this.youtubeIsPaused && !this.youtubeIsEnded) \r\n && !this.disableControlHide && !this.pipIsActive) {\r\n if(this.displayControlsTimeout) {\r\n clearTimeout(this.displayControlsTimeout);\r\n }\r\n this.displayControlsTimeout = setTimeout(() =>{ this.mediaPlayerMouseLeave() }, 3000);\r\n }\r\n }\r\n\r\n mediaPlayerMouseLeave():void {\r\n if((!this.actualVideo.isYoutubeVideo && !this.videoElement.paused && !this.videoElement.ended || this.actualVideo.isYoutubeVideo && !this.youtubeIsPaused && !this.youtubeIsEnded)\r\n && !this.disableControlHide && !this.pipIsActive) {\r\n if(!this.isMobileDevice)\r\n this.openSubtitles(true);\r\n\r\n this.renderer.setStyle(this.mediaPlayer.nativeElement, \"cursor\", `none`)\r\n this.renderer.setStyle(this.mediaControlContainer.nativeElement, \"opacity\", `0`)\r\n this.renderer.setStyle(this.mediaControlContainer.nativeElement, \"visibility\", \"hidden\");\r\n this.renderer.setStyle(this.meterContainer.nativeElement, \"opacity\", `0`)\r\n \r\n if(this.videoTitleContainer)\r\n this.renderer.setStyle(this.videoTitleContainer.nativeElement, \"opacity\", \"0\")\r\n\r\n if(this.mobileDeviceMainPprContainer) {\r\n this.visibleMobileDeviceMainPprContainer = false;\r\n this.renderer.setStyle(this.mobileDeviceMainPprContainer.nativeElement, \"visibility\", \"hidden\");\r\n this.renderer.setStyle(this.mobileDeviceMainPprContainer.nativeElement, \"opacity\", \"0\");\r\n }\r\n }\r\n }\r\n\r\n mediaPlayerFocus():void {\r\n this.mediaPlayerIsFocused = true;\r\n }\r\n\r\n mediaPlayerFocusOut():void {\r\n this.mediaPlayerIsFocused = false; \r\n }\r\n\r\n @HostListener('document:keypress', ['$event'])\r\n handleDocumentKeyboardEvent(event: KeyboardEvent):void { \r\n if(this.pauseKeyboardCodes.find(item => item == event.code) && this.mediaPlayerIsFocused)\r\n this.playPause();\r\n }\r\n\r\n @HostListener('document:click', ['$event'])\r\n handleDocumentClickEvent(event: MouseEvent):void { \r\n this.openSubtitles(true);\r\n }\r\n\r\n @HostListener('window:resize', ['$event'])\r\n handleDocumentResizeEvent(event: MouseEvent):void { \r\n this.resizeVideoListContainer();\r\n }\r\n\r\n private resizeVideoListContainer() {\r\n const mediaPlayerHeight = this.mediaPlayer.nativeElement.offsetHeight;\r\n this.renderer.setStyle(this.videoListContainer.nativeElement, \"height\", `${mediaPlayerHeight}px`)\r\n }\r\n\r\n mediaControlContainerMouseEnter():void {\r\n if(this.isMobileDevice)\r\n return;\r\n\r\n this.disableControlHide = true;\r\n }\r\n\r\n mediaControlContainerMouseLeave():void {\r\n if(this.isMobileDevice)\r\n return;\r\n\r\n this.disableControlHide = false;\r\n }\r\n\r\n //Value range [0..this.progressSliderMaxValue]\r\n setProgressSlider(value):void {\r\n const duration = this.actualVideo.isYoutubeVideo ? this.youtubePlayer.getDuration() : this.videoElement.duration;\r\n const currentTime = duration * value / this.progressSliderMaxValue;;\r\n if(this.actualVideo.isYoutubeVideo) {\r\n var playerState = this.youtubePlayer.getPlayerState();\r\n if(playerState == YoutubeStateConstant.VideoCued) {\r\n this.youtubePlayer.loadVideoById(this.actualVideo.src, currentTime);\r\n }\r\n else\r\n this.youtubePlayer.seekTo(currentTime, true);\r\n }\r\n else {\r\n this.videoElement.currentTime = currentTime;\r\n }\r\n\r\n this.clearCountDownCircleTimeout();\r\n }\r\n\r\n progressThumbMouseMove(event: MouseEvent):void {\r\n if(!this.canPlay)\r\n return;\r\n\r\n this.renderer.setStyle(this.mediaControlContainer.nativeElement, \"height\", \"50px\");\r\n this.renderer.setStyle(this.meterContainer.nativeElement, \"height\", \"6px\");\r\n const percentage = (event.offsetX / (event.target as HTMLInputElement).clientWidth) * 100;\r\n if(percentage >= 0 && percentage <= 100)\r\n this.renderer.setStyle(this.progressContainerHover.nativeElement, \"width\", `${percentage}%`);\r\n }\r\n\r\n progressThumbMouseLeave():void {\r\n this.renderer.removeStyle(this.mediaControlContainer.nativeElement, \"height\");\r\n this.renderer.removeStyle(this.meterContainer.nativeElement, \"height\");\r\n this.renderer.removeStyle(this.progressContainerHover.nativeElement, \"width\");\r\n this.renderer.removeStyle(this.progressSlider.nativeElement, \"display\");\r\n }\r\n\r\n openSubtitles(instantHide: boolean = false):void {\r\n \r\n if(this.isMobileDevice) \r\n {\r\n if(!this.subtitleModal)\r\n return;\r\n\r\n if(instantHide || this.subtitleModal.nativeElement.classList.contains('show'))\r\n this.renderer.removeClass(this.subtitleModal.nativeElement, \"show\");\r\n else\r\n this.renderer.addClass(this.subtitleModal.nativeElement, \"show\");\r\n }\r\n else \r\n {\r\n if(!this.dropUpContent)\r\n return;\r\n\r\n if(instantHide || this.dropUpContent.nativeElement.classList.contains('show'))\r\n this.renderer.removeClass(this.dropUpContent.nativeElement, \"show\");\r\n else\r\n this.renderer.addClass(this.dropUpContent.nativeElement, \"show\"); \r\n }\r\n\r\n }\r\n\r\n setSubtitle(id: string):void {\r\n this.actualSubtitleId = id;\r\n\r\n for(var i = 0; i < this.videoElement.textTracks.length; i++) {\r\n this.videoElement.textTracks[i].mode = \"disabled\";\r\n }\r\n \r\n if(id) {\r\n this.videoElement.textTracks.getTrackById(id).mode = \"showing\";\r\n }\r\n }\r\n\r\n videoClickEvent():void {\r\n if(this.isMobileDevice)\r\n {\r\n if(this.visibleMobileDeviceMainPprContainer){\r\n this.mediaPlayerMouseLeave();\r\n }\r\n else {\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"visibility\");\r\n this.renderer.removeStyle(this.mobileDeviceMainPprContainer.nativeElement, \"opacity\");\r\n this.visibleMobileDeviceMainPprContainer = true;\r\n }\r\n }\r\n else{\r\n this.playPause();\r\n }\r\n }\r\n\r\n emptyVoid(): void {\r\n\r\n }\r\n\r\n ngOnDestroy() {\r\n this.clearYoutubeCurrentTimeInterval();\r\n }\r\n}\r\n","<div class=\"video-main-container\">\r\n <div *ngIf=\"isMobileDevice && subtitles && subtitles.length > 0\" class=\"subtitle-modal\" #subtitleModal>\r\n <div stopPropagation class=\"modal-content\">\r\n <!-- <span class=\"close\" (click)=\"closeSubtitleModal()\">&times;</span> -->\r\n <div class=\"modal-title\">\r\n {{ config.subtitleText || 'Subtitles' }}\r\n </div>\r\n <div class=\"modal-container\">\r\n <div [ngClass]=\"{'active': !actualSubtitleId}\" (click)=\"setSubtitle()\">\r\n {{ config.subtitleOffText || 'Off' }}\r\n </div>\r\n <div *ngFor=\"let subtitle of subtitles\" [ngClass]=\"{ 'active': actualSubtitleId == subtitle.id }\" (click)=\"setSubtitle(subtitle.id)\">\r\n {{ subtitle.name }}\r\n </div>\r\n </div>\r\n <div class=\"close-button-container\">\r\n <button class=\"close-button\" (click)=\"openSubtitles(true)\">Ok</button>\r\n </div>\r\n </div> \r\n </div>\r\n <div id='media-player' class=\"custom-col-8\" tabindex=\"-1\" (focus)=\"mediaPlayerFocus()\" (focusout)=\"mediaPlayerFocusOut()\" #mediaPlayer (mousemove)=\"mediaPlayerMouseMove()\" (mouseleave)=\"mediaPlayerMouseLeave()\">\r\n <div class=\"main-ppr-icon-container\" *ngIf=\"canPlay != null && (videoElement.paused || videoElement.ended || !canPlay || (actualVideo != null && actualVideo.isYoutubeVideo && (youtubeIsPaused || youtubeIsEnded)))\">\r\n <svg height=\"100\" width=\"100\" (click)=\"!isMobileDevice ? playPause() : emptyVoid()\">\r\n <circle *ngIf=\"!isMobileDevice && actualVideo != null && (!actualVideo.isYoutubeVideo || youtubeIsPaused || youtubeIsEnded)\" cx=\"50\" cy=\"50\" r=\"40\" style=\"cursor: pointer;\" stroke=\"rgb(234 13 191 / 45%)\" stroke-width=\"1\" fill=\"rgb(255 255 255 / 23%)\" />\r\n <polygon *ngIf=\"!isMobileDevice && canPlay && (actualVideo != null && (!actualVideo.isYoutubeVideo && videoElement.paused && !videoElement.ended || actualVideo.isYoutubeVideo && youtubeIsPaused))\" points=\"40,30 40,70 70,50\" style=\"fill:#ea0dbf;stroke:purple;stroke-width:1;cursor: pointer;\" />\r\n <use *ngIf=\"!isMobileDevice && (actualVideo != null && (!actualVideo.isYoutubeVideo && videoElement.ended || actualVideo.isYoutubeVideo && youtubeIsEnded))\" xlink:href=\"./assets/media-controls.svg#replay\" href=\"./assets/media-controls.svg#replay\" x=\"1\" y=\"0\" style=\"fill:#ea0dbf;stroke:purple;stroke-width:1\" />\r\n <use *ngIf=\"!canPlay && !isMobileDevice\" xlink:href=\"./assets/media-controls.svg#can_not_play\" href=\"./assets/media-controls.svg#can_not_play\" x=\"0\" y=\"0\" style=\"fill:#ea0dbf;stroke:purple;stroke-width:1\" />\r\n <use *ngIf=\"!canPlay && isMobileDevice\" xlink:href=\"./assets/media-controls.svg#can_not_play_mobile\" href=\"./assets/media-controls.svg#can_not_play_mobile\" x=\"11\" y=\"5\" style=\"fill:#ea0dbf;stroke:purple;stroke-width:1\" />\r\n </svg>\r\n </div>\r\n <div *ngIf=\"isMobileDevice && canPlay == true\" class=\"mobile-device-main-ppr-container\" #mobileDeviceMainPprContainer (click)=\"videoClickEvent()\">\r\n <div class=\"mobile-device-main-ppr-container-helper\">\r\n <div>\r\n <svg (click)=\"prev()\" height=\"33\" width=\"33\">\r\n <use xlink:href=\"./assets/media-controls.svg#prev\" href=\"./assets/media-controls.svg#prev\" x=\"0\" y=\"0\" />\r\n </svg>\r\n </div>\r\n <div style=\"margin-left: 2px;\">\r\n <svg (click)=\"playPause()\" height=\"33\" width=\"33\">\r\n <path id='line1' d=\"M 8 7 L 26 17 L 26 17 L 8 26\" style=\"fill:white;\">\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\" \r\n from=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n to=\"M 8 7 L 13 7 L 13 26 L 8 26\"\r\n begin=\"indefinite\"\r\n fill=\"freeze\"\r\n #from_pause_to_play />\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\"\r\n from=\"M 8 7 L 13 7 L 13 26 L 8 26\"\r\n to=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n fill=\"freeze\"\r\n #from_play_to_pause\r\n begin=\"indefinite\" />\r\n </path>\r\n <path id='line2' d=\"M 8 7 L 26 17 L 26 17 L 8 26\" style=\"fill:white;\">\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\" \r\n from=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n to=\"M 19 7 L 24 7 L 24 26 L 19 26\"\r\n begin=\"indefinite\"\r\n fill=\"freeze\"\r\n #from_pause_to_play />\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\"\r\n from=\"M 19 7 L 24 7 L 24 26 L 19 26\"\r\n to=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n fill=\"freeze\"\r\n #from_play_to_pause\r\n begin=\"indefinite\" />\r\n </path> \r\n </svg>\r\n </div> \r\n <div>\r\n <svg *ngIf=\"isNextVideo()\" (click)=\"next()\" height=\"33\" width=\"33\">\r\n <use xlink:href=\"./assets/media-controls.svg#next\" href=\"./assets/media-controls.svg#next\" x=\"0\" y=\"0\" />\r\n </svg>\r\n </div>\r\n </div> \r\n </div>\r\n <div *ngIf=\"(config.isVideoLoader == null || config.isVideoLoader) && canPlay == null\" class=\"loader-wrapper\" [ngClass]=\"{ 'mobile-device': isMobileDevice }\">\r\n <div class=\"loader\"></div>\r\n </div>\r\n <div *ngIf=\"((canPlay != null && (actualVideo != null && (!actualVideo.isYoutubeVideo && videoElement.ended || actualVideo.isYoutubeVideo && youtubeIsEnded))) || canPlay == false) && isNextVideo()\" class=\"next-loader\" [ngClass]=\"{ 'mobile-device': isMobileDevice }\">\r\n <ng-container *ngIf=\"isMobileDevice\">\r\n <svg>\r\n <circle cx=\"50%\" cy=\"50%\" r=\"11%\"/>\r\n </svg>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isMobileDevice\">\r\n <svg >\r\n <circle cx=\"50%\" cy=\"50%\" r=\"42\"/>\r\n </svg>\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"videoName && (actualVideo == null || !actualVideo.isYoutubeVideo)\" class=\"video-title\" #videoTitleContainer>\r\n <div class=\"video-title-text\">\r\n {{ videoName }} \r\n </div>\r\n </div>\r\n <div class=\"video-container\">\r\n <div class=\"youtube-video-container\" (click)=\"playPause()\" [hidden]=\"actualVideo && !actualVideo.isYoutubeVideo\" style=\"text-align: center;\" (mousemove)=\"mediaPlayerMouseMove()\" (mouseleave)=\"mediaPlayerMouseLeave()\">\r\n <youtube-player id=\"youtubePlayer\" #youtubePlayer style=\"position: absolute; left: 0; pointer-events: none;\"></youtube-player>\r\n </div>\r\n <video #mediaVideo [hidden]=\"actualVideo && actualVideo.isYoutubeVideo\" width=\"100%\" (click)=\"videoClickEvent()\">\r\n <source #mediaVideoSource [type]='videoType'>\r\n <track *ngFor=\"let subtitle of subtitles; let i = index\" [id]=\"subtitle.id\" [label]=\"subtitle.name\" kind=\"subtitles\" [src]=\"subtitle.src\" [attr.default]=\"subtitle.id == actualSubtitleId ? true : null\">\r\n </video>\r\n </div>\r\n <div id=\"media-control-container\" #mediaControlContainer (mouseenter)=\"mediaControlContainerMouseEnter()\" (mouseleave)=\"mediaControlContainerMouseLeave()\">\r\n <div id=\"media-controls\">\r\n <div class=\"progress-thumb\">\r\n <input [attr.disabled]=\"!canPlay ? true : null\" type=\"range\" min=\"0\" [max]=\"progressSliderMaxValue\" [value]=\"progressSliderValue\" class=\"progress-slider\" [ngClass]=\"{ 'mobile-device': isMobileDevice }\" #progressSlider (input)=\"setProgressSlider(progressSlider.value)\" (mousemove)=\"progressThumbMouseMove($event)\" (mouseleave)=\"progressThumbMouseLeave()\">\r\n </div>\r\n <div class=\"meter\" #meter>\r\n <span #progressContainer class=\"progress-container progress-base\">\r\n <span class=\"progress\">\r\n </span>\r\n </span>\r\n <span #progressContainerHover class=\"progress-container progress-hover\">\r\n <span class=\"progress\"></span>\r\n </span>\r\n <span class=\"progress-container progress-helper\" (mousemove)=\"progressHelperMouseMove($event)\">\r\n <span class=\"progress\"></span>\r\n </span>\r\n </div>\r\n <div id=\"control-buttons\" [ngClass]=\"{ 'mobile-device': isMobileDevice }\">\r\n <div *ngIf=\"!isMobileDevice\">\r\n <svg (click)=\"prev()\">\r\n <use xlink:href=\"./assets/media-controls.svg#prev\" href=\"./assets/media-controls.svg#prev\" x=\"0\" y=\"0\" />\r\n </svg>\r\n </div>\r\n <div *ngIf=\"!isMobileDevice\">\r\n <svg (click)=\"playPause()\">\r\n <path id='line1' d=\"M 8 7 L 26 17 L 26 17 L 8 26\" style=\"fill:white;\">\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\" \r\n from=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n to=\"M 8 7 L 13 7 L 13 26 L 8 26\"\r\n begin=\"indefinite\"\r\n fill=\"freeze\"\r\n #from_pause_to_play />\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\"\r\n from=\"M 8 7 L 13 7 L 13 26 L 8 26\"\r\n to=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n fill=\"freeze\"\r\n #from_play_to_pause\r\n begin=\"indefinite\" />\r\n </path>\r\n <path id='line2' d=\"M 8 7 L 26 17 L 26 17 L 8 26\" style=\"fill:white;\">\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\" \r\n from=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n to=\"M 19 7 L 24 7 L 24 26 L 19 26\"\r\n begin=\"indefinite\"\r\n fill=\"freeze\"\r\n #from_pause_to_play />\r\n <animate\r\n attributeName=\"d\"\r\n dur=\"300ms\"\r\n from=\"M 19 7 L 24 7 L 24 26 L 19 26\"\r\n to=\"M 8 7 L 26 17 L 26 17 L 8 26\"\r\n fill=\"freeze\"\r\n #from_play_to_pause\r\n begin=\"indefinite\" />\r\n </path> \r\n </svg>\r\n </div>\r\n <div *ngIf=\"!isMobileDevice && isNextVideo()\">\r\n <svg (click)=\"next()\">\r\n <use xlink:href=\"./assets/media-controls.svg#next\" href=\"./assets/media-controls.svg#next\" x=\"0\" y=\"0\" />\r\n </svg>\r\n <