Skip to content

Commit

Permalink
[wip] feat/controller: support domand server
Browse files Browse the repository at this point in the history
  • Loading branch information
xpadev-net committed Nov 9, 2023
1 parent e07eb83 commit 5564695
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 115 deletions.
1 change: 1 addition & 0 deletions electron/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const startMovieDownload = async (): Promise<void> => {
try {
await download(
targetQueue.url,
//@ts-ignore
targetQueue.format,
targetQueue.path,
(total, downloaded) => {
Expand Down
105 changes: 69 additions & 36 deletions src/@types/niconico.d.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
export type TWatchV3Metadata = {
export type TWatchV3Metadata<T extends "delivery" | "domand" | "" = ""> = {
meta: {
status: 200;
};
data: {
comment: V3MetadataComment;
media: {
delivery: {
recipeId: string;
encryption: null | {
encryptedKey: string;
keyUri: string;
};
movie: {
contentId: string;
audios: V3MetadataAudioItem[];
videos: V3MetadataVideoItem[];
session: {
recipeId: string;
playerId: string;
videos: string[];
audios: string[];
movies: [];
protocols: ["http", "hls"] | ["hls"];
AuthTypes: { [key in "http" | "hls"]: "ht2" };
serviceUserId: string;
token: string;
signature: string;
contentId: string;
heartbeatLifetime: number;
contentKeyTimeout: number;
priority: number;
transferPresets: [] | ["standard2"];
urls: {
url: string;
isWellKnownPort: boolean;
isSsl: boolean;
}[];
};
};
trackingId: string;
};
delivery: T extends "delivery"
? V3MetadataDeliveryMedia
: V3MetadataDeliveryMedia | null;
domand: T extends "domand"
? V3MetadataDomandMedia
: V3MetadataDomandMedia | null;
};
video: {
id: string;
Expand Down Expand Up @@ -99,6 +70,68 @@ export type V3MetadataVideoItem = {
};
};

export type V3MetadataDeliveryMedia = {
recipeId: string;
encryption: null | {
encryptedKey: string;
keyUri: string;
};
movie: {
contentId: string;
audios: V3MetadataAudioItem[];
videos: V3MetadataVideoItem[];
session: {
recipeId: string;
playerId: string;
videos: string[];
audios: string[];
movies: [];
protocols: ["http", "hls"] | ["hls"];
AuthTypes: { [key in "http" | "hls"]: "ht2" };
serviceUserId: string;
token: string;
signature: string;
contentId: string;
heartbeatLifetime: number;
contentKeyTimeout: number;
priority: number;
transferPresets: [] | ["standard2"];
urls: {
url: string;
isWellKnownPort: boolean;
isSsl: boolean;
}[];
};
};
trackingId: string;
};

export type V3MetadataDomandMedia = {
videos: V3MetadataDomandVideoItem[];
audios: V3MetadataDomandAudioItem[];
};

export type V3MetadataDomandVideoItem = {
id: string;
isAvailable: boolean;
label: string;
bitRate: number;
width: number;
height: number;
qualityLevel: number;
recommendedHighestAudioQualityLevel: number;
};

export type V3MetadataDomandAudioItem = {
id: string;
isAvailable: boolean;
bitRate: number;
samplingRate: number;
integratedLoudness: number;
truePeak: number;
qualityLevel: number;
};

export type V3MetadataComment = {
server: {
url: string;
Expand Down
18 changes: 17 additions & 1 deletion src/@types/queue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ export type TMovieItemRemote = {
ref: MovieQueue;
};

export type TRemoteServerType = "delivery" | "domand";
export type TRemoteMovieItemFormat = TDomandFormat | TDeliveryFormat;

export type TDeliveryFormat = {
type: "delivery";
format: {
audio: string;
video: string;
};
};

export type TDomandFormat = {
type: "domand";
format: [string, string];
};

export type ConvertQueue = BaseQueue & {
type: "convert";
comment: TCommentItem;
Expand All @@ -65,7 +81,7 @@ export type ConvertQueue = BaseQueue & {
export type MovieQueue = BaseQueue & {
type: "movie";
url: NicoId;
format: NicovideoMovieFormat;
format: TRemoteMovieItemFormat;
path: string;
};

Expand Down
83 changes: 83 additions & 0 deletions src/controller/movie-picker/remote/delivery/delivery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { MenuItem, Select } from "@mui/material";
import type { FC } from "react";
import { useEffect, useState } from "react";

import type { TWatchV3Metadata } from "@/@types/niconico";
import type { TDeliveryFormat } from "@/@types/queue";
import { SelectField } from "@/components/SelectField";
import Styles from "@/controller/movie/movie.module.scss";
import { getDeliveryBestSegment } from "@/util/niconico";

type Props = {
metadata: TWatchV3Metadata<"delivery">;
onChange: (val: TDeliveryFormat | undefined) => void;
};

const DeliveryMoviePicker: FC<Props> = ({ metadata, onChange }) => {
const [selectedVideo, setSelectedVideo] = useState<string>("");
const [selectedAudio, setSelectedAudio] = useState<string>("");
useEffect(() => {
setSelectedAudio(
getDeliveryBestSegment(metadata.data.media.delivery.movie.audios).id,
);
setSelectedVideo(
getDeliveryBestSegment(metadata.data.media.delivery.movie.videos).id,
);
}, [metadata]);
useEffect(() => {
onChange({
type: "delivery",
format: {
video: selectedVideo,
audio: selectedAudio,
},
});
}, [selectedAudio, selectedVideo]);
return (
<>
<SelectField label={"動画"} className={Styles.input}>
<Select
label={"動画"}
variant={"standard"}
value={selectedVideo}
defaultValue={
getDeliveryBestSegment(metadata.data.media.delivery.movie.videos).id
}
className={Styles.input}
onChange={(e) => setSelectedVideo(e.target.value)}
>
{metadata.data.media.delivery.movie.videos.map((val) => {
if (!val.isAvailable) return <></>;
return (
<MenuItem key={val.id} value={val.id}>
{val.id}
</MenuItem>
);
})}
</Select>
</SelectField>
<SelectField label={"音声"} className={Styles.input}>
<Select
label={"音声"}
variant={"standard"}
className={Styles.input}
defaultValue={
getDeliveryBestSegment(metadata.data.media.delivery.movie.audios).id
}
value={selectedAudio}
onChange={(e) => setSelectedAudio(e.target.value)}
>
{metadata.data.media.delivery.movie.audios.map((val) => {
return (
<MenuItem key={val.id} value={val.id}>
{val.id}
</MenuItem>
);
})}
</Select>
</SelectField>
</>
);
};

export { DeliveryMoviePicker };
1 change: 1 addition & 0 deletions src/controller/movie-picker/remote/delivery/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./delivery";
81 changes: 81 additions & 0 deletions src/controller/movie-picker/remote/domand/domand.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { MenuItem, Select } from "@mui/material";
import type { FC } from "react";
import { useEffect, useState } from "react";

import type { TWatchV3Metadata } from "@/@types/niconico";
import type { TDomandFormat } from "@/@types/queue";
import { SelectField } from "@/components/SelectField";
import Styles from "@/controller/movie/movie.module.scss";
import { getDomandBestSegment } from "@/util/niconico";

type Props = {
metadata: TWatchV3Metadata<"domand">;
onChange: (val: TDomandFormat | undefined) => void;
};

const DomandMoviePicker: FC<Props> = ({ metadata, onChange }) => {
const [selectedVideo, setSelectedVideo] = useState<string>("");
const [selectedAudio, setSelectedAudio] = useState<string>("");
useEffect(() => {
setSelectedAudio(
getDomandBestSegment(metadata.data.media.domand.audios).id,
);
setSelectedVideo(
getDomandBestSegment(metadata.data.media.domand.videos).id,
);
}, [metadata]);

useEffect(() => {
onChange({
type: "domand",
format: [selectedVideo, selectedAudio],
});
}, [selectedAudio, selectedVideo]);
return (
<>
<SelectField label={"動画"} className={Styles.input}>
<Select
label={"動画"}
variant={"standard"}
value={selectedVideo}
defaultValue={
getDomandBestSegment(metadata.data.media.domand.videos).id
}
className={Styles.input}
onChange={(e) => setSelectedVideo(e.target.value)}
>
{metadata.data.media.domand.videos.map((val) => {
if (!val.isAvailable) return <></>;
return (
<MenuItem key={val.id} value={val.id}>
{val.id}
</MenuItem>
);
})}
</Select>
</SelectField>
<SelectField label={"音声"} className={Styles.input}>
<Select
label={"音声"}
variant={"standard"}
className={Styles.input}
defaultValue={
getDomandBestSegment(metadata.data.media.domand.audios).id
}
value={selectedAudio}
onChange={(e) => setSelectedAudio(e.target.value)}
>
{metadata.data.media.domand.audios.map((val) => {
return (
<MenuItem key={val.id} value={val.id}>
{val.id}
</MenuItem>
);
})}
</Select>
</SelectField>
</>
);
};

export { DomandMoviePicker };
1 change: 1 addition & 0 deletions src/controller/movie-picker/remote/domand/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./domand";
Loading

0 comments on commit 5564695

Please sign in to comment.