From 4b80c5849eb53a08be2ed95449b9e161714073eb Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 11 Oct 2023 17:35:30 +0200 Subject: [PATCH 1/2] Fix audio identify on some cases --- transcoder/src/identify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transcoder/src/identify.rs b/transcoder/src/identify.rs index 81695eafc..17d742939 100644 --- a/transcoder/src/identify.rs +++ b/transcoder/src/identify.rs @@ -222,7 +222,7 @@ pub async fn identify(path: String) -> Option { .members() .filter(|x| x["@type"] == "Audio") .map(|a| Audio { - index: parse::(&a["StreamOrder"]).unwrap() - 1, + index: parse::(&a["@typeorder"]).unwrap_or(1) - 1, title: a["Title"].as_str().map(|x| x.to_string()), language: a["Language"].as_str().map(|x| x.to_string()), // TODO: format is invalid. Channels count missing... From ab614b4d625f61c49fae894f9b87502bdc8d5cd8 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 11 Oct 2023 19:18:34 +0200 Subject: [PATCH 2/2] Use a better display name for audios --- .../models/src/resources/watch-info.ts | 26 ++++++++++++++++--- .../ui/src/player/components/hover.tsx | 5 +++- .../src/player/components/right-buttons.tsx | 17 ++++-------- front/packages/ui/src/player/index.tsx | 1 + front/packages/ui/src/player/video.tsx | 6 ++--- front/packages/ui/src/player/video.web.tsx | 13 ++++++---- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/front/packages/models/src/resources/watch-info.ts b/front/packages/models/src/resources/watch-info.ts index 4c2ed400d..116ba71e9 100644 --- a/front/packages/models/src/resources/watch-info.ts +++ b/front/packages/models/src/resources/watch-info.ts @@ -20,6 +20,17 @@ import { z } from "zod"; import { imageFn } from "../traits"; +import i18next from "i18next"; + +const getDisplayName = (sub: Track) => { + const languageNames = new Intl.DisplayNames([i18next.language ?? "en"], { type: "language" }); + const lng = sub.language ? languageNames.of(sub.language) : undefined; + + if (lng && sub.title && sub.title !== lng) return `${lng} - ${sub.title}`; + if (lng) return lng; + if (sub.title) return sub.title; + return `Unknwon (${sub.index})`; +}; /** * A audio or subtitle track. @@ -50,14 +61,23 @@ export const TrackP = z.object({ */ isForced: z.boolean(), }); -export type Audio = z.infer; +export type Track = z.infer; + +export const AudioP = TrackP.transform((x) => ({ + ...x, + displayName: getDisplayName(x), +})); +export type Audio = z.infer; export const SubtitleP = TrackP.extend({ /* * The url of this track (only if this is a subtitle).. */ link: z.string().transform(imageFn).nullable(), -}); +}).transform((x) => ({ + ...x, + displayName: getDisplayName(x), +})); export type Subtitle = z.infer; export const ChapterP = z.object({ @@ -97,7 +117,7 @@ export const WatchInfoP = z.object({ /** * The list of audio tracks. */ - audios: z.array(TrackP), + audios: z.array(AudioP), /** * The list of subtitles tracks. */ diff --git a/front/packages/ui/src/player/components/hover.tsx b/front/packages/ui/src/player/components/hover.tsx index b1f796b52..5f39d8a5a 100644 --- a/front/packages/ui/src/player/components/hover.tsx +++ b/front/packages/ui/src/player/components/hover.tsx @@ -33,7 +33,7 @@ import { tooltip, ts, } from "@kyoo/primitives"; -import { Chapter, KyooImage, Subtitle } from "@kyoo/models"; +import { Chapter, KyooImage, Subtitle, Audio } from "@kyoo/models"; import { useAtomValue, useSetAtom, useAtom } from "jotai"; import { ImageStyle, Platform, Pressable, View, ViewProps } from "react-native"; import { useTranslation } from "react-i18next"; @@ -52,6 +52,7 @@ export const Hover = ({ poster, chapters, subtitles, + audios, fonts, previousSlug, nextSlug, @@ -68,6 +69,7 @@ export const Hover = ({ poster?: KyooImage | null; chapters?: Chapter[]; subtitles?: Subtitle[]; + audios?: Audio[]; fonts?: string[]; previousSlug?: string | null; nextSlug?: string | null; @@ -123,6 +125,7 @@ export const Hover = ({ . */ -import { Subtitle } from "@kyoo/models"; +import { Audio, Subtitle } from "@kyoo/models"; import { IconButton, tooltip, Menu, ts } from "@kyoo/primitives"; import { useAtom } from "jotai"; import { Platform, View } from "react-native"; @@ -33,23 +33,15 @@ import { fullscreenAtom, subtitleAtom } from "../state"; import { AudiosMenu, QualitiesMenu } from "../video"; import i18next from "i18next"; -export const getDisplayName = (sub: Subtitle) => { - const languageNames = new Intl.DisplayNames([i18next.language ?? "en"], { type: "language" }); - const lng = sub.language ? languageNames.of(sub.language) : undefined; - - if (lng && sub.title) return `${lng} - ${sub.title}`; - if (lng) return lng; - if (sub.title) return sub.title; - return `Unknwon (${sub.index})`; -}; - export const RightButtons = ({ + audios, subtitles, fonts, onMenuOpen, onMenuClose, ...props }: { + audios?: Audio[]; subtitles?: Subtitle[]; fonts?: string[]; onMenuOpen: () => void; @@ -81,7 +73,7 @@ export const RightButtons = ({ {subtitles.map((x) => ( setSubtitle(x)} @@ -94,6 +86,7 @@ export const RightButtons = ({ icon={MusicNote} onMenuOpen={onMenuOpen} onMenuClose={onMenuClose} + audios={audios} {...tooltip(t("player.audios"), true)} {...spacing} /> diff --git a/front/packages/ui/src/player/index.tsx b/front/packages/ui/src/player/index.tsx index 599bd76fd..4e3e83398 100644 --- a/front/packages/ui/src/player/index.tsx +++ b/front/packages/ui/src/player/index.tsx @@ -77,6 +77,7 @@ const mapData = ( href: data ? (data.type === "movie" ? `/movie/${data.slug}` : `/show/${data.show!.slug}`) : "#", poster: data.type === "movie" ? data.poster : data.show!.poster, subtitles: info.subtitles, + audios: info.audios, chapters: info.chapters, fonts: info.fonts, previousSlug, diff --git a/front/packages/ui/src/player/video.tsx b/front/packages/ui/src/player/video.tsx index ae04b3f63..9b0df0b58 100644 --- a/front/packages/ui/src/player/video.tsx +++ b/front/packages/ui/src/player/video.tsx @@ -34,7 +34,7 @@ declare module "react-native-video" { export * from "react-native-video"; -import { Subtitle, getToken } from "@kyoo/models"; +import { Audio, Subtitle, getToken } from "@kyoo/models"; import { IconButton, Menu } from "@kyoo/primitives"; import { ComponentProps, forwardRef, useEffect, useRef } from "react"; import { atom, useAtom, useAtomValue, useSetAtom } from "jotai"; @@ -119,7 +119,7 @@ const Video = forwardRef(function Video( export default Video; type CustomMenu = ComponentProps>>; -export const AudiosMenu = (props: CustomMenu) => { +export const AudiosMenu = ({ audios, ...props }: CustomMenu & { audios?: Audio[] }) => { const info = useAtomValue(infoAtom); const [audio, setAudio] = useAtom(audioAtom); @@ -130,7 +130,7 @@ export const AudiosMenu = (props: CustomMenu) => { {info.audioTracks.map((x) => ( setAudio(x.index)} /> diff --git a/front/packages/ui/src/player/video.web.tsx b/front/packages/ui/src/player/video.web.tsx index 843fb1935..4251a4dfe 100644 --- a/front/packages/ui/src/player/video.web.tsx +++ b/front/packages/ui/src/player/video.web.tsx @@ -18,7 +18,7 @@ * along with Kyoo. If not, see . */ -import { getToken, Subtitle } from "@kyoo/models"; +import { getToken, Subtitle, Audio } from "@kyoo/models"; import { forwardRef, RefObject, @@ -38,7 +38,6 @@ import Hls, { Level, LoadPolicy } from "hls.js"; import { useTranslation } from "react-i18next"; import { Menu } from "@kyoo/primitives"; import toVttBlob from "srt-webvtt"; -import { getDisplayName } from "./components/right-buttons"; let hls: Hls | null = null; @@ -256,7 +255,7 @@ const useSubtitle = ( const addSubtitle = async () => { const track: HTMLTrackElement = htmlTrack ?? document.createElement("track"); track.kind = "subtitles"; - track.label = getDisplayName(value); + track.label = value.displayName; if (value.language) track.srclang = value.language; track.src = value.codec === "subrip" ? await toWebVtt(value.link!) : value.link!; track.className = "subtitle_container"; @@ -300,14 +299,18 @@ const toWebVtt = async (srtUrl: string) => { return await toVttBlob(srt); }; -export const AudiosMenu = (props: ComponentProps) => { +export const AudiosMenu = ({ + audios, + ...props +}: ComponentProps & { audios?: Audio[] }) => { if (!hls || hls.audioTracks.length < 2) return null; + console.log(audios); return ( {hls.audioTracks.map((x, i) => ( (hls!.audioTrack = i)} />