発話音声からリアルなリップシンクを生成する技術 第1回:音素とwav2vec

発話音声からリアルなリップシンクを生成する技術 第1回:音素とwav2vec

こんにちは!

今日は当社のMotionVox でも実際に使っている「リップシンク」技術について総合的に解説してみたいとおもいます。


音声に合わせて自然な口の動きを生成するリップシンク技術は、AIアバターや3Dアニメーション制作においても重要な技術です。

本記事では、最新のディープラーニング技術を活用したリップシンク学習の基礎から実装まで、技術的な観点から詳しく解説します。

1. リップシンク学習の基礎概念

1.1 問題設定

リップシンク学習とは、音声データから対応する口の動きを予測する回帰問題ととらえることができます

f: 音声特徴量(t) → 口の動きパラメータ(t)

この問題のコアは

音韻(音の特徴)と視素(視覚的な口の形)の対応関係を学習する

ことにあります。

1.2 音韻-視素マッピングの複雑性

ただし!
人間の発話における音と口の形の関係は、単純な1対1マッピングではないんです。

同じ音でも文脈で変化

「あ」の発音でも:
- 「か」の後の「あ」→ 口がやや狭めから開く
- 「ん」の後の「あ」→ 口が閉じた状態から大きく開く

調音結合(Coarticulation)

「かんぱい」の「ん」:
- 単独の「ん」→ 口を完全に閉じる
- 「ぱ」の前の「ん」→ 口を半開きで次の調音に備える

この複雑さがリアルなリップシンク実現の醍醐味であり、学習の技術的チャレンジとなっています。

2. 顔表情パラメータ表現

2.1 仮想FaceModelの仕様

本記事では、以下のような仮顔表情モデル(QualitegFaceModel=QFMとよびます)を想定して説明します

顔全体の表情パラメータは120で、うち、口回り、つまりリップシンクの制御につかうパラメータ数は26です。

# FaceModel パラメータ構成
total_params = 120  # 全表情パラメータ数
mouth_params = 26   # 口周りパラメータ数(インデックス: 94-119)

# パラメータ分類
expression_groups = {
    "eyebrow": [0, 1, 2, 3, 4, 5, 6, 7],          # 眉の動き (8個)
    "eyelid": [8, 9, 10, 11, 12, 13, 14, 15],     # まぶたの動き (8個)
    "eye_gaze": [16, 17, 18, 19],                 # 視線方向 (4個)
    "cheek": [20, 21, 22, 23, 24, 25, 26, 27],    # 頬の動き (8個)
    "nose": [28, 29, 30, 31, 32, 33],             # 鼻の動き (6個)
    "general": [34, 35, 36, 37, 38, 39, ..., 93], # その他全体表情 (60個)
    "mouth": [94, 95, 96, 97, 98, 99, ..., 119]   # 口周り (26個)
}

2.2 口周りパラメータの詳細分類

リップシンクにおいて最も重要な口周りの26パラメータは以下のようになります

mouth_parameter_details = {
    # 基本的な口の開閉・形状 (8個)
    "jaw_open": 94,           # 顎の開き
    "mouth_open": 95,         # 口の開き
    "mouth_wide": 96,         # 口の横幅
    "mouth_narrow": 97,       # 口の狭まり
    "lip_upper_up": 98,       # 上唇の上昇
    "lip_lower_down": 99,     # 下唇の下降
    "mouth_round": 100,       # 口の丸み(「う」音用)
    "mouth_stretch": 101,     # 口の横引き(「い」音用)
    
    # 左右非対称の動き (6個)
    "mouth_left": 102,        # 口の左移動
    "mouth_right": 103,       # 口の右移動
    "lip_corner_left_up": 104,    # 左口角上昇
    "lip_corner_right_up": 105,   # 右口角上昇
    "lip_corner_left_down": 106,  # 左口角下降
    "lip_corner_right_down": 107, # 右口角下降
    
    # 唇の細かい動き (8個)
    "lip_upper_left": 108,    # 上唇左部
    "lip_upper_right": 109,   # 上唇右部
    "lip_lower_left": 110,    # 下唇左部  
    "lip_lower_right": 111,   # 下唇右部
    "lip_pucker": 112,        # 唇の突出
    "lip_press": 113,         # 唇の圧迫
    "lip_bite_upper": 114,    # 上唇噛み
    "lip_bite_lower": 115,    # 下唇噛み
    
    # 特殊な調音動作 (4個)
    "tongue_tip_up": 116,     # 舌先上昇(「ら」行用)※1
    "tongue_back_up": 117,    # 舌奥上昇(「か」行用)※1
    "lip_trill": 118,         # 唇の震え(「ぶ」音用)
    "mouth_dimple": 119       # えくぼ(笑顔時)
}

※1 舌の動きに関するパラメータについて
実際の顔キャプチャーやアバターシステムでは、舌の動きは外部から観察がむずかしいため、実運用上は別システムで扱いますが、本例ではリップシンクの精度向上のためにデータに含めています。

2.3 音韻との対応例

では、実際の「こんにちは」という発話をするときの具体的な日本語音素と口回りのパラメータの対応をみてみましょう。

あくまでシンプル化した例ですが、「こんにちは」のそれぞれの音素を口回りのパラメータであらわすとそれぞれ以下のようになります。(実際はもっとふくざつです)

はい、要するに、この「こ」という音と、「こ」と発音したときの口の形(をあらわす制御パラメータ=口形)の対応関係を学習すればよいことになります。

というかんじで、学習のテーマとしてはシンプルなんです。対応関係も直観的です。


phoneme_mapping = {
    "こ": {  # 「こ」音
        "jaw_open": 0.5,      # 中程度に開く
        "mouth_open": 0.6,    # 口を開く
        "mouth_round": 0.4,   # やや丸める
        "tongue_back_up": 0.7 # 舌奥を上げる(「か」行特徴)
    },
    "ん": {  # 「ん」音
        "jaw_open": 0.0,      # 閉じる
        "mouth_open": 0.0,    # 口を閉じる
        "lip_press": 0.9,     # 唇を圧迫
        "mouth_round": 0.0    # 丸めない
    },
    "に": {  # 「に」音
        "jaw_open": 0.3,      # 少し開く
        "mouth_stretch": 0.6, # やや横に引く
        "tongue_tip_up": 0.8, # 舌先を上げる
        "lip_corner_left_up": 0.3,
        "lip_corner_right_up": 0.3,
    }
}

主要音素の口形パラメータ例

ただし、シンプルだからといって簡単なわけではありません。

音素と口形の例

3.wav2vec がなぜ必要なのか~コンピューターが音を理解するための特徴量~

3.1 音声の「特徴量」とは何か

コンピューターは生の音を理解できない

「こんにちは」という音声をコンピューターに聞かせても、コンピューターにはただの数値の羅列にしか見えません

# 「こんにちは」の生音声データ(16kHz、1秒間)
raw_audio = [0.001, -0.002, 0.003, -0.001, 0.004, -0.002, ...]
# ↑ 16,000個の細かい数値が並んでいるだけ

# コンピューターから見ると:
「これは何の意味があるの?どこが「こ」でどこが「ん」?」

人間なら「ああ、挨拶の言葉だな」と瞬時に理解できますが、コンピューターには音の意味がわかりません。

特徴量=「意味のある情報」への変換

特徴量とは、生データを「コンピューターが理解しやすく、かつ意味のある形に変換したものです

# 生音声 → 特徴量への変換
raw_audio = [0.001, -0.002, 0.003, ...]  # 意味不明な数値列
↓ 特徴量抽出
meaningful_features = [0.8, -0.2, 0.5, ...]  # 意味のある表現

# 特徴量の各数値が意味を持つ:
# 0.8 → 「母音っぽさ」の強さ
# -0.2 → 「高周波成分」の少なさ  
# 0.5 → 「後ろ舌音」の程度

3.2 なぜ特徴量が必要なのか~人間の例で理解しよう~

人間が「こんにちは」を理解する過程

人間の脳も実は特徴抽出をしています

【人間の音声理解プロセス】

1. 耳で音波をキャッチ
   ↓
2. 「低い音」「高い音」「継続時間」などを抽出
   ↓  
3. 「これは母音」「これは子音」と分類
   ↓
4. 「こ-ん-に-ち-は」と音韻を認識
   ↓
5. 「挨拶の言葉だ」と意味を理解

コンピューターも同じことをしたいのですが、人間のような直感的理解ができないため、数学的な特徴量が必要だよね、というわけです。

3.3 従来の方式(MFCC)の問題点

さて、せっかくなので、この音声特徴量の歴史について少しだけふれて理解を深めてみましょう。

MFCCの根本的限界

従来、音声認識やリップシンクには 「メル周波数ケプストラム係数」=MFCC(Mel-frequency Cepstral Coefficients)が広く使われていました。しかし、MFCCにはいろいろと不都合がありました。

クラシック、といっても数年前までの音声信号処理を学んできた方には非常にメジャーな特徴量で音声信号処理や音声認識といったら「メルスペクトル」とか「メル周波数ケプストラム係数(MFCC)」は聞き覚えがあるはずです。

「信号波形じゃ音声の特徴はわからん、メルスペクトルで分析するんじゃ!」とみんな口々にいっていましたが、今にしてみればメルスペクトルでも、思ってみれば、あんまりよくわからなかったですなぁ、ということで技術の進歩というのはすごいですね。

さて、昔話はおいておいてMFCCは以下のような処理フローをとります。

【MFCCの処理フロー】
生音声 → フーリエ変換 → メルフィルタバンク → 対数変換 → DCT → MFCC係数

MFCCの問題点

さて、MFCCには以下のような問題がありました。(もちろん当時はそれしかないので、問題としてあんまり認識していませんでした。コロンブスのゆで卵というか、技術もサイエンスもそういうものですよね)

  1. 手工芸的特徴量
    ⇒人間の聴覚、聞こえ方にもとづいており、人間が恣意的に設計した固定的な特徴抽出
  2. 音韻の意味は理解しない
    ⇒単純な周波数分析
  3. 文脈情報の欠如
    ⇒フレーム単位の独立処理
  4. 個人差への対応不足
    ⇒話者に依存しやすい傾向

具体的な例

ディープラーニング以前または黎明期で音声認識をこの古い手法でやっていたとき以下のようなことがおこっていました

①調音位置の類似性を捉えられない

「か」と「が」:
- 物理的に同じ調音位置(軟口蓋)
- 口の形もほぼ同じ
- MFCCでは: 全く異なる特徴ベクトル
- ゆえに、、、モデルが「か」と「が」の類似性を学習できない

②文脈による音韻変化を無視

「ん」の発音:
- 「かん」の「ん」→ 口を完全に閉じる
- 「かんぱい」の「ん」→ 次の「ぱ」に備えて半開き
- MFCCでは: どちらも同じ「ん」として処理
- ゆえに、、、文脈を考慮しない不自然な口の動き

③話者の差への脆弱性

同じ「あ」でも:
- 男性(低い基本周波数): MFCC = [1.2, -0.5, 0.8, ...]
- 女性(高い基本周波数): MFCC = [2.1, -1.2, 1.5, ...]
- ゆえに、、、性別が変わると全く違う口の動きを予測

そこで、満を持して登場したのが wav2vec です

その名の通り、wav(音声信号)をvec(ベクトル)にしてやろうという代物です。

ざっくりいうとあの有名なword2vec と同じような考え方です

3.4Wav2Vecの革新的アプローチ

wav2vecとは具体的には、MetaAI(旧Facebook AI)が開発したニューラルネットワークベースの音声特徴抽出モデル※2です。

自己教師あり学習による音韻理解

wav2vecは何がすごいのでしょうか。

それは
wav2vecは「音韻の意味を理解する」ことです

技術的には、wav2vecはCNNエンコーダーで生音声から局所的な音響パターンを抽出し、その後Transformerエンコーダーで音韻の文脈的関係を理解して、最終的に768次元※3の特徴ベクトルを出力します。この処理により、単なる音響情報ではなく、音韻の意味的情報を含んだ豊かな表現を獲得できる 「音の意味を理解する特徴抽出器」になりました。

※現在は wav2vec 2.0が主流です。

  • ※3 Base modelで768次元、Large modelで1024次元です

データ駆動の特徴学習

wav2vecの最大の革新は、MFCCのように人間が設計した固定的な変換ではなく、ニューラルネットワークがデータから最適な特徴抽出方法を学習する点です。CNNエンコーダーは生音声から最適な音響特徴抽出方法を学習し、Transformerエンコーダーは音韻間の関係を理解して最適な文脈統合方法を獲得します

この学習プロセスにより、MFCCでは表現できなかった複雑で非線形な音韻関係を捉えることが可能になり、また、学習データや学習目標を変更することで、特定のタスクに最適化された特徴表現を獲得することもできます

音韻的類似性の獲得

wav2vecは大量の音声データを使った自己教師学習により、音韻の意味的関係を理解します。マスク言語モデルと同様の手法で、音声の一部をマスクして予測するタスクを通じて、音韻間の類似性や関係性も自動的に発見できます。結果として、言語学的に類似した音素は特徴空間上でも近い位置に配置されます。「か」と「が」のような調音位置が同じ音素は高いコサイン類似度を持ち、「か」と「あ」のような全く異なる音素は低い類似度となります。この音韻的類似性の獲得により、学習効率が大幅に向上し、未知の音韻組み合わせに対する汎化性能も向上します。このような特徴はword2vecとも似ていますね。

話者不変表現の学習

Wav2Vecは学習時に多様な話者の音声を使用することで、話者固有の特徴(基本周波数、フォルマント周波数など)に依存しない音韻表現を獲得します。学習目標は「異なる話者の同じ音素を同じ特徴ベクトルにマップする」ことであり、これにより話者不変性が実現されます。

結果として、男性・女性・子供・高齢者など、様々な話者が同じ音素を発音した場合でも、wav2vecは類似した特徴ベクトルを出力します。この話者ロバスト性により、少ない学習データでも多様な話者に対応できるリップシンクシステムの構築が可能になります。

4. 言語別学習によるwav2vec特徴量抽出器の最適化

wav2vecの基本モデルは多言語対応可能ですが、リップシンクのような高精度が要求されるタスクでは、言語固有の音韻体系に特化した特徴量抽出器を構築することで、さらなる精度向上が期待できます。

なぜ言語別学習が重要なのか

各言語は独自の音韻体系を持っています。例えば日本語は5つの母音(あいうえお)で構成されるシンプルな体系ですが、英語は15以上の母音を持ち、さらに複雑な子音の組み合わせ("street"の"str"など)が存在します。

日本語特有の現象として、「ん」の発音は後続する音によって大きく変化します。「さんぽ」の「ん」は唇を閉じますが、「さんか」の「ん」は口を開けたままです。また、「っ」(促音)や「ー」(長音)といった特殊音素も日本語独自のものです。

汎用的なwav2vecモデルは、これらすべての言語の特徴を「平均的に」学習しているため、特定言語の細かな特徴を見逃してしまう可能性があります。それはちょうど、「全世界の料理を作れるシェフ」と「日本料理専門の板前」の違いのようなものです。リップシンクという繊細な作業には、その言語の「専門家」が必要なのです。

言語別学習がもたらす具体的な効果

日本語に特化したwav2vecモデルを学習すると、驚くべき精度向上が見られます。この精度向上は、リップシンクの品質に直接的に反映されます。日本語特化モデルは「こんにちは」の「ん」と「こんばんは」の「ん」の微妙な口形の違いを正確に捉え、より自然な口の動きを生成できるようになります。

英語特化モデルの場合は、"think"の"th"のような日本語にない音素での舌の位置や、子音が連続する際の唇の複雑な動きを正確に予測できるようになります。中国語特化モデルでは、同じ音でも声調によって変わる微妙な口形の違いまで識別可能になります。

実際の学習プロセス

言語別のwav2vec学習には、その言語の大規模な音声データセットが必要です。日本語の場合、数百時間~数千時間単位の音声データを使用し、様々な年齢・性別・方言の話者を含めることが重要です。多様なジャンルを含め、すべての音素が均等に現れるようにバランスを取ります。

まとめ

wav2vecは単なる「新しい特徴抽出法」ではなく、「音韻の意味を理解する人工知能」として位置づけてもよいでしょう。

MFCCが人間の考えた音の分析方法に基づいて周波数分布パターンのみを扱うのに対し、wav2vecはAIが発見した音の理解方法により、音韻の意味的関係と文脈を深く理解します。

この技術革新により、従来のMFCCベースシステムではできそうもなかった高精度・リアリティの高いリップシンクの実現が見込めます。

また、言語別に学習したwav2vec特徴量抽出器を使用することで

  1. その言語特有の音韻現象を正確に捉えることができ
  2. 文脈に応じた細かな音の変化を識別でき
  3. 結果として、より自然で正確なリップシンクが実現できます

特に日本語のような、文脈による音韻変化が豊富な言語では、言語特化型のwav2vecモデルの使用が、リップシンクの品質を大きく左右します。

今後は、リップシンクのドリフト制御、wav2vecでとらえた特徴量をもとに、実際に発話とリップシンクの対応関係を学習していく手順など、順次解説予定です。

それではまた次回お会いしましょう!

Read more

NVIDIA GeForce RTX 50xx with CUDA capability sm_120 is not compatible with the current PyTorch installation. が発生したとき

NVIDIA GeForce RTX 50xx with CUDA capability sm_120 is not compatible with the current PyTorch installation. が発生したとき

こんにちは、PyTorch 2.6.0 環境で以下のような問題が発生したときの対処方法について解説いたします。 NVIDIA GeForce RTX 5090 with CUDA capability sm_120 is not compatible with the current PyTorch installation. The current PyTorch install supports CUDA capabilities sm_50 sm_60 sm_70 sm_75 sm_80 sm_86 sm_90. 他のBlackwell GeForce の場合は以下のようなメッセージとなります。 NVIDIA GeForce RTX

By Qualiteg プロダクト開発部
OpenCV cv2.imwrite で発生する「_img.empty()」エラーと「動画安定化」による解決法

OpenCV cv2.imwrite で発生する「_img.empty()」エラーと「動画安定化」による解決法

こんにちは! 画像処理や動画解析の現場で広く利用されている OpenCV。 しかし実務で動画処理を行っていると、時折以下のようなエラーに遭遇することがあります。 cv2.error: OpenCV(4.11.0) /io/opencv/modules/imgcodecs/src/loadsave.cpp:929: error: (-215:Assertion failed) !_img.empty() in function 'imwrite' このエラーは、cv2.imwrite() に渡された画像が空(None またはサイズ0) の場合に発生します。 一見単純に見える問題ですが、背後には「入力動画の不安定さ」や「並列処理の競合」といった要因が潜んでいることが少なくありません。 本記事では、このエラーの発生原因を掘り下げ、実務で効果のある解決策として 「動画の安定化(正規化)」 を紹介します。 TL;

By Qualiteg プロダクト開発部
発話音声からリアルなリップシンクを生成する技術 第5回(前編):Transformerの実装と実践的な技術選択

発話音声からリアルなリップシンクを生成する技術 第5回(前編):Transformerの実装と実践的な技術選択

こんにちは!リップシンク技術シリーズもいよいよ終盤となりました。 前回(第4回)では、LSTMの学習プロセスと限界について詳しく解説しました。限られたデータでも効果的に学習できるLSTMの強みを理解する一方で、長距離依存の処理に限界があることも明らかになりました。そして、この問題を解決する革新的なアプローチとして、すべての位置の情報を同時に参照できるTransformerのSelf-Attention機構を紹介しました。 第5回の今回は、 Transformerの具体的なネットワーク設計から始め、その実装上の課題を明らかにします。(前編※) そして、LSTMとTransformerの長所を組み合わせたハイブリッドアプローチを紹介し、実際の製品開発における技術選択の指針を示します。最後に、感情表現への拡張という次なる挑戦についても触れていきます。(後編※) ※Transformerの仕組みは複雑であるため、第5回は前編と後編に分けて解説させていただく予定です。 1. Transformerベースのネットワーク設計 1.1 全体アーキテクチャ図 では、さっそく、Tran

By Qualiteg 研究部, Qualiteg コンサルティング
大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第2回 ドメイン環境の構築

大企業のAIセキュリティを支える基盤技術 - 今こそ理解するActive Directory 第2回 ドメイン環境の構築

こんにちは、今回はシリーズ第2回ドメイン環境の構築 - 検証環境の構築手順について解説いたします! 連載の構成 第1章:基本概念の理解 - Active DirectoryとKerberos/NTLM認証の基礎 【★今回です★】第2章:ドメイン環境の構築 - 検証環境の構築手順 第3章:クライアントとサーバーのドメイン参加 - ドメイン参加の詳細手順 第4章:プロキシサーバーと統合Windows認証 第5章:ブラウザ設定と認証 - 各ブラウザでの設定方法 第6章:トラブルシューティング - よくある問題と解決方法 第7章:セキュリティとベストプラクティス - 本番環境での考慮事項 第8章:実践的な構成例 - AIセキュリティツールとの統合事例 第2章:ドメイン環境の構築 2.1 ドメイン名の設計 2.1.1 ドメイン名の命名規則 Active Directoryを構築する際、

By Qualiteg コンサルティング