save changes

This commit is contained in:
2025-09-10 12:59:50 +02:00
parent 9e056b752d
commit 0521b28626
5 changed files with 109 additions and 85 deletions

View File

@ -1,7 +1,8 @@
import { downloadImagesFromPinterestPin } from './lib/downloader';
import { callOpenAIWithFile } from './lib/openai';
import { generateVideo } from './lib/video-generator';
import { generateImage } from './lib/image-generator-mix-style';
import { generateImage as generateImageMixStyle } from './lib/image-generator-mix-style';
import { generateImage as generateImage } from './lib/image-generator';
import { logger } from './lib/logger';
import * as fs from 'fs/promises';
import dotenv from 'dotenv';
@ -11,6 +12,8 @@ import { VideoModel } from './lib/db/video';
dotenv.config();
const USE_REFERENCE_IMAGE = (process.env.USE_REFERENCE_IMAGE || 'true').toLowerCase() === 'true';
// Utility: extract JSON substring from a text.
// Tries fenced ```json``` blocks first, otherwise extracts first {...} span.
@ -248,32 +251,47 @@ async function generateImageForTask(task: GenerationTask, server: { baseUrl: str
const sourceFileNames: string[] = [];
try {
for (const sourcePath of renamedImagePaths) {
const fileName = path.basename(sourcePath);
const destPath = path.join(inputDir, fileName);
await fs.copyFile(sourcePath, destPath);
sourceFileNames.push(fileName);
logger.info(`Copied ${sourcePath} to ${destPath}`);
if (USE_REFERENCE_IMAGE) {
// Copy renamed source images to the server input directory
for (const sourcePath of renamedImagePaths) {
const fileName = path.basename(sourcePath);
const destPath = path.join(inputDir, fileName);
await fs.copyFile(sourcePath, destPath);
sourceFileNames.push(fileName);
logger.info(`Copied ${sourcePath} to ${destPath}`);
}
// generateImageMixStyle expects two source files; if we only have one, pass the same one twice
const srcA = sourceFileNames[0];
const srcB = sourceFileNames[1] || sourceFileNames[0];
const generatedImagePath = await generateImageMixStyle(
imagePrompt,
srcA,
srcB,
imageFileName,
baseUrl,
outputDir,
{ width: 720, height: 1280 }
);
return generatedImagePath;
} else {
// Use Pinterest images only to create the prompt; generate final image using the single-image generator
const generatedImagePath = await generateImage(
imagePrompt,
imageFileName,
baseUrl,
outputDir,
'qwen',
{ width: 720, height: 1280 }
);
return generatedImagePath;
}
// generateImage expects two source files; if we only have one, pass the same one twice
const srcA = sourceFileNames[0];
const srcB = sourceFileNames[1] || sourceFileNames[0];
const generatedImagePath = await generateImage(
imagePrompt,
srcA,
srcB,
imageFileName,
baseUrl,
outputDir,
{ width: 720, height: 1280 }
);
return generatedImagePath;
} catch (error) {
logger.error(`Failed to generate image for ${imageFileName} on server ${baseUrl}:`, error);
return null;
} finally {
// cleanup local renamed images and any files copied to the server input dir
for (const sourcePath of renamedImagePaths) {
try {
await fs.unlink(sourcePath);
@ -338,8 +356,30 @@ async function getPinUrlFromPinterest(keyword: string): Promise<string | null> {
return;
}
/*
allKeywords = allKeywords.filter(a => {
return (a.genre == "sports" && a.subGenre == "Motocross")
return (a.genre == "city" && a.subGenre == "Bridges") ||
(a.genre == "city" && a.subGenre == "Castles") ||
(a.genre == "city" && a.subGenre == "Cathedrals") ||
(a.genre == "city" && a.subGenre == "Factories") ||
(a.genre == "city" && a.subGenre == "Futuristic Cities") ||
(a.genre == "city" && a.subGenre == "Historic Towns") ||
(a.genre == "city" && a.subGenre == "Libraries") ||
(a.genre == "city" && a.subGenre == "Markets") ||
(a.genre == "city" && a.subGenre == "Modern Plazas") ||
(a.genre == "city" && a.subGenre == "Museums") ||
(a.genre == "city" && a.subGenre == "Palaces") ||
(a.genre == "city" && a.subGenre == "Residential Blocks") ||
(a.genre == "city" && a.subGenre == "Skylines") ||
(a.genre == "city" && a.subGenre == "Stadiums") ||
(a.genre == "city" && a.subGenre == "Street Cafes") ||
(a.genre == "city" && a.subGenre == "Urban Parks") ||
(a.genre == "city" && a.subGenre == "Skyscrapers") ||
(a.genre == "city" && a.subGenre == "Slums")
});
*/
allKeywords = allKeywords.filter(a => {
return (a.genre == "city")
});
function shuffle<T>(arr: T[]): T[] {
@ -350,9 +390,10 @@ async function getPinUrlFromPinterest(keyword: string): Promise<string | null> {
return arr;
}
const selectedEntries = shuffle(allKeywords.slice()).slice(0, Math.min(20, allKeywords.length));
//const selectedEntries = shuffle(allKeywords.slice()).slice(0, Math.min(20, allKeywords.length));
const selectedEntries = allKeywords;
// Download up to `count` images from a pin URL by opening the pin page and scrolling up to 5 times to trigger lazy loading
// Download up to `count` images from a pin URL by opening the pin page and scro lling up to 5 times to trigger lazy loading
// Returns an array of saved image paths (may be empty)
async function downloadOneImageFromPin(pinUrl: string, count: number = 1): Promise<string[]> {
const browser = await puppeteer.launch({ headless: false });
@ -459,7 +500,9 @@ async function getPinUrlFromPinterest(keyword: string): Promise<string | null> {
const { genre, subGenre } = genreSubGenre;
for (const pinId of genreSubGenre.pinIds) {
const pickedUpPinIds = shuffle<string>(genreSubGenre.pinIds).slice(0, 2);
for (const pinId of pickedUpPinIds) {
const pin = `https://www.pinterest.com/pin/${pinId}/`;
logger.info(`--- Starting processing for pin: ${pin} ---`);