1. はじめに
近年、いわゆる、バーチャルキャラクター、特に「トーキングヘッド」と呼ばれる、おしゃべりする上半身キャラクターという分野が注目/研究されてきた。テキストや2D画像、音声に変わる、 よりフレンドリーな新たなヒューマンインターフェースとしての、「会話する人の顔」が重要になってきたことを示す。
そのアイディアの原型はMax Headroom (注1)に遡る。 当時はまだコンピューターのCPUパワーがインタラクティブ3D表示をするには不足していたため、(あるいは3DCGを制作するコストが高かったため)実際は俳優のメークにてこの特殊なキャラクターは作られていた。
ウェッブブラウザで動作するインタラクティブ 3D (Web 3D)プラグインで実現できる「トーキングヘッド」は、 Haptek,Pulse, QEDSoft,bioVirtualなど多くの内外の企業により開発され商品化されてきている。 マルチユーザーワールド内でのアバタ―(Avatar:ユーザーの化身)としては、ソニーの「こみゅ〜3D」や、blaxxun, ActiveWorldsなどが研究を進めてきている。 また、TVML研究開発チームによるTVML は、TVシナリオの言語化を試みている 。 バーチャルキャスターの動き/音声、合成音による会話、スーパーインポー ズタイトル、舞台設定などを記述することができる。
この論文では、ユーザーとフレンドリーなインタラクションを持たせる、「 トーキングヘッド」を実現するための二つのアイディア、 「視覚言語と音声、リップシンクの統合手法」と、「インタラクティブスト ーリーを記述するためのデータフォーマットの提案」 に関して述べている。
2. 視覚言語と音声、リップシンクの統合手法
近年、「テキストチャット」に変わるものとして、3Dバーチャルワールド内での「3Dチャット」の研究/実験が様々に試みられた。 しかし、テキストと3Dとの関係が明確に考察されておらず、キャラクターが3D表示されている意味があまりないと感じられるものが多かった。
2.1 視覚言語
現実の人間が話す言語とは、 1) 音声、 2) 口唇と舌の動き、 3) 会話動作、 4) 感情表現 の組み合わされたものである。
1)は聴覚により認知されるものであるが、2~4)は視覚によるものであり、「 視覚言語」と呼ぶことができるであろう。
2) はいわゆるリップシンク、発音記号と唇、舌の形の同期した対応付け、 3)は「うなずき」など、頭/首の動き、さらには身振り手振りのジェスチャーまで含む。
4)は、目蓋、眉、頬などの顔面の筋肉の動きによ る感情表現であり、瞬きの速度や頻度を含めることもできる。
1)と2)の関係(リップシンク)についてはさまざまな研究がなされている。 LIPSinc社は音声データをリアルタイムに解析して、発音記号とタイミングを取り出し、3Dアニメーションやインタラクティブキャラクター制作 を行うためのSDKを発売している。 また、いわゆる音声認識ソフトを逆用して、音声の発音記号とタイミングを 取り出すことも考えられる。
しかし、3),4)の研究に関しては未熟であり、例えば、ある製品では、リップシンクと同様に音声から自動でこれらのデータを作成している。
だが、「yes」の意味の「うなずき動作」、「?」の意味の「首傾げ動作」、 「no」の意味の「首振り動作」、「好ましくない意思表示」の「眉しかめ」...などなど会話動作、感情表現は、単にランダムに会話中で行われるものではなく、「犬」、「歩く」、「青い」...などと同じく、意味のある会話構成要素のひとつである。 つまり、「視覚言語」として、必要な時に相応しいタイミングで会話中に挿入されるべきものである。
こうした視覚言語の要素化に関しては、"visume"(視覚素)という言葉が使われることもある。 これは、"phoneme"(音素)に対応した造語である。
これら、「視覚言語」を3Dアニメーションで実現する従来の手法としては 、3DCGツールにて、3Dデザイナーがすべて制作するか、モーションキャプチャーのようなシステムによって、実際のアクターの動きを記録して使用するかのどちらかである。しかし、いずれも手間とコストのかかるものである。
2.2 動作/感情記号
ここで提案するのは、視覚言語を音声言語とまったく同列に扱い、テキストによって記述する手法である。
具体的には、発音記号として、「あ」に[a]を割り当てるように、たとえば 、「yes」の意味でうなずく動作には、[*]を、 わからない意味の首振り動作には[?]の記号(動作記号)を、眉をひそめる動作には[~]の記号(感情記号)を割り当てるとする。
たとえば、こんな科白を俳優になったつもりで考えて欲しい。
| 「…ああ、あなたのおっしゃることはわかった。 だが、どうして彼ら はここにやってこないんだ。 かれらこそ、この事件の当事者のはずだ。」 |
これに、上で定義した動作/感情記号を入れてみよう。
| 「…*ああ、あなたのおっしゃることはわかった。 だが、~どうして彼 らはここにやってこないんだ。? かれらこそ、~この事件の当事者のはずだ。」 |
実際には音声発音記号と共にこう書き表されるはずだ。
| 「 *A,anatanosarukotowawakat-- dag,~dOsitekarerawakokoniyatekonainnd?, -- karerakoso,~konojikenotOjisanohazd」 |
(実際の発声は書き言葉と異なるため、発音記号は会話文章を単に記号に置き換えたものではない。)
これらの動作/感情記号は単に動作の始まりのきっかけを示す。リップシンク、動作、感情表現はそれぞれ独立したシステムであるため、たがいに邪魔をすることはない。
このように、視覚言語は言葉の意味をビジュアルに補足し、さらには、「目は口ほどに物を言い」と言われるように言葉以上の、また時には言葉とは反対の意味を持たせることまでできるものである。
以上述べてきたことを踏まえ、会話動作のアニメーションデータベース、感情表現モーフのデータベースをあらかじめ単位として制作しておけば、この手法を用いて、3Dデザイナーという特殊な技能を持ったユーザーでなくとも、テキストベースで簡単に効率よく大量に会話する3Dアニメーションを制作することができる 。
3Dコンピューターグラフィックにおけるテクニックでは、リップシンクは唇と舌の形の3Dターゲットモーフ、 感情表現は、眉、目、頬、口などの3Dターゲットモーフ、動作は階層構造またはボーン構造のアニメーション により実現されるだろう。
また、各動作に対して時間長や誇張度、動作ミキシングなどのパラメーターを設けることにより、準備した動作単位以上のバリエーションを作り出すことも可能である。
3. StoryGraph - インタラクティブストーリーを記述するデータフォーマット
「はじめに」で述べたように、現在様々な「トーキングヘッド」の研究/開発/商品化の試みがなされている。 3D表示エンジン/インターフェースとしてのバーチャルキャラクターが充実すると、次に考えるべきステップは、それをいかに制御してストーリーを組み立てるかである。
現時点ではほとんどの「トーキングヘッド」を使った製品やデモは、ムービーのように一方通行の時間軸に従って、科白とアニメーションをプレイバックするものに留まっている。
しかし、「トーキングヘッド」はインタラクティブなヒューマンインターフ ェースとしても発展させられるべきである。 それは、ストーリーゲーム、CRM (注2)、AI機能を備えたコンピュー ターエージェント、音声認識システムのインターフェース、チャットボット Q/Aシステムなど、多様な応用が考えられる。
一般的に、従来の様々なデータ形式は、階層構造データ、あるいは、直線的な逐次データを記述するものが基本である。 今後は、こういったインタラクティブな「分岐ストーリー」を記述できる、 「ネットワーク」的、あるいは「相互リンク」的なデータを記述するためのデータ形式の重要性が増すであろう。
現在ある、「分岐ストーリー」を記述する方法には、Macromedia社の Director Shockwave Studio のように、「タイムライン」を多数用意しスクリプトでつなげて行く方式がひとつあげられる。 また、多くのゲームプログラムは、内部的に分岐がプログラミング言語で記述され、外部においてデータ構造化されていないないものがほとんどであるはずだ。
ここでは、インタラクティブストーリーを記述するためのデータ形式として StoryGraph を提案する。
3.1 StoryNode
StoryGraphにおいて、ストーリーは、その展開における、それぞれの小ステージ(ストーリーノード)の組み合わせで成立すると考える。 各ストーリーノードでは、キャラクターのひとまとまりの会話が再生され、 同時に、キャラクターのアニメーション再生、その他、小道具、舞台背景などストーリーを組み立てるために必要なものに対して、様々な事象が起こるとする。また、ユーザーからの入力も、ノード毎に評価されるとする。
3.2 分岐
単純なストーリーでは、ストーリーノードが一次元的に連続される。(時として、スタートタイミングが重なり合い、並列進行することはある。) しかし、ユーザーフィードバック/インタラクションのある、インタラクティブストーリーにおいては、このストーリーノードが互いに複雑にリンクしあい、ネットワーク状のデータを形成すると考えられる。
筆者はこのネットワーク形成に必要なストーリー分岐を次の四つに分類した 。
StoryGraphでは、各StoryNodeのリンク形態以外に、各StoryNodeで起こる様々な事象 - 指定会話再生、スクリプト実行、3Dモデルやバーチャルキャラクターに対するコマンド、環境に対するコマンド、イベントアウト、 データロードなど、さまざまなイベントを起こすことができるよう ファンクションを取り決めている。
4. おわりに
以上述べてきたように、キャラクターの会話/動作を一元的に扱い、また、インタラクティブストーリーを扱うデータを使用することにより、会話動作/感情表現まで含めた「しゃべる」バーチャルキャラクターを使用した、ユーザーインタラクションを持ったストーリー、という複雑なコンテンツを容易に開発することができるであろう。
従来のCGアニメーションは、ミクロからマクロまで同一のツール/データ内にあった。これは、複雑なシーンやストーリーを作り上げるためには大きな障害であると考えられる。
現実は、ミクロからマクロまで様々な次元で運動は起こっている。たとえば、あるキャラクターの指先の動作や唇の動きが、ワールド全体のアニメーションの流れと同レベルで考えられるべきではない。
ここでははっきりふれなかったが、このように、会話データ/ストーリーデータという風に、データをレイヤー分けして構築していくことにより、より大きな次元でのアニメーションコントロールにおいては、低次元でのアニメーションコントロールを意識しなくてよく、クリエーターにより便利なコンテンツ開発環境を与えることになるはずである。
(注1) Max Headroom 80年代半ばに英国、「チャンネル4」で作られたTV番組シリーズ。
ヘビーにメークされたMatt Frewerにより演じられた、元祖サイバーパンク番組。のちに米国でリメークされる。
ストーリー: 世界最大のテレビ局、「Network 23」がレポーター、Editon Carterの「心」をダウンロードして化身としてのCGキャラクターを作る。しかしそれは自分の勝手な意思を持つようになり、Max Headroomとなってネットワークに潜み、あらゆるTVモニターに神出鬼没に出現し始める…
(注2) CRM (Customer Relationship Managemant) 全社レベルで顧客情報とコンタクト履歴を共有・管理し、つねに個々の顧客に最適化したサービスを提供するための新しいビジネス・コンセプトのこと。顧客はWeb、コールセンターなどのあらゆる媒体から企業にコンタクトすることができる。単純には、この企業ウェッブサイトや電話での顧客へのQ/Aサービスや苦情処理のことを指す。
StoryGraph はデータ形態としてはVRMLと類似した、{ }で囲まれたノード、その要素としてのフィールドからなる。また、フィールドが複数要素を持つ場合は、[ ]で囲む。
なお、このドキュメントの記載法として、
フィールドの要素、ノード固有名に関しては太字で表記するとする。
A.1 ヘッダー
A.2 StoryAttribute
データのグローバルなアトリビュートを設定する。
A.3 SpecialNode
スペシャルノードの設定。特殊なリンク先をグローバルに設定する 。
A.4 StoryNode
ストーリーノード。ストーリーグラフを組み立てる基本単位。
A.5 モデルファンクション
モデルファンクションはキャラクターや3Dモデルに働きかける。
動作させたいStoryNode内に任意の回数、記述できる。
A.6 プロパティファンクション
プロパティファンクションは画面の見え方に関するファンクションである。
動作させたいStoryNode毎に記述できる。
付録B: StoryGraph のサンプル
動作:背景に2枚の画像を表示し、キャラクターに説明させる。
ユーザーにどちらか欲しい絵を選ばせ、選んだ絵をGIFにてブラウザに表示する。
コメント行は # で始まるとする。
# 以下のテキスト部分はフィールドの説明である。
#STORYGRAPH V2.0
StoryGraph はこの行から始まる。
StoryAttribute {
sentenceFile "file-name" # センテンスファイル名 会話タグを参照する
grammerFile "file-name" # グラマーファイル名 ユーザー入力を参照する
parameter parameter-name default-value # グローバル変数
}
SpecialNode {
exceptNode node-name # 例外ノードのデフォルト
unknownNode node-name # 知らない入力の場合に飛ぶノードのデフォルト
startNode node-name # このノードから始まる
timeoutNode node-name # ユーザー入力なしタイムアウト時
globalInput node-name input_key # どの時点においても、一致するユーザー入力があれば、割り込みしてこの指定ノードへ飛ぶ
}
StoryNode node-name {
type DIRECT/INPUT/AUTO/SWITCH # ノードの分岐タイプ 直接/入力条件/自動確率/パラメーター条件
tag sentence-tag/NULL # 再生文章 文章ファイルのタグを参照
duration dur # このノードに留まる期間(秒)*音声がある場合で、onEnd=TRUEの場合は再生後の待ち時間
delt delt # 留まる期間の変動 duration * rand(0~1) * delt
onEnd TRUE/FALSE # AUTO/DIRECTの場合、音声再生が終わってからリンクするか?(default=TRUE)
except node-name # 個別のexceptNode設定
unknown node-name # 個別のunknownNode設定
set "script" # スクリプトの設定
load "URL" # ここからリンクするStoryGraphのロード/ ダウンロードを開始する URL=NONE ロードなし
selectiveRandom TRUE/FALSE # AUTO分岐の場合 、同じリンクが続かないようランダムなリンク先を選択する
eventOut "event" # 外部へのイベントアウト
link node-name # type=DIRECTの場合のリンクノード定義
select [ # type=INPUT の場合の分岐定義
node-name input_key, # ユーザー入力タグ *グラマーファイルで定義
]
branch [ # type=AUTOの場合の分岐定義
node-name rate, #分岐確率(0~1)
]
case [ # type=SWITCHの場合の分岐定義
to-node-name "parameter-script" # スクリプト条件
]
}
loadModel "URL" model_name tx ty tz rx ry rz sc TRUE/FALSE # モデルのロード/ダウンロードを開始する
moveModel model_name tx ty tz rx ry rz # モデルの回転移動
moveToModel model_name tx ty tz rx ry rz dur # モデルを現在位置からdur=期間(秒)で回転移動
visibleModel model_name TRUE/FALSE # モデルの表示
visibleParts model_name part_name TRUE/FALSE # モデルパートの表示
toggleParts model_name part_name # モデルパートの表示のトグル
doRotate model_name drx dry drz # モデルの連続回転の実行 (回転角/秒)
stopRotate model_name # 回転を止める
resetRotate model_name # 回転のリセット
doTranslate model_name dtx dty dtz # モデルの連続移動の実行(移動量/秒)
stopTranslate model_name # 移動を止める
resetTranslate model_name # 移動のリセット
playAction model_name motion_name dur grad_dur
backColor red green blue gdur # 背景色 gdur=現在の状態からの変移秒
lightPos x y z gdur # 光源の位置
viewAngle angle front back gdur # 画角の設定
worldTrans x y z gdur # ワールドの位置
worldRotate x y z gdur # ワールドの回転量
#STORYGRAPH V2.0
SpecialNode {
exceptNode start
unknownNode start
startNode start
}
StoryAttribute {
sentenceFile "illust_sent.txt"
grammerFile "illust_memo.txt"
parameter select middle #テキストパラメーター
}
StoryNode start { #ここからスタート
tag NULL
type DIRECT
duration 1.0
delt 0
link hello
}
StoryNode hello { #「こんにちわ」としゃべらせる
tag HELLO
type DIRECT
duration 1.0
delt 0.5
link walk
}
StoryNode walk { #キャラクターを移動させる
tag TALK
type DIRECT
duration 3
delt 0.0
moveToModel kaori 0 -5 -20 0 0 0 1.0
link order
}
#「どの絵がいいですか?」- 「右」または「左」などとユーザーに答えさせる
StoryNode order { #ユーザー入力により分岐させる
tag NULL
type INPUT
duration 10.0
delt 0.0
onInput TRUE
except order
unknown dontknow
eventOut "text:help" #ヘルプ表示
select [
pre_sel_left left
pre_sel_right right
dontwant no
]
}
StoryNode pre_sel_left { #selectパラメーターのセット
tag NULL
type DIRECT
duration 0.1
delt 0.0
set "select=left"
link thanks
}
StoryNode pre_sel_right { #selectパラメーターのセット
tag NULL
type DIRECT
duration 0.1
delt 0.0
set "select=right"
link thanks
}
StoryNode thanks { #「ありがとう」と言った後、条件分岐させる
tag THANKS
type SWITCH
duration 2
delt 0.0
case [
sel_right "select==right"
sel_left "select==left"
]
}
StoryNode sel_left { #「左の絵ですね?」
tag ASK_LEFT
type DIRECT
duration 2.0
delt 0.0
eventOut "text:left" #左の絵の表示
link hereyou
}
StoryNode sel_right {#「右の絵ですね?」
tag ASK_RIGHT
type DIRECT
duration 2.0
delt 0.0
eventOut "text:right" #右の絵の表示
link hereyou
}
StoryNode dontknow { #「ごめんね。」としゃべらせる
tag SORRY
type DIRECT
duration 2
delt 0.0
link order
}
StoryNode dontwant { #「そんなこと言わないでよ」としゃべらせる
tag ANGRY
type DIRECT
duration 2
delt 0.0
link order
}
StoryNode hereyou {#「はいどうぞ」
tag HERE
type DIRECT
duration 1.5
delt 0.0
link order #繰り返し
}
|
付録C: 参考画像- 発音/感情表現/会話動作の単位イメージ例