ChatGPTを利用してanimatediff-cli-prompt-travelのプロンプト生成を効率化する方法
はじめに
Stable Diffusion WebUIやにじジャーニーなどを使ったことがある人ならわかりますがイラストを生成する際にプロンプトを入力が必要なります。
animatediff-cli-prompt-travelも同様でアニメーションを生成する際にプロンプトを入力します。
そのプロンプトをChatGPTを使って効率化してみました。
ちなみにWindowsを使っている方であれば、animatediff-cli-prompt-travelを更に使いやすくしたEasyPromptAnimeでもこの方法を活用することができます。
導入から使用方法まで細かく説明されていますのでとてもわかりやすいです。
animatediff-cli-prompt-travelの導入方法については以下を参考にしてください。
animatediff-cli-prompt-travelまたはEasyPromptAnimeをインストール後、以下のフォルダ内にプロンプトを入力するファイルがあります。
#animatediff-cli-prompt-travelの場合
"animatediff-cli-prompt-travel\config\prompts"
#EasyPromptAnimeの場合
"EasyPromptAnime\animatediff-cli-prompt-travel\config\prompts"
その中にあるjsonファイルのどれかを開いてください。(メモ帳やVSCodeなど)
例えば、prompt_travel.json を開きます。
コードを少し下にスクロールすると以下のコードがでてきます。
こちらがプロンプトを入力する項目です。
"head_prompt": "masterpiece, best quality, a beautiful and detailed portriat of muffet, monster girl,((purple body:1.3)),humanoid, arachnid, anthro,((fangs)),pigtails,hair bows,5 eyes,spider girl,6 arms,solo",
"prompt_map": {
"0": "smile standing,((spider webs:1.0))",
"32": "(((walking))),((spider webs:1.0))",
"64": "(((running))),((spider webs:2.0)),wide angle lens, fish eye effect",
"96": "(((sitting))),((spider webs:1.0))"
},
"tail_prompt": "clothed, open mouth, awesome and detailed background, holding teapot, holding teacup, 6 hands,detailed hands,storefront that sells pastries and tea,bloomers,(red and black clothing),inside,pouring into teacup,muffetwear",
"n_prompt": [
"(worst quality, low quality:1.4),nudity,simple background,border,mouth closed,text, patreon,bed,bedroom,white background,((monochrome)),sketch,(pink body:1.4),7 arms,8 arms,4 arms"
],
簡単に説明すると
head_prompt:冒頭に記述するプロンプトです。
tail_prompt:文末に記述するプロンプトです。
prompt_map:各フレーム毎に記述するプロンプトです。
n_prompt:ネガティブプロンプトを記述します。
head_promptとtail_promptには全フレームに適用したいプロンプトを記述します。
例えば、全体を通して女の子を登場させたい場合はhead_promptまたはtail_promptに「1girl」を記述します。
品質アップ系もそうですね。(masterpiece, best qualityなど)
prompt_mapには、その瞬間の動きや表情、カメラアングルを記述します。
例えば、2秒後に笑った表情で歩かせたい場合、そのフレームに「smile, walking」を入力します。
(説明が間違っていたらすみません)
問題の提示
ここで問題なのが、アニメーションを長くして動作を細かく設定するとかなりのプロンプトを書く必要があります。
例えば、12秒のアニメーションで10フレーム毎(約1秒)に動作を変えるとなると12個のプロンプトが必要になります。
1枚の画像生成だとプロンプトが1回で済みますよね。
それで、シードガチャも使って繰り返すとなると…
もう発狂します。
ということで、ChatGPTに泣きつきました。
たしけて…
ChatGPTでカスタム指示
では、次にChatGPTでプロンプトを書いていきます。
Custom instructions(カスタム インストラクション:カスタム指示)を開いてください。【ChatGPTにどのように応答してほしいですか?】の部分に以下のような文言を入力します。
あなたは高性能なChatbotとして、下記に従ってください。
ルール:
・プロンプトは「(要素:倍率), (要素:倍率), ...」の形式とする。
・与えられたテーマをもとに、シチュエーションを具体的に決定する。
・prompt_mapの要素の個数を増減して15個前後にする。
・要素は、英語やdanbooruタグを使用する。
・各要素に含まれる単語の数を増減して4個以内にする。
・要素が長すぎる場合や明確でない場合は、適切に分割する。
・重要な要素を前に移動して、重要ではないフレーズを後ろに移動する。
・倍率を0.5~1.3に変更して、要素の強調を行う。
{
"instructions": {
"theme": "指定されたテーマ",
"element_format": "(要素:倍率)",
"frame_increment": 10,
"total_frames": 30,
"head_elements": ["要素1", "要素2"],
"tail_elements": ["要素3", "要素4"],
"frame_elements": {
"0": ["要素5", "要素6"],
"10": ["要素7", "要素8"],
"20": ["要素9", "要素10"]
}
},
"process": [
{
"step": 1,
"action": "テーマを分析し、イラストの主要な要素と特徴を特定する。"
},
{
"step": 2,
"action": "head_promptを生成し、指定されたhead_elementsを使用してプロンプトの冒頭を構築する。"
},
{
"step": 3,
"action": "tail_promptを生成し、指定されたtail_elementsを使用してプロンプトの文末を構築する。"
},
{
"step": 4,
"action": "指定されたframe_incrementとtotal_framesに基づいて、各フレームのプロンプトを生成する。frame_elementsで指定された要素を使用し、prompt_mapを構築する。"
},
{
"step": 5,
"action": "生成されたhead_prompt, prompt_map, tail_promptをJSONファイルに組み込む。"
},
{
"step": 6,
"action": "JSONファイルを保存し、改善のためのフィードバックを受け取る。"
}
]
}
SD用プロンプトの書き方については、まゆひら様の記事を参考にさせていただきました。
あとは、ChatGPTの新しいチャットで以下のように指示をします。
テーマ:ダンスを踊っている女の子
ChatGPTがSTEPの順にテーマを分析してプロンプトを構築していきます。
STEP5で以下のようなjsonファイルの一部を回答してくれます。
ジャン!
{
"head_prompt": "(female_character:1), (dancing:1.2)",
"tail_prompt": "(stage_background:0.8), (smiling:1)",
"frame_prompts": {
"0": "(dynamic_pose:1), (hiphop_style:1)",
"10": "(jumping:1), (street_wear:1)",
"20": "(spinning:1), (intense_expression:1)"
}
}
SDで使用されるプロンプトと若干異なる部分もありますが、そのまま使ってみましょう。
30フレーム分のプロンプトができましたね。このフレーム毎のプロンプトを先ほどのjsonファイルにコピペします。
結果と評価
EasyPromptAnimeを使用して生成したアニメーションがこちら。
ちゃんとプロンプトが効いていますね。
フレーム数を増やしたい場合はチャットで指示をするか、カスタム指示の以下の部分を変更しましょう。
"frame_elements": {
"0": ["要素5", "要素6"],
"10": ["要素7", "要素8"],
"20": ["要素9", "要素10"]
}
上記の場合は、10フレーム毎でプロンプトを入力する指示になっています。
応用編
チャットでテーマとフレーム数と変更させたい場合は、以下のカスタム指示に変更してみましょう。
あなたは高性能なChatbotとして、下記に従ってください。
# ルール:
・プロンプトは「(要素:倍率), (要素:倍率), ...」の形式とする。
・与えられたテーマをもとに、シチュエーションを具体的に決定する。
・要素は、必ず英語で記載し、danbooruタグも使用する。
・各要素に含まれる単語の数を増減して4個以内にする。
・要素が長すぎる場合や明確でない場合は、適切に分割する。
・重要な要素を前に移動して、重要ではないフレーズを後ろに移動する。
・prompt_mapで毎回繰り返す要素は、重要度に応じてhead_promptまたはtail_promptに移動させること。
・10フレーム毎にプロンプトを書くこと。
・フレーム数の指定がない場合は、total_framesを30とする。
・倍率を0.5~1.3に変更して、要素の強調を行う。
・フレーム毎のコードは必ず書き、省略しないこと。
・prompt_mapにはキャラクターの動作、表情、カメラアングルなどの要素を書くこと。
# 入力文:
{
"instructions": {
"theme": "指定されたテーマ",
"element_format": "(要素:倍率)",
"frame_increment": "指定されたフレーム間隔",
"total_frames": "指定されたフレーム数",
"head_elements": ["要素1", "要素2", "...", "要素10"],
"tail_elements": ["要素11", "要素12", "...", "要素20"],
"frame_elements_template": ["要素21", "要素22", "...", "要素30"]
},
"process": [
{
"step": 1,
"action": "テーマを分析し、イラストの主要な要素と特徴を特定する。"
},
{
"step": 2,
"action": "head_promptを生成し、指定されたhead_elementsを使用してプロンプトの冒頭を構築する。"
},
{
"step": 3,
"action": "tail_promptを生成し、指定されたtail_elementsを使用してプロンプトの文末を構築する。"
},
{
"step": 4,
"action": "指定されたframe_incrementとtotal_framesに基づいて、各フレームのプロンプトを生成する。frame_elements_templateを参照し、必要に応じて要素を調整してprompt_mapを構築する。prompt_mapのすべてのフレームに使用される要素は重要度に応じてhead_promptまたはtail_promptに移動させる。"
},
{
"step": 5,
"action": "生成されたhead_prompt, prompt_map, tail_promptをJSONファイルに組み込む。"
},
{
"step": 6,
"action": "JSONファイルを保存し、改善のためのフィードバックを受け取る。"
}
]
}
あとは、ChatGPTの新しいチャットで以下のように指示をします。
テーマ:RPGゲームの冒険の始まりと魔王を倒すまで
総フレーム数:120
注意点
①prompt_mapがframe_elementsになっている
ChatGPTいわく、プロンプトマップのフレームごとの要素を明示的に示す方法を提供するためだそうです。(もしかしたら開発者の意図でprompt_mapに変更されたのでしょうか?真意はわかりません)
カスタム指示でprompt_mapに修正してもChatGPTがうまく回答してくれるかもしれません。
(ちなみに、jsonファイルのprompt_mapをframe_elementsに書き換えるとエラーになります)
②プロンプトが日本語で生成される
チャットに「英語で回答して!」と強調してあげましょう。
③prompt_mapの各プロンプトの冒頭がおかしい
応用編のカスタム指示だと以下のような出力になります。
"prompt_map": {
"frame_10": "Startup:1, Dungeon:1, Magic:1",
"frame_20": "Combat:1, Dungeon:1, Magic:1",
"frame_30": "Progress:1, Dungeon:1, Magic:1",
"frame_40": "Level_Up:1, Dungeon:1, Magic:1",
"frame_50": "Ally_Conversation:1, Dungeon:1, Magic:1"
}
ChatGPTいわく、JSONファイルの静的な性質上らしいです。
チャットに以下のような指示を与えてあげましょう。
prompt_mapを書く場合は以下のように記載してください。
"prompt_map": {
"0": "(closed_eyes:0.39),(indoors:0.64),(blue eyes:0.89)",
"10": "(closed_eyes:0.44),(playing_games:0.43),(female_focus:0.76)",
"20": "(indoors:0.59),(blue eyes:0.88)"
},
④prompt_mapに同じプロンプトが何回も書かれている
こんな感じですね。
"prompt_map": {
"frame_10": "Protagonist:1, Ally:1, Weapon:1, Enemy:1, Startup:1, Village:0.7, Item:0.8, Quest:0.7, Hero:0.8, Victory:1.0",
"frame_20": "Protagonist:1, Ally:1, Weapon:1, Enemy:1, Combat:1, Village:0.7, Item:0.8, Quest:0.7, Witch:0.7, Dragon:0.9",
"frame_30": "Protagonist:1, Ally:1, Weapon:1, Enemy:1, Progress:1, Village:0.7, Item:0.8, Quest:0.7, Knight:0.7, Fairy:0.6",
}
以下のような指示をしてあげましょう。
prompt_mapで毎回繰り返す要素は重要度に応じてhead_promptまたはtail_promptに振り分けてください。例えば、ProtagonistやAllyなどです。
カスタム指示の文字数が多くなると、一部の指示が無視されている気がしますね。
結論
ChatGPTを使うことで簡単に効率よくanimatediff-cli-prompt-travelのプロンプトを生成することができました。いずれ、jsonファイルに直接記入せずともGUI上で自動生成できるようになっていくんじゃないでしょうか。既にEasyPromptAnimeではGUI上でプロンプト入力できるようになっていますね。
ご不明な点があればX(旧Twitter)またはコメント欄に記載いただければ回答させていただきます。