Skip to content

Commit

Permalink
chore: Added none and auto to quality and text selection
Browse files Browse the repository at this point in the history
  • Loading branch information
matvp91 committed Sep 5, 2024
1 parent f31d181 commit fe1266d
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 57 deletions.
1 change: 1 addition & 0 deletions packages/hlsjs/lib/Controls/components/CheckList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
}

.mix-checklist-item {
min-width: 8em;
height: 2.5em;
display: flex;
align-items: center;
Expand Down
10 changes: 8 additions & 2 deletions packages/hlsjs/lib/Controls/components/CheckList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import cn from "clsx";

export type CheckListItem = {
id: number | null;
label: React.ReactNode;
checked: boolean;
};

type CheckListProps = {
onSelect(id: number): void;
items: { id: number; label: string; checked: boolean }[];
onSelect(id: CheckListItem["id"]): void;
items: CheckListItem[];
};

export function CheckList({ items, onSelect }: CheckListProps) {
Expand Down
21 changes: 16 additions & 5 deletions packages/hlsjs/lib/Controls/components/QualitiesPane.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { CheckList } from "./CheckList";
import { Pane } from "./Pane";
import type { HlsFacade, HlsState } from "../../main";
import type { CheckListItem } from "./CheckList";

type QualitiesPaneProps = {
state: HlsState;
facade: HlsFacade;
};

export function QualitiesPane({ facade, state }: QualitiesPaneProps) {
const activeQuality = state.qualities.find((it) => it.active);

const qualityItems = state.qualities.map<CheckListItem>((it) => ({
id: it.id,
label: `${it.level.height}p`,
checked: !state.autoQuality && activeQuality === it,
}));

qualityItems.push({
id: null,
label: "Auto",
checked: state.autoQuality,
});

return (
<Pane title="Quality">
<CheckList
onSelect={(id) => facade.setQuality(id)}
items={state.qualities.map((quality) => ({
id: quality.id,
label: `${quality.height}p`,
checked: quality.active,
}))}
items={qualityItems}
/>
</Pane>
);
Expand Down
27 changes: 18 additions & 9 deletions packages/hlsjs/lib/Controls/components/TextAudioPane.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
import { CheckList } from "./CheckList";
import { Pane } from "./Pane";
import type { HlsFacade, HlsState } from "../../main";
import type { CheckListItem } from "./CheckList";

type QualitiesPaneProps = {
state: HlsState;
facade: HlsFacade;
};

export function TextAudioPane({ facade, state }: QualitiesPaneProps) {
const subtitleItems = state.subtitleTracks.map<CheckListItem>((it) => ({
id: it.id,
label: toLang(it.playlist.name),
checked: it.active,
}));

subtitleItems.push({
id: null,
label: "None",
checked: !state.subtitleTracks.some((it) => it.active),
});

return (
<div className="mix-textaudiopane">
<Pane title="Subtitles">
<CheckList
onSelect={(id) => facade.setSubtitleTrack(id)}
items={state.subtitleTracks.map((subtitleTrack) => ({
id: subtitleTrack.id,
label: toLang(subtitleTrack.name),
checked: subtitleTrack.active,
}))}
items={subtitleItems}
/>
</Pane>
<Pane title="Audio">
<CheckList
onSelect={(id) => facade.setAudioTrack(id)}
items={state.audioTracks.map((audioTrack) => ({
id: audioTrack.id,
label: toLang(audioTrack.name),
checked: audioTrack.active,
items={state.audioTracks.map((it) => ({
id: it.id,
label: toLang(it.playlist.name),
checked: it.active,
}))}
/>
</Pane>
Expand Down
79 changes: 39 additions & 40 deletions packages/hlsjs/lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Hls from "hls.js";
import update from "immutability-helper";
import EventEmitter from "eventemitter3";
import type { Spec } from "immutability-helper";
import type { Level, MediaPlaylist } from "hls.js";

export { Controls as HlsControls } from "./Controls";

Expand All @@ -11,20 +12,20 @@ export type HlsInterstitial = {

export type HlsQuality = {
id: number;
height: number;
active: boolean;
level: Level;
};

export type HlsSubtitleTrack = {
id: number;
name: string;
active: boolean;
playlist: MediaPlaylist;
};

export type HlsAudioTrack = {
id: number;
name: string;
active: boolean;
playlist: MediaPlaylist;
};

export type HlsSeekRange = {
Expand All @@ -39,6 +40,7 @@ export type HlsState = {
interstitial: HlsInterstitial | null;
cuePoints: number[];
qualities: HlsQuality[];
autoQuality: boolean;
subtitleTracks: HlsSubtitleTrack[];
audioTracks: HlsAudioTrack[];
};
Expand All @@ -54,7 +56,13 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
super();

hls.once(Hls.Events.BUFFER_CREATED, () => {
this.syncState_();
this.syncTimings_();
});

hls.on(Hls.Events.INTERSTITIAL_ASSET_PLAYER_CREATED, (_, data) => {
data.player.once(Hls.Events.BUFFER_CREATED, () => {
this.syncTimings_();
});
});

hls.on(Hls.Events.LEVEL_SWITCHING, () => {
Expand All @@ -65,14 +73,12 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
this.syncAudioTracks_();
});

hls.on(Hls.Events.SUBTITLE_TRACK_SWITCH, () => {
hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, () => {
this.syncSubtitleTracks_();
});

hls.on(Hls.Events.INTERSTITIAL_ASSET_PLAYER_CREATED, (_, data) => {
data.player.once(Hls.Events.BUFFER_CREATED, () => {
this.syncState_();
});
hls.on(Hls.Events.SUBTITLE_TRACK_SWITCH, () => {
this.syncSubtitleTracks_();
});

hls.on(Hls.Events.INTERSTITIAL_STARTED, (_, data) => {
Expand Down Expand Up @@ -115,19 +121,11 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
interstitial: null,
cuePoints: [],
qualities: [],
autoQuality: this.hls.autoLevelEnabled,
subtitleTracks: [],
audioTracks: [],
};

private onTick_() {
const { integrated } = this.getInterstitialsManager_();

this.setState_({
time: { $set: integrated.currentTime },
seekRange: { $set: { start: 0, end: integrated.duration } },
});
}

playOrPause() {
const media = this.getMedia_();
const { playheadState } = this.state;
Expand All @@ -152,27 +150,18 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
}

setQuality(id: number | null) {
if (id) {
this.hls.nextLevel = id - 1;
} else {
this.hls.nextLevel = -1;
}
this.setState_({
autoQuality: { $set: id === null },
});
this.hls.nextLevel = id ? id - 1 : -1;
}

setSubtitleTrack(id: number | null) {
if (id) {
this.hls.subtitleTrack = id - 1;
} else {
this.hls.subtitleTrack = -1;
}
this.hls.subtitleTrack = id ? id - 1 : -1;
}

setAudioTrack(id: number | null) {
if (id) {
this.hls.audioTrack = id - 1;
} else {
this.hls.audioTrack = -1;
}
this.hls.audioTrack = id ? id - 1 : -1;
}

private setState_(spec: Spec<HlsState>) {
Expand Down Expand Up @@ -200,20 +189,30 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
return media;
}

private syncState_() {
private syncTimings_() {
clearInterval(this.intervalId_);
this.intervalId_ = setInterval(() => this.onTick_(), 500);
this.onTick_();

const onTick = () => {
const { integrated } = this.getInterstitialsManager_();

this.setState_({
time: { $set: integrated.currentTime },
seekRange: { $merge: { start: 0, end: integrated.duration } },
});
};

this.intervalId_ = setInterval(onTick, 500);
onTick();
}

private syncQualities_() {
const qualities = this.hls.levels.map<HlsQuality>((level, index) => ({
id: index + 1,
height: level.height ?? 0,
active: index === this.hls.nextLoadLevel,
level,
}));

qualities.sort((a, b) => b.height - a.height);
qualities.sort((a, b) => b.level.height - a.level.height);

this.setState_({
qualities: { $set: qualities },
Expand All @@ -224,8 +223,8 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
const audioTracks = this.hls.audioTracks.map<HlsAudioTrack>(
(audioTrack, index) => ({
id: index + 1,
name: audioTrack.name,
active: index === this.hls.audioTrack,
playlist: audioTrack,
}),
);

Expand All @@ -238,8 +237,8 @@ export class HlsFacade extends EventEmitter<HlsFacadeEvent> {
const subtitleTracks = this.hls.subtitleTracks.map<HlsSubtitleTrack>(
(subtitleTrack, index) => ({
id: index + 1,
name: subtitleTrack.name,
active: index === this.hls.subtitleTrack,
playlist: subtitleTrack,
}),
);

Expand Down
2 changes: 1 addition & 1 deletion packages/hlsjs/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Object.assign(window, { facade });
// hls.config.startPosition = 10;

hls.loadSource(
"http://127.0.0.1:52002/session/6371e172-bf65-4e7c-a0bd-b167c1256ba0/master.m3u8",
"https://streamer.ams3.cdn.digitaloceanspaces.com/package/293e9584-f5b0-4d43-a365-ac1c5e232af8/hls/master.m3u8",
);

const root = ReactDOM.createRoot(document.getElementById("root")!);
Expand Down

0 comments on commit fe1266d

Please sign in to comment.