videoflix/frontend/src/app/components/home/video-player/video-player.component.ts

145 lines
4.3 KiB
TypeScript

import { Component, OnInit, OnDestroy, ElementRef, Input } from '@angular/core';
import { ResolutionService } from '../../../services/resolution.service';
import Hls from 'hls.js';
@Component({
selector: 'app-video-player',
standalone: true,
imports: [],
templateUrl: './video-player.component.html',
styleUrls: ['./video-player.component.scss'],
})
export class VideoPlayerComponent implements OnInit, OnDestroy {
@Input() playVideo: string = '';
private hls: Hls | null = null;
private videoElement: HTMLVideoElement | null = null;
private resolutionUrls: { [key: string]: string } = {};
private defaultResolution: string;
/**
* Initializes the VideoPlayerComponent with the ElementRef and ResolutionService.
* Get the default resolution.
*/
constructor(
private elementRef: ElementRef,
private resolutionService: ResolutionService
) {
this.defaultResolution = this.resolutionService.getDefaultResolution();
}
/**
* Angular lifecycle hook: Called once the component is initialized.
* Initializes the video player with the default resolution.
*/
ngOnInit(): void {
this.initializePlayer();
}
/**
* Angular lifecycle hook: Called once the component is about to be destroyed.
* Cleans up HLS resources.
*/
ngOnDestroy(): void {
this.hls?.destroy();
}
/**
* Initializes the video player and loads the default resolution.
*/
private initializePlayer(): void {
this.videoElement = this.elementRef.nativeElement.querySelector('video');
if (!this.playVideo || !this.videoElement) return;
this.resolutionUrls = this.getResolutionUrls();
const defaultUrl = this.resolutionUrls[this.defaultResolution];
if (Hls.isSupported()) {
this.initHlsPlayer(defaultUrl);
} else if (this.videoElement.canPlayType('application/vnd.apple.mpegurl')) {
this.initNativePlayer(defaultUrl);
}
this.updateScreenDimensions();
}
/**
* Generates a mapping of available resolutions to their respective URLs.
* @returns An object containing resolution-URL pairs.
*/
private getResolutionUrls(): { [key: string]: string } {
return Object.fromEntries(
this.resolutionService
.getAvailableResolutions()
.map((res) => [res, `${this.playVideo}_${res}.m3u8`])
);
}
/**
* Initializes the video player using HLS.js if supported.
* @param url - The URL of the video stream to load.
*/
private initHlsPlayer(url: string): void {
if (!this.videoElement) return;
this.hls = new Hls();
this.hls.loadSource(url);
this.hls.attachMedia(this.videoElement);
this.hls.on(Hls.Events.MANIFEST_PARSED, () => this.videoElement?.play());
}
/**
* Initializes the native HTML5 video player if HLS is natively supported.
* @param url - The URL of the video stream to load.
*/
private initNativePlayer(url: string): void {
if (!this.videoElement) return;
this.videoElement.src = url;
this.videoElement.addEventListener('canplay', () =>
this.videoElement?.play()
);
}
/**
* Updates the video element's dimensions to match the window size.
*/
private updateScreenDimensions(): void {
if (!this.videoElement) return;
this.videoElement.style.width = `${window.innerWidth}px`;
this.videoElement.style.height = `${window.innerHeight}px`;
}
/**
* Switches the video resolution to the specified one, or falls back to the default resolution if not available.
* @param resolution - The desired resolution (e.g., '720p', '1080p').
*/
public switchResolution(resolution: string): void {
const targetUrl =
this.resolutionUrls[resolution] ||
this.resolutionUrls[this.defaultResolution];
if (targetUrl) {
this.hls
? this.loadHlsSource(targetUrl)
: this.loadNativeSource(targetUrl);
} else {
console.error(`No URL found for resolution '${resolution}'`);
}
}
/**
* Loads a new video stream source using HLS.js.
* @param url - The URL of the new video stream.
*/
private loadHlsSource(url: string): void {
this.hls?.loadSource(url);
this.hls?.attachMedia(this.videoElement!);
}
/**
* Loads a new video stream source using the native HTML5 player.
* @param url - The URL of the new video stream.
*/
private loadNativeSource(url: string): void {
if (!this.videoElement) return;
this.videoElement.src = url;
}
}