UnityでYoutubeの動画を再生する
はじめに
Youtube、言わずと知れた動画サイトで、あらゆる動画コンテンツがあります。
そして、UnityでYoutubeの動画を再生できれば、自分で色々な機能を追加できると思われます。
データとして取れれば、Unity内で編集してMAD動画をつくれたり、ゲーム内で使えたり、バーチャル空間で再生なんかもできます!
夢がひろがりますね!
もちろん著作権など諸々の話はあるので注意が必要です。
※自己責任でお願いします!
注意点
Youtubeは動画のダウンロードを禁止しています。注意を払って実装しなければいけません。
www.youtube.com
なので、今回は「いったんデータを取得して、Unityの実行を終了したらそのデータを消す」という実装にしています。
また、UnityEditor上でしか動作しない実装になっています。
動作環境
OS : Windows10
Unityバージョン : 2018.3.7f1
VideoLibrary : 2.0.3
制作フロー
VideoLibraryをUnityに組み込む
Youtubeの動画を再生するためには、とにかくデータを取得する手段が必要です。
「VideoLibrary」というYoutubeの動画を取得できるNuGetパッケージがあるので、それを使用します。
www.nuget.org
UnityでNugetパッケージを使用する方法として以下のページを参考にしました。
qiita.com
VideoLibraryを使って動画データの取得
各種パッケージ
using System; //NonSerializedなど using System.IO; //入出力 using VideoLibrary; //Youtubeデータ取得 using System.Threading.Tasks; //非同期処理 using UnityEngine.Video; //動画再生 using UnityEditor; //アセット操作
動画情報取得からの動画取得
private string uri = "Youtubeの動画のURI"; [NonSerialized] public string movieTitle; [NonSerialized] public string moviePath; private async void Start () { var v = await GetVideoInforationAsync(uri); if(v == null) return; if(!(IsFormatSupport(v.FileExtension))) return; movieTitle = v.FullName; moviePath = Application.dataPath + @"/Movies/" + movieTitle; if(IsFileExist(moviePath)) return; var t = await DownLoadMovieFromYoutubeAsync(v); if(t == null) return; File.WriteAllBytes(moviePath,t); AssetDatabase.Refresh(); }
それぞれのフェーズでデータが取れているかをチェックしていきます。どこかで不具合があれば動画を取得しないようにします。
(1)URIから動画の情報を取得。
private async Task<YouTubeVideo> GetVideoInforationAsync (string uri) { try { var youTube = YouTube.Default; var video = await youTube.GetVideoAsync(uri); Debug.Log("動画情報を取得しました。"); return video; } catch(Exception e) { Debug.Log("動画情報取得時にエラーが発生しました。:" + e); return null; } }
(2)Unityに対応している動画のフォーマットはあらかじめ決まっているので、チェック。
private bool IsFormatSupport (string fileExtention) { string[] supportFormat = { ".asf",".avi",".dv",".m4v",".mov",".mp4",".mpg",".mpeg",".ogv",".vp8",".webm",".wmv" }; for(int i = 0;i < supportFormat.Length;i++) { if(fileExtention.Equals(supportFormat[i])) { return true; } } Debug.Log("対応していない動画フォーマットです:" + fileExtention); return false; }
対応フォーマットは以下のページに書いてあります。OSごとに対応するファイルが違うので注意です。
docs.unity3d.com
(3)Unity内に取得済動画があるかどうかチェック。
private bool IsFileExist (string path) { if(File.Exists(path)) { Debug.Log("ファイルが存在します。"); return true; } return false; }
(4)動画のデータを取得。
private async Task<byte[]> DownLoadMovieFromYoutubeAsync (YouTubeVideo y) { try { if(!y.IsEncrypted) { Debug.Log("動画の再生準備中です。少しお待ちください。"); byte[] bytes = await y.GetBytesAsync(); Debug.Log("完了しました!"); return bytes; } else { Debug.Log("再生できない動画です。"); return null; } } catch(Exception e) { Debug.Log("動画再生準備時にエラーが発生しました。:" + e); return null; } }
IsEncryptedで暗号化されて取得できない動画をはじきます。
(5)動画データを一時的に保存。
File.WriteAllBytes()を使用します。
(6)動画データをUnityにアセットとして認識させる。
AssetDatabase.Reflesh()を使用します。
tofgame.hatenablog.com
ここまでで動画のデータの準備ができました!
あとは画面に映すだけです。
動画の再生
private VideoPlayer videoPlayer; private VideoClip videoClip; private bool moviePlayFlag; private void Awake(){ videoPlayer = GetComponent<VideoPlayer>(); } private void Update () { if(!moviePlayFlag) { videoClip = AssetDatabase.LoadAssetAtPath(@"Assets/Movies/" + movieTitle,typeof(VideoClip)) as VideoClip; if(!IsFileExist(moviePath) || videoClip == null) return; videoPlayer.clip = videoClip; Debug.Log(videoPlayer.clip); videoPlayer.Play(); moviePlayFlag = true; } }
VideoPlayerを使用して動画を表示します。
docs.unity3d.com
動画データが取得でき次第VideoClipにして再生します。(雑な実装)
動画データの後始末
private void OnApplicationQuit () { videoPlayer.clip = null; if(IsFileExist(moviePath)) { File.Delete(moviePath); Debug.Log("動画ファイルを削除しました。"); } if(IsFileExist(moviePath + ".meta")) { File.Delete(moviePath + ".meta"); Debug.Log("メタファイルを削除しました。"); } AssetDatabase.Refresh(); }
Unityの実行を止めるタイミングで残っている動画データを削除します。
metaファイルも生成されているので、それも削除。
ゲームオブジェクトの設定
作成したスクリプトとVideoPlayerをアタッチします。
スクリプトはMovieManagerなり、お好きな名前にしてください。
VideoPlayerのAspect Ratioは「Fit Inside」がおすすめです。
終わりに
再生までできたので、シークバー、検索機能、簡単MAD作成機能など、思い付きで機能追加していきます。