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

@ -23,8 +23,8 @@
},
"3": {
"inputs": {
"width": 320,
"height": 640,
"width": 720,
"height": 1280,
"batch_size": 1
},
"class_type": "EmptySD3LatentImage",
@ -34,7 +34,7 @@
},
"4": {
"inputs": {
"seed": 803508963683741,
"seed": 844515265883614,
"steps": 20,
"cfg": 1,
"sampler_name": "euler",
@ -45,7 +45,7 @@
0
],
"positive": [
"18",
"11",
0
],
"negative": [
@ -127,7 +127,7 @@
},
"11": {
"inputs": {
"strength": 0.20000000000000004,
"strength": 0.6000000000000001,
"conditioning": [
"14",
0
@ -157,7 +157,7 @@
},
"13": {
"inputs": {
"image": "fd2dc3bbc879703b03abf892d4189667.jpg"
"image": "7a103725df2576b79c7306f0d3050991.jpg"
},
"class_type": "LoadImage",
"_meta": {
@ -166,7 +166,7 @@
},
"14": {
"inputs": {
"text": "Ethereal realistic girl with flowing blue hair, glowing sparkles and stardust, elegant backless dress shimmering with cosmic light, dreamy profile pose, soft glowing skin, fantasy night atmosphere, luminous and magical aesthetic",
"text": "scify movie scene",
"clip": [
"1",
0
@ -189,52 +189,5 @@
"_meta": {
"title": "Save Image"
}
},
"16": {
"inputs": {
"image": "a09ee3d44fff05f20c88976555f8fa10.jpg"
},
"class_type": "LoadImage",
"_meta": {
"title": "Load Image 2"
}
},
"17": {
"inputs": {
"crop": "center",
"clip_vision": [
"10",
0
],
"image": [
"16",
0
]
},
"class_type": "CLIPVisionEncode",
"_meta": {
"title": "CLIP Vision Encode"
}
},
"18": {
"inputs": {
"strength": 0.20000000000000004,
"conditioning": [
"11",
0
],
"style_model": [
"8",
0
],
"clip_vision_output": [
"17",
0
]
},
"class_type": "ApplyStyleModelAdjust",
"_meta": {
"title": "Apply Style Model (Adjusted)"
}
}
}

View File

@ -14,10 +14,10 @@ interface VideoRecord {
}
const servers = [
/*{
{
baseUrl: process.env.SERVER1_COMFY_BASE_URL,
outputDir: process.env.SERVER1_COMFY_OUTPUT_DIR,
},*/
},
{
baseUrl: process.env.SERVER2_COMFY_BASE_URL,
outputDir: process.env.SERVER2_COMFY_OUTPUT_DIR,
@ -61,7 +61,7 @@ async function worker(server: any) {
while (true) {
await sleep(Math.random() * 3000); // Random delay
const videosToProcess = (await query(
"SELECT * FROM video WHERE (video_path IS NULL OR video_path = '') AND modified_at < '2025-08-22' LIMIT 1"
"SELECT * FROM video WHERE (image_path IS NULL OR image_path = '') LIMIT 1"
)) as any[];
if (videosToProcess.length === 0) {

View File

@ -30,7 +30,7 @@ async function generateImage(
workflow['13']['inputs']['image'] = imageName1;
// Set image name
workflow['16']['inputs']['image'] = imageName2;
//workflow['16']['inputs']['image'] = imageName2;
workflow['3']['inputs']['width'] = size.width;
workflow['3']['inputs']['height'] = size.height;

View File

@ -3043,7 +3043,7 @@
},
{
"genre": "fantasy",
"subGenre": "ddreamy room",
"subGenre": "dreamy room",
"pinIds": [
"2533343538161690",
"22236591907669199",
@ -3645,6 +3645,34 @@
"64387469667053244"
]
},
{
"genre": "fantasy",
"subGenre": "Magics",
"pinIds": [
"44332377578826021",
"914862421098890",
"105201341292428725",
"396035361002191644",
"41517627812390162",
"1618549864404055",
"31877109857926612",
"3518505954100471",
"35114072091147253",
"716846465726941759",
"17170042324986575",
"492649953385330",
"2111131072434296",
"11329436558460911",
"281543723928763",
"6122149487574205",
"1337074889544820",
"8655424281626310",
"4292562140536462",
"1970393583505897",
"37436240649695593",
"44332377578826021"
]
},
{
"genre": "fashion",
"subGenre": "Accessories",

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} ---`);