import { downloadPinterestImages } from './lib/downloader'; import { describeImage } from './lib/image-describer'; import { generateImage } from './lib/image-generator'; import { generateVideo } from './lib/video-generator'; import { logger } from './lib/logger'; import * as fs from 'fs/promises'; import dotenv from 'dotenv'; dotenv.config(); const COMFY_BASE_URL = process.env.COMFY_BASE_URL1 || ""; const COMFY_OUTPUT_DIR = process.env.COMFY_OUTPUT_DIR1 || ""; async function prepareImageForKeyword(keyword: string): Promise<{ keyword: string; generatedImagePath: string } | null> { const numberOfPages = 1; const imagePaths = await downloadPinterestImages(keyword, numberOfPages); logger.debug(`Downloaded ${imagePaths.length} images for keyword: ${keyword}`); if (imagePaths.length === 0) { logger.warn(`No images downloaded for keyword "${keyword}", cannot proceed.`); return null; } const randomImagePath = imagePaths[Math.floor(Math.random() * imagePaths.length)]; logger.debug(`Randomly selected image for "${keyword}": ${randomImagePath}`); // Delete all other images for (const imagePath of imagePaths) { if (imagePath !== randomImagePath) { try { await fs.unlink(imagePath); logger.debug(`Deleted image: ${imagePath}`); } catch (error) { logger.error(`Failed to delete image ${imagePath}:`, error); } } } try { const imagePromptResponse = await describeImage(randomImagePath, `Describe this image as a prompt for an image generation model. Prompt should be in 200 words. Output should be in this format --- { "prompt":"Ultra detialed realistic photo, {result comes here}" } --- `); const imagePrompt = imagePromptResponse.prompt; logger.info(`Description for ${randomImagePath}:`, imagePrompt); const timestamp = new Date().getTime(); const imageFileName = `${keyword.replace(/\s/g, '_')}_${timestamp}.png`; const generatedImagePath = await generateImage( imagePrompt, imageFileName, COMFY_BASE_URL, COMFY_OUTPUT_DIR, 'flux', { width: 720, height: 1280 } ); logger.debug(`Generated new image from prompt, saved to: ${generatedImagePath}`); return { keyword, generatedImagePath }; } catch (error) { logger.error(`Failed to process ${randomImagePath} for keyword "${keyword}":`, error); return null; } } async function generateVideoFromImagePath(keyword: string, generatedImagePath: string) { try { const videoPromptResponse = await describeImage(generatedImagePath, `Generate a prompt for an 8-second video based on the provided image. The prompt should describe a dynamic scene that evolves from the static image. Output should be in this format --- { "prompt":"" } --- `); const videoPrompt = videoPromptResponse.prompt; logger.info(`Generated video prompt for ${generatedImagePath}: ${videoPrompt}`); const timestamp = new Date().getTime(); const videoFileName = `${keyword.replace(/\s/g, '_')}_${timestamp}.mp4`; const generatedVideoPath = await generateVideo( videoPrompt, generatedImagePath, videoFileName, COMFY_BASE_URL, COMFY_OUTPUT_DIR, { width: 720, height: 1280 } ); logger.debug(`Generated video from prompt, saved to: ${generatedVideoPath}`); } catch (error) { logger.error(`Failed to generate video for ${generatedImagePath}:`, error); } } (async () => { const keywords = [ "beautiful fantasy scene", "AI art", "beautiful scifi scene", "illumunate scene", "night aesthetic", "stars aesthetic", "letro woman", "magic aesthetic", "fire aesthetic", "high fashion outfits", "led fashion", "halloween", "horror aethstetic", "1890s fashion women" ]; while (1) { const preparedImages = []; logger.info('--- Starting image preparation phase ---'); for (const keyword of keywords) { const startTime = Date.now(); logger.info(`--- Preparing image for keyword: ${keyword} ---`); const result = await prepareImageForKeyword(keyword); if (result) { preparedImages.push(result); } const endTime = Date.now(); const durationInSeconds = (endTime - startTime) / 1000; logger.info(`--- Finished preparing image for keyword: ${keyword} in ${durationInSeconds.toFixed(2)} seconds ---`); } logger.info('--- Finished image preparation phase ---'); logger.info('--- Starting video generation phase ---'); for (const { keyword, generatedImagePath } of preparedImages) { const startTime = Date.now(); logger.info(`--- Generating video for keyword: ${keyword} ---`); await generateVideoFromImagePath(keyword, generatedImagePath); const endTime = Date.now(); const durationInSeconds = (endTime - startTime) / 1000; logger.info(`--- Finished generating video for keyword: ${keyword} in ${durationInSeconds.toFixed(2)} seconds ---`); } logger.info('--- Finished video generation phase ---'); } })();