Spaces:
Sleeping
Sleeping
画像生成シーケンス図
概要
FV画像とコンテンツ画像の生成・最適化フローを示すシーケンス図です。OpenAI/Gemini APIで画像を生成し、WebP形式への圧縮とリサイズを行った後、URL形式で配信します。
FV画像生成フロー
sequenceDiagram
participant Client as クライアント
participant API as /api/cn-html-preview
participant FvService as FvGenerationService
participant ImgGen as OpenAI/Gemini Generator
participant Optimizer as ImageOptimizer
participant Cache as TempStorageCache
participant ExtAPI as OpenAI/Gemini API
Client->>API: POST /api/cn-html-preview<br/>[HTTP/JSON]<br/>screenshotUrl (PNG Base64)<br/>fvData (object)<br/>provider (openai or gemini)
API->>FvService: generateFvHtml(options)<br/>[TypeScript]
FvService->>FvService: executeSimplePipeline()
alt ダミーモード
FvService-->>API: ダミー画像返却<br/>JPEG Base64
else 本番モード
FvService->>ImgGen: editImage()<br/>[TypeScript]<br/>image Buffer (PNG)<br/>mask Buffer (PNG)<br/>size 1024x1536
Note over ImgGen: プロンプト生成<br/>OpenAI/Gemini用
ImgGen->>ExtAPI: 画像生成API<br/>[HTTPS/REST]<br/>OpenAI - multipart/form-data<br/>Gemini - application/json
ExtAPI-->>ImgGen: 生成画像<br/>URL or Base64
ImgGen->>Optimizer: optimizeFvImage()<br/>[TypeScript]<br/>Buffer (PNG/JPEG)
Note over Optimizer: Sharp処理<br/>WebP変換<br/>品質65%
Optimizer-->>ImgGen: WebP Buffer<br/>圧縮率 60-80%
ImgGen->>Cache: store(id, buffer)<br/>[TypeScript]<br/>WebP Buffer保存
Note over Cache: /tmp/image-cache<br/>ファイル書き込み<br/>24時間保持
Cache-->>ImgGen: URL返却<br/>/api/temp-images/id
ImgGen-->>FvService: ImageEditResult<br/>buffer + url<br/>metadata
FvService->>FvService: generateFvHtml()<br/>URLをimgタグに埋め込み
FvService-->>API: HTML (URL埋め込み)
end
API-->>Client: HTTP 200 OK<br/>JSON Response<br/>html (string)<br/>css (string)<br/>batchId (string)<br/>message (string)
コンテンツ画像生成フロー
sequenceDiagram
participant Client as クライアント
participant StartAPI as /start-contents-image-generation
participant StatusAPI as /image-generation-status/batchId
participant ImgGen as ContentImagesGenerator
participant OpenAI as OpenAIContentsImageGenerator
participant Optimizer as ImageOptimizer
participant Cache as TempStorageCache
participant PromptGen as ImagePromptGenerator
participant AI as AI (Claude/OpenAI)
participant OpenAIAPI as OpenAI Images API
Client->>StartAPI: POST /start-contents-image-generation<br/>[HTTP/JSON]<br/>html (string)<br/>tabName (string)<br/>cnData (object)<br/>provider (openai or claude)
StartAPI->>ImgGen: ContentImagesGenerator.getInstance()<br/>[TypeScript]
StartAPI->>ImgGen: startImageGenerationBatch()<br/>[TypeScript]<br/>htmlContent + contentContext
Note over ImgGen: HtmlImageAnalyzer<br/>画像要素抽出<br/>5-10個
ImgGen->>PromptGen: generateImageInstructions()<br/>[TypeScript]<br/>elements[] + context
par 各画像要素に対して並列処理
PromptGen->>AI: プロンプト生成API<br/>[HTTPS/REST]<br/>OpenAI or Anthropic API
AI-->>PromptGen: 最適化されたプロンプト
end
PromptGen-->>ImgGen: ImageInstruction[]<br/>imageId + prompt + context
ImgGen->>ImgGen: バッチとジョブ作成<br/>batchId生成
ImgGen-->>StartAPI: batchId + estimatedTime
StartAPI-->>Client: HTTP 200 OK<br/>JSON Response
Note over ImgGen: 非同期バッチ処理開始
ImgGen->>OpenAI: generateMultipleImages()<br/>[TypeScript]<br/>maxConcurrency 3
par 各画像を並列生成 (最大3並列)
OpenAI->>OpenAIAPI: 画像生成API<br/>[HTTPS/REST]<br/>gpt-image-1<br/>1024x1024 low quality
OpenAIAPI-->>OpenAI: 生成画像<br/>URL or Base64
end
par 各画像を最適化処理
OpenAI->>Optimizer: optimizeContentImage()<br/>[TypeScript]<br/>Buffer or Base64
Note over Optimizer: Sharp処理<br/>800x800リサイズ<br/>800x600クロップ<br/>WebP 65%
Optimizer-->>OpenAI: WebP Buffer<br/>サイズ 20-40%
OpenAI->>Cache: store(id, buffer)<br/>[TypeScript]<br/>WebP Buffer保存
Note over Cache: /tmp/image-cache<br/>ファイル書き込み<br/>24時間保持
Cache-->>OpenAI: URL返却<br/>/api/temp-images/id
end
OpenAI-->>ImgGen: Map(imageId -> URL)
ImgGen->>ImgGen: ジョブステータス更新
loop クライアントポーリング (2秒間隔)
Client->>StatusAPI: GET /image-generation-status/batchId<br/>[HTTP]
StatusAPI->>ImgGen: getBatchStatus(batchId)<br/>[TypeScript]
ImgGen-->>StatusAPI: バッチオブジェクト
StatusAPI-->>Client: HTTP 200 OK<br/>status + completedJobs + totalJobs<br/>completedImages[] (URLs)
alt 新しい画像が完了
Client->>Client: JavaScript DOM操作<br/>img.src = URL<br/>loading=lazy
end
end
Note over ImgGen: バッチ完了<br/>20分後に自動削除
Note over Client: 全画像生成完了
処理の詳細
1. FV画像生成
- 入力: スクリーンショット、FVデータ、プロバイダー選択
- 処理:
- OpenAI: マスク画像を使用した編集、gpt-image-1モデル
- Gemini: マスクフリー編集、gemini-2.5-flash-imageモデル
- 最適化: WebP 65%品質に圧縮
- 保存: TempStorageCacheで/tmpディレクトリに保存
- 出力: URL形式 (/api/temp-images/id)
2. コンテンツ画像生成
- バッチ処理: 5-10枚の画像を非同期で生成
- 並列実行: 最大3枚同時生成で効率化
- 画像最適化:
- 800x800にリサイズ
- 上下100pxをクロップして800x600に
- WebP 65%品質で圧縮
- 保存: TempStorageCacheで/tmpディレクトリに保存
- 出力: URL形式 (/api/temp-images/id)
- フォールバック: 生成失敗時はno-image.jpgを使用
3. 画像圧縮・最適化
- ImageOptimizer (
server/utils/image-optimizer.ts)- FV画像: WebP変換のみ
- コンテンツ画像: リサイズ+クロップ+WebP変換
- 圧縮率: 約60-80%のファイルサイズ削減
4. 画像キャッシュ管理
- TempStorageCache (
server/utils/temp-storage-cache.ts)- 保存先:
/tmp/image-cache/ディレクトリ - 保持期間: 24時間(自動削除)
- クリーンアップ: 6時間ごと
- 容量制限: 1GB超過時に古いファイルから削除
- シングルトンパターンでインスタンス管理
- 保存先:
5. クライアント側の更新
- 2秒間隔でステータスをポーリング
- 完了した画像から順次JavaScriptで動的に置換
- 遅延読み込み:
loading="lazy"属性で最適化 - プログレスバーで進捗を可視化
データ形式とプロトコル
プロトコル
- HTTP/JSON: クライアント↔API間の通信
- TypeScript: サーバー内部の関数呼び出し
- HTTPS/REST: 外部API(OpenAI、Gemini、Anthropic)との通信
- multipart/form-data: OpenAIへの画像送信
- application/json: Geminiへのデータ送信
データ形式
- 入力画像: data:image/png;base64形式
- 処理中: Buffer(Node.js内部バイナリ)
- 保存形式: WebP形式ファイル(/tmpディレクトリ)
- 画像配信: URL形式
/api/temp-images/{id} - HTMLへの埋め込み:
<img src="/api/temp-images/{id}" loading="lazy"> - APIレスポンス: JSON形式
{ html: string, css: string, batchId?: string, message: string } - 圧縮率: 60-80%削減(WebP 65%品質)
- コンテンツ画像サイズ: 800x600固定
パフォーマンス最適化
並列処理
- 最大3枚同時生成で総処理時間を短縮
- 10枚の場合: 逐次30-100秒 → 並列10-20秒
画像圧縮
- WebP形式採用で60-80%のサイズ削減
- 品質65%で視覚的品質とファイルサイズのバランス
リソース管理
- ContentImagesGeneratorはシングルトンパターン
- TempStorageCacheはシングルトンパターン
- バッチは20分後に自動削除
- 画像ファイルは24時間後に自動削除
- メモリ効率を考慮した実装
配信最適化
- URL形式配信でJSONパースのオーバーヘッド削減
- ブラウザキャッシュ活用(Cache-Control: max-age=86400)
- 遅延読み込み(loading="lazy")で初期表示高速化
環境変数要件
# FV画像生成用
OPENAI_TEMPLATE_AI_DEV=your_openai_key # OpenAI使用時
GCP_TEMPLATE_AI_DEV=your_gcp_key # Gemini使用時
# コンテンツ画像生成用
OPENAI_TEMPLATE_AI_DEV=your_openai_key # OpenAI画像生成
# プロンプト生成AI
OPENAI_API_KEY=your_openai_key # OpenAI使用時
ANTHROPIC_API_KEY=your_anthropic_key # Claude使用時