diff --git a/client/src/app/shared/components/vjs-player/vjs-player.component.html b/client/src/app/shared/components/vjs-player/vjs-player.component.html
index bd0a96978..213a09bde 100644
--- a/client/src/app/shared/components/vjs-player/vjs-player.component.html
+++ b/client/src/app/shared/components/vjs-player/vjs-player.component.html
@@ -1,3 +1,14 @@
-
+
+
+
+
+
+ {{ 'No stream available' | translate }}
+
+
+
diff --git a/client/src/app/shared/components/vjs-player/vjs-player.component.scss b/client/src/app/shared/components/vjs-player/vjs-player.component.scss
index c376df5c5..7b063c773 100644
--- a/client/src/app/shared/components/vjs-player/vjs-player.component.scss
+++ b/client/src/app/shared/components/vjs-player/vjs-player.component.scss
@@ -1,38 +1,50 @@
.video-wrapper {
display: flex;
width: 100%;
- .video-js {
- margin: auto;
+ min-height: 200px;
- // we keep the button for now
- // .vjs-big-play-button {
- // left: 0;
- // top: 0;
- // width: 100%;
- // height: 100%;
- // border: 0;
- // border-radius: 0;
- // background-color: rgba(0, 0, 0, 0);
- // .vjs-icon-placeholder {
- // display: none !important;
- // }
- // }
+ .is-offline-wrapper {
+ width: 100%;
+ margin: 1em;
+ text-align: center;
+ }
- .vjs-control-bar {
- .vjs-subs-caps-button {
- display: none !important;
- }
+ .player-container {
+ height: 100%;
+ width: 100%;
+ .video-js {
+ margin: auto;
- .vjs-descriptions-button {
- display: none !important;
- }
+ // we keep the button for now
+ // .vjs-big-play-button {
+ // left: 0;
+ // top: 0;
+ // width: 100%;
+ // height: 100%;
+ // border: 0;
+ // border-radius: 0;
+ // background-color: rgba(0, 0, 0, 0);
+ // .vjs-icon-placeholder {
+ // display: none !important;
+ // }
+ // }
- .vjs-picture-in-picture-control {
- display: none !important;
- }
+ .vjs-control-bar {
+ .vjs-subs-caps-button {
+ display: none !important;
+ }
- .vjs-audio-button {
- display: none !important;
+ .vjs-descriptions-button {
+ display: none !important;
+ }
+
+ .vjs-picture-in-picture-control {
+ display: none !important;
+ }
+
+ .vjs-audio-button {
+ display: none !important;
+ }
}
}
}
diff --git a/client/src/app/shared/components/vjs-player/vjs-player.component.spec.ts b/client/src/app/shared/components/vjs-player/vjs-player.component.spec.ts
index 36fc25132..4eefdb1a4 100644
--- a/client/src/app/shared/components/vjs-player/vjs-player.component.spec.ts
+++ b/client/src/app/shared/components/vjs-player/vjs-player.component.spec.ts
@@ -1,5 +1,7 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { E2EImportsModule } from 'e2e-imports.module';
+
import { VjsPlayerComponent } from './vjs-player.component';
describe('VjsPlayerComponent', () => {
@@ -8,7 +10,7 @@ describe('VjsPlayerComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [VjsPlayerComponent]
+ imports: [E2EImportsModule]
}).compileComponents();
}));
diff --git a/client/src/app/shared/components/vjs-player/vjs-player.component.ts b/client/src/app/shared/components/vjs-player/vjs-player.component.ts
index cb6104b8c..7793364e8 100644
--- a/client/src/app/shared/components/vjs-player/vjs-player.component.ts
+++ b/client/src/app/shared/components/vjs-player/vjs-player.component.ts
@@ -10,6 +10,9 @@ import {
ViewEncapsulation
} from '@angular/core';
+import { of } from 'rxjs';
+import { ajax, AjaxResponse } from 'rxjs/ajax';
+import { catchError, map } from 'rxjs/operators';
import videojs from 'video.js';
import { ConfigService } from 'app/core/ui-services/config.service';
@@ -32,14 +35,17 @@ enum MimeType {
encapsulation: ViewEncapsulation.None
})
export class VjsPlayerComponent implements OnInit, OnDestroy {
- @ViewChild('videoPlayer', { static: true }) private videoPlayer: ElementRef;
-
+ @ViewChild('videoPlayer', { static: true })
+ private videoPlayer: ElementRef;
private _videoUrl: string;
+ private posterUrl: string;
+ public player: videojs.Player;
+ public isUrlOnline: boolean;
@Input()
public set videoUrl(value: string) {
this._videoUrl = value;
- this.playVideo();
+ this.checkVideoUrl();
}
@Output()
@@ -49,8 +55,6 @@ export class VjsPlayerComponent implements OnInit, OnDestroy {
return this._videoUrl;
}
- public player: videojs.Player;
-
private get videoSource(): VideoSource {
return {
src: this.videoUrl,
@@ -58,8 +62,6 @@ export class VjsPlayerComponent implements OnInit, OnDestroy {
};
}
- private posterUrl: string;
-
public constructor(config: ConfigService) {
config.get('general_system_stream_poster').subscribe(posterUrl => {
this.posterUrl = posterUrl;
@@ -67,14 +69,7 @@ export class VjsPlayerComponent implements OnInit, OnDestroy {
}
public async ngOnInit(): Promise {
- this.player = videojs(this.videoPlayer.nativeElement, {
- textTrackSettings: false,
- fluid: true,
- autoplay: 'any',
- liveui: true,
- poster: this.posterUrl
- });
- this.playVideo();
+ this.initPlayer();
}
public ngOnDestroy(): void {
@@ -83,13 +78,52 @@ export class VjsPlayerComponent implements OnInit, OnDestroy {
}
}
- private playVideo(): void {
- if (this.player) {
- this.player.src(this.videoSource);
- this.started.next();
+ public async checkVideoUrl(): Promise {
+ /**
+ * Using observable would not make sense, because without it would not automatically update
+ * if a Ressource switches from online to offline
+ */
+ const ajaxResponse: AjaxResponse = await ajax(this.videoUrl)
+ .pipe(
+ map(response => response),
+ catchError(error => {
+ return of(error);
+ })
+ )
+ .toPromise();
+
+ /**
+ * there is no enum for http status codes in the whole Angular stack...
+ */
+ if (ajaxResponse.status === 200) {
+ this.isUrlOnline = true;
+ this.playVideo();
+ } else {
+ this.isUrlOnline = false;
+ if (this.player) {
+ this.player.pause();
+ }
+ this.player.src('');
}
}
+ private initPlayer(): void {
+ if (!this.player) {
+ this.player = videojs(this.videoPlayer.nativeElement, {
+ textTrackSettings: false,
+ fluid: true,
+ autoplay: 'any',
+ liveui: true,
+ poster: this.posterUrl
+ });
+ }
+ }
+
+ private playVideo(): void {
+ this.player.src(this.videoSource);
+ this.started.next();
+ }
+
private determineContentTypeByUrl(url: string): MimeType {
if (url) {
if (url.startsWith('rtmp')) {
diff --git a/client/src/styles.scss b/client/src/styles.scss
index 7449851c7..666823d4d 100644
--- a/client/src/styles.scss
+++ b/client/src/styles.scss
@@ -774,3 +774,10 @@ button.mat-menu-item.selected {
height: 0px;
width: 0px;
}
+
+/**
+ * simply hide something
+ */
+.hide {
+ display: none;
+}