Merge branch 'master' of https://git.yasue.org/ken/RandomVideoMaker
This commit is contained in:
@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
"7": {
|
"7": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"seed": 838097333311955,
|
"seed": 920668017513581,
|
||||||
"steps": 8,
|
"steps": 8,
|
||||||
"cfg": 1,
|
"cfg": 1,
|
||||||
"sampler_name": "euler",
|
"sampler_name": "euler",
|
||||||
@ -101,14 +101,56 @@
|
|||||||
"title": "VAE Decode"
|
"title": "VAE Decode"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"9": {
|
||||||
|
"inputs": {
|
||||||
|
"font_file": "Alibaba-PuHuiTi-Heavy.ttf",
|
||||||
|
"font_size": 40,
|
||||||
|
"border": 32,
|
||||||
|
"color_theme": "light",
|
||||||
|
"reel_1": [
|
||||||
|
"10",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"class_type": "LayerUtility: ImageReelComposit",
|
||||||
|
"_meta": {
|
||||||
|
"title": "LayerUtility: Image Reel Composit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"inputs": {
|
||||||
|
"image1_text": "Original image",
|
||||||
|
"image2_text": "Reference",
|
||||||
|
"image3_text": "Result",
|
||||||
|
"image4_text": "image4",
|
||||||
|
"reel_height": 512,
|
||||||
|
"border": 32,
|
||||||
|
"image1": [
|
||||||
|
"11",
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"image2": [
|
||||||
|
"11",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"image3": [
|
||||||
|
"8",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"class_type": "LayerUtility: ImageReel",
|
||||||
|
"_meta": {
|
||||||
|
"title": "LayerUtility: Image Reel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"11": {
|
"11": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"prompt": [
|
"prompt": [
|
||||||
"21",
|
"21",
|
||||||
0
|
0
|
||||||
],
|
],
|
||||||
"enable_resize": true,
|
"enable_resize": false,
|
||||||
"enable_vl_resize": true,
|
"enable_vl_resize": false,
|
||||||
"upscale_method": "lanczos",
|
"upscale_method": "lanczos",
|
||||||
"crop": "disabled",
|
"crop": "disabled",
|
||||||
"instruction": "<|im_start|>system\nDescribe the key features of the input image (color, shape, size, texture, objects, background), then explain how the user's text instruction should alter or modify the image. Generate a new image that meets the user's requirements while maintaining consistency with the original input where appropriate.<|im_end|>\n<|im_start|>user\n{}<|im_end|>\n<|im_start|>assistant\n",
|
"instruction": "<|im_start|>system\nDescribe the key features of the input image (color, shape, size, texture, objects, background), then explain how the user's text instruction should alter or modify the image. Generate a new image that meets the user's requirements while maintaining consistency with the original input where appropriate.<|im_end|>\n<|im_start|>user\n{}<|im_end|>\n<|im_start|>assistant\n",
|
||||||
@ -121,11 +163,11 @@
|
|||||||
0
|
0
|
||||||
],
|
],
|
||||||
"image1": [
|
"image1": [
|
||||||
"24",
|
"23",
|
||||||
0
|
0
|
||||||
],
|
],
|
||||||
"image2": [
|
"image2": [
|
||||||
"15",
|
"24",
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -134,9 +176,18 @@
|
|||||||
"title": "TextEncodeQwenImageEditPlus 小志Jason(xiaozhijason)"
|
"title": "TextEncodeQwenImageEditPlus 小志Jason(xiaozhijason)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"14": {
|
||||||
|
"inputs": {
|
||||||
|
"image": "f81662775bd0e7950e4794933ef4b3d973fbb9c2db397c8b46809797954d0074.png"
|
||||||
|
},
|
||||||
|
"class_type": "LoadImage",
|
||||||
|
"_meta": {
|
||||||
|
"title": "Load Image"
|
||||||
|
}
|
||||||
|
},
|
||||||
"15": {
|
"15": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"image": "ComfyUI_00067_.png"
|
"image": "monster_554.png"
|
||||||
},
|
},
|
||||||
"class_type": "LoadImage",
|
"class_type": "LoadImage",
|
||||||
"_meta": {
|
"_meta": {
|
||||||
@ -145,7 +196,7 @@
|
|||||||
},
|
},
|
||||||
"20": {
|
"20": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"filename_prefix": "qwenedit",
|
"filename_prefix": "combined",
|
||||||
"images": [
|
"images": [
|
||||||
"8",
|
"8",
|
||||||
0
|
0
|
||||||
@ -158,49 +209,94 @@
|
|||||||
},
|
},
|
||||||
"21": {
|
"21": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"value": "change camera angle to closeup face from image1, change background to light gray with faing gradient, change face angle to look at directry look at camera"
|
"value": "只提取图2中的怪物,怪物站在图1的女生身后,使用图1的背景,并调整怪物的光线以符合图1。\n\n\n\n\n\n\n"
|
||||||
},
|
},
|
||||||
"class_type": "PrimitiveStringMultiline",
|
"class_type": "PrimitiveStringMultiline",
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"title": "String (Multiline)"
|
"title": "String (Multiline)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"22": {
|
||||||
|
"inputs": {
|
||||||
|
"filename_prefix": "ComfyUI",
|
||||||
|
"images": [
|
||||||
|
"9",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"class_type": "SaveImage",
|
||||||
|
"_meta": {
|
||||||
|
"title": "Save Image"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"23": {
|
||||||
|
"inputs": {
|
||||||
|
"width": [
|
||||||
|
"25",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"height": [
|
||||||
|
"26",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"upscale_method": "nearest-exact",
|
||||||
|
"keep_proportion": "stretch",
|
||||||
|
"pad_color": "0, 0, 0",
|
||||||
|
"crop_position": "center",
|
||||||
|
"divisible_by": 2,
|
||||||
|
"device": "cpu",
|
||||||
|
"image": [
|
||||||
|
"14",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"class_type": "ImageResizeKJv2",
|
||||||
|
"_meta": {
|
||||||
|
"title": "Resize Image v2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"24": {
|
"24": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"measurement": "pixels",
|
"width": [
|
||||||
"width": 720,
|
"25",
|
||||||
"height": 1280,
|
0
|
||||||
"fit": "contain",
|
],
|
||||||
"method": "nearest-exact",
|
"height": [
|
||||||
|
"26",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"upscale_method": "nearest-exact",
|
||||||
|
"keep_proportion": "stretch",
|
||||||
|
"pad_color": "0, 0, 0",
|
||||||
|
"crop_position": "center",
|
||||||
|
"divisible_by": 2,
|
||||||
|
"device": "cpu",
|
||||||
"image": [
|
"image": [
|
||||||
"64",
|
"15",
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"class_type": "Image Resize (rgthree)",
|
"class_type": "ImageResizeKJv2",
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"title": "Image Resize (rgthree)"
|
"title": "Resize Image v2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"64": {
|
"25": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"image": "1337074888177434_1758776251440_2.png"
|
"Number": "1280"
|
||||||
},
|
},
|
||||||
"class_type": "LoadImage",
|
"class_type": "Int",
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"title": "Load Image"
|
"title": "width"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"65": {
|
"26": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"images": [
|
"Number": "720"
|
||||||
"24",
|
|
||||||
0
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"class_type": "PreviewImage",
|
"class_type": "Int",
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"title": "Preview Image"
|
"title": "height"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,9 +81,9 @@ async function convertImageWithFile(
|
|||||||
|
|
||||||
workflow = JSON.parse(await fs.readFile('src/comfyworkflows/edit_image_2_qwen.json', 'utf-8'));
|
workflow = JSON.parse(await fs.readFile('src/comfyworkflows/edit_image_2_qwen.json', 'utf-8'));
|
||||||
workflow['21']['inputs']['value'] = prompt;
|
workflow['21']['inputs']['value'] = prompt;
|
||||||
workflow['24']['inputs']['width'] = size.width;
|
workflow['25']['inputs']['width'] = size.width;
|
||||||
workflow['24']['inputs']['height'] = size.height;
|
workflow['26']['inputs']['height'] = size.height;
|
||||||
workflow['64']['inputs']['image'] = baseFileName;
|
workflow['14']['inputs']['image'] = baseFileName;
|
||||||
workflow['15']['inputs']['image'] = secondFileName;
|
workflow['15']['inputs']['image'] = secondFileName;
|
||||||
|
|
||||||
const response = await axios.post(`${COMFY_BASE_URL}/prompt`, { prompt: workflow });
|
const response = await axios.post(`${COMFY_BASE_URL}/prompt`, { prompt: workflow });
|
||||||
@ -97,7 +97,7 @@ async function convertImageWithFile(
|
|||||||
} while (!history || Object.keys(history.outputs).length === 0);
|
} while (!history || Object.keys(history.outputs).length === 0);
|
||||||
|
|
||||||
const files = await fs.readdir(COMFY_OUTPUT_DIR!);
|
const files = await fs.readdir(COMFY_OUTPUT_DIR!);
|
||||||
const generatedFiles = files.filter(file => file.startsWith('qwenedit'));
|
const generatedFiles = files.filter(file => file.startsWith('combined'));
|
||||||
|
|
||||||
const fileStats = await Promise.all(
|
const fileStats = await Promise.all(
|
||||||
generatedFiles.map(async (file) => {
|
generatedFiles.map(async (file) => {
|
||||||
|
|||||||
78
src/musicspot_generator/v2/combine_image.ts
Normal file
78
src/musicspot_generator/v2/combine_image.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { convertImageWithFile } from '../../lib/image-converter';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
const girlDir = path.join(__dirname, '../../../input/girl');
|
||||||
|
const monsterDir = path.join(__dirname, '../../../input/monster');
|
||||||
|
const outputDir = path.join(__dirname, '../../../generated');
|
||||||
|
const prompt = "只提取图1中的女生,把她放在图2的怪物之间。";
|
||||||
|
|
||||||
|
if (!fs.existsSync(outputDir)) {
|
||||||
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const comfyBaseUrl = process.env.SERVER2_COMFY_BASE_URL;
|
||||||
|
const comfyOutputDir = process.env.SERVER2_COMFY_OUTPUT_DIR;
|
||||||
|
|
||||||
|
if (!comfyBaseUrl || !comfyOutputDir) {
|
||||||
|
console.error("Please define SERVER1_COMFY_BASE_URL and SERVER1_COMFY_OUTPUT_DIR in your .env file");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const comfyInputDir = comfyOutputDir.replace("output", "input");
|
||||||
|
if (!fs.existsSync(comfyInputDir)) {
|
||||||
|
fs.mkdirSync(comfyInputDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function combineImages() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const girlImages = fs.readdirSync(girlDir).filter(file => /\.(jpg|jpeg|png)$/i.test(file));
|
||||||
|
const monsterImages = fs.readdirSync(monsterDir).filter(file => /\.(jpg|jpeg|png)$/i.test(file));
|
||||||
|
|
||||||
|
if (girlImages.length === 0 || monsterImages.length === 0) {
|
||||||
|
console.log('Input directories are empty. Waiting...');
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomGirlImage = girlImages[Math.floor(Math.random() * girlImages.length)];
|
||||||
|
const randomMonsterImage = monsterImages[Math.floor(Math.random() * monsterImages.length)];
|
||||||
|
|
||||||
|
const image1Path = path.join(girlDir, randomGirlImage);
|
||||||
|
const image2Path = path.join(monsterDir, randomMonsterImage);
|
||||||
|
|
||||||
|
// Copy files to comfy input directory
|
||||||
|
const destImage1Path = path.join(comfyInputDir, randomGirlImage);
|
||||||
|
const destImage2Path = path.join(comfyInputDir, randomMonsterImage);
|
||||||
|
fs.copyFileSync(image1Path, destImage1Path);
|
||||||
|
fs.copyFileSync(image2Path, destImage2Path);
|
||||||
|
|
||||||
|
console.log(`Combining ${randomGirlImage} and ${randomMonsterImage}`);
|
||||||
|
|
||||||
|
const generatedFilePath = await convertImageWithFile(prompt, randomGirlImage, randomMonsterImage, comfyBaseUrl!, comfyOutputDir!);
|
||||||
|
|
||||||
|
if (generatedFilePath && fs.existsSync(generatedFilePath)) {
|
||||||
|
const timestamp = new Date().getTime();
|
||||||
|
const newFileName = `combined_${timestamp}.png`;
|
||||||
|
const newFilePath = path.join(outputDir, newFileName);
|
||||||
|
|
||||||
|
fs.renameSync(generatedFilePath, newFilePath);
|
||||||
|
console.log(`Renamed generated file to ${newFilePath}`);
|
||||||
|
} else {
|
||||||
|
console.log("Failed to generate or find the image file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('An error occurred:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a bit before the next iteration
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
combineImages();
|
||||||
@ -52,7 +52,7 @@ async function generatePhotos() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await generateImage(
|
await generateImage(
|
||||||
`realistic photo of woman, wavy long brown hair, fullbody shot, ${scene.imagePrompt.location},${scene.imagePrompt.angle},${scene.imagePrompt.lighting},${scene.imagePrompt.outfit}`,
|
`Scary realistic photo, ${scene.imagePrompt.location},${scene.imagePrompt.angle},${scene.imagePrompt.lighting},${scene.imagePrompt.outfit}`,
|
||||||
faceFilePath,
|
faceFilePath,
|
||||||
scene.baseImagePath,
|
scene.baseImagePath,
|
||||||
imgFileName,
|
imgFileName,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const promptInstructions = `
|
|||||||
Video prompt: No slowmotion, Be creative and generate gengle action scene.
|
Video prompt: No slowmotion, Be creative and generate gengle action scene.
|
||||||
`;
|
`;
|
||||||
6
|
6
|
||||||
const inputDir = path.resolve(process.cwd(), 'input');
|
const inputDir = path.resolve(process.cwd(), 'input/static');
|
||||||
const outputFilePath = path.resolve(process.cwd(), 'src/musicspot_generator/v2/scenes.json');
|
const outputFilePath = path.resolve(process.cwd(), 'src/musicspot_generator/v2/scenes.json');
|
||||||
|
|
||||||
interface Scene {
|
interface Scene {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import dotenv from 'dotenv';
|
|||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const inputFolderPath = path.join(__dirname, '..', '..', '..', 'input');
|
const inputFolderPath = path.join(__dirname, '..', '..', '..', 'input/static');
|
||||||
const generatedFolderPath = path.join(__dirname, '..', '..', '..', 'generated');
|
const generatedFolderPath = path.join(__dirname, '..', '..', '..', 'generated');
|
||||||
|
|
||||||
async function processImages() {
|
async function processImages() {
|
||||||
|
|||||||
@ -13,8 +13,8 @@ const PINS_TO_COLLECT = 5;
|
|||||||
|
|
||||||
// Hard-coded user prompt
|
// Hard-coded user prompt
|
||||||
const HARDCODED_USER_PROMPT = process.env.HARDCODED_USER_PROMPT || `
|
const HARDCODED_USER_PROMPT = process.env.HARDCODED_USER_PROMPT || `
|
||||||
Generate 20 keywords for photos of a girl in scary scene for music video for haloween. All keywords should containe girl in a scene.
|
Generate 20 keywords for photos of a ghotst or monster from all over the world. "Cute Japanese yokai" is mandatory, also add "Realistic photo cute" keyword to all genearated keywords first.
|
||||||
Example output : ["a girl in grave yard,"a girl in scary forest","",... and 20 items in array]
|
Example output : ["Cute Japanese yokai","Realistic photo Cute ghost","Realistic photo cute monster","Realistic photo cute haloween monster","Realistic photo cute haloween ghost"... and 20 items in array]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
async function getPinUrlsFromPinterest(keyword: string, scrollCount = SCROLL_SEARCH, limit = PINS_TO_COLLECT): Promise<string[]> {
|
async function getPinUrlsFromPinterest(keyword: string, scrollCount = SCROLL_SEARCH, limit = PINS_TO_COLLECT): Promise<string[]> {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user