mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Cleaning up the support list
This commit is contained in:
parent
a988d2b75b
commit
199e541997
@ -22,7 +22,7 @@ import { PeopleListComponent } from './components/people-list/people-list.compon
|
||||
import {
|
||||
BufferToWidthPipe,
|
||||
FormatTimePipe,
|
||||
PlayerComponent,
|
||||
PlayerComponent, SupportedButtonPipe,
|
||||
VolumeToButtonPipe
|
||||
} from "./pages/player/player.component";
|
||||
import { SearchComponent } from './pages/search/search.component';
|
||||
@ -67,7 +67,8 @@ import { MatBadgeModule } from "@angular/material/badge";
|
||||
ShowGridComponent,
|
||||
FormatTimePipe,
|
||||
BufferToWidthPipe,
|
||||
VolumeToButtonPipe
|
||||
VolumeToButtonPipe,
|
||||
SupportedButtonPipe
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
155
src/app/pages/player/playbackMethodDetector.ts
Normal file
155
src/app/pages/player/playbackMethodDetector.ts
Normal file
@ -0,0 +1,155 @@
|
||||
import { detect } from "detect-browser";
|
||||
import { Track, WatchItem } from "../../models/watch-item";
|
||||
|
||||
export enum method
|
||||
{
|
||||
direct = "Direct Play",
|
||||
transmux = "Transmux",
|
||||
transcode = "Transcode"
|
||||
}
|
||||
|
||||
export class SupportList
|
||||
{
|
||||
container: boolean;
|
||||
videoCodec: boolean;
|
||||
audioCodec: boolean[];
|
||||
|
||||
getPlaybackMethod(): method
|
||||
{
|
||||
if (this.container)
|
||||
{
|
||||
if (this.videoCodec && this.audioCodec)
|
||||
return method.direct;
|
||||
return method.transcode;
|
||||
}
|
||||
|
||||
if (this.videoCodec && this.audioCodec)
|
||||
return method.transmux;
|
||||
return method.transcode;
|
||||
}
|
||||
}
|
||||
|
||||
export function getWhatIsSupported(player: HTMLVideoElement, item: WatchItem): SupportList
|
||||
{
|
||||
let supportList: SupportList = new SupportList();
|
||||
let browser = detect();
|
||||
|
||||
if (!browser)
|
||||
{
|
||||
supportList.container = false;
|
||||
supportList.videoCodec = false;
|
||||
supportList.audioCodec = item.audios.map(() => false);
|
||||
}
|
||||
else
|
||||
{
|
||||
supportList.container = containerIsSupported(player, item.container, browser.name) && item.audios.length <= 1;
|
||||
supportList.videoCodec = videoCodecIsSupported(player, item.video.codec, browser.name);
|
||||
supportList.audioCodec = item.audios.map((x: Track) => audioCodecIsSupported(player, x.codec, browser.name));
|
||||
}
|
||||
return (supportList);
|
||||
}
|
||||
|
||||
function containerIsSupported(player: HTMLVideoElement, container: string, browser: string): boolean
|
||||
{
|
||||
switch (container)
|
||||
{
|
||||
case "asf":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "avi":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "mpg":
|
||||
case "mpeg":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "flv":
|
||||
return browser == "tizen" || browser == "orsay";
|
||||
case "3gp":
|
||||
case "mts":
|
||||
case "trp":
|
||||
case "vob":
|
||||
case "vro":
|
||||
return browser == "tizen" || browser == "orsay";
|
||||
case "mov":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge" || browser == "chrome";
|
||||
case "m2ts":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "wmv":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "ts":
|
||||
return browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
case "mp4":
|
||||
case "m4v":
|
||||
return true;
|
||||
case "mkv":
|
||||
if (browser == "tizen" || browser == "orsay" || browser == "chrome" || browser == "edge")
|
||||
return true;
|
||||
return !!(player.canPlayType("video/x-matroska") || player.canPlayType("video/mkv"));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//SHOULD CHECK FOR DEPTH (8bits ok but 10bits unsupported for almost every browsers)
|
||||
function videoCodecIsSupported(player: HTMLVideoElement, codec: string, browser: string): boolean
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case "h264":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
|
||||
case "h265":
|
||||
case "hevc":
|
||||
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
||||
return true;
|
||||
//SHOULD SUPPORT CHROMECAST ULTRA
|
||||
// if (browser.chromecast)
|
||||
// {
|
||||
|
||||
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
||||
// if (isChromecastUltra)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
||||
case "mpeg2video":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "vc1":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "msmpeg4v2":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "vp8":
|
||||
return !!player.canPlayType('video/webm; codecs="vp8');
|
||||
case "vp9":
|
||||
return !!player.canPlayType('video/webm; codecs="vp9"');
|
||||
case "vorbis":
|
||||
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//SHOULD CHECK FOR NUMBER OF AUDIO CHANNEL (2 ok but 5 not in some browsers)
|
||||
function audioCodecIsSupported(player: HTMLVideoElement, codec: string, browser: string): boolean
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case "mp3":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"') ||
|
||||
!!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"');
|
||||
case "aac":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"');
|
||||
case "mp2":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "pcm_s16le":
|
||||
case "pcm_s24le":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "aac_latm":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "opus":
|
||||
return !!player.canPlayType('audio/ogg; codecs="opus"');
|
||||
case "flac":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
@ -37,25 +37,25 @@
|
||||
Video Container:
|
||||
<span>
|
||||
{{this.item.container}}
|
||||
<i class="material-icons">{{getSupportedFeature("container")}}</i>
|
||||
<i class="material-icons">{{this.supportList | supportedButton: "container"}}</i>
|
||||
</span>
|
||||
<br />
|
||||
Video Codec:
|
||||
<span>
|
||||
{{this.item.video.codec}}
|
||||
<i class="material-icons">{{getSupportedFeature("video")}}</i>
|
||||
<i class="material-icons">{{this.supportList | supportedButton: "video"}}</i>
|
||||
</span>
|
||||
<br />
|
||||
Audio Codec:
|
||||
<span>
|
||||
{{this.item.audios[0].codec}}
|
||||
<i class="material-icons">{{getSupportedFeature("audio")}}</i>
|
||||
{{this.item.audios[this.selectedAudio].codec}}
|
||||
<i class="material-icons">{{this.supportList | supportedButton: "audio":this.selectedAudio}}</i>
|
||||
</span>
|
||||
<br />
|
||||
Subtitle Codec:
|
||||
<span>
|
||||
{{this.selectedSubtitle ? this.selectedSubtitle.codec : "none"}}
|
||||
<i class="material-icons">{{getSupportedFeature("subtitle")}}</i>
|
||||
{{this.selectedSubtitle != -1 ? this.item.subtitles[this.selectedSubtitle].codec : "none"}}
|
||||
<i class="material-icons">{{this.supportList | supportedButton: "subtitle"}}</i>
|
||||
</span>
|
||||
<br />
|
||||
</mat-card-content>
|
||||
@ -130,7 +130,8 @@
|
||||
<p>{{player.currentTime | formatTime: player.duration}} / {{player.duration | formatTime}}</p>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button id="volume" *ngIf="this.item.audios.length > 1" mat-icon-button matTooltipPosition="above" matTooltip="Select audio track">
|
||||
<button *ngIf="this.item.audios.length > 1" mat-icon-button
|
||||
matTooltipPosition="above" matTooltip="Select audio track">
|
||||
<mat-icon>music_note</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="this.item.subtitles.length > 0" mat-icon-button [matMenuTriggerFor]="subtitles"
|
||||
@ -158,12 +159,13 @@
|
||||
|
||||
<mat-menu #subtitles="matMenu" (closed)="this.isMenuOpen = false">
|
||||
<ng-template matMenuContent>
|
||||
<button [ngClass]="{'selected': this.selectedSubtitle == null}" mat-menu-item (click)="selectSubtitle(null)">
|
||||
<button [ngClass]="{'selected': this.selectedSubtitle === -1}" mat-menu-item
|
||||
(click)="selectSubtitle(null)">
|
||||
<span>None</span>
|
||||
</button>
|
||||
|
||||
<div *ngFor="let subtitle of this.item.subtitles">
|
||||
<button [ngClass]="{'selected': this.selectedSubtitle == subtitle}"
|
||||
<div *ngFor="let subtitle of this.item.subtitles; index as i">
|
||||
<button [ngClass]="{'selected': this.selectedSubtitle === i}"
|
||||
mat-menu-item *ngIf="subtitle.codec === 'ass' || subtitle.codec === 'subrip';
|
||||
else elseBlock"
|
||||
(click)="selectSubtitle(subtitle)">
|
||||
|
@ -16,11 +16,10 @@ import { ActivatedRoute, Event, NavigationCancel, NavigationEnd, NavigationStart
|
||||
import { OidcSecurityService } from "angular-auth-oidc-client";
|
||||
import * as Hls from "hls.js";
|
||||
import {
|
||||
getPlaybackMethod,
|
||||
getWhatIsSupported,
|
||||
method,
|
||||
SupportList
|
||||
} from "../../../videoSupport/playbackMethodDetector";
|
||||
} from "./playbackMethodDetector";
|
||||
import { AppComponent } from "../../app.component";
|
||||
import { Track, WatchItem } from "../../models/watch-item";
|
||||
|
||||
@ -76,6 +75,30 @@ export class VolumeToButtonPipe implements PipeTransform
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: "supportedButton",
|
||||
pure: true
|
||||
})
|
||||
export class SupportedButtonPipe implements PipeTransform
|
||||
{
|
||||
transform(supports: SupportList, selector: string, audioIndex: number = 0): string
|
||||
{
|
||||
if (!supports)
|
||||
return "help";
|
||||
switch (selector)
|
||||
{
|
||||
case "container":
|
||||
return supports.container ? "check_circle" : "cancel";
|
||||
case "video":
|
||||
return supports.videoCodec ? "check_circle" : "cancel";
|
||||
case "audio":
|
||||
return supports.audioCodec[audioIndex] ? "check_circle" : "cancel";
|
||||
default:
|
||||
return "help";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "app-player",
|
||||
templateUrl: "./player.component.html",
|
||||
@ -85,7 +108,8 @@ export class VolumeToButtonPipe implements PipeTransform
|
||||
export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
{
|
||||
item: WatchItem;
|
||||
selectedSubtitle: Track;
|
||||
selectedAudio: number = 0;
|
||||
selectedSubtitle: number = -1;
|
||||
playMethod: method = method.direct;
|
||||
supportList: SupportList;
|
||||
playing: boolean = true;
|
||||
@ -182,11 +206,11 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
switch (true)
|
||||
{
|
||||
case event instanceof NavigationStart:
|
||||
this.loading = false;
|
||||
this.loading = true;
|
||||
break;
|
||||
case event instanceof NavigationEnd:
|
||||
case event instanceof NavigationCancel:
|
||||
this.loading = true;
|
||||
this.loading = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -207,11 +231,25 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
|
||||
ngAfterViewInit()
|
||||
{
|
||||
if (this.oidcSecurity === undefined)
|
||||
this.oidcSecurity = this.injector.get(OidcSecurityService);
|
||||
this.hlsPlayer.config.xhrSetup = xhr =>
|
||||
{
|
||||
const token = this.oidcSecurity.getToken();
|
||||
if (token)
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
||||
};
|
||||
|
||||
this.showControls = true;
|
||||
|
||||
setTimeout(() => this.route.data.subscribe(() =>
|
||||
{
|
||||
// TODO remove the query param for the method (should be a session setting).
|
||||
let queryMethod: string = this.route.snapshot.queryParams["method"];
|
||||
this.selectPlayMethod(queryMethod ? method[queryMethod] : getPlaybackMethod(this.player, this.item));
|
||||
this.supportList = getWhatIsSupported(this.player, this.item);
|
||||
this.selectPlayMethod(queryMethod ? method[queryMethod] : this.supportList.getPlaybackMethod());
|
||||
|
||||
// TODO remove this, it should be a user's setting.
|
||||
const subSlug: string = this.route.snapshot.queryParams["sub"];
|
||||
if (subSlug != null)
|
||||
{
|
||||
@ -220,10 +258,7 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
const sub: Track = this.item.subtitles.find(x => x.language == languageCode && x.isForced == forced);
|
||||
this.selectSubtitle(sub, false);
|
||||
}
|
||||
|
||||
this.supportList = getWhatIsSupported(this.player, this.item);
|
||||
}));
|
||||
this.showControls = true;
|
||||
}
|
||||
|
||||
get isFullScreen(): boolean
|
||||
@ -304,16 +339,6 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
selectPlayMethod(playMethod: method)
|
||||
{
|
||||
this.playMethod = playMethod;
|
||||
|
||||
if (this.oidcSecurity === undefined)
|
||||
this.oidcSecurity = this.injector.get(OidcSecurityService);
|
||||
this.hlsPlayer.config.xhrSetup = xhr =>
|
||||
{
|
||||
const token = this.oidcSecurity.getToken();
|
||||
if (token)
|
||||
xhr.setRequestHeader("Authorization", "Bearer " + token);
|
||||
};
|
||||
|
||||
if (this.playMethod == method.direct)
|
||||
this.player.src = `/video/${this.item.slug}`;
|
||||
else
|
||||
@ -377,8 +402,16 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
document.body.requestFullscreen();
|
||||
}
|
||||
|
||||
selectSubtitle(subtitle: Track, changeUrl: boolean = true)
|
||||
selectSubtitle(subtitle: Track | number, changeUrl: boolean = true)
|
||||
{
|
||||
if (typeof(subtitle) === "number")
|
||||
{
|
||||
this.selectedSubtitle = subtitle;
|
||||
subtitle = this.item.subtitles[subtitle];
|
||||
}
|
||||
else
|
||||
this.selectedSubtitle = this.item.subtitles.indexOf(subtitle);
|
||||
|
||||
if (changeUrl)
|
||||
{
|
||||
let subSlug: string;
|
||||
@ -393,11 +426,10 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
relativeTo: this.route,
|
||||
queryParams: {sub: subSlug},
|
||||
replaceUrl: true,
|
||||
queryParamsHandling: "merge"
|
||||
queryParamsHandling: "merge",
|
||||
});
|
||||
}
|
||||
|
||||
this.selectedSubtitle = subtitle;
|
||||
|
||||
if (subtitle == null)
|
||||
{
|
||||
@ -442,23 +474,6 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
}
|
||||
}
|
||||
|
||||
getSupportedFeature(feature: string) : string
|
||||
{
|
||||
if (!this.supportList)
|
||||
return "help";
|
||||
switch (feature)
|
||||
{
|
||||
case "container":
|
||||
return this.supportList.container ? "check_circle" : "cancel";
|
||||
case "video":
|
||||
return this.supportList.videoCodec ? "check_circle" : "cancel";
|
||||
case "audio":
|
||||
return this.supportList.audioCodec ? "check_circle" : "cancel";
|
||||
default:
|
||||
return "help";
|
||||
}
|
||||
}
|
||||
|
||||
removeHtmlTrack()
|
||||
{
|
||||
let elements = this.player.getElementsByTagName("track");
|
||||
@ -466,17 +481,14 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
elements.item(0).remove();
|
||||
}
|
||||
|
||||
getThumb(url: string)
|
||||
{
|
||||
return this.sanitizer.bypassSecurityTrustStyle("url(" + url + ")");
|
||||
}
|
||||
|
||||
@HostListener("document:keyup", ["$event"])
|
||||
keypress(event: KeyboardEvent): void
|
||||
{
|
||||
switch (event.key)
|
||||
{
|
||||
case " ":
|
||||
case "k":
|
||||
case "K":
|
||||
this.togglePlayback();
|
||||
break;
|
||||
|
||||
@ -499,18 +511,17 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
});
|
||||
break;
|
||||
|
||||
case "v":
|
||||
case "V":
|
||||
const subtitleIndex: number = this.item.subtitles.indexOf(this.selectedSubtitle);
|
||||
const nextSub: Track = subtitleIndex + 1 <= this.item.subtitles.length
|
||||
? this.item.subtitles[subtitleIndex + 1]
|
||||
: this.item.subtitles[0];
|
||||
this.selectSubtitle(nextSub);
|
||||
this.selectSubtitle((this.selectedSubtitle + 2) % (this.item.subtitles.length + 1) - 1);
|
||||
break;
|
||||
|
||||
case "f":
|
||||
case "F":
|
||||
this.fullscreen();
|
||||
break;
|
||||
|
||||
case "m":
|
||||
case "M":
|
||||
this.muted = !this.muted;
|
||||
this.snackBar.open(this.player.muted ? "Sound muted." : "Sound unmuted", null, {
|
||||
@ -521,10 +532,12 @@ export class PlayerComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
});
|
||||
break;
|
||||
|
||||
case "n":
|
||||
case "N":
|
||||
this.next();
|
||||
break;
|
||||
|
||||
case "p":
|
||||
case "P":
|
||||
this.previous();
|
||||
break;
|
||||
|
@ -1,159 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var detect_browser_1 = require("detect-browser");
|
||||
var method;
|
||||
(function (method) {
|
||||
method["direct"] = "Direct Play";
|
||||
method["transmux"] = "Transmux";
|
||||
method["transcode"] = "Transcode";
|
||||
})(method = exports.method || (exports.method = {}));
|
||||
;
|
||||
var SupportList = /** @class */ (function () {
|
||||
function SupportList() {
|
||||
}
|
||||
return SupportList;
|
||||
}());
|
||||
exports.SupportList = SupportList;
|
||||
function getPlaybackMethod(player, item) {
|
||||
var supportList = getWhatIsSupported(player, item);
|
||||
if (supportList.container) {
|
||||
if (supportList.videoCodec && supportList.audioCodec)
|
||||
return method.direct;
|
||||
return method.transcode;
|
||||
}
|
||||
if (supportList.videoCodec && supportList.audioCodec)
|
||||
return method.transmux;
|
||||
return method.transcode;
|
||||
}
|
||||
exports.getPlaybackMethod = getPlaybackMethod;
|
||||
function getWhatIsSupported(player, item) {
|
||||
var supportList = new SupportList();
|
||||
var browser = detect_browser_1.detect();
|
||||
if (!browser) {
|
||||
supportList.container = false;
|
||||
supportList.videoCodec = false;
|
||||
supportList.audioCodec = false;
|
||||
}
|
||||
else {
|
||||
supportList.container = containerIsSupported(player, item.container, browser.name) && item.audios.length <= 1;
|
||||
supportList.videoCodec = videoCodecIsSupported(player, item.video.codec, browser.name);
|
||||
supportList.audioCodec = audioCodecIsSupported(player, item.audios.map(function (value) { return value.codec; }), browser.name);
|
||||
}
|
||||
return (supportList);
|
||||
}
|
||||
exports.getWhatIsSupported = getWhatIsSupported;
|
||||
function containerIsSupported(player, container, browser) {
|
||||
var supported = false;
|
||||
switch (container) {
|
||||
case "asf":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
//videoAudioCodecs = [];
|
||||
break;
|
||||
case "avi":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "mpg":
|
||||
case "mpeg":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "flv":
|
||||
supported = browser == "tizen" || browser == "orsay";
|
||||
break;
|
||||
case "3gp":
|
||||
case "mts":
|
||||
case "trp":
|
||||
case "vob":
|
||||
case "vro":
|
||||
supported = browser == "tizen" || browser == "orsay";
|
||||
break;
|
||||
case "mov":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge" || browser == "chrome";
|
||||
break;
|
||||
case "m2ts":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "wmv":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
//videoAudioCodecs = [];
|
||||
break;
|
||||
case "ts":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "mp4":
|
||||
case "m4v":
|
||||
supported = true;
|
||||
break;
|
||||
case "mkv":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "chrome" || browser == "edge";
|
||||
if (supported)
|
||||
break;
|
||||
if (player.canPlayType("video/x-matroska") || player.canPlayType("video/mkv"))
|
||||
supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
//SHOULD CHECK FOR DEPTH (8bits ok but 10bits unsuported for almost every browsers)
|
||||
function videoCodecIsSupported(player, codec, browser) {
|
||||
switch (codec) {
|
||||
case "h264":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); //The !! is used to parse the string as a bool
|
||||
case "h265":
|
||||
case "hevc":
|
||||
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
||||
return true;
|
||||
//SHOULD SUPPORT CHROMECAST ULTRA
|
||||
// if (browser.chromecast)
|
||||
// {
|
||||
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
||||
// if (isChromecastUltra)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
||||
case "mpeg2video":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "vc1":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "msmpeg4v2":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "vp8":
|
||||
return !!player.canPlayType('video/webm; codecs="vp8');
|
||||
case "vp9":
|
||||
return !!player.canPlayType('video/webm; codecs="vp9"');
|
||||
case "vorbis":
|
||||
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//SHOULD CHECK FOR NUMBER OF AUDIO CHANNEL (2 ok but 5 not in some browsers)
|
||||
function audioCodecIsSupported(player, codecs, browser) {
|
||||
for (var _i = 0, codecs_1 = codecs; _i < codecs_1.length; _i++) {
|
||||
var codec = codecs_1[_i];
|
||||
switch (codec) {
|
||||
case "mp3":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"') ||
|
||||
!!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"');
|
||||
case "aac":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"');
|
||||
case "mp2":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "pcm_s16le":
|
||||
case "pcm_s24le":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "aac_latm":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "opus":
|
||||
return !!player.canPlayType('audio/ogg; codecs="opus"');
|
||||
case "flac":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=playbackMethodDetector.js.map
|
@ -1 +0,0 @@
|
||||
{"version":3,"file":"playbackMethodDetector.js","sourceRoot":"","sources":["playbackMethodDetector.ts"],"names":[],"mappings":"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"}
|
@ -1,179 +0,0 @@
|
||||
import { detect } from "detect-browser";
|
||||
import { Track, WatchItem } from "../app/models/watch-item";
|
||||
|
||||
export enum method
|
||||
{
|
||||
direct = "Direct Play",
|
||||
transmux = "Transmux",
|
||||
transcode = "Transcode"
|
||||
}
|
||||
|
||||
export class SupportList
|
||||
{
|
||||
container: boolean;
|
||||
videoCodec: boolean;
|
||||
audioCodec: boolean;
|
||||
}
|
||||
|
||||
export function getPlaybackMethod(player: HTMLVideoElement, item: WatchItem): method
|
||||
{
|
||||
let supportList: SupportList = getWhatIsSupported(player, item);
|
||||
|
||||
if (supportList.container)
|
||||
{
|
||||
if (supportList.videoCodec && supportList.audioCodec)
|
||||
return method.direct;
|
||||
return method.transcode;
|
||||
}
|
||||
|
||||
if (supportList.videoCodec && supportList.audioCodec)
|
||||
return method.transmux;
|
||||
return method.transcode;
|
||||
}
|
||||
|
||||
export function getWhatIsSupported(player: HTMLVideoElement, item: WatchItem): SupportList
|
||||
{
|
||||
let supportList: SupportList = new SupportList();
|
||||
let browser = detect();
|
||||
|
||||
if (!browser)
|
||||
{
|
||||
supportList.container = false;
|
||||
supportList.videoCodec = false;
|
||||
supportList.audioCodec = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
supportList.container = containerIsSupported(player, item.container, browser.name) && item.audios.length <= 1;
|
||||
supportList.videoCodec = videoCodecIsSupported(player, item.video.codec, browser.name);
|
||||
supportList.audioCodec = audioCodecIsSupported(player, item.audios.map((value: Track) => value.codec), browser.name);
|
||||
}
|
||||
return (supportList);
|
||||
}
|
||||
|
||||
function containerIsSupported(player: HTMLVideoElement, container: string, browser: string): boolean
|
||||
{
|
||||
let supported: boolean = false;
|
||||
|
||||
switch (container)
|
||||
{
|
||||
case "asf":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
//videoAudioCodecs = [];
|
||||
break;
|
||||
case "avi":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "mpg":
|
||||
case "mpeg":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "flv":
|
||||
supported = browser == "tizen" || browser == "orsay";
|
||||
break;
|
||||
case "3gp":
|
||||
case "mts":
|
||||
case "trp":
|
||||
case "vob":
|
||||
case "vro":
|
||||
supported = browser == "tizen" || browser == "orsay";
|
||||
break;
|
||||
case "mov":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge" || browser == "chrome";
|
||||
break;
|
||||
case "m2ts":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "wmv":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
//videoAudioCodecs = [];
|
||||
break;
|
||||
case "ts":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "edge";
|
||||
break;
|
||||
case "mp4":
|
||||
case "m4v":
|
||||
supported = true;
|
||||
break;
|
||||
case "mkv":
|
||||
supported = browser == "tizen" || browser == "orsay" || browser == "chrome" || browser == "edge";
|
||||
|
||||
if (supported)
|
||||
break;
|
||||
|
||||
if (player.canPlayType("video/x-matroska") || player.canPlayType("video/mkv"))
|
||||
supported = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
//SHOULD CHECK FOR DEPTH (8bits ok but 10bits unsuported for almost every browsers)
|
||||
function videoCodecIsSupported(player: HTMLVideoElement, codec: string, browser: string): boolean
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case "h264":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); //The !! is used to parse the string as a bool
|
||||
case "h265":
|
||||
case "hevc":
|
||||
if (browser == "tizen" || browser == "orsay" || browser == "xboxOne" || browser == "ios")
|
||||
return true;
|
||||
//SHOULD SUPPORT CHROMECAST ULTRA
|
||||
// if (browser.chromecast)
|
||||
// {
|
||||
|
||||
// var isChromecastUltra = userAgent.indexOf('aarch64') !== -1;
|
||||
// if (isChromecastUltra)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
return !!player.canPlayType('video/hevc; codecs="hevc, aac"');
|
||||
case "mpeg2video":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "vc1":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "msmpeg4v2":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "vp8":
|
||||
return !!player.canPlayType('video/webm; codecs="vp8');
|
||||
case "vp9":
|
||||
return !!player.canPlayType('video/webm; codecs="vp9"');
|
||||
case "vorbis":
|
||||
return browser == "orsay" || browser == "tizen" || !!player.canPlayType('video/webm; codecs="vp8');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//SHOULD CHECK FOR NUMBER OF AUDIO CHANNEL (2 ok but 5 not in some browsers)
|
||||
function audioCodecIsSupported(player: HTMLVideoElement, codecs: string[], browser: string): boolean
|
||||
{
|
||||
for (let codec of codecs)
|
||||
{
|
||||
switch (codec)
|
||||
{
|
||||
case "mp3":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.69"') ||
|
||||
!!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.6B"');
|
||||
case "aac":
|
||||
return !!player.canPlayType('video/mp4; codecs="avc1.640029, mp4a.40.2"');
|
||||
case "mp2":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "pcm_s16le":
|
||||
case "pcm_s24le":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
case "aac_latm":
|
||||
return browser == "orsay" || browser == "tizen";
|
||||
case "opus":
|
||||
return !!player.canPlayType('audio/ogg; codecs="opus"');
|
||||
case "flac":
|
||||
return browser == "orsay" || browser == "tizen" || browser == "edge";
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user