YouTube Data API v3 を使ってプレイリストを作成する（業務実例付き）

## はじめに
本記事では、Node.js上でYouTube Data API v3を使いプレイリストを一括作成する手順を紹介します。

言語はTypeScript、[Google APIs Node.js Client](https://github.com/googleapis/google-api-nodejs-client)を用います。

https://github.com/googleapis/google-api-nodejs-client

そもそも大量のプレイリストを必要とするケースがどんなものか、さほど明白ではないと思われる[^1]ので、最初に筆者の業務実例を簡単に触れておきます。（記事本文に進みたい方は[こちら](#環境)）

[^1]:日本語で書かれたYouTube Data API v3に関する過去記事を見ても「プレイリストへの動画の追加」を扱ったものはあっても、プレイリスト自体を作る記事は管見の限りありませんでした。
---

#### 業務実例　〜コンクールでの動画審査
[全日本ピアノ指導者協会（ピティナ）](https://qiita.com/organizations/piano)は国内最大規模のコンクール、ピティナ・ピアノコンペティション[^2]を運営しています。

[^2]:最高賞の「特級グランプリ」には、今をときめくCateenこと角野隼斗さんや、ロン＝ティボー国際音楽コンクール第１位の亀井聖矢さんらが名を連ねています。

ピティナ・ピアノコンペティションでは新型コロナウイルスを契機に、2020年度より「特級」ほか上位の部門（級）で「動画審査」を導入しました。

**動画審査の応募動画の一例（2022年度：特級グランプリ 北村 明日人さん）**
<iframe width="560" height="315" src="https://www.youtube.com/embed/0jpJ-GJ7n-g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<caption></caption>

コンクールは通常、1時間〜1時間30分を1グループとして、上位級では**1日に5~6つのグループ**を審査します。これが複数の級で何日かにわたって行われます。

動画審査でも同様の形式となりますが、審査の便宜をはかり、各グループごとに再生リストを用意することになりました。

こうして、「「2022特級一次A 1グループ」といったプレイリストを、2020年度は56、2021年度は92、2022年度は68、作成する必要が生じました。加えて、再生リストは **限定公開（unlisted）** でなければいけません。

:::note 
**目標**
動画審査用に限定公開で大量のプレイリストを作成する。

**例**
 「2022特級一次A 1グループ」「2022特級一次A 2グループ」...「2022特級一次A 6グループ」…「2022特級一次D 6グループ」
「2022Pre特級一次A 1グループ」...
「2022G級A 1グループ」...
:::

---

## 環境
- Node.js
  - v. 18.16.1
  - Voltaでのバージョン管理。
- macOS Ventura 13.4.1 

Voltaを使ったNode.jsの導入については本記事では扱いません。

**参考**
https://qiita.com/KokiSakano/items/1bfcad79a0ba5e549186

## 想定読者
- YouTube Data API v3を活用したい方
  - 非エンジニアの方も念頭に、作業ステップを細かめに記述しています。 
- Google Cloud Platformのアカウント作成済みの方
- YouTube Data APIでプレイリストを作りたい方
  - YouTube Data APIについての概論は省きます。 

## Node.jsプロジェクトの準備
VSCode等のエディタを開き、プロジェクトを作ります。

```sh
node -v
v18.16.1

mkdir <Your Project Name>
cd <Your Project Name>
npm init -y
```

`package.json`を下記に書き換え、`npm install`を行い、依存パッケージをインストールします。

```package.json
{
  "name": "<your project name>",
  "version": "1.0.0",
  "description": "create playlist using YouTube Data API v3",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@google-cloud/local-auth": "^2.1.1",
    "googleapis": "^118.0.0"
  },
  "devDependencies": {
    "@types/node": "^20.3.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.1.3"
  }
}
```

加えて、認証情報を保管する`secrets`ディレクトリを作成します。
git管理する場合`secrets`はgitignoreすることを忘れずに。

:::note
📦your_project
 ┣ 📂node_modules
 ┣ 📂secrets
 ┣ 📜package-lock.json
 ┗ 📜package.json
:::

## YouTube Data APIの準備 〜 認証用JSONの作成
最初にYouTube API Data API v3の設定〜実装を行います。認証用のJSONデータをローカルにダウンロードするのが目標です。この辺りは別記事も数多くありますので参照してください。

### Google Cloud Platformで新規プロジェクト作成
[GCP](https://console.cloud.google.com)にアクセスし、新規プロジェクトを作成します。

### YouTube Data API v3を有効化

| 検索窓よりMarketPlaceへ | 有効化 |
|:-------:|:-------:|
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/ac95c219-32cc-e8ac-d860-c4cd19e92665.png)   | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/c89a24d6-297e-63ac-3329-8897d134f860.png)  |

### 認証情報へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/65472484-8346-b785-cc54-34f45ac879f2.png)

### OAuthクライアントIDを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/3d119903-3e0b-7482-81db-968c2565323b.png)

 「承認済みのリダイレクトURI」 に`http://localhost:3000/oauth2callback`を指定。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/7289068f-b80d-80c2-bb07-27d3b4d3cb11.png)

### 作成完了ダイアログから「JSONをダウンロード」。
  - 先ほど作成したNode.jsプロジェクトの`secrets`配下に`oauth2.keys.json`として保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/838c5d50-2427-8476-1f90-b8177f3cadd4.png)

### 「OAuth同意画面」でテストユーザーを追加する
  - 下記の「テストユーザー」の項よりテストユーザーとしてチャンネルオーナーのgmailアドレスを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/359cdc6b-534a-8e7c-1f0c-f862838754e8.png)

:::note
📦your_project
 ┣ 📂node_modules
 ┣ 📂secrets
 ┃ ┗ 📜oauth2.keys.json
 ┣ 📜package-lock.json
 ┗ 📜package.json
:::


## コードを書く
`createPlayList.ts`を作成します。

```ts:createPlayList.ts 
import { google } from "googleapis";
import path from "path";
import { authenticate } from "@google-cloud/local-auth";

const youtube = google.youtube("v3");

// 作成するプレイリスト名を配列で指定する
const playListTitles = ["2023特級一次A 1グループ", "2023特級一次A 2グループ"] 

async function main() {
  const auth = await authenticate({
    keyfilePath: path.join(__dirname, "secrets/oauth2.keys.json"),
    scopes: ["https://www.googleapis.com/auth/youtube"],
  });
  google.options({ auth });

  playListTitles.forEach(title => {
    createPlaylist(title).then(res =>
      console.log(`${res.data.snippet?.title},id:${res.data.id}`)
    )
  }
  )

  console.log("success!")
}

async function createPlaylist(title: string) {
  const res = await youtube.playlists.insert({
    "part": ["snippet", "status"],
    "requestBody": {
      "snippet": {
        title: title
      },
      "status": {
        privacyStatus: "unlisted"
      },
    }
  }
  );
  return res
}

main()
```

「限定公開」指定をするには、`part`にstatusを追加し、status.privacyStatusをunlistedで指定します。

:::note
📦your_project
 ┣ 📂node_modules
 ┣ 📂secrets
 ┃ ┗ 📜oauth2.keys.json.json
 ┣ 📜createPlayList.ts
 ┣ 📜package-lock.json
 ┗ 📜package.json
:::

## 実行
最後にコードを実行します。

コードの実行はts-nodeで行っています。

```sh
ts-node "createPlayList.ts"
```

するとログインプロンプトが表示されます。チャンネルが複数ある場合は、プレイリストを作成したいチャンネルを選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/cc4e1875-12b6-e351-6006-cf4bf47245df.png)

アラートが表示されますが、「詳細」から「＜アプリ名＞に移動」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/74ea8b3d-d717-27e3-7a03-7948035d9151.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2722903/2765c4d2-7be3-fa6f-5f5a-00940a83b82e.png)

アカウント権限の承認を行うと、実行が完了します。

```sh
success!
2023特級一次A 1グループ,id:PLA1PkDYbNMjeRczV_Qj7pfuzjPY-iEg3o
2023特級一次A 2グループ,id:PLA1PkDYbNMjdL9SYfL0-9P9Ayj6i0fFl8
```

:::note warn
##### Quota（使用可能量）について
YouTube Data API v3はデフォルトで10,000 per dayのQuotaがあります。
Quotaの使用量はメソッドによって変わりますが、今回は **50/request**なります。

したがって1日あたり200までAPIでのプレイリスト作成が可能ということになります。

Quota使用量の一覧は下記で確認できます。
https://developers.google.com/youtube/v3/determine_quota_cost?hl=ja
:::

## おわりに
こうして作られたプレイリストによって、コロナ禍での動画審査がスムーズに進みました。
2023年度もホールでの実地審査と合わせ、動画審査も行われます。[^3]

[^3]:コンペティションの最高峰、「特級」では毎年新しいスターが生まれます。最終審査となる8/21の「特級ファイナル」ではサントリホールでオーケストラとの協奏曲が演奏されます。気になった方は[公式Twitter](https://twitter.com/ptna_tokkyu)を覗いてみてください。

「プレイリストを大量に作る」という場面はあまり多くはないかもしれませんが、ピティナでの実例を参考に、身の回りの業務自動化にご活用いただけましたら幸いです。