# DEVLOG — comfyui-comic-creater --- ## 2026-10-22(MOSS-Image タブ: 吹き出しなしの単独テキストの取込、panelラベルの使い分け、空の文字枠の送信除外、未リリース) **1. 吹き出しなしの単独テキストの取り込み(新機能)** - 「フキダシ・セリフを取り込む」に、チェックボックス「吹き出しなしの文字も取り込む」(既定オン)を追加。テキストツールで置いた `` を文字枠として取り込む。フキダシ内のテキスト(`g.balloon-shape` の子)と `defs` / `clipPath` / `mask` / `pattern` 内のテキストは対象外。 - 回転・拡縮・せん断・縦書きを含む実際の見た目の範囲が要るため、文字だけの新しいSVGを画面外(`position:fixed; left:-100000px`)へ描画し、`getBoundingClientRect()` で実測する(`extractFreeTexts`)。`document.fonts.ready` を待ってから測る。枠は実測範囲+フォントサイズの0.15倍の余白で、`fitBox=false`(文字を編集しても枠が縮まない)。フォントサイズは `font-size` × `data-scale-x/y` の幾何平均 × キャンバス倍率。縦書きは `style` の `writing-mode`。 - caption は文字数による簡易な推定(6文字以下=`Sound effect.`、それ以外=`Narration text.`)。回転した文字は外接矩形になる(MOSS-Imageの枠は回転を表せない)。 - 再取込は、取り込み済みの枠(`src: 'balloon'` / `'text'`)だけを入れ替える。チェックを外して取り込むと、前回の単独テキストの枠は残る。 **2. セキュリティ修正(取込の途中で発見・修正)** - 初版は保存済みページのSVG文字列を `innerHTML` で画面外のDOMへ入れていたため、保存済みSVGに紛れた `onload` / `onerror` 等が実行されうる(旧方式では実際に実行されることを確認)。まず `DOMParser` + `sanitizeSvgTree()` に変えたが、禁止リスト方式では名前空間付きの要素(``)、`` / ``、`style` 内の `url()` 等の抜け道を塞ぎきれない。 - 最終形は許可リスト方式: 保存済みSVGは描画せず(パースしただけのDOMは何も実行しない)、`` / `` と許可リストの属性(`x y dx dy font-* letter-spacing text-anchor transform data-scale-*`)・許可プロパティだけの `style`・祖先 `` の `transform`(`matrix/translate/scale/rotate/skew` の形式のみ)を、新しく作ったSVGへ写して測る。値は括弧・`;`・`:`・`/` を通さない。攻撃用SVG(名前空間付き `script`、XHTMLの `iframe srcdoc`、`set` / `animate`、`javascript:` のリンク、`style` 内の `url()`)で、スクリプトの実行0件・外部通信0件を確認した。 **3. 枠固定の文字の表示** - 取り込んだフキダシ・単独テキスト(`fitBox=false`)の表示を、枠の幅で折り返す(`white-space: pre-wrap`)。実ページの思考フキダシの長い英文が、枠の外へ1行ではみ出して見えていたため。MOSS-Image も枠の中で折り返す。単独テキストは左上(縦書きは右上)から置く。 **4. panel ラベルの使い分けと、空の文字枠の送信除外** - 描画種別・種別セレクトに「コマ」(`panel` ラベル)を追加(黄色)。コマ取込の `panel` ラベル化はチェックボックス(既定は `object`)。`panel` は学習時にあるラベルだが、公開仕様は `object / character / text` のみ。32枚(8シード×4通り)の測定で、`object` との差は誤差の範囲内(枠線・ガターの再現度)、`summary.canvas: "multi_panel"` も同様だった。ユーザーが使い分けられるように選べる形にした。 - 文字が空(空白のみ)の `text` item は、`_moss_layout_prompt` で除外する。送ると、モデルがその領域を「文字を書く領域」と解釈して、罫線入りの紙のようなものを描いてしまう(8シード中8)。公式コンパイラも空の `text` を拒否する。UIでは破線で薄く表示する(入力のたびに切り替わる)。 **5. 調査(実装なし)** - MOSS-Image の bbox: 公式仕様では、`items` のキーは `label / caption / bbox / text / tags / palette` のみ、bbox は軸並行の長方形(4つの数値)。回転角・形状(多角形)の項目はない(公式コンパイラは未知のフィールドを拒否)。非公式の `rotation` 項目は無視される。caption の英文での回転指示は、回転後の外接矩形と併用すると傾くが、文字が崩れやすい。形状は caption の英文で表現する。 - 参照画像ノード `ThetaCursed/ComfyUI-MOSSImageTextEncoder`(Qwen3.5の視覚タワー経由の参照画像条件づけ)を実機で検証(導入はコミット `289170a` 固定。CC本体は未使用): エラーなく動き、参照なしは標準と画素同一、時間・VRAM問題なし。レイアウトなしでは参照が構図を乗っ取る(シート全体を渡すとシートそのものが出る)。レイアウトJSON併用なら構図は保たれるが、全身の参照は近景のコマに白背景が漏れる。単純なデザインでは文章の外見説明で参照と同等に揃う。このため「キャラ設定(文章)の登録・自動挿入」を先に検討したが、今回は見送り(スクリプトタブの要素・Autoタブの脚本との関係を整理してから再検討)。 **6. 検証** - 実ページ(ユーザーの保存済み45ページ)で、フキダシ168件・単独テキスト8件を、エラー・異常値なしで抽出できた。実ページ「これはTEST_p1_1791201461030」の取込結果(位置・大きさ・フォントサイズ)を元データと突き合わせて一致を確認し、取り込んだレイアウトで生成して、縦長の吹き出し・思考フキダシ(英文)・擬音「あ」が指定の位置に描かれた。 - 未確認: 英語・中国語UIの表示、擬音かナレーションかの推定の精度、回転した単独テキストの実ページでの見た目。 - `py/ccc.py` を変更したため、反映にはComfyUIの再起動が必要(再起動後に、`panel` ラベルの通過と空の文字枠の除外をAPIで確認済み)。 **How to apply** - ページのSVG文字列を、保存済みでも外部由来でも、`innerHTML` でDOMへ入れない。DOMへ描画する必要があるなら、許可リスト方式で必要な要素・属性だけを新しいDOMへ写す。禁止リスト方式(`sanitizeSvgTree`)は、名前空間付きの要素やアニメーション要素を塞ぎきれない。 - 外部モデルの仕様外の入力(空の `text` など)は、「無視されるだけ」と仮定せず、同じシードで有無を比べて確かめる。 - 回転・拡縮を含む `` の範囲は、数式ではなく、画面外に描画して `getBoundingClientRect()` で測るのが確実(`document.fonts.ready` を待つ)。 - 再取込できる要素には `src` のような印を付け、再取込では印の付いたものだけを入れ替える。 --- ## 2026-10-22(MOSS-Image タブ: シードの動作モード、フキダシ・セリフの自動取込、シード欄のレイアウト変更、v1.58.1) **1. シードの動作モード(修正・改善)** - 従来は、シードが `-1`(ランダム)のとき、生成のたびに使われたシード値が入力欄へ書き戻されていた。そのため次の生成からは固定シードになり、ランダムのままにするには毎回 `-1` へ戻す必要があった。 - 「ランダム(既定)/固定/生成ごとに+1」を選べるようにした。ランダムのときは入力欄の値に関係なく毎回 `-1` を送る(入力欄は無効表示)。固定は入力欄の値。「+1」は入力欄の値から始め、生成後に使った枚数ぶん進める(入力欄が負のときは初回だけランダム)。 - ランダムで使われたシードは「直前のシード」に表示し、「このシードを固定」で固定モードへ切り替えられる(気に入った結果の再現用)。コマ単位モードは「元のシード+コマの順番」で、直前のシードには最初のコマの値を出す。モードは localStorage に保存。 - 右パネルのシード欄は 1 行目=「シード:」、2 行目=モードと値、3 行目=直前のシード(左)と固定ボタン(右寄せ)の 3 行構成にし、生成の状態表示(「生成完了」など)をシード欄の下へ移した。 **2. フキダシ・セリフの自動取込(新機能)** - レイアウトエディタに「フキダシ・セリフを取り込む」ボタンを追加。ページのレコード(`dbGet('pages', …)`)のオーバーレイ(`overlaySvgContent`)と各コマ(`panelSvgContent`)から `g.balloon-shape` を取り出し、セリフ(`data-bubble-text`)が入っているものを「文字」枠として取り込む。 - 位置・大きさは `data-cx/cy/rx/ry`(ページのSVG座標)から、コマ取込と同じ換算(キャンバス/ページ)で作る。枠は**フキダシの輪郭**。フォントサイズは `data-font-size-svg` × 縦の倍率、縦書きは `data-bubble-text-vertical`、形は `data-shape-type` を caption の英文(Speech bubble. / Thought bubble. / Shouting burst-shaped bubble. など)へ変換する。読み順(上から下、同じ段は右から左)に並べる。 - 取り込んだ枠には `src: 'balloon'` を付け、再取込では取り込み済みの枠だけを入れ替える(手で足した枠は残す)。キャンバスの縦横比がページと違うときは、ページに合わせて既存の枠も拡縮する(確認ダイアログ)。 - 文字枠に `fitBox` を追加し、「選択中の要素」に「枠を文字の大きさに合わせる」を追加した。取り込んだ枠は `fitBox=false`(文字を編集しても枠が縮まない。表示は枠の中央)。`autoSizeText` と手動リサイズ後のフォントサイズ更新は `fitBox=false` では行わない。 - 単独のテキスト要素(吹き出しなしの文字)は対象外(今後の検討)。コマ単位モードでは使われない。 **3. 検証** - テスト用のページレコードを IndexedDB へ書き込み、縦書き・思考・爆発の 3 種のフキダシを取り込んで、座標・フォントサイズの換算、セリフなしのスキップ、再取込の入れ替え(手で足した物体が残る)、`fitBox` の切替を Playwright で確認した。取り込んだレイアウトで生成すると、縦書きの吹き出しと叫びの吹き出しが指定の位置・大きさで描かれた。 - シードは、ランダム(2 回とも `-1` 送信、入力欄は不変)、固定(同じシード)、+1(100 → 101)を実機生成で確認した。 - 未確認: 実際に使っているページでの取込、英語・中国語 UI の表示、コマ単位モードでのシード(コマごとの値)。 **How to apply** - 「ランダムなら毎回違う値」の機能で、使った値を入力欄へ書き戻すと次回から固定になる。入力欄は「指定する値」専用にし、使った値は別の表示(直前のシード)に出す。 - 取り込み元を持つ要素には `src` のような印を付け、再取込では印の付いたものだけを入れ替える。手編集した要素を消さずに済む。 - 枠のサイズを内容から自動決定する要素でも、外部の形(フキダシの輪郭など)に合わせたい場合は自動サイズを切れるフラグ(`fitBox`)を持たせる。 --- ## 2026-10-21(MOSS-Image タブ(ローカル生成・レイアウトエディタ)を追加、v1.58.0) **1. MOSS-Image タブ(新機能)** - ComfyUI 本体がネイティブ対応した画像生成モデル MOSS-Image(OpenMOSS、5B DiT、テキストエンコーダ Qwen3.5-9B、VAE FLUX.2、Apache-2.0)を、専用タブ「MOSS-Image」からローカル生成する。Comfy クレジット・外部 API キーは不要。日本語を含む文字の描画に強く、物体・キャラ・文字の位置を bbox で指定できる。 - 画面は 3 カラム: 左=レイアウトエディタ、中=設定パネル(プロンプト / JSON / モデル・サンプラー の上部タブ。プロンプトタブ最上段の「生成対象」は `
` で折りたたみ可)、右=生成・結果・配置。 - 生成モードは「1 頁まるごと」(ページ全面のオーバーレイへ配置)「コマ単位」(各コマの縦横比から約 1MP で生成し、`insertImage` の placement と `preserveAspectRatio:'none'` でコマへストレッチ配置)「自由サイズ」(生成のみ)。 - 「現在のページのコマを取り込む」でコマ枠を物体の枠として取り込み(キャンバスはページの縦横比・約 2MP に自動調整、caption に位置表現)。設定とレイアウトは localStorage(`ccc_moss_v1`)に保存。 **2. バックエンド(`py/ccc.py`)** - `_moss_workflow` で API 形式のワークフロー(`UNETLoader` →(`LoraLoaderModelOnly`)→(`SkipLayerGuidanceDiTSimple` 層 22・0〜0.5)→ `KSampler`、`CLIPLoader`(type=`moss_image`)、`VAELoader`、`EmptyFlux2LatentImage`、`SaveImage`(`cc_moss/MOSS`))を組み立て、Nanobanana のネイティブ経路と同じ方式で `/prompt` へ直接投入する。ワークフロー JSON ファイルは持たない。 - `_native_nb_run` に出力ノード ID・client_id・タイムアウトを引数化し、API キーが空ならパートナー認証を付けない(従来の呼び出しは既定値で同じ動作)。 - ルート `POST /api/ccc/moss/generate`(生成。画像本体は返さず `/view` 用の参照のみ)と `POST /api/ccc/moss/layout-prompt`(レイアウト → JSON のプレビュー用)。モデル一覧は ComfyUI 自身の `/object_info` から取得する。 - レイアウト JSON は ComfyUI 標準の `MOSSImageLayoutPrompt` と同じ形式(`summary` / `items`(label・caption・text・bbox)/ `bbox_coord_space=abs_centralized` / `bbox_format=yxyx`。bbox はキャンバス中心原点のピクセル `[y0,x0,y1,x1]`)を `_moss_layout_prompt` で生成する。 **3. レイアウトエディタと文字枠** - 描画種別(物体=緑・キャラ=ピンク・文字=水色)をボタンで選び、ドラッグで枠を描く。前面へ/背面へ/削除、Delete キー、枠の縁・番号・選択中の枠の内側のドラッグで移動、角で拡縮。 - 未選択の枠の内側のドラッグは「その上に新しい枠を描く」(クリックのみなら選択)、Shift+ドラッグは常に描画。枠の内側を常に移動にすると、コマ(物体)の上にセリフ枠を置けなかったための仕様。 - 文字枠は描いた直後に枠内へ直接入力(Escape / Ctrl+Enter で確定)。フォントサイズ(画像上の px)を持ち、枠は入力した文字の大きさになる(全角 1em・半角 0.55em・行間 1.2・余白 0.3 倍の近似)。手動リサイズすると、その枠に収まる最大のフォントサイズへ更新される。 - 縦書き: 「文字」の右隣の横書き/縦書きトグルは新しく描く文字枠の既定のみ(選択中の枠には作用させない。作用させると、描いた直後に切り替えるとその枠が書き換わるため)。描いた後は「選択中の要素」の書字方向で変更する。縦書きは改行=列(右→左)として表示・入力・サイズ見積もりを縦組みにする。MOSS-Image のレイアウト形式に書字方向の項目は無いため、縦書きの文字枠は caption の末尾に `Vertical text, written top to bottom, columns from right to left.` を自動付与する。この指示だけで縦書きに描かれることを実機生成で確認した。 **4. 検証** - API 経由で 832×1216・25step・日本語セリフ入りの 2 コマレイアウトを生成(約 35 秒)し、コマ構図・セリフ・擬音が指定位置に描画された。縦書き指定を含むレイアウトでも、縦書き(右→左の列)で描画された。UI の生成ボタンから DMD 8step でも生成できた。 - 枠の描画・移動・拡縮・クリック選択・文字の直接入力と再編集・フォントサイズ変更・縦書き切替・3 カラムとタブ切替・リロード後の復元を Playwright / Kapture で確認。 - 未確認: ページのコマ取り込みの実機動作、コマ単位/1 頁モードでの配置、英語・中国語 UI の表示、画面幅 1500px 未満の折り返し表示、指定フォントサイズと実際の文字サイズの一致、縦書きの安定性(1 回の生成のみ)。 **5. 未対応・検討** - フキダシ・セリフ(`g.balloon-shape` の `dataset.bubbleText` など)の自動取込、Auto タブの画像生成エンジンへの追加は未実装(`PLAN_backlog.md` に記載)。 - ヘルプ(日英中)・README(日英中)に MOSS-Image の節を追加した。 **How to apply** - キャンバス上のドラッグ操作で `pointerdown` に `preventDefault()` を入れると、ブラウザの `dblclick` が発火しないことがある。二度押しは `pointerdown` の時刻と対象で自前判定する。 - 枠の上に別の要素を描きたいキャンバスでは、「枠内のドラッグ=移動」を固定にせず、選択状態と Shift で描画と移動を切り分ける。 - `py/ccc.py` に新しいルートを足したときは、ComfyUI の再起動後でないと 404 になる(JS・HTML・CSS はリロードで反映)。 - レイアウト形式に無い指示(縦書きなど)は、caption の英文で渡すと効く場合がある。 --- ## 2026-10-17(動画ツールの移動モードとオーバーレイのはみ出し修正、テキスト・描画図形の保存抑制、v1.57.0) **1. 動画ツール: 移動モード(✥)を追加** - 動画サブタブでは動画オブジェクトをクリックするだけでオーバーレイのプレビュー状態になり、位置を動かすには他のツールへ切り替える必要があった。再生ボタン(▶)の左隣に ✥ ボタンを追加。ON中は `_videoSuspendOverlay()` でオーバーレイを透明・クリック透過にして動画だけ止め、下の `` を通常の画像と同じようにドラッグ移動・リサイズ・回転できる。ON中は動画オブジェクトをクリックしてもオーバーレイは出ない(`_ccVideoOnObjectSelected` で抑止)。OFFにすると移動後の位置でオーバーレイを再表示する。状態は `state.video.moveMode`。 **2. 動画オーバーレイがページ上端からはみ出してツールメニューに重なる問題(修正)** - 原因: オーバーレイ(`z-index:150`)は動画オブジェクトの表示矩形をそのまま使うため、ページ端からはみ出した動画では直上のツールメニューへ食い込み(実機再現で約100px)、クリックを奪っていた。 - 実装: `_videoSyncPosition` で、プレビュー領域(`#layout-preview`)の範囲に `clip-path: inset(...)` でクリップする。 **3. テキスト・描画図形のクリックだけの保存を抑制** - v1.56.0 で画像・フキダシ・グループに入れたものと同じ。テキスト(`09e-text-tool.js`)と描画図形(`17c-layer-draw-handles.js`)も、実際に動かした場合だけ `savePanelSvg` / `saveOverlaySvg` を呼ぶ。クリック選択だけでは全SVGの複製・直列化・DB保存を走らせない。 - 描画図形のドラッグには `pushHistory`(Ctrl+Z 用履歴)が無い(未対応)。 **How to apply** - 絶対配置のオーバーレイをSVG上の要素に重ねる機能は、プレビュー領域でのクリップを必ず入れる(はみ出し対象が他のUIを覆わないように)。 - ドラッグ系の mouseup で保存する処理は、「動かしたか」のフラグで保存を分ける。 --- ## 2026-10-17(レイアウトタブの操作遅延の解消、テキスト角ハンドルの拡縮方向、フキダシ内テキストの位置ドラッグ、v1.56.0) **1. レイアウトタブでオブジェクトの操作が遅い・レイヤーパネルの選択が効かない(修正)** - 原因: 3Dポーズ画像の要素に `data-pose3d-model`(VRMモデルのbase64、1枚あたり約56MB)が埋め込まれており、実機のページでSVG全体が約114MBになっていた。クリックしただけでも `mouseup` で `savePanelSvg`(SVG全体の複製・直列化・IndexedDB保存)が走るため、次の操作が詰まり、保存完了時の `renderLayerPanel()` でクリック中のレイヤー行が差し替わって `click` が届かなかった。 - 実装: `23-pose3d-bridge.js` でモデルを埋め込まないようにした(読み出し側は元々無く、再編集はポーズJSON `data-pose3d-pose` のみで足りる)。`renderLayoutTab` でページを開く際に既存の `data-pose3d-model` を正規表現で除去してDBへ書き戻し(`_stripPose3dModelFromPage`)、`savePanelSvg` でも保存時に除去する。実機でSVGが約114MB→約1.1MBに低下。 - 画像・フキダシ・グループのドラッグ処理(`08-panels-images.js`、`06a-polygon-geometry.js`)は、実際に動かした場合だけ保存する(クリック選択のみでは保存しない)。 - 未対応: テキスト・描画図形のドラッグにも同種の構造が残っている可能性がある(未調査)。 **2. テキストの角ハンドルのリサイズ方向(変更)** - 従来は中心からの距離比で拡縮していたため、どの角をドラッグしても同じ動きだった。反対側の角を固定し、固定角→ドラッグ角の対角線上へカーソルを射影した比でフォントサイズを決める方式に変更(`09e-text-tool.js`)。拡縮でずれた固定角はテキストごと平行移動して戻す。回転・変形したテキストでも変形後の角座標(`_textLocalToSvg`)で扱う。辺ハンドルの縦横伸縮・回転は従来どおり。 **3. フキダシ内テキストの位置をドラッグで移動(新機能)** - テキストを内包したフキダシの選択時、テキストの周りに紫の点線ボックスを表示し、左下の三角コーナーのドラッグでテキストだけを動かせる。ダブルクリック(三角コーナー・フキダシ)で従来のモーダル。 - 位置は `data-text-offset-x/y`(フキダシのローカル座標での寄せ位置からの追加移動量)に保存し、`_bubbleTextRenderText` で全tspanへ加算する。回転したフキダシでも向きに沿って動く。モーダルで上下寄せ・文字寄せを変えるとオフセットは解除(寄せ位置を優先)。 - 点線ボックス(`.balloon-textbox`)と三角コーナー(`.balloon-textbox-mark`)は編集用の表示で、保存用クローン(`savePanelSvg` / `saveOverlaySvg`)から除外する。実装は `09c-balloon-handles.js`(`updateBubbleTextBox`)、ドラッグ処理は `09d-balloon-tools.js`。動かしたときだけ履歴・保存を行う。 **How to apply** - 保存が重いと感じたら、まず `svg.outerHTML.length` と、巨大な属性(`data-*`)を持つ要素がないかを疑う。 - 新たに要素へ大きなデータ属性を埋め込む機能を作る場合は、SVGへ永続化する前に別ストアへ逃がすこと。 --- ## 2026-10-14(Nanobanana: 生成方式を設定タブで切替し、半自動マンガ・Autoタブにも適用、v1.55.0) v1.54.0 で Nanobanana タブにだけ追加した「ComfyUIネイティブノード」方式を、共通の設定として設定タブで切り替えられるようにし、半自動マンガ(スクリプト)と Auto タブの Nanobanana 生成にも適用した。3か所とも `requestNanobananaGenerate(payload)`(base64画像の配列を返す共通の入口)を通るため、呼び出し側はほぼ無改修。 **UI** - 設定タブに「Nanobanana 設定」(`settings-nanobanana-engine`)を追加。選択は localStorage(`ccc_nanobanana_engine`)に保存し、Nanobanana タブの選択欄と `ccc-nanobanana-engine-changed` イベントで連動する。接続状態(Gemini キー / `COMFY_API_KEY`)も表示。 - `nanobanana.js`: `getNanobananaEngine` / `setNanobananaEngine` を追加・export。`checkNanobananaKeyStatus`(半自動マンガのモーダルでも使用)と `requestNanobananaGenerate` が設定に従う。 **バックエンド(`ccc.py`)** - `POST /api/ccc/nanobanana/native/generate` に `return_b64` を追加: ワークフローの出力を `SaveImage` ではなく `PreviewImage`(temp、再起動で消える)にし、結果を `/view` から base64 で返す。呼び出し側が自前の保存先(`cc_nanobanana` / `cc_auto`)へ保存するため、ComfyUI の `output` に重複ファイルを残さない。PNG の `prompt` / `workflow` 埋め込みは SaveImage と同様に付くので、保存先のPNGにもメタデータが残る。 - モデル名の対応: 半自動マンガ・Auto は Gemini の ID で指定してくるため、`gemini-nano-banana-2.1` → `Gemini Nano Banana 2.1`、`gemini-3.1-flash-image` → `Nano Banana 2 (Gemini 3.1 Flash Image)`、`gemini-3.1-flash-lite-image` → `Nano Banana 2 Lite` に対応づけ。`gemini-3-pro-image`(Nano Banana Pro)はネイティブでは別ノード(`GeminiImage2Node`)のため **未対応**(`nanobanana_native_unsupported_model`)。Lite の 2K/4K はエラー(黙って1Kに丸めない)。エラー文言は3言語。 **実機確認(ComfyUI_5 / ポート8189、v0.40.0)** - 設定タブの切替が Nanobanana タブ(選択欄・モデル欄・接続状態)に連動すること、Pro 未対応・Lite の 2K・不正モデルのエラー文言が出ることを確認(課金なし)。 - 半自動マンガと同じ形(参考画像1枚付き I2I、`gemini-nano-banana-2.1`)で共通の入口を実呼び出し: 18.4秒、base64 の PNG(848×1264、`prompt` / `workflow` チャンク入り)が返り、`output/cc_nanobanana_native/` に重複は増えない(プレビューと参考画像は temp)。 - Auto タブの `generateAutoImage` は、生成リクエストをスタブにして、設定に応じて `/native/generate`(`return_b64: true`)と従来の `/nanobanana/generate` が切り替わり、どちらも `save-auto-image` へ保存することを確認。モデル名の対応表は関数単位で確認(高価な `gemini-3.1-flash-image` は課金回避のため実生成せず)。 **注意** - 半自動マンガの画像は `cc_nanobanana` に保存される。Workflow Studio v0.8.6 で、メタデータが埋め込まれた画像は Prompt タブが表示されるようにした。 - パートナーAPIノードの認証は、これまでどおり Comic Creator 側の `.env` の `COMFY_API_KEY`(サーバー側から付与)。 ## 2026-10-14(Nanobanana: ComfyUIネイティブノード経由の生成を併用可能に、v1.54.0) ComfyUI v0.40.0 の確認の流れで、Nanobanana のメタデータ・履歴の扱いを見直した。現行の Gemini API 直叩き経路は、返却画像をバイト列のまま保存するため PNG に生成条件が入らず、`history.jsonl` への別記録が必要だった。一方 ComfyUI 本体のパートナーAPIノード(Nano Banana 2.1)は SaveImage が `prompt` / `workflow` を PNG に埋め込むため、履歴ファイルが不要になる。そこで **置き換えではなく併用** として、ネイティブ経路を追加した。 **UI(Nanobanana タブ)** - 基本設定に「生成方式」を追加(`Gemini API(自分のAPIキー)` / `ComfyUIネイティブノード(Comfyクレジット)`)。選択は localStorage(`ccc_nanobanana_engine`)に保存。 - ネイティブ選択時はモデル欄が Gemini Nano Banana 2.1 / Nano Banana 2 (Gemini 3.1 Flash Image) / Nano Banana 2 Lite に切り替わり、履歴の自動記録・「履歴に記録」ボタンは非表示。接続状態表示は `COMFY_API_KEY` の有無を見る。 - 結果は ComfyUI の `/view` から表示し、Eagle 自動登録は絶対URLで行う(相対パスはプラグイン内ファイル扱いになるため)。 **バックエンド(`ccc.py`)** - `GET /api/ccc/nanobanana/native/status`(キーの有無のみ)、`POST /api/ccc/nanobanana/native/generate` を追加。API形式のワークフロー(`GeminiNanoBanana2V2` + `SaveImage`、参考画像は `LoadImage`)を組み立て、ComfyUI 自身の `/prompt` へ投入して `/history` で完了を待つ。 - 認証は `.env` の `COMFY_API_KEY`(platform.comfy.org で発行)を `extra_data.api_key_comfy_org` としてサーバー側から渡す(ブラウザへは出さない)。参考画像は temp 領域へアップロードし、`name [temp]` で参照する。 - キー名: DynamicCombo の子入力は `model.aspect_ratio` / `model.resolution` / `model.thinking_level`、参考画像(Autogrow)は `model.images.image_`。本体の展開ロジックで確定(未知キーは無視されるため、検証が通っても正しいとは限らない点に注意)。 - 出力先は `output/cc_nanobanana_native/NB_*.png`。`cc_nanobanana` とは別フォルダにしたのは、Workflow Studio 側が `cc_nanobanana` を「メタデータ無し+history.jsonl参照」の特別扱いにしているため。 - `seed` は Gemini へは送られず ComfyUI のキャッシュキーとしてだけ働く(実コードで確認)。同じ入力の再実行はキャッシュが返るため、枚数ごとに seed をずらす。ネガティブプロンプトの専用入力は無いため、従来どおり `NEGATIVE_PROMPT:` としてプロンプト末尾へ追記する。 - Lite は 1K のみ(2K/4K 指定は `nanobanana_native_resolution_unsupported`)。エラーコード(`nanobanana_native_key_missing` / `_unauthorized` / `_failed` / `_invalid_model` / `_resolution_unsupported`)は i18n(ja/en/zh)に追加。 **実機確認(ComfyUI_5 / ポート8189、v0.40.0)** - ダミーキーで参考画像アップロード → `/prompt` 投入 → `/history` 判定 → `nanobanana_native_unauthorized` への変換まで確認(課金なし)。 - 実キーで Nano Banana 2.1(1K・2:3)を1枚生成: 18秒、848×1264。PNG に `prompt` / `workflow` チャンクが入り、モデル・アスペクト比・解像度・thinking_level・シード・プロンプトが読める。 - Workflow Studio の Metadata 抽出(モデル名・シード・プロンプト)と Gallery 一覧・画像メタ取得で、通常の画像として扱えることを確認(`cc_nanobanana_native` は history.jsonl 非対応のフォルダ)。 - 画面操作(方式切替・生成ボタン・結果表示・「コマに挿入」の有効化)は、生成リクエストだけをスタブ化して確認。 **対象外** - 半自動マンガの一括生成(Nanobanana バッチ)は従来の Gemini API 経路のまま。 - 既存の `history.jsonl` と、Workflow Studio 側の `cc_nanobanana` フォルダの特別扱いは、過去の画像のため残す。 ## 2026-10-13(マニュアル執筆中に見つかった改善候補20件への対応、v1.53.2) マニュアル執筆中に洗い出した仕様の落とし穴(`manual/改善候補メモ.md`、v1.53.1対象の20件)をすべて対応した。方針はユーザー判断で、実装・ヘルプ修正・項目削除のいずれかを項目ごとに選んだ。 **テンプレート・ページ** - #1 初回起動時に基本テンプレート「A4縦_3コマ」「A4横_3コマ」を自動登録(`06b-template-manager.js`の`_tmplSeedDefaultTemplates`)。ウィザードと同じSVG形式(0.01mm単位・白背景rect + panel_0 + panel_N)を生成して`parseSVGForTemplate`で登録。localStorageのフラグ(`ccc_default_templates_seeded_v1`)で一度だけ実行し、削除しても再登録しない。既存ユーザーにも次回起動時に1回だけ追加される。テンプレート名は表示言語ごと(`tmpl.defaultA4Portrait/Landscape`)。 - #2 「ページ新規作成」を「クイック」に改称(`page.createPage`)し、コマ線幅のprompt()を廃止。テンプレートの線幅のまま1ページ作成してレイアウトタブへ移動する(線幅の変更はレイアウトタブの「コマ枠線幅」)。`insertTemplatePageToWork()`への統一はせず、1ページ即作成のメニューとして位置付けた。 **出力** - #3 `_updateExportPageRange`: 総ページ数が変わった(作品/グループの切替等)ときだけ範囲を「1〜総数」にリセットし、同じ総数での再描画ではユーザー入力を保持。 - #4 `onSwitchToOutputTab`: 作業中の作品があれば自動でその作品に絞り込む。作業中の作品が変わったときだけ適用し、手動でフィルタ解除した場合は同じ作品の間は再適用しない。 - #9 書き出しで参照されていなかった「フキダシのみ」を削除(HTML・排他制御・i18n)。 - #10 PDF・EPUB選択時は「背景のみ」「zip保存」を無効(グレー)表示。 **i18n・表記** - #5 トップバーCCボタンのツールチップを英語表記(`web/comfyui/ccc_menu.js`)。 - #6 初回の表示言語を`navigator.languages`から決定(ja/en/zh、該当なしは日本語)。保存済みの言語設定があればそちらを優先。 - #16 Imageタブのトースト・prompt約69種を`image.msg.*`としてi18n化(ja/en/zh)。値を含む文言は関数形式。`image-tab.js`内では`const t`の局所変数による隠蔽があるため`window.t`で呼ぶ。Open PSDのツールチップもi18n化。 - #17 Imageタブのテキスト入力欄をレイアウトタブの「テキスト入力」に合わせ、Enter=改行・Ctrl/Cmd+Enter=確定・Esc=キャンセルに統一。プレースホルダーにヒントを表示。 - #7 ヘルプの「右サイドパネル」表記のうち、ツールのサブタブ説明を「プレビュー上部のツール設定帯」に修正(レイヤーパネル・表示サイズは実際に右側なので据え置き)。#11 作品管理の「グループから削除」を「stockへ移動」に修正(テンプレートタブの同名ボタンは実在するため据え置き)。#15 フキダシ形状一覧に「キャプション(直角・尻尾なし)」を追記。いずれもja/en/zh。 **機能の実装・修正** - #12 レイアウトタブ「画像」サブタブのBiRefNetを、Imageタブと同じMask Editor Oneの`/mask_editor/birefnet/*`ルートで実装(`16-processing-edit-tabs.js`)。画面を開いたときに`/mask_editor/birefnet/status`で利用可否を確認し、利用できない場合は選択肢を無効化して理由をラベルに表示する。 - #13 画像サブタブの実行結果が元画像の位置・表示サイズ・回転(`transform`・`preserveAspectRatio`)を引き継いで挿入されるようにし、成功後に元画像を非表示にする(レイヤーパネルの👁と同じ状態)。非表示化は挿入の履歴(undo)には含まれない。 - #14 My曲線の既定画像を`static/img/mychain_default.png`として同梱し、読み込み先を`/ccc_static/img/`に変更(`assets/**/*.png`は`.gitignore`対象のため従来は新規環境に届かなかった)。 - #18 Nanobananaで2枚以上生成したとき、全結果をサムネイル表示し、選んだ画像を「コマに挿入」できるようにした(`showResult(index)`・`selectedResultIndex`)。 - #19 Generateの挿入は置き換えではなく既存画像の上への重ね追加が実際の動作のため、挙動は変えずヘルプ・コードコメントを実態に合わせた。置き換えにする場合は挿入前に元画像を削除する処理が別途必要。 - #20 Eagle設定の「ComfyUI 生成画像を自動保存」は、どの処理からも参照されていなかったためグレーアウトし、Workflow Studioの設定タブ>Eagleで設定するよう案内文を追加。保存ボタンはこの値を書き込まない。 **配布** - #8 `.comfyignore`に`!docs/manual/`を追加し、同梱版マニュアルを配布物に含める。Registry側が否定パターンを解釈するかは未確認。 **起動ログ**: `[ccc] Comic Creator loaded → http://127.0.0.1:8189/ccc`のポートが固定だったため、`comfy.cli_args`の`port`/`listen`から組み立てるように修正(`0.0.0.0`・`::`は`127.0.0.1`、IPv6は`[...]`で囲む)。 **検証**: Kaptureで#1・#2・#3・#4・#9・#10・#12(選択肢の有効/ラベル)・#20を実機確認。Playwrightで#6(en/zh/ja/frの4ロケール)・ヘルプ文面(17項目を巡回、3言語)・#16(「New」のダイアログ・トースト・Open PSDツールチップ、3言語)を確認。#12/#13の実行、#17のテキスト入力、#18の複数枚表示はユーザーが実機確認済み。起動ログのポート組み立ては、実際に別ポートで起動せず、該当コードのみ`port`/`listen`を変えて実行して確認。 **How to apply**: Playwrightのコンテキスト作成時の`locale`指定で、初回言語・多言語表示を保存設定なしで検証できる。ヘルプのようにタブ内で項目を切り替えて描画する画面は、全項目を巡回して実画面のテキストで照合する(ソースの文字列検索だけでは描画漏れを見落とす)。 --- ## 2026-10-09(Nanobanana生成履歴をJSON Lines形式へ変更、v1.53.1) v1.53.0でリリースした生成履歴機能(自由記述のテキストブロック形式、`history.txt`)について、ユーザーから「Workflow Studio側で履歴ファイルを読んで別表示する連携を確実にやる」という方針が示されたため、着手前にフォーマットをJSON Lines(1行1件のJSON)へ変更した。自由記述テキストは外部ツールからのパースが不安定になるため、プログラムからも人の手編集からも扱いやすいJSONLへ先に揃えておく判断。 - **ファイル名を`history.txt`→`history.jsonl`に変更**(`py/ccc.py`の`_NANOBANANA_HISTORY_FILENAME`)。旧`history.txt`は参照しなくなるが自動削除・移行はしていない(テスト記録2件が残ったまま、ユーザー判断で削除可)。 - **`handle_nanobanana_history_append`**: 従来の`====`区切りテキストブロック生成をやめ、`{timestamp, engine, model, width, height, image_size, seed, filenames, prompt, negative_prompt}`の辞書を`json.dumps(..., ensure_ascii=False) + '\n'`で1行追記するだけに変更。`engine`フィールドは今回追加(既定`'gemini'`)で、[[comic-creator-workflow]]に記録予定の次回作業(`PLAN_nanobanana_local_image_edit.md`、ローカルImage Edit対応)で`'local'`等を入れられるようにする先回りの変更。 - **`handle_nanobanana_history_get`**: ファイルを1行ずつ`json.loads`し、`entries`配列として返すように変更(従来の生テキスト`text`も互換のため残す)。手編集等で壊れた行は例外を握りつぶさず`{line, raw, parse_error}`として`entries`に含め、エラーで履歴全体が読めなくなることを避けた。 - **フロント(`nanobanana.js`)**: 履歴サブタブの表示は後方互換のため変更せず、`fetchNanobananaHistory()`が返す`entries`から`formatHistoryEntry()`で従来と同じ見た目のブロックテキストを組み立ててtextareaへ表示する(保存形式はJSONLだが、UI上の見た目は変えていない)。`appendNanobananaHistoryEntry()`自体は送信フィールドの形は変えておらず、`lastGenerationMeta`に`engine: 'gemini'`を追加しただけ。 - ヘルプ(ja/en/zh)・README(ja/en/zh)の`history.txt`表記をすべて`history.jsonl`に更新し、JSON Lines形式である旨を明記した。 **検証**: `python -m py_compile`・`node --check`・`vm.SourceTextModule`で構文確認のみ実施。ComfyUI再起動後の実機確認(自動記録・手動記録・履歴表示、特に`formatHistoryEntry`が旧形式と同じ見た目で表示されること)は未実施。 **How to apply**: 外部ツール(Workflow Studio等)からの連携を予定しているログ・記録系ファイルは、自由記述テキストではなく最初からJSON Lines等の構造化フォーマットで設計する。UI側の見た目を変えたくない場合は、保存はJSONL・表示はクライアント側で整形、という形で両立できる(今回の`formatHistoryEntry()`参照)。 --- ## 2026-10-09(Nanobananaタブに生成履歴(テキストファイル)機能を追加、v1.53.0) ユーザーから「Nanobananaで生成した画像にプロンプトを埋め込み、Workflow StudioのGalleryのプロンプト/Metadataタブで見たい」という依頼を受け、まずWFS側(`ComfyUI-Workflow-Studio`リポジトリ)のGallery実装を調査した。 **調査結果(コード変更前の事前調査)**: WFSの「プロンプト」「Metadata」タブ(`static/js/gallery-tab.js`の`renderPromptTab`・`static/js/metadata-tab.js`)は、PNGの`tEXt`チャンク(キー`prompt`、ComfyUI API形式のワークフローJSON)からノードを解析する仕組みで、**PNG専用**(`py/services/gallery_service.py`の`_read_png_metadata`/`_read_jpeg_metadata`を確認。JPEGは単純なCOMコメントマーカーしか読まず、構造化されたワークフロー解析には対応していない)。Nanobanana(Gemini API)の生成結果は多くの場合JPEGで返るため、この仕組みに正攻法で乗せるには常時PNG保存への変更か、WFS側コードの拡張が必要と判明。この調査結果と、PNG保存+ダミーワークフローノード(`WFS_PromptText`)埋め込み案を含む3案をAskUserQuestionで提示しようとしたところ、ユーザーからツール自体を却下され、「WFSのGalleryへの埋め込みではなく、Nanobananaタブ自身の機能として生成履歴をテキストファイルで残したい」という明確な代替要望が示された。 **実装(ユーザー指定仕様)**: 画像ファイルへの埋め込みではなく、1つのテキストファイルに「ファイル名・日時・プロンプト・設定」をまとめて記録する方式にした。編集・削除はアプリ側にUIを設けず、ユーザーがテキストファイルを直接編集する前提(この方がWFS側の実装に依存せず、PNG/JPEGどちらでも同じように使える)。 - **保存先**: `output/cc_nanobanana/history.txt`(画像の保存先と同じフォルダ)に、生成1回=1ブロックで追記(`py/ccc.py`の`handle_nanobanana_history_append`)。モデル・解像度・出力解像度・シード・ファイル名(バッチ全体をまとめて1ブロック)・Positive/Negativeプロンプトを記録。`GET /api/ccc/nanobanana/history`で全文取得、`POST /api/ccc/nanobanana/history/append`で追記(ルートはdispatchテーブル`_DISPATCH_GET`/`_DISPATCH_POST`と明示`add_get`/`add_post`の両方に登録。既存エンドポイントが両方に重複登録されている既存パターンに合わせた)。各フィールドは`_clip_history_field()`で長さ上限(prompt/negativeは4000文字、ファイル名は300文字×最大50件)を設け、異常に大きいリクエストでファイルが際限なく肥大化しないようにした。 - **UI(`templates/index.html`・`static/js/nanobanana.js`)**: Nanobananaタブの基本設定に「生成時に自動で履歴に記録」チェックボックス(`#nanobanana-history-auto`、`localStorage`の`ccc_nanobanana_history_auto`に保存、ブラウザ間では共有されない)を追加。サブタブに「履歴」を新設し、`history.txt`の全文を読み取り専用の`