(videoId: string)
| 100 | } |
| 101 | |
| 102 | async function validateAndSetProcessing(videoId: string): Promise<VideoData> { |
| 103 | "use step"; |
| 104 | |
| 105 | const groqClient = getGroqClient(); |
| 106 | if (!groqClient && !serverEnv().OPENAI_API_KEY) { |
| 107 | throw new FatalError("Missing Groq or OpenAI API key"); |
| 108 | } |
| 109 | |
| 110 | const query = await db() |
| 111 | .select({ video: videos, orgSettings: organizations.settings }) |
| 112 | .from(videos) |
| 113 | .leftJoin(organizations, eq(videos.orgId, organizations.id)) |
| 114 | .where(eq(videos.id, videoId as Video.VideoId)); |
| 115 | |
| 116 | if (query.length === 0 || !query[0]?.video) { |
| 117 | throw new FatalError("Video does not exist"); |
| 118 | } |
| 119 | |
| 120 | const { video } = query[0]; |
| 121 | const metadata = (video.metadata as VideoMetadata) || {}; |
| 122 | |
| 123 | if (video.transcriptionStatus !== "COMPLETE") { |
| 124 | throw new FatalError("Transcription not complete"); |
| 125 | } |
| 126 | |
| 127 | if (metadata.summary && metadata.chapters) { |
| 128 | throw new FatalError("AI metadata already generated"); |
| 129 | } |
| 130 | |
| 131 | await db() |
| 132 | .update(videos) |
| 133 | .set({ |
| 134 | metadata: { |
| 135 | ...metadata, |
| 136 | aiGenerationStatus: "PROCESSING", |
| 137 | }, |
| 138 | }) |
| 139 | .where(eq(videos.id, videoId as Video.VideoId)); |
| 140 | |
| 141 | return { |
| 142 | video, |
| 143 | metadata, |
| 144 | aiGenerationLanguage: parseAiGenerationLanguage( |
| 145 | query[0]?.orgSettings?.aiGenerationLanguage, |
| 146 | ), |
| 147 | }; |
| 148 | } |
| 149 | |
| 150 | async function fetchTranscript( |
| 151 | videoId: string, |
no test coverage detected