LoginSignup
12
4
お題は不問!Qiita Engineer Festa 2023で記事投稿!

【Unity】Unity上でYoutubeの指定動画のサムネイルをとってくる方法【Youtube】

Posted at

TL;DR

  • Youtubeにはサムネ取得用URLがあるのでそこにパラメータを入れれば入手可能
  • UnityはデフォルトではHTTPリクエストは禁止しているのでHTTPSに変更するかセキュリティリスクを背負ってHTTPリクエストを有効化しよう

概要

ひょんなことから仕事で UnityでYoutube の動画を再生したいけど、再生リストを作れないか? と言われたのでまずはサムネイルを取得できないと話にならんと思い調査した記録になります。

制作環境

項目 説明
Unity 2022LTS
UniTask 2.3.3

手順

  1. Youtubeの対象の動画のURLを取得
  2. URLから動画IDを抽出
  3. サムネイルの品質を選択
  4. サムネイル取得用URLの生成
  5. UnityWebRequest経由でサムネイルをとりにいく
  6. [Optional] UIで表示

という手順になります。

1. Youtubeの対象の動画のURLを取得

https://www.youtube.com/watch?v=動画 ID というフォーマットで取得しましょう。
こちらは手入力でもいいし、コピペでも良いです。

ただし、再生リストの情報などは不必要なのでカットしましょう。

2. URLから動画IDを抽出

先ほどのフォーマットであれば = より後ろがあれば十分なので、以下のようにすればとってこれるはずです。

GetID.cs

public string GetId(string url)
{
    string[] urls = url.Split("=");
    if (urls.Length != 2)
    {
       return null;
    }
    return urls[urls.Length -1];
}

3. サムネイルの品質を選択

品質は 標準, , , HQ, FullHD` の5択です。
また、それぞれに紐づくファイル名も決まっています。

品質 ファイル名
標準 default.jpg
mqdefault.jpg
hqdefault.jpg
HQ sddefault.jpg
FullHD maxresdefault.jpg

HQなのにhqdefault.jpg じゃないのかよ!っていうツッコミはなしです

とりまとめると、以下のように定義しておくと良いでしょう。

quality.cs

    private static readonly string[] FILENAMES = new string[]
    {
        "default.jpg",
        "mqdefault.jpg",
        "hqdefault.jpg",
        "sddefault.jpg",
        "maxresdefault.jpg",
    };
    
    public enum Quality
    {
        Default,
        Mid,
        High,
        HQ,
        FHD
    }

4. サムネイル取得用URLの生成

こちらのブログでも紹介されている通りで、 http://img.youtube.com/vi/動画ID/画像サイズ , https://img.youtube.com/vi/動画ID/画像サイズ いずれかのURLで取得することが出来ます。

5. UnityWebRequest経由でサムネイルをとりにいく

普通に UnityWebRequest.GetTexture を利用しましょう。

また、今回は最近の時流にのっかり Async/Await で書いてみるので UniTask を利用しましょう。

GetThumbnail.cs

    public void OnSubmit()
    {
        if (cts != null)
        {
            cts.Cancel();
            cts.Dispose();
        }

        cts = new CancellationTokenSource();
        GetThumbnailAsync(m_url.text, currentQuality, cts.Token).Forget(e=> Debug.LogError(e));
        
    }

    private async UniTask GetThumbnailAsync(string url, Quality quality, CancellationToken token)
    {
        string thumbnail_url = string.Empty;
        try
        {
            string youtubeId = string.Empty;
            if (url.Contains("watch?v="))
            {
                string[] urls = url.Split("=");
                if (urls.Length != 2)
                {
                    throw new Exception("Invalid URL:" + url);
                }

                youtubeId = urls[1];
            }
            else
            {
                string[] urls = url.Split("/");
                youtubeId = urls[urls.Length - 1];
            }
            if(string.IsNullOrEmpty(youtubeId))throw new Exception("Invalid youtubeId:" + youtubeId);

            thumbnail_url = $"https://img.youtube.com/vi/{youtubeId}/{FILENAMES[(int)quality]}";

            Debug.Log("Try Download Thumbnail:"+thumbnail_url);
            
            var www = UnityWebRequestTexture.GetTexture(thumbnail_url);

            await www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
            {
                Texture2D texture = DownloadHandlerTexture.GetContent(www);
                if (m_thumbnail[(int)quality].texture != null)
                {
                    var prev = m_thumbnail[(int)quality].texture;
                    m_thumbnail[(int)quality].texture = null;
                    Destroy(prev);
                }
                m_thumbnail[(int)quality].texture = texture;
            }
            else
            {
                Debug.LogError("Failed to download texture: " + www.error);
            }
        }
        catch (OperationCanceledException e)
        {
            Debug.LogWarning($"Operation was canceled. (URL:{thumbnail_url})");
        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
    }

つまづいたところ

素直に技術ブログ通りに http リクエストを行ったところ以下のエラーがおきました。

InvalidOperationException: Insecure connection not allowed

調べたところ以下の記事が大変参考になりました。

ざっくり言うと、HTTPはセキュリティ的に危ないからデフォルトでNGにしてるので、PlayerSettingsから有効化するときは自前でリスクを負ってね! というものです。

6. [Optional] UIで表示

今回はUI上にRawImage を用意して、それぞれのサイズで表示できるようにしました。
なお、RawImage で差し替える時は先ほどのコードにあるように、前のTextureはDestroyで破棄するようにしておかないとメモリリークを引き起こすためご注意ください。

NotMemoryLeak.cs

                if (m_thumbnail[(int)quality].texture != null)
                {
                    var prev = m_thumbnail[(int)quality].texture;
                    m_thumbnail[(int)quality].texture = null;
                    Destroy(prev);
                }

動作チェック

動画は以前、私が登壇した時の録画を利用します。

なお、上記動画の文字起こし版の記事もあるのでぜひよろしくお願いします。

GetThumbnail.gif

リポジトリ

今回作ったUnityプロジェクトはこちらで公開しています。

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4