トーフメモ

主にゲーム制作

UnityでYoutubeの動画を再生する

f:id:tofgame:20190428235106j:plain

はじめに

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」がおすすめです。

f:id:tofgame:20190531232724p:plain

実行すると

www.youtube.com

再生されます!やったー!

終わりに

再生までできたので、シークバー、検索機能、簡単MAD作成機能など、思い付きで機能追加していきます。