録音した音声ファイルからリップシンクを行う

#はじめに
リップシンクにはOVRLipsyncを用います。本来、マイクの入力からによるリアルタイムリップシンクが想定されていますが、既に録音してある音声ファイルからリップシンクを行うようにします。
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="cy" dir="ltr">© Unity Technologies Japan/UCL <a href="https://t.co/28ZyTnVpVh">pic.twitter.com/28ZyTnVpVh</a></p>&mdash; かいき (@kaikiofkaiki) <a href="https://twitter.com/kaikiofkaiki/status/1107231184545697792?ref_src=twsrc%5Etfw">March 17, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

記事中にある僕の書いたソースコードはパブリックドメインとします。

#使い時
**歌のMV収録なんかするときに便利**です。毎回歌わないで済みます。
また、直接音声を流し込めるのでリップシンクの動作テストにおいても便利です。**声質によってリップシンクの値は変わるので、ちゃんと本人の声でパラメータ調整をしましょう**。

#動作環境
 - Windows10
 - Unity2017.4.12f1
 - [OVRLipsync ver1.30](https://developer.oculus.com/downloads/package/oculus-lipsync-unity/)

#セットアップ
##1.OVRLipsyncセットアップ
何らかのモデルを配置し、OVRLipsyncが正常に動作するようにします。こちらのセットアップにおいては[「Unity でリップシンクができる OVRLipSync を試してみた」](http://tips.hecomi.com/entry/2016/02/16/202634)がとても参考になります。
セットアップが終了し、以下のように`AudioSource`,`OVRLipSync`,`OVRLipSyncContextMorphTarget`,`OVRLipSyncContext`,`OVRLipSyncMicInput`のコンポーネントがシーン内存在しているとして進めていきます。本記事のモデルと音声ファイルは、[ユニティちゃん](http://unity-chan.com/)に含まれるものを利用しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140271/2c92bb30-e8db-1c2e-91c6-d8f7261b6ca7.png)

##2.マイク無効化
`OVRLipSyncMicInput`がマイクの入力を受け取り、その音声をAudioSourceに渡します。今回はマイク入力が必要ではないので、この`OVRLipSyncMicInput`を非アクティブにしてしまうか、コンポーネントから外します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140271/7a9bc93a-c851-f0b8-55da-0965f7f2b031.png)

##3.AudioSourceに音声セット
AudioSourceのAudioClipにリップシンクをさせたい音声ファイルをセットします。

![キャプチャ2.png](https://qiita-image-store.s3.amazonaws.com/0/140271/b1fc1373-9549-f137-a362-475dafb9a16f.png)

以上です。これで再生すると音声ファイルからリップシンクが行われます。


##4.拡張：スライダーで自由タイミング再生
セリフ一部分だけとか、Aメロ部分だけ再生したいとかあるので、スライダーで好きなタイミングから再生できるものも作りました。以下がソースコードです。

```c#:AudioController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioController : MonoBehaviour {

	public AudioSource audioSource;
	public float AudioTimeNow = 0.0f;
	public float AudioFullLength;
	public bool Stop = false;
	private AudioClip audioClip;

	void Start () {
		if(!audioSource){
			Debug.LogWarning("AudioSourceがセットされていません");
			return;
		}
		if(!audioSource.clip){
			Debug.LogWarning("AudioClipがセットされていません");
			return;
		}
		audioClip = audioSource.clip;
		AudioFullLength = audioClip.length;
	}
	
	void Update () {
		if(!audioSource){
			Debug.LogWarning("AudioSourceがセットされていません");
			return;
		}
		if(Stop){
			if(audioSource.isPlaying){
				audioSource.Pause();
			}
			return;
		}else{
			if(!audioSource.isPlaying){
				audioSource.UnPause();
			}
		}
		AudioTimeNow = audioSource.time;
	}

	private void OnValidate(){
		audioSource.time = AudioTimeNow;
	}
}
```
```c#:AudioControllerEditor.cs
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(AudioController))]
public class AudioControllerEditor : Editor {

	public override void OnInspectorGUI()
    {
        var audioController = target as AudioController;
		// -- 再生時間 --
		EditorGUILayout.LabelField( "再生時間(最小/現在時間/最大)" );
		EditorGUILayout.BeginHorizontal();
		EditorGUILayout.FloatField(0, GUILayout.Width(48) );
		audioController.audioSource.time = EditorGUILayout.Slider(audioController.audioSource.time, 0f, audioController.AudioFullLength);
		EditorGUILayout.FloatField(audioController.AudioFullLength, GUILayout.Width(48) );
		EditorGUILayout.EndHorizontal();
		// -- 	一時停止 --
		EditorGUILayout.LabelField( "一時停止" );
		audioController.Stop = EditorGUILayout.Toggle(audioController.Stop);
    }
}
```

上記のスクリプトを作成し、アタッチすることで以下の動画のように音声を早送りしたり途中から始めたりできるようになります。
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="cy" dir="ltr">© Unity Technologies Japan/UCL <a href="https://t.co/uLO0hjSnfc">pic.twitter.com/uLO0hjSnfc</a></p>&mdash; かいき (@kaikiofkaiki) <a href="https://twitter.com/kaikiofkaiki/status/1107276168531595264?ref_src=twsrc%5Etfw">March 17, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>





#注意
OVRLipsyncは機械学習ベースで動いているため、音声に雑音が混ざっていると反応が悪くなります。なので、歌も楽器や曲の音が入っているとリップシンクの精度が著しく落ちてしまいます。**歌のみの音源も録音しておき、リップシンクにはそちらの音源を利用しましょう**。

"OVRLipSyncContext"のAudioLoopBackをアクティブにすると再生音声が聞こえるようになります。こちらをアクティブにしておくとリップシンクの確認が行いやすいです。

"AudioSource"のPlayOnAwakeがアクティブになっているとUnity再生時に自動で音も再生されます。音が鳴らない時もこちらを確認すると良いでしょう。



![imageLicenseLogo.png](https://qiita-image-store.s3.amazonaws.com/0/140271/02e29e01-283d-c27e-3bf3-3233e164dc4b.png)
本記事はユニティちゃんライセンス条項の元に提供されています