mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-20 14:37:43 +01:00
fix custom subs + download
This commit is contained in:
parent
0883942093
commit
ca402a219d
5 changed files with 40 additions and 12 deletions
|
@ -13,7 +13,7 @@ interface Props {
|
|||
className?: string;
|
||||
href?: string;
|
||||
disabled?: boolean;
|
||||
download?: boolean;
|
||||
download?: string;
|
||||
}
|
||||
|
||||
export function Button(props: Props) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import { Input } from "@/components/player/internals/ContextMenu/Input";
|
|||
import { SelectableLink } from "@/components/player/internals/ContextMenu/Links";
|
||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||
import { usePlayerStore } from "@/stores/player/store";
|
||||
import { useSubtitleStore } from "@/stores/subtitles";
|
||||
|
||||
export function CaptionOption(props: {
|
||||
countryCode?: string;
|
||||
|
@ -94,6 +95,7 @@ function searchSubs(
|
|||
function CustomCaptionOption() {
|
||||
const lang = usePlayerStore((s) => s.caption.selected?.language);
|
||||
const setCaption = usePlayerStore((s) => s.setCaption);
|
||||
const setCustomSubs = useSubtitleStore((s) => s.setCustomSubs);
|
||||
const fileInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
return (
|
||||
|
@ -118,6 +120,7 @@ function CustomCaptionOption() {
|
|||
language: "custom",
|
||||
srtData: converted,
|
||||
});
|
||||
setCustomSubs();
|
||||
});
|
||||
reader.readAsText(e.target.files[0], "utf-8");
|
||||
}}
|
||||
|
@ -126,9 +129,7 @@ function CustomCaptionOption() {
|
|||
);
|
||||
}
|
||||
|
||||
// TODO on initialize, download captions
|
||||
// TODO fix language names, some are unknown
|
||||
// TODO delay setting for captions
|
||||
export function CaptionsView({ id }: { id: string }) {
|
||||
const router = useOverlayRouter(id);
|
||||
const lang = usePlayerStore((s) => s.caption.selected?.language);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Button } from "@/components/Button";
|
|||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { OverlayPage } from "@/components/overlays/OverlayPage";
|
||||
import { Menu } from "@/components/player/internals/ContextMenu";
|
||||
import { convertSubtitlesToDataurl } from "@/components/player/utils/captions";
|
||||
import { convertSubtitlesToSrtDataurl } from "@/components/player/utils/captions";
|
||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||
import { usePlayerStore } from "@/stores/player/store";
|
||||
|
||||
|
@ -24,11 +24,13 @@ export function DownloadView({ id }: { id: string }) {
|
|||
const downloadUrl = useDownloadLink();
|
||||
|
||||
const selectedCaption = usePlayerStore((s) => s.caption?.selected);
|
||||
const subtitleUrl = selectedCaption
|
||||
? convertSubtitlesToDataurl(selectedCaption?.srtData)
|
||||
: null;
|
||||
|
||||
console.log(subtitleUrl);
|
||||
const subtitleUrl = useMemo(
|
||||
() =>
|
||||
selectedCaption
|
||||
? convertSubtitlesToSrtDataurl(selectedCaption?.srtData)
|
||||
: null,
|
||||
[selectedCaption]
|
||||
);
|
||||
|
||||
if (!downloadUrl) return null;
|
||||
|
||||
|
@ -66,7 +68,7 @@ export function DownloadView({ id }: { id: string }) {
|
|||
href={subtitleUrl ?? undefined}
|
||||
disabled={!subtitleUrl}
|
||||
theme="secondary"
|
||||
download
|
||||
download="subtitles.srt"
|
||||
>
|
||||
Download current caption
|
||||
</Button>
|
||||
|
|
|
@ -35,13 +35,31 @@ export function convertSubtitlesToVtt(text: string): string {
|
|||
return vtt;
|
||||
}
|
||||
|
||||
export function convertSubtitlesToSrt(text: string): string {
|
||||
const textTrimmed = text.trim();
|
||||
if (textTrimmed === "") {
|
||||
throw new Error("Given text is empty");
|
||||
}
|
||||
const srt = convert(textTrimmed, "srt");
|
||||
if (detect(srt) === "") {
|
||||
throw new Error("Invalid subtitle format");
|
||||
}
|
||||
return srt;
|
||||
}
|
||||
|
||||
export function parseSubtitles(text: string): CaptionCueType[] {
|
||||
const vtt = convertSubtitlesToVtt(text);
|
||||
return parse(vtt).filter((cue) => cue.type === "caption") as CaptionCueType[];
|
||||
}
|
||||
|
||||
export function convertSubtitlesToDataurl(text: string): string {
|
||||
return `data:text/vtt,${convertSubtitlesToVtt(text)}`;
|
||||
function stringToBase64(input: string): string {
|
||||
return btoa(String.fromCodePoint(...new TextEncoder().encode(input)));
|
||||
}
|
||||
|
||||
export function convertSubtitlesToSrtDataurl(text: string): string {
|
||||
return `data:application/x-subrip;base64,${stringToBase64(
|
||||
convertSubtitlesToSrt(text)
|
||||
)}`;
|
||||
}
|
||||
|
||||
export function convertSubtitlesToObjectUrl(text: string): string {
|
||||
|
|
|
@ -27,6 +27,7 @@ export interface SubtitleStore {
|
|||
delay: number;
|
||||
updateStyling(newStyling: Partial<SubtitleStyling>): void;
|
||||
setLanguage(language: string | null): void;
|
||||
setCustomSubs(): void;
|
||||
setOverrideCasing(enabled: boolean): void;
|
||||
setDelay(delay: number): void;
|
||||
}
|
||||
|
@ -60,6 +61,12 @@ export const useSubtitleStore = create(
|
|||
if (lang) s.lastSelectedLanguage = lang;
|
||||
});
|
||||
},
|
||||
setCustomSubs() {
|
||||
set((s) => {
|
||||
s.enabled = true;
|
||||
s.lastSelectedLanguage = null;
|
||||
});
|
||||
},
|
||||
setOverrideCasing(enabled) {
|
||||
set((s) => {
|
||||
s.overrideCasing = enabled;
|
||||
|
|
Loading…
Reference in a new issue