Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions lib/services/elevenlabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
type WordTimestamp,
type SceneAudioResult,
} from "@/lib/utils/audio-timestamps";
import { getConfigValue } from "@/lib/config";

const ELEVENLABS_API_BASE = "https://api.elevenlabs.io/v1";

Expand Down Expand Up @@ -62,9 +63,12 @@ interface TTSWithTimestampsResponse {
* @returns The resolved {@link ElevenLabsConfig}.
* @throws {Error} If required environment variables are missing.
*/
function getConfig(): ElevenLabsConfig {
async function getElevenLabsConfig(): Promise<ElevenLabsConfig> {
const apiKey = process.env.ELEVENLABS_API_KEY;
const voiceId = process.env.ELEVENLABS_VOICE_ID;
const voiceId = await getConfigValue(
"pipeline_config", "elevenLabsVoiceId",
process.env.ELEVENLABS_VOICE_ID || "pNInz6obpgDQGcFmaJgB"
);

if (!apiKey) {
throw new Error(
Expand All @@ -73,13 +77,6 @@ function getConfig(): ElevenLabsConfig {
);
}

if (!voiceId) {
throw new Error(
"Missing ELEVENLABS_VOICE_ID environment variable. " +
"Set it in your .env.local or deployment environment."
);
}

return { apiKey, voiceId };
}

Expand All @@ -106,7 +103,7 @@ export async function generateSpeech(text: string): Promise<Buffer> {
throw new Error("Cannot generate speech from empty text.");
}

const { apiKey, voiceId } = getConfig();
const { apiKey, voiceId } = await getElevenLabsConfig();

const url = `${ELEVENLABS_API_BASE}/text-to-speech/${voiceId}`;

Expand Down Expand Up @@ -244,7 +241,7 @@ export async function generateSpeechWithTimestamps(
throw new Error("Cannot generate speech from empty text.");
}

const { apiKey, voiceId } = getConfig();
const { apiKey, voiceId } = await getElevenLabsConfig();

const url = `${ELEVENLABS_API_BASE}/text-to-speech/${voiceId}/with-timestamps`;

Expand Down
13 changes: 7 additions & 6 deletions lib/services/gcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

import * as crypto from "crypto";
import { getConfigValue } from "@/lib/config";

// ---------------------------------------------------------------------------
// Types
Expand Down Expand Up @@ -63,9 +64,9 @@ const TOKEN_REFRESH_MARGIN_MS = 5 * 60 * 1000; // 5 minutes
* The private key may contain literal `\\n` sequences from the env var;
* these are converted to real newline characters.
*/
export function getGCSConfig(): GCSConfig {
const bucket = process.env.GCS_BUCKET;
const projectId = process.env.GCS_PROJECT_ID;
export async function getGCSConfig(): Promise<GCSConfig> {
const bucket = await getConfigValue("gcs_config", "bucketName", process.env.GCS_BUCKET);
const projectId = await getConfigValue("gcs_config", "projectId", process.env.GCS_PROJECT_ID);
const clientEmail = process.env.GCS_CLIENT_EMAIL;
let privateKey = process.env.GCS_PRIVATE_KEY;

Expand Down Expand Up @@ -205,7 +206,7 @@ async function getAccessToken(): Promise<string> {
return cachedToken.accessToken;
}

const config = getGCSConfig();
const config = await getGCSConfig();
const jwt = createServiceAccountJWT(config);
cachedToken = await exchangeJWTForToken(jwt);
return cachedToken.accessToken;
Expand All @@ -231,7 +232,7 @@ export async function uploadToGCS(
path: string,
contentType: string
): Promise<UploadResult> {
const config = getGCSConfig();
const config = await getGCSConfig();
const token = await getAccessToken();

const encodedPath = encodeURIComponent(path);
Expand Down Expand Up @@ -338,7 +339,7 @@ export async function getSignedUrl(
expiresInMinutes = 60
): Promise<string> {
// We still validate config to fail fast if env vars are missing
const config = getGCSConfig();
const config = await getGCSConfig();

// For public objects, the public URL is sufficient
void expiresInMinutes; // acknowledged but unused for public objects
Expand Down
21 changes: 11 additions & 10 deletions lib/services/remotion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import {
getRenderProgress,
type AwsRegion,
} from "@remotion/lambda/client";
import { getConfigValue } from "@/lib/config";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface RemotionConfig {
export interface RemotionLambdaConfig {
awsAccessKeyId: string;
awsSecretAccessKey: string;
region: string;
Expand Down Expand Up @@ -130,11 +131,11 @@ function mapInputProps(input: RenderInput): Record<string, unknown> {
* Get Remotion Lambda configuration from environment variables.
* Throws if any required env var is missing.
*/
export function getRemotionConfig(): RemotionConfig {
export async function getRemotionConfig(): Promise<RemotionLambdaConfig> {
const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID;
const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
const region = process.env.REMOTION_AWS_REGION;
const serveUrl = process.env.REMOTION_SERVE_URL;
const region = await getConfigValue("remotion_config", "awsRegion", process.env.REMOTION_AWS_REGION);
const serveUrl = await getConfigValue("remotion_config", "serveUrl", process.env.REMOTION_SERVE_URL);

const missing: string[] = [];
if (!awsAccessKeyId) missing.push("AWS_ACCESS_KEY_ID");
Expand All @@ -161,8 +162,8 @@ export function getRemotionConfig(): RemotionConfig {
/**
* Get the Lambda function name from env or use the default.
*/
function getFunctionName(): string {
return process.env.REMOTION_FUNCTION_NAME || DEFAULT_FUNCTION_NAME;
async function getFunctionName(): Promise<string> {
return getConfigValue("remotion_config", "functionName", process.env.REMOTION_FUNCTION_NAME || DEFAULT_FUNCTION_NAME);
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -202,8 +203,8 @@ async function startRender(
composition: string,
input: RenderInput
): Promise<{ renderId: string; bucketName: string }> {
const config = getRemotionConfig();
const functionName = getFunctionName();
const config = await getRemotionConfig();
const functionName = await getFunctionName();
const region = config.region as AwsRegion;

log(`Starting render for composition "${composition}"`, {
Expand Down Expand Up @@ -291,8 +292,8 @@ export async function checkRenderProgress(
renderId: string,
bucketName: string
): Promise<RenderProgressResult> {
const config = getRemotionConfig();
const functionName = getFunctionName();
const config = await getRemotionConfig();
const functionName = await getFunctionName();
const region = config.region as AwsRegion;

const progress = await getRenderProgress({
Expand Down
Loading