Files
amz-pic-flow/poc-workflow-v2.js

396 lines
12 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* POC Workflow V2: 强化产品一致性
* 核心改进:
* 1. 极致详细的产品描述 (Golden Description)
* 2. 移除AI生成logo后期处理
* 3. 分级策略A级严格复制B级可控创意
* 4. 对比图特殊处理
*/
require('dotenv').config();
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
// 配置
const API_KEY = 'G9rXx3Ag2Xfa7Gs8zou6t6HqeZ';
const API_BASE = 'https://api.wuyinkeji.com/api';
const OUTPUT_DIR = path.join(__dirname, 'output_poc_v2');
const MATERIAL_DIR = path.join(__dirname, '素材/素材/已有的素材');
// R2客户端
const r2Client = new S3Client({
region: 'auto',
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
},
forcePathStyle: true,
});
async function uploadToR2(filePath) {
const fileName = `poc-v2-${Date.now()}-${path.basename(filePath)}`;
const fileBuffer = fs.readFileSync(filePath);
await r2Client.send(new PutObjectCommand({
Bucket: process.env.R2_BUCKET_NAME || 'ai-flow',
Key: fileName,
Body: fileBuffer,
ContentType: filePath.endsWith('.png') ? 'image/png' : 'image/jpeg',
}));
const publicUrl = process.env.R2_PUBLIC_DOMAIN
? `${process.env.R2_PUBLIC_DOMAIN}/${fileName}`
: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${process.env.R2_BUCKET_NAME}/${fileName}`;
return publicUrl;
}
// ============================================================
// 🔥 核心改进1: 黄金产品描述 (Golden Product Description)
// ============================================================
const GOLDEN_PRODUCT_DESC = `
EXACT PRODUCT APPEARANCE (MUST MATCH PRECISELY):
- Shape: 8-PETAL FLOWER/FAN shape, C-shaped opening (like Pac-Man), NOT a full circle
- Color: ICE BLUE / Light aqua blue (#C5E8ED approximate)
- Material: Glossy waterproof PU fabric with visible stitching lines between petals
- Edge binding: TEAL/TURQUOISE color binding around the inner neck hole
- Closure: White velcro strap on one petal end
- Logo: "TOUCHDOG®" embroidered in matching blue thread on one petal (small, subtle)
- Texture: Smooth, slightly shiny, NOT matte, NOT cotton fabric
- Structure: Soft but structured, maintains petal shape, NOT floppy
CRITICAL PROHIBITIONS:
- ❌ NO printed patterns or colorful fabric designs
- ❌ NO hard plastic transparent cones
- ❌ NO fully circular/closed shapes
- ❌ NO matte cotton or fleece textures
- ❌ NO random brand logos or text
`;
// ============================================================
// 🔥 核心改进2: 分级Prompt策略
// ============================================================
// A级严格产品复制 (必须和参考图几乎一致)
function createPromptA_Strict(sceneDesc) {
return `
[PRODUCT REPRODUCTION - HIGHEST FIDELITY]
${GOLDEN_PRODUCT_DESC}
SCENE: ${sceneDesc}
INSTRUCTION: Reproduce the EXACT product from reference image.
The product shape, color, and material must be IDENTICAL to reference.
Only change the background/scene as described.
DO NOT add any brand logo overlays or text graphics.
`.trim();
}
// B级可控创意 (产品保持一致,场景可发挥)
function createPromptB_Controlled(sceneDesc, extraInstructions = '') {
return `
[CONTROLLED CREATIVE - PRODUCT CONSISTENCY REQUIRED]
${GOLDEN_PRODUCT_DESC}
SCENE: ${sceneDesc}
${extraInstructions}
INSTRUCTION: Keep product appearance EXACTLY as described above.
Creative freedom allowed ONLY for background, lighting, and composition.
DO NOT modify product shape, color, or material.
DO NOT add any brand logo overlays.
`.trim();
}
// C级对比图专用 (左边严格,右边自由)
function createPromptC_Comparison() {
return `
[COMPARISON IMAGE - SPLIT SCREEN]
LEFT SIDE (OUR PRODUCT - STRICT):
${GOLDEN_PRODUCT_DESC}
- Happy, comfortable cat/dog wearing the ICE BLUE 8-PETAL soft cone
- Bright, colorful, warm lighting
- GREEN CHECKMARK overlay
RIGHT SIDE (GENERIC COMPETITOR - FLEXIBLE):
- Generic transparent HARD PLASTIC cone (the traditional "lamp shade" type)
- Sad, uncomfortable looking cat/dog
- Grayscale / desaturated colors
- RED X-MARK overlay
LAYOUT: Side by side, clear visual contrast
TEXT HEADER: "Soft & Comfortable" vs "Hard & Uncomfortable"
CRITICAL: Left side product must be ICE BLUE 8-PETAL FLOWER shape, NOT any other design!
`.trim();
}
// 生图任务提交
async function submitImageTask(prompt, refImageUrl, aspectRatio = '1:1') {
try {
const payload = {
key: API_KEY,
prompt: prompt,
img_url: refImageUrl, // 强参考图
aspectRatio: aspectRatio,
imageSize: '1K'
};
console.log(` 提交任务...`);
const response = await axios.post(`${API_BASE}/img/nanoBanana-pro`, payload);
const taskId = response.data.data?.id;
if (!taskId) {
console.error('Submit response:', response.data);
throw new Error('No task ID returned');
}
return taskId;
} catch (error) {
console.error('Submit failed:', error.message);
throw error;
}
}
// 轮询图片结果
async function pollImageResult(taskId) {
let attempts = 0;
const maxAttempts = 60;
while (attempts < maxAttempts) {
try {
const response = await axios.get(`${API_BASE}/img/drawDetail`, {
params: { key: API_KEY, id: taskId }
});
const data = response.data.data;
if (data && data.status === 2 && data.image_url) {
return data.image_url;
} else if (data && data.status === 3) {
throw new Error('Generation failed: ' + (data.fail_reason || 'Unknown'));
}
process.stdout.write('.');
await new Promise(r => setTimeout(r, 2000));
attempts++;
} catch (error) {
if (error.message.includes('Generation failed')) throw error;
console.error('Poll error:', error.message);
throw error;
}
}
throw new Error('Timeout waiting for image');
}
// 生成单张图(含重试)
async function generateSingleImage(item, refUrls) {
console.log(`\n🎨 [${item.level}级] ${item.id}: ${item.name}`);
let retryCount = 0;
const maxRetries = 2;
// 根据类型选择最佳参考图
let refUrl = refUrls.flat; // 默认用平铺图
if (item.useWornRef) {
refUrl = refUrls.worn;
}
while (retryCount <= maxRetries) {
try {
if (retryCount > 0) console.log(` 重试第 ${retryCount} 次...`);
const taskId = await submitImageTask(item.prompt, refUrl, item.aspectRatio);
console.log(` Task ID: ${taskId}`);
const imageUrl = await pollImageResult(taskId);
console.log('\n ✓ 生成成功');
// 下载保存
const imgRes = await axios.get(imageUrl, { responseType: 'arraybuffer' });
fs.writeFileSync(path.join(OUTPUT_DIR, `${item.id}.jpg`), imgRes.data);
console.log(' ✓ 保存本地');
return true;
} catch (error) {
console.error(`\n ✗ 失败: ${error.message}`);
retryCount++;
await new Promise(r => setTimeout(r, 3000));
}
}
console.error(`${item.id} 最终失败`);
return false;
}
// ============================================================
// 主流程
// ============================================================
async function main() {
if (!fs.existsSync(OUTPUT_DIR)) fs.mkdirSync(OUTPUT_DIR, { recursive: true });
// 1. 上传核心参考图
console.log('📤 上传核心参考图...');
const flatImgPath = path.join(MATERIAL_DIR, 'IMG_5683.png'); // 平铺图(最清晰产品细节)
const wornImgPath = path.join(MATERIAL_DIR, 'IMG_6514.JPG'); // 佩戴图
const refUrls = {
flat: await uploadToR2(flatImgPath),
worn: await uploadToR2(wornImgPath)
};
console.log(' 平铺图:', refUrls.flat);
console.log(' 佩戴图:', refUrls.worn);
// 2. 定义优化后的图片任务
const tasks = [
// ========== A级严格复制 ==========
{
id: 'Main_01_Hero',
name: '场景首图',
level: 'A',
aspectRatio: '1:1',
useWornRef: true,
prompt: createPromptA_Strict(`
Cute white fluffy cat wearing the product.
Cone opens OUTWARD around face (like flower petals spreading out).
Cat looks comfortable and relaxed.
Warm, cozy home interior background (soft focus).
Professional Amazon product photography, 8K quality.
`)
},
{
id: 'Main_02_Flat',
name: '平铺白底图',
level: 'A',
aspectRatio: '1:1',
useWornRef: false,
prompt: createPromptA_Strict(`
Product flat lay on PURE WHITE background.
Shot from directly above (bird's eye view).
Show the 8-petal flower/fan shape clearly.
C-shaped opening (gap between velcro ends) visible.
Clean studio lighting, no shadows.
Product photography style.
`)
},
// ========== B级可控创意 ==========
{
id: 'Main_03_Function',
name: '功能演示',
level: 'B',
aspectRatio: '1:1',
useWornRef: false,
prompt: createPromptB_Controlled(`
Close-up of hands adjusting the white velcro strap.
Show the velcro closure mechanism clearly.
Demonstrate "adjustable fit" feature.
Clean, bright lighting.
`)
},
{
id: 'Main_04_Scenarios',
name: '多场景使用',
level: 'B',
aspectRatio: '1:1',
useWornRef: true,
prompt: createPromptB_Controlled(`
2x2 grid showing different usage scenarios:
- Cat eating from bowl while wearing cone (cone allows eating)
- Cat drinking water comfortably
- Cat sleeping peacefully
- Cat walking around home
All showing the ICE BLUE 8-PETAL cone product.
`)
},
{
id: 'APlus_01_Banner',
name: 'A+横幅',
level: 'B',
aspectRatio: '3:2',
useWornRef: true,
prompt: createPromptB_Controlled(`
Wide banner shot for Amazon A+ content.
Beautiful modern living room scene.
White cat wearing the ICE BLUE 8-petal cone walking on soft rug.
Left side has empty space for text overlay.
Warm, inviting home atmosphere.
Professional lifestyle photography.
`)
},
{
id: 'APlus_03_Detail',
name: '材质细节',
level: 'B',
aspectRatio: '3:2',
useWornRef: false,
prompt: createPromptB_Controlled(`
Extreme close-up macro photography.
Focus on the ICE BLUE glossy PU material texture.
Water droplets beading on the waterproof surface.
Show the neat stitching between petals.
Show the TEAL edge binding around neck hole.
High-end product detail photography.
`)
},
{
id: 'APlus_04_Waterproof',
name: '防水演示',
level: 'B',
aspectRatio: '3:2',
useWornRef: false,
prompt: createPromptB_Controlled(`
Action shot demonstrating waterproof feature.
Water being poured onto the ICE BLUE 8-petal cone.
Water droplets rolling off the glossy PU surface.
Dynamic splash photography style.
Bright lighting, white background.
`)
},
// ========== C级对比图 ==========
{
id: 'APlus_02_Comparison',
name: '对比图',
level: 'C',
aspectRatio: '3:2',
useWornRef: true,
prompt: createPromptC_Comparison()
},
];
// 3. 执行生成
console.log('\n🚀 开始V2优化版生成...\n');
console.log('=' .repeat(50));
let successCount = 0;
for (const task of tasks) {
const success = await generateSingleImage(task, refUrls);
if (success) successCount++;
}
console.log('\n' + '='.repeat(50));
console.log(`✅ 完成! 成功 ${successCount}/${tasks.length}`);
console.log(`📁 输出目录: ${OUTPUT_DIR}`);
// 4. 说明跳过的图
console.log('\n⚠ 以下图片建议后期处理不适合纯AI生成:');
console.log(' - Main_05_Size (尺寸图) → 用设计软件+产品抠图');
console.log(' - Main_06_Brand (品牌图) → 用设计软件+官方logo');
console.log(' - APlus_05_Storage (收纳图) → 需要真实折叠产品素材');
console.log(' - APlus_06_Guide (选购指南) → 用设计软件模板');
}
main().catch(console.error);