Skip to content

Commit dc8a15a

Browse files
author
Miriad
committed
feat: wire infographic URLs from Sanity doc through pipeline to Remotion
1 parent b0c61b5 commit dc8a15a

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

lib/services/remotion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface RenderInput {
4848
bRollKeywords?: string[];
4949
sceneNumber?: number;
5050
durationEstimate?: number;
51+
infographicUrl?: string;
5152
}>;
5253
cta: string;
5354
};
@@ -117,6 +118,7 @@ function mapInputProps(input: RenderInput): Record<string, unknown> {
117118
sceneNumber: s.sceneNumber,
118119
durationEstimate: s.durationEstimate,
119120
bRollUrl: input.bRollUrls[i],
121+
...(s.infographicUrl ? { infographicUrl: s.infographicUrl } : {}),
120122
})),
121123
cta: input.script.cta,
122124
sponsor: input.sponsor,

lib/services/video-pipeline.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import { createClient, type SanityClient } from 'next-sanity';
1313
import { apiVersion, dataset, projectId } from '@/sanity/lib/api';
14+
import imageUrlBuilder from '@sanity/image-url';
1415
import { generateSpeechFromScript } from '@/lib/services/elevenlabs';
1516
import { generatePerSceneAudio } from '@/lib/services/elevenlabs';
1617
import type { WordTimestamp } from '@/lib/utils/audio-timestamps';
@@ -50,6 +51,12 @@ interface AutomatedVideoDocument {
5051
videoUrl?: string;
5152
shortUrl?: string;
5253
flaggedReason?: string;
54+
infographics?: Array<{
55+
asset: { _ref: string; _type: string };
56+
alt?: string;
57+
caption?: string;
58+
}>;
59+
researchData?: string; // JSON string
5360
}
5461

5562
interface SponsorLeadDocument {
@@ -58,6 +65,61 @@ interface SponsorLeadDocument {
5865
contactName?: string;
5966
}
6067

68+
// --- Infographic URL Extraction ---
69+
70+
/**
71+
* Extract infographic CDN URLs from the Sanity document.
72+
*
73+
* Priority:
74+
* 1. `doc.infographics[]` — Sanity image assets resolved via @sanity/image-url
75+
* 2. `doc.researchData` — JSON string with `infographicUrls: string[]` (backward compat)
76+
*
77+
* Never throws — returns empty array on failure so the pipeline continues
78+
* with Pexels B-roll fallback.
79+
*/
80+
function getInfographicUrls(doc: AutomatedVideoDocument): string[] {
81+
try {
82+
// Primary: resolve Sanity image assets to CDN URLs
83+
if (doc.infographics?.length) {
84+
const builder = imageUrlBuilder({ projectId, dataset });
85+
const urls = doc.infographics
86+
.map((img) => {
87+
try {
88+
return builder.image(img.asset).url();
89+
} catch {
90+
return null;
91+
}
92+
})
93+
.filter((url): url is string => !!url);
94+
95+
if (urls.length > 0) {
96+
console.log(`[VIDEO-PIPELINE] Resolved ${urls.length} infographic URL(s) from Sanity image assets`);
97+
return urls;
98+
}
99+
}
100+
101+
// Fallback: parse researchData JSON for infographicUrls
102+
if (doc.researchData) {
103+
const parsed = JSON.parse(doc.researchData);
104+
if (Array.isArray(parsed?.infographicUrls) && parsed.infographicUrls.length > 0) {
105+
const urls = parsed.infographicUrls.filter(
106+
(u: unknown): u is string => typeof u === 'string' && u.length > 0
107+
);
108+
if (urls.length > 0) {
109+
console.log(`[VIDEO-PIPELINE] Resolved ${urls.length} infographic URL(s) from researchData fallback`);
110+
return urls;
111+
}
112+
}
113+
}
114+
} catch (err) {
115+
console.warn(
116+
`[VIDEO-PIPELINE] Failed to extract infographic URLs (non-fatal): ${err instanceof Error ? err.message : String(err)}`
117+
);
118+
}
119+
120+
return [];
121+
}
122+
61123
// --- Sanity Write Client ---
62124

63125
function getSanityWriteClient(): SanityClient {
@@ -132,6 +194,12 @@ export async function processVideoProduction(documentId: string): Promise<void>
132194
`[VIDEO-PIPELINE] Script validated: ${script.scenes.length} scenes, hook="${script.hook.substring(0, 50)}..."`
133195
);
134196

197+
// Step 2.5: Extract infographic URLs from Sanity doc
198+
const infographicUrls = getInfographicUrls(doc);
199+
if (infographicUrls.length > 0) {
200+
console.log(`[VIDEO-PIPELINE] ${infographicUrls.length} infographic URL(s) will be distributed across scenes`);
201+
}
202+
135203
// Step 3: Update status to audio_gen
136204
console.log(`[VIDEO-PIPELINE] Updating status to "audio_gen"`);
137205
await updateStatus(client, documentId, { status: 'audio_gen' });
@@ -243,6 +311,9 @@ export async function processVideoProduction(documentId: string): Promise<void>
243311
scenes: script.scenes.map((s, i) => ({
244312
...s,
245313
wordTimestamps: sceneWordTimestamps[i],
314+
...(infographicUrls.length > 0
315+
? { infographicUrl: infographicUrls[i % infographicUrls.length] }
316+
: {}),
246317
})),
247318
cta: script.cta,
248319
},

0 commit comments

Comments
 (0)