Initial commit: PodcastYes — AI podcast platform
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
export const TONES = [
|
||||
"Conversational",
|
||||
"Professional",
|
||||
"Humorous",
|
||||
"Educational",
|
||||
"Inspirational",
|
||||
"Storytelling",
|
||||
"Investigative",
|
||||
"Casual",
|
||||
] as const;
|
||||
|
||||
export const FORMATS = [
|
||||
{ value: "SOLO", label: "Solo", description: "One host narrating the episode." },
|
||||
{ value: "INTERVIEW", label: "Interview", description: "A host interviewing a guest." },
|
||||
{ value: "MULTI_HOST", label: "Multi-host", description: "A panel of co-hosts in conversation." },
|
||||
] as const;
|
||||
|
||||
export const LANGUAGES = [
|
||||
{ code: "en", label: "English" },
|
||||
{ code: "es", label: "Spanish" },
|
||||
{ code: "fr", label: "French" },
|
||||
{ code: "de", label: "German" },
|
||||
{ code: "it", label: "Italian" },
|
||||
{ code: "pt", label: "Portuguese" },
|
||||
{ code: "nl", label: "Dutch" },
|
||||
{ code: "pl", label: "Polish" },
|
||||
{ code: "hi", label: "Hindi" },
|
||||
{ code: "ja", label: "Japanese" },
|
||||
{ code: "ko", label: "Korean" },
|
||||
{ code: "zh", label: "Chinese (Mandarin)" },
|
||||
{ code: "ar", label: "Arabic" },
|
||||
{ code: "tr", label: "Turkish" },
|
||||
{ code: "ru", label: "Russian" },
|
||||
] as const;
|
||||
|
||||
export const LENGTH_OPTIONS = [5, 10, 15, 20, 30, 45, 60, 90] as const;
|
||||
|
||||
/** The speaker roles required for each format. */
|
||||
export const FORMAT_SPEAKERS: Record<string, { speakerKey: string; defaultName: string }[]> = {
|
||||
SOLO: [{ speakerKey: "host", defaultName: "Host" }],
|
||||
INTERVIEW: [
|
||||
{ speakerKey: "host", defaultName: "Host" },
|
||||
{ speakerKey: "guest", defaultName: "Guest" },
|
||||
],
|
||||
MULTI_HOST: [
|
||||
{ speakerKey: "host", defaultName: "Host" },
|
||||
{ speakerKey: "cohost", defaultName: "Co-host" },
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
import { prisma } from "@/lib/db";
|
||||
import type { EpisodeStatus } from "@prisma/client";
|
||||
|
||||
/** Update an episode's pipeline status (and optional human-readable stage / error). */
|
||||
export async function setEpisodeStatus(
|
||||
episodeId: string,
|
||||
status: EpisodeStatus,
|
||||
opts: { stage?: string; errorMessage?: string | null } = {}
|
||||
): Promise<void> {
|
||||
await prisma.episode.update({
|
||||
where: { id: episodeId },
|
||||
data: {
|
||||
status,
|
||||
stage: opts.stage ?? null,
|
||||
...(opts.errorMessage !== undefined ? { errorMessage: opts.errorMessage } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Mark a GenerationJob as running. */
|
||||
export async function startJob(jobId: string, pgBossJobId?: string): Promise<void> {
|
||||
await prisma.generationJob.update({
|
||||
where: { id: jobId },
|
||||
data: { status: "running", startedAt: new Date(), pgBossJobId: pgBossJobId ?? undefined },
|
||||
});
|
||||
}
|
||||
|
||||
/** Mark a GenerationJob as completed or failed. */
|
||||
export async function finishJob(
|
||||
jobId: string,
|
||||
result: { status: "completed" | "failed"; error?: string; stage?: string }
|
||||
): Promise<void> {
|
||||
await prisma.generationJob.update({
|
||||
where: { id: jobId },
|
||||
data: {
|
||||
status: result.status,
|
||||
error: result.error ?? null,
|
||||
stage: result.stage,
|
||||
finishedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** Terminal episode states — used by the UI/SSE to stop polling. */
|
||||
export function isTerminal(status: EpisodeStatus): boolean {
|
||||
return status === "READY" || status === "FAILED";
|
||||
}
|
||||
Reference in New Issue
Block a user