mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
feat: Implement new Reel creation functionality with dedicated mobile and desktop UIs, server-side API routes, and a new FFmpeg processing service.
This commit is contained in:
1 parent
ae0048a6e1
commit
3a5acd425c
5 files changed
+42
-2
No files matched your search
@@ -63,6 +63,7 @@ export default function MobileNewReel() {
|
||||
// État audio preview
|
||||
const [isPlaying, setIsPlaying] = useState<string | null>(null);
|
||||
const [stabilize, setStabilize] = useState(true); // Activé par défaut pour les Reels
|
||||
const [enableEndingEffect, setEnableEndingEffect] = useState(true);
|
||||
|
||||
|
||||
const { data: pages = [] } = useQuery<SocialPage[]>({
|
||||
@@ -204,6 +205,7 @@ export default function MobileNewReel() {
|
||||
drawText: true,
|
||||
ttsEnabled,
|
||||
ttsVoice,
|
||||
enableEndingEffect,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -395,6 +397,17 @@ export default function MobileNewReel() {
|
||||
className="text-lg"
|
||||
rows={3}
|
||||
/>
|
||||
<div className="flex items-center space-x-2 mt-4">
|
||||
<Switch
|
||||
id="enable-ending-effect"
|
||||
checked={enableEndingEffect}
|
||||
onCheckedChange={setEnableEndingEffect}
|
||||
/>
|
||||
<Label htmlFor="enable-ending-effect" className="font-medium cursor-pointer">
|
||||
Activer l'effet de fin (logo + fondu)
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2 mt-4">
|
||||
<Switch
|
||||
id="tts-mode"
|
||||
|
||||
@@ -68,6 +68,7 @@ export default function NewReel() {
|
||||
const [ttsVoice, setTtsVoice] = useState("fr-FR-VivienneMultilingualNeural");
|
||||
const [drawText, setDrawText] = useState(true);
|
||||
const [stabilize, setStabilize] = useState(true); // default to true
|
||||
const [enableEndingEffect, setEnableEndingEffect] = useState(true);
|
||||
|
||||
// Enable TTS by default on mobile
|
||||
useEffect(() => {
|
||||
@@ -336,6 +337,7 @@ export default function NewReel() {
|
||||
ttsVoice,
|
||||
drawText,
|
||||
stabilize: stabilize,
|
||||
enableEndingEffect,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -710,6 +712,17 @@ export default function NewReel() {
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2 mt-4">
|
||||
<Switch
|
||||
id="enable-ending-effect"
|
||||
checked={enableEndingEffect}
|
||||
onCheckedChange={setEnableEndingEffect}
|
||||
/>
|
||||
<Label htmlFor="enable-ending-effect" className="font-medium cursor-pointer">
|
||||
Activer l'effet de fin (logo + fondu)
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2 mt-4">
|
||||
<Switch
|
||||
id="tts-mode"
|
||||
|
||||
@@ -161,6 +161,7 @@ class ReelRequest(BaseModel):
|
||||
tts_voice: str = "fr-FR-VivienneMultilingualNeural"
|
||||
draw_text: bool = True
|
||||
stabilize: bool = False # Stabilisation vidéo via vidstab
|
||||
enable_ending_effect: bool = True
|
||||
|
||||
|
||||
def clean_text_for_display(text: str) -> str:
|
||||
@@ -861,7 +862,7 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
|
||||
v_chain += text_filter
|
||||
|
||||
if has_watermark:
|
||||
if request.store_name:
|
||||
if request.store_name and request.enable_ending_effect:
|
||||
# Ouro Party Mode + Persistent bottom right
|
||||
|
||||
# We need two scaled versions of the logo
|
||||
@@ -890,7 +891,9 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
|
||||
v_chain += "[v_pre_wm];[v_pre_wm][wm]overlay=W-w-20:H-h-20"
|
||||
|
||||
# Add Video Fade Out
|
||||
v_chain += f",fade=t=out:st={fade_start}:d={fade_duration}"
|
||||
if request.enable_ending_effect:
|
||||
v_chain += f",fade=t=out:st={fade_start}:d={fade_duration}"
|
||||
|
||||
|
||||
# End of video chain
|
||||
v_chain += "[vout]"
|
||||
|
||||
@@ -302,6 +302,7 @@ reelsRouter.post('/reels/preview', async (req: Request, res: Response) => {
|
||||
musicVolume = 0.25,
|
||||
drawText = true,
|
||||
stabilize = false,
|
||||
enableEndingEffect = true,
|
||||
} = req.body;
|
||||
|
||||
// Récupérer le média vidéo
|
||||
@@ -360,6 +361,7 @@ reelsRouter.post('/reels/preview', async (req: Request, res: Response) => {
|
||||
drawText,
|
||||
stabilize,
|
||||
watermarkUrl,
|
||||
enableEndingEffect,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
@@ -471,6 +473,7 @@ async function processReelBackground(
|
||||
musicVolume?: number;
|
||||
drawText?: boolean;
|
||||
stabilize?: boolean;
|
||||
enableEndingEffect?: boolean;
|
||||
},
|
||||
storeName?: string
|
||||
) {
|
||||
@@ -489,6 +492,7 @@ async function processReelBackground(
|
||||
musicVolume,
|
||||
drawText,
|
||||
stabilize,
|
||||
enableEndingEffect,
|
||||
} = data;
|
||||
|
||||
console.log(`🔄 [Background] Starting processing for Post ${postId}`);
|
||||
@@ -570,6 +574,7 @@ async function processReelBackground(
|
||||
stabilize,
|
||||
watermarkUrl,
|
||||
storeName,
|
||||
enableEndingEffect,
|
||||
});
|
||||
|
||||
console.log(`⏱️ [Background] FFmpeg took ${(Date.now() - startTime) / 1000}s`);
|
||||
@@ -728,6 +733,7 @@ reelsRouter.post('/reels', async (req: Request, res: Response) => {
|
||||
musicVolume = 0.25,
|
||||
drawText = true,
|
||||
stabilize = false,
|
||||
enableEndingEffect = true,
|
||||
} = req.body;
|
||||
|
||||
// Validation immédiate
|
||||
|
||||
@@ -20,6 +20,7 @@ interface FFmpegReelRequest {
|
||||
stabilize?: boolean; // Stabilisation vidéo via vidstab (default: false)
|
||||
watermark_url?: string; // URL du logo
|
||||
store_name?: string; // Nom du magasin pour l'outro
|
||||
enable_ending_effect?: boolean; // Activer l'effet de fin (logo+fondu)
|
||||
}
|
||||
|
||||
interface FFmpegReelResponse {
|
||||
@@ -77,6 +78,7 @@ export class FFmpegService {
|
||||
stabilize?: boolean;
|
||||
watermarkUrl?: string;
|
||||
storeName?: string;
|
||||
enableEndingEffect?: boolean;
|
||||
} = {}
|
||||
): Promise<{ success: boolean; videoBase64?: string; duration?: number; error?: string }> {
|
||||
const config = this.ensureConfigured();
|
||||
@@ -95,6 +97,7 @@ export class FFmpegService {
|
||||
stabilize: options.stabilize ?? false,
|
||||
watermark_url: options.watermarkUrl,
|
||||
store_name: options.storeName,
|
||||
enable_ending_effect: options.enableEndingEffect ?? true,
|
||||
};
|
||||
|
||||
// Remove undefined values
|
||||
@@ -176,6 +179,7 @@ export class FFmpegService {
|
||||
stabilize?: boolean;
|
||||
watermarkUrl?: string;
|
||||
storeName?: string;
|
||||
enableEndingEffect?: boolean;
|
||||
} = {}
|
||||
): Promise<{ success: boolean; videoBase64?: string; duration?: number; error?: string }> {
|
||||
const config = this.ensureConfigured();
|
||||
@@ -194,6 +198,7 @@ export class FFmpegService {
|
||||
stabilize: options.stabilize ?? false,
|
||||
watermark_url: options.watermarkUrl,
|
||||
store_name: options.storeName,
|
||||
enable_ending_effect: options.enableEndingEffect ?? true,
|
||||
};
|
||||
|
||||
// Remove undefined values
|
||||
|
||||
Reference in new issue
Block a user