Fix transcription create (#1081)
* refactor transcription loading model * abort transcribe when auto download * refactor
This commit is contained in:
@@ -14,24 +14,14 @@ import {
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@renderer/components/ui";
|
||||
import { CheckCircleIcon, CircleAlertIcon, LoaderIcon } from "lucide-react";
|
||||
import { CircleAlertIcon, LoaderIcon } from "lucide-react";
|
||||
import { t } from "i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { TranscriptionCreateForm, TranscriptionsList } from "../transcriptions";
|
||||
import { SttEngineOptionEnum } from "@/types/enums";
|
||||
|
||||
export const MediaLoadingModal = () => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
media,
|
||||
decoded,
|
||||
decodeError,
|
||||
transcription,
|
||||
transcribing,
|
||||
transcribingProgress,
|
||||
transcribingOutput,
|
||||
generateTranscription,
|
||||
} = useContext(MediaShadowProviderContext);
|
||||
const { decoded, transcription } = useContext(MediaShadowProviderContext);
|
||||
|
||||
return (
|
||||
<AlertDialog open={!decoded || !Boolean(transcription?.result?.timeline)}>
|
||||
@@ -43,84 +33,109 @@ export const MediaLoadingModal = () => {
|
||||
{t("itMayTakeAWhileToPrepareForTheFirstLoad")}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
|
||||
{decoded ? (
|
||||
transcription?.result?.timeline ? (
|
||||
<div className="flex items-center space-x-4">
|
||||
<CheckCircleIcon className="w-4 h-4 text-green-500" />
|
||||
<span>{t("transcribedSuccessfully")}</span>
|
||||
</div>
|
||||
) : (
|
||||
<Tabs defaultValue="transcribe">
|
||||
<TabsList className="w-full grid grid-cols-2 mb-4">
|
||||
<TabsTrigger value="transcribe">{t("transcribe")}</TabsTrigger>
|
||||
<TabsTrigger value="download">
|
||||
{t("downloadTranscript")}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="transcribe">
|
||||
<TranscriptionCreateForm
|
||||
originalText={transcription?.result?.originalText}
|
||||
onSubmit={(data) => {
|
||||
generateTranscription({
|
||||
originalText: data.text,
|
||||
language: data.language,
|
||||
service: data.service as SttEngineOptionEnum | "upload",
|
||||
isolate: data.isolate,
|
||||
});
|
||||
}}
|
||||
onCancel={() => navigate(-1)}
|
||||
transcribing={transcribing}
|
||||
transcribingProgress={transcribingProgress}
|
||||
transcribingOutput={transcribingOutput}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent value="download">
|
||||
<TranscriptionsList
|
||||
media={media}
|
||||
transcription={transcription}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
{decodeError ? (
|
||||
<div className="mb-4 flex items-center space-x-4">
|
||||
<div className="w-4 h-4">
|
||||
<CircleAlertIcon className="text-destructive w-4 h-4" />
|
||||
</div>
|
||||
<div className="select-text">
|
||||
<div className="mb-2">{decodeError}</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{t("failedToDecodeWaveform")}:{" "}
|
||||
<span className="break-all ">{media?.src}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mb-4 flex items-center space-x-4">
|
||||
{media?.src ? (
|
||||
<>
|
||||
<LoaderIcon className="w-4 h-4 animate-spin" />
|
||||
<span>{t("decodingWaveform")}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CircleAlertIcon className="text-destructive w-4 h-4" />
|
||||
<span>{t("cannotFindSourceFile")}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<AlertDialogFooter>
|
||||
<Button variant="secondary" onClick={() => navigate(-1)}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</>
|
||||
)}
|
||||
<LoadingContent />
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const LoadingContent = () => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
media,
|
||||
decoded,
|
||||
decodeError,
|
||||
transcription,
|
||||
transcribing,
|
||||
transcribingProgress,
|
||||
transcribingOutput,
|
||||
generateTranscription,
|
||||
} = useContext(MediaShadowProviderContext);
|
||||
if (decoded) {
|
||||
// Decoded and transcription created but not ready
|
||||
if (transcription && !transcription.result?.timeline) {
|
||||
return (
|
||||
<Tabs defaultValue="transcribe">
|
||||
<TabsList className="w-full grid grid-cols-2 mb-4">
|
||||
<TabsTrigger value="transcribe">{t("transcribe")}</TabsTrigger>
|
||||
<TabsTrigger value="download">
|
||||
{t("downloadTranscript")}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="transcribe">
|
||||
<TranscriptionCreateForm
|
||||
originalText={transcription?.result?.originalText}
|
||||
onSubmit={(data) => {
|
||||
generateTranscription({
|
||||
originalText: data.text,
|
||||
language: data.language,
|
||||
service: data.service as SttEngineOptionEnum | "upload",
|
||||
isolate: data.isolate,
|
||||
});
|
||||
}}
|
||||
onCancel={() => navigate(-1)}
|
||||
transcribing={transcribing}
|
||||
transcribingProgress={transcribingProgress}
|
||||
transcribingOutput={transcribingOutput}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent value="download">
|
||||
<TranscriptionsList media={media} transcription={transcription} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className="flex items-center space-x-4">
|
||||
<LoaderIcon className="w-4 h-4 animate-spin" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Decode error
|
||||
} else if (decodeError) {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex items-center space-x-4">
|
||||
<div className="w-4 h-4">
|
||||
<CircleAlertIcon className="text-destructive w-4 h-4" />
|
||||
</div>
|
||||
<div className="select-text">
|
||||
<div className="mb-2">{decodeError}</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{t("failedToDecodeWaveform")}:{" "}
|
||||
<span className="break-all ">{media?.src}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AlertDialogFooter>
|
||||
<Button variant="secondary" onClick={() => navigate(-1)}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex items-center space-x-4">
|
||||
{media?.src ? (
|
||||
<>
|
||||
<LoaderIcon className="w-4 h-4 animate-spin" />
|
||||
<span>{t("decodingWaveform")}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CircleAlertIcon className="text-destructive w-4 h-4" />
|
||||
<span>{t("cannotFindSourceFile")}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<AlertDialogFooter>
|
||||
<Button variant="secondary" onClick={() => navigate(-1)}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@ export const useTranscriptions = (media: AudioType | VideoType) => {
|
||||
const { transcribe, output } = useTranscribe();
|
||||
const [transcribingProgress, setTranscribingProgress] = useState<number>(0);
|
||||
const [transcribing, setTranscribing] = useState<boolean>(false);
|
||||
const [creating, setCreating] = useState<boolean>(false);
|
||||
const [transcribingOutput, setTranscribingOutput] = useState<string>("");
|
||||
const [service, setService] = useState<SttEngineOptionEnum | "upload">(
|
||||
sttEngine
|
||||
@@ -42,40 +43,45 @@ export const useTranscriptions = (media: AudioType | VideoType) => {
|
||||
async (): Promise<TranscriptionType | void> => {
|
||||
if (!media) return;
|
||||
if (transcription?.targetId === media.id) return;
|
||||
if (creating) return;
|
||||
|
||||
const tr = await EnjoyApp.transcriptions.findOrCreate({
|
||||
targetId: media.id,
|
||||
targetType: media.mediaType,
|
||||
});
|
||||
try {
|
||||
setCreating(true);
|
||||
const tr = await EnjoyApp.transcriptions.findOrCreate({
|
||||
targetId: media.id,
|
||||
targetType: media.mediaType,
|
||||
});
|
||||
|
||||
if (!tr?.result?.timeline) {
|
||||
tr.result = {
|
||||
originalText: tr.result?.originalText,
|
||||
};
|
||||
}
|
||||
if (!tr?.result?.timeline) {
|
||||
tr.result = {
|
||||
originalText: tr.result?.originalText,
|
||||
};
|
||||
}
|
||||
|
||||
const transcriptionOnline = await findTranscriptionOnline();
|
||||
if (transcriptionOnline && !tr?.result?.timeline) {
|
||||
return EnjoyApp.transcriptions
|
||||
.update(tr.id, {
|
||||
const transcriptionOnline = await findTranscriptionOnline();
|
||||
if (transcriptionOnline && !tr?.result?.timeline) {
|
||||
await EnjoyApp.transcriptions.update(tr.id, {
|
||||
state: "finished",
|
||||
result: transcriptionOnline.result,
|
||||
engine: transcriptionOnline.engine,
|
||||
model: transcriptionOnline.model,
|
||||
language: transcriptionOnline.language || media.language,
|
||||
})
|
||||
.then(() => {
|
||||
toast.success(t("downloadedTranscriptionFromCloud"));
|
||||
setTranscription(transcriptionOnline);
|
||||
return transcriptionOnline;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
return tr;
|
||||
});
|
||||
} else {
|
||||
setTranscription(tr);
|
||||
return tr;
|
||||
setTranscription(transcriptionOnline);
|
||||
toast.success(t("downloadedTranscriptionFromCloud"));
|
||||
if (transcribing) {
|
||||
abortGenerateTranscription();
|
||||
}
|
||||
return transcriptionOnline;
|
||||
} else {
|
||||
setTranscription(tr);
|
||||
return tr;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return null;
|
||||
} finally {
|
||||
setCreating(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user