SVGがパースでき、安全な要素だけで構成されていても、そのデザインが実用的とは限りません。
ブラウザで動作するローカルファースト動画編集ツール Timeline Studio に、ChromeのPrompt API(Gemini Nano)を利用したベクター生成機能を実装する中で、この差が大きな課題になりました。
この記事では、現在のブラウザ内SVG生成パイプライン、安全性の検証だけでは見つけられない品質問題、そして今後試したい決定論的チェックと1回だけのローカル修復について整理します。
すべての処理はブラウザ内で完結します。デザイン指示やプロジェクト素材をサーバーへ送信するクラウドフォールバックは使用しません。
現在の生成パイプライン
Timeline StudioのAIベクター生成は、次の順序で処理します。
- Language Detector APIで入力言語を判定する
- 英語以外の入力はTranslator APIで英語へ変換する
- Prompt APIを通してGemini NanoにSVG生成を依頼する
- Markdownコードブロックや前後の説明文を除き、最初の完全な
<svg>を抽出する - 要素・属性・URL・スクリプトをサニタイズする
- 1200×1200のviewBoxへ正規化する
- 「My Assets」へ追加する(タイムラインへは自動挿入しない)
実装の中心部分は、概念的には次のようになっています。
const raw = await session.prompt(
buildVectorDesignPrompt(englishRequest),
);
const vectorXml = extractVectorXml(raw);
const vectorBody = sanitizeGeneratedVectorXml(vectorXml, scope);
モデルは常にSVGだけを返すとは限りません。コードフェンスで囲んだり、前に説明文を付けたり、旧形式の<vector>ラッパーを使用したりします。そのため抽出処理は多少寛容にしつつ、セキュリティ境界は後段のサニタイザーで厳格にしています。
サニタイザーが検出できること
現在の検証は、構造と安全性に関する問題を拒否できます。
- SVGマークアップが存在しない、または壊れている
-
scriptやイベントハンドラーを含む - 許可していない要素や属性を含む
- 外部URLやリモートコンテンツを参照する
- エディタの座標系へ正規化できない
生成AIの出力であっても、信頼できない入力として扱う必要があります。したがって、この検証は必須です。
しかし、安全なSVGでも「良いデザイン」とは限りません。
構文検証だけでは見つからない問題
実際には、次のような出力も正常なXMLとして通過します。
- viewBoxは正しいが、重要な図形が端で切れている
- 指示には合っているが、構図が一般的すぎて使いにくい
- 透明背景を要求したのに、画面全体を覆う背景矩形がある
- 表示される図形がほとんどなく、実質的に空である
- 小さな図形が多すぎて編集しにくい
-
<g>はあるものの、IDや階層に意味がない - 文字、余白、コントラストが動画素材として不十分である
- 翻訳後に単語は残っているが、デザイン意図が失われている
つまり、現在のサニタイザーが答えられるのは「安全に読み込めるか」であって、「ユーザーが使いたいと思うか」ではありません。
まずは再現可能な品質ベンチマークを作る
プロンプトを感覚的に調整し続ける前に、比較できる小さなベンチマークが必要です。最初のセットとして、少なくとも24個のプロンプトを用意する予定です。
- アイコンと単純なシンボル
- ローワーサードとタイトルグラフィック
- チャートとインフォグラフィック要素
- 吹き出し、ラベル、バッジ
- フレームやマスクに近い構図
- 抽象的なモーショングラフィック素材
- 4件以上の非英語入力
各出力は、以下の観点で人間が評価します。
- 要求への忠実度:依頼した内容が表現されているか
- 構図:余白、バランス、視覚的階層が実用的か
- 完成度:偶然できた形ではなく、意図されたデザインに見えるか
- 編集可能性:グループや図形が後から編集しやすい構造か
- 安全性と透明性:SVGの制約と透明背景の要求を満たすか
目的は万能な「品質スコア」を作ることではありません。プロンプトや実装を変更したときに、以前より良くなったのか、別のケースを壊していないかを再現可能にすることです。
モデルを再実行する前にできる決定論的チェック
視覚的な問題の一部は、2回目の推論を行わなくても静的に近似できます。
- 可視領域が空、または極端に小さい
- 図形がviewBoxの外へ大きくはみ出している
- 不透明な図形がキャンバスのほぼ全体を覆っている
- 座標値が極端に大きい
- 図形数やフィルターの複雑度が高すぎる
- グループIDが重複、欠落、または無意味である
- コンテンツがキャンバスのごく一部に偏っている
これらのチェックだけでデザインを理解することはできません。しかし、単なる「生成に失敗しました」ではなく、修復処理や開発者へ機械可読な理由を渡せます。
たとえば、品質レポートは次のような形にできます。
type SvgQualityReport = {
repairable: boolean;
warnings: Array<
| "CONTENT_OUTSIDE_VIEWBOX"
| "FULL_CANVAS_BACKGROUND"
| "EFFECTIVELY_EMPTY"
| "EXCESSIVE_COMPLEXITY"
| "UNHELPFUL_GROUP_STRUCTURE"
>;
};
修復はローカルで1回だけ行う
次に試したいのは、実験フラグの後ろに置く「1回だけの修復」です。これはまだ実装済みの機能ではなく、現在検討中のプロトタイプです。
const report = analyzeSvgQuality(vectorXml);
if (report.repairable && experiments.svgRepair) {
const repaired = await repairOnce({
request: englishRequest,
svg: vectorXml,
report,
});
return sanitizeGeneratedVectorXml(
extractVectorXml(repaired),
scope,
);
}
修復プロンプトには、元の英語リクエスト、生成済みSVG、静的チェックの警告を渡します。許可するSVG要素と安全性の制約は、最初の生成と同じです。
回数を1回に制限する理由は、ブラウザ上の処理だからです。無制限の生成・検査・修復ループは、ユーザーのPCでメモリ、バッテリー、待ち時間を予測不能にします。キャンセル可能で、1回だけ実行し、改善しなければ元の結果か明確なエラーへ戻す方が扱いやすくなります。
また、修復後の結果も必ず同じ抽出処理とサニタイザーを通します。修復処理をセキュリティ上の例外にはしません。
ローカルファーストという制約
クラウド上の高性能なVisionモデルを利用すれば、評価や修復は簡単になるかもしれません。しかし、それではプロダクトの境界が変わります。Timeline Studioでは、素材やデザイン指示をバックエンドへアップロードせず、ブラウザだけでどこまで実用的な編集環境を作れるかを検証しています。
そのため、次の原則を維持します。
- サーバー側のSVG修復サービスを使用しない
- 非表示のクラウドフォールバックを用意しない
- 無制限に再試行しない
- ブラウザAIやローカル翻訳が利用できない場合は明確に通知する
- 生成素材は編集可能な状態で保存し、自動的にタイムラインへ置かない
これはプライバシーだけの話ではありません。品質改善の仕組みを、小さく、説明可能で、再現可能にするための制約でもあります。
コントリビューターを募集しています
このテーマについて、2つのResearch Issueを公開しています。
- Research spike: improve browser-local AI SVG generation quality
- Prototype an SVG quality checker and local repair pass for Gemini Nano
ブラウザAI、SVG内部構造、評価設計、プロンプト設計、開発者ツールに興味がある方に向いたタスクです。システム全体を完成させる必要はありません。プロンプトセット、静的チェックを1つ、失敗パターンの分類、または小さな修復プロトタイプだけでも大きな前進になります。
生成SVGの「構文上の正しさ」と「デザインとしての有用性」をどのように分けて評価しているか、経験やアイデアがあればぜひ教えてください。SVGがパースでき、安全な要素だけで構成されていても、そのデザインが実用的とは限りません。
ブラウザで動作するローカルファースト動画編集ツール Timeline Studio に、ChromeのPrompt API(Gemini Nano)を利用したベクター生成機能を実装する中で、この差が大きな課題になりました。
この記事では、現在のブラウザ内SVG生成パイプライン、安全性の検証だけでは見つけられない品質問題、そして今後試したい決定論的チェックと1回だけのローカル修復について整理します。
すべての処理はブラウザ内で完結します。デザイン指示やプロジェクト素材をサーバーへ送信するクラウドフォールバックは使用しません。
現在の生成パイプライン
Timeline StudioのAIベクター生成は、次の順序で処理します。
- Language Detector APIで入力言語を判定する
- 英語以外の入力はTranslator APIで英語へ変換する
- Prompt APIを通してGemini NanoにSVG生成を依頼する
- Markdownコードブロックや前後の説明文を除き、最初の完全な
<svg>を抽出する - 要素・属性・URL・スクリプトをサニタイズする
- 1200×1200のviewBoxへ正規化する
- 「My Assets」へ追加する(タイムラインへは自動挿入しない)
実装の中心部分は、概念的には次のようになっています。
const raw = await session.prompt(
buildVectorDesignPrompt(englishRequest),
);
const vectorXml = extractVectorXml(raw);
const vectorBody = sanitizeGeneratedVectorXml(vectorXml, scope);
モデルは常にSVGだけを返すとは限りません。コードフェンスで囲んだり、前に説明文を付けたり、旧形式の<vector>ラッパーを使用したりします。そのため抽出処理は多少寛容にしつつ、セキュリティ境界は後段のサニタイザーで厳格にしています。
サニタイザーが検出できること
現在の検証は、構造と安全性に関する問題を拒否できます。
- SVGマークアップが存在しない、または壊れている
-
scriptやイベントハンドラーを含む - 許可していない要素や属性を含む
- 外部URLやリモートコンテンツを参照する
- エディタの座標系へ正規化できない
生成AIの出力であっても、信頼できない入力として扱う必要があります。したがって、この検証は必須です。
しかし、安全なSVGでも「良いデザイン」とは限りません。
構文検証だけでは見つからない問題
実際には、次のような出力も正常なXMLとして通過します。
- viewBoxは正しいが、重要な図形が端で切れている
- 指示には合っているが、構図が一般的すぎて使いにくい
- 透明背景を要求したのに、画面全体を覆う背景矩形がある
- 表示される図形がほとんどなく、実質的に空である
- 小さな図形が多すぎて編集しにくい
-
<g>はあるものの、IDや階層に意味がない - 文字、余白、コントラストが動画素材として不十分である
- 翻訳後に単語は残っているが、デザイン意図が失われている
つまり、現在のサニタイザーが答えられるのは「安全に読み込めるか」であって、「ユーザーが使いたいと思うか」ではありません。
まずは再現可能な品質ベンチマークを作る
プロンプトを感覚的に調整し続ける前に、比較できる小さなベンチマークが必要です。最初のセットとして、少なくとも24個のプロンプトを用意する予定です。
- アイコンと単純なシンボル
- ローワーサードとタイトルグラフィック
- チャートとインフォグラフィック要素
- 吹き出し、ラベル、バッジ
- フレームやマスクに近い構図
- 抽象的なモーショングラフィック素材
- 4件以上の非英語入力
各出力は、以下の観点で人間が評価します。
- 要求への忠実度:依頼した内容が表現されているか
- 構図:余白、バランス、視覚的階層が実用的か
- 完成度:偶然できた形ではなく、意図されたデザインに見えるか
- 編集可能性:グループや図形が後から編集しやすい構造か
- 安全性と透明性:SVGの制約と透明背景の要求を満たすか
目的は万能な「品質スコア」を作ることではありません。プロンプトや実装を変更したときに、以前より良くなったのか、別のケースを壊していないかを再現可能にすることです。
モデルを再実行する前にできる決定論的チェック
視覚的な問題の一部は、2回目の推論を行わなくても静的に近似できます。
- 可視領域が空、または極端に小さい
- 図形がviewBoxの外へ大きくはみ出している
- 不透明な図形がキャンバスのほぼ全体を覆っている
- 座標値が極端に大きい
- 図形数やフィルターの複雑度が高すぎる
- グループIDが重複、欠落、または無意味である
- コンテンツがキャンバスのごく一部に偏っている
これらのチェックだけでデザインを理解することはできません。しかし、単なる「生成に失敗しました」ではなく、修復処理や開発者へ機械可読な理由を渡せます。
たとえば、品質レポートは次のような形にできます。
type SvgQualityReport = {
repairable: boolean;
warnings: Array<
| "CONTENT_OUTSIDE_VIEWBOX"
| "FULL_CANVAS_BACKGROUND"
| "EFFECTIVELY_EMPTY"
| "EXCESSIVE_COMPLEXITY"
| "UNHELPFUL_GROUP_STRUCTURE"
>;
};
修復はローカルで1回だけ行う
次に試したいのは、実験フラグの後ろに置く「1回だけの修復」です。これはまだ実装済みの機能ではなく、現在検討中のプロトタイプです。
const report = analyzeSvgQuality(vectorXml);
if (report.repairable && experiments.svgRepair) {
const repaired = await repairOnce({
request: englishRequest,
svg: vectorXml,
report,
});
return sanitizeGeneratedVectorXml(
extractVectorXml(repaired),
scope,
);
}
修復プロンプトには、元の英語リクエスト、生成済みSVG、静的チェックの警告を渡します。許可するSVG要素と安全性の制約は、最初の生成と同じです。
回数を1回に制限する理由は、ブラウザ上の処理だからです。無制限の生成・検査・修復ループは、ユーザーのPCでメモリ、バッテリー、待ち時間を予測不能にします。キャンセル可能で、1回だけ実行し、改善しなければ元の結果か明確なエラーへ戻す方が扱いやすくなります。
また、修復後の結果も必ず同じ抽出処理とサニタイザーを通します。修復処理をセキュリティ上の例外にはしません。
ローカルファーストという制約
クラウド上の高性能なVisionモデルを利用すれば、評価や修復は簡単になるかもしれません。しかし、それではプロダクトの境界が変わります。Timeline Studioでは、素材やデザイン指示をバックエンドへアップロードせず、ブラウザだけでどこまで実用的な編集環境を作れるかを検証しています。
そのため、次の原則を維持します。
- サーバー側のSVG修復サービスを使用しない
- 非表示のクラウドフォールバックを用意しない
- 無制限に再試行しない
- ブラウザAIやローカル翻訳が利用できない場合は明確に通知する
- 生成素材は編集可能な状態で保存し、自動的にタイムラインへ置かない
これはプライバシーだけの話ではありません。品質改善の仕組みを、小さく、説明可能で、再現可能にするための制約でもあります。
コントリビューターを募集しています
このテーマについて、2つのResearch Issueを公開しています。
- Research spike: improve browser-local AI SVG generation quality
- Prototype an SVG quality checker and local repair pass for Gemini Nano
ブラウザAI、SVG内部構造、評価設計、プロンプト設計、開発者ツールに興味がある方に向いたタスクです。システム全体を完成させる必要はありません。プロンプトセット、静的チェックを1つ、失敗パターンの分類、または小さな修復プロトタイプだけでも大きな前進になります。
生成SVGの「構文上の正しさ」と「デザインとしての有用性」をどのように分けて評価しているか、経験やアイデアがあればぜひ教えてください。