Files
Socialflow/shared/reel.ts
T
Claude da9a74dbe6 Retire le générateur vidéo, les badges « New » et permet d'effacer les Reels en échec
- Suppression de la page « Générateur Vidéo » (/remotion) : routes
  /api/remotion, pipeline de rendu d'images, composition ImageVideo et
  aperçu associé. Le générateur de Reels est conservé.
- Plus de badge « New » à côté des menus.
- Tableau de bord : bouton pour supprimer un Reel en échec et sa
  notification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tFkVXQDATYfw5aFtjQahi
2026-09-29 13:32:17 +00:00

62 lines
2.4 KiB
TypeScript

/**
* Paramètres des rendus de Reels, validés à l'entrée des routes et stockés tels
* quels dans `reel_jobs.params` : un job repris après redémarrage retrouve ainsi
* exactement ce que l'utilisateur avait demandé.
*/
import { z } from "zod";
import { CAPTION_STYLES, DEFAULT_CAPTION_STYLE } from "./captions";
import { srtCuesSchema } from "./srt";
import { TTS_ENGINES, TTS_STYLES } from "./voices";
const optionalText = z
.string()
.trim()
.optional()
.transform((value) => (value ? value : undefined));
/** Reel construit à partir d'une vidéo de la médiathèque. */
export const videoReelParamsSchema = z.object({
videoMediaId: z.string({ required_error: "Vidéo requise" }).min(1, "Vidéo requise"),
pageIds: z
.array(z.string().min(1), { required_error: "Au moins une page requise" })
.min(1, "Au moins une page requise"),
musicTrackId: optionalText,
musicUrl: optionalText,
overlayText: optionalText,
// Sous-titres SRT : remplacent le texte libre, la voix lit chacun à son instant
srtCues: srtCuesSchema.optional(),
description: optionalText,
ttsEnabled: z.boolean().default(false),
ttsVoice: optionalText,
ttsEngine: z.enum(TTS_ENGINES).optional(),
ttsStyle: z.enum(TTS_STYLES).optional(),
scheduledFor: optionalText,
// Ancien réglage, ignoré : le minutage vient désormais de la voix elle-même
wordDuration: z.number().optional(),
fontSize: z.number().int().min(16).max(200).default(64),
musicVolume: z.number().min(0).max(2).default(0.25),
drawText: z.boolean().default(true),
captionStyle: z.enum(CAPTION_STYLES).default(DEFAULT_CAPTION_STYLE),
stabilize: z.boolean().default(false),
// Petit logo pendant la vidéo ; le grand logo de fin dépend de enableEndingEffect
showLogo: z.boolean().default(true),
enableEndingEffect: z.boolean().default(true),
// Déterminé par le serveur à partir de la première page, jamais par le client
storeName: z.string().optional(),
});
export type VideoReelParams = z.infer<typeof videoReelParamsSchema>;
/** Aperçu de la voix. */
export const ttsPreviewSchema = z.object({
text: z.string({ required_error: "Texte requis" }).trim().min(1, "Texte requis").max(2000),
ttsVoice: optionalText,
ttsEngine: z.enum(TTS_ENGINES).optional(),
ttsStyle: z.enum(TTS_STYLES).optional(),
});
export type ReelJobKind = "video";
export type ReelJobStatus = "pending" | "processing" | "completed" | "failed";