Spotify Web API を利用してカテゴリーのプレイリストを取得する

Spotify Web APIを利用して「ポップ」や「ロック」など特定のカテゴリーのプレイリストを取得することができる。

指定できるカテゴリーについては、これもSpotify Web APIを利用して一覧を取得することができる。まず、このカテゴリー一覧を取得するコードの例が下記となる。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl --silent' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$params = [
  'country' => 'JP',
  'locale' => 'ja_JP',
  'limit' => 50,
];
$response = $client->get("browse/categories", $params);

foreach ($response['categories']['items'] as $i => $item)
{
  echo "{$item['id']}, {$item['name']}\n";
}

Spotifyのカテゴリー一覧を取得するには、下記URL

https://api.spotify.com/v1/browse/categories

に対してGETリクエストを行えば良い。

オプションのクエリパラメータとして、country パラメータに2文字の国名コードを指定すると、その国向けのカテゴリーを取得することができる。

また、locale パラメータを指定すると、指定した言語でカテゴリー名を得ることができる(カテゴリーによっては指定した言語で取得できないものもある)。ja_JP のように2文字の言語コードと国名コードをアンダースコアで繋げた文字列を指定する。

limit パラメータは、APIレスポンスに含める最大の結果件数を指定するもので、今回のAPIリクエストでは、APIレスポンスに含める最大カテゴリー数に該当する。上記のコードの例では、50 を指定し最大50件のカテゴリーを取得するようにしている。

下記はコードの出力結果。APIレスポンスとして返ってくるデータの categories キー下にある items キーにカテゴリー情報が配列データとして含まれている。この配列データの各要素には id キーと name キーがあり、上記のコードの例では、この値を参照し出力している。id キーと name キーはそれぞれ、カテゴリーID(例:toplists)とカテゴリー名(例:トップリスト)に対応する。


toplists, トップリスト
radar, Early Noise
j_tracks, J-トラック
pop, ポップ
mood, Mood

...省略...

family, キッズ&ファミリー

次に、取得したカテゴリーIDを使って、特定のカテゴリーのプレイリストをリクエストするコードの例が下記。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl --silent' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$categoryId = 'pop';
$params = [
  'country' => 'JP',
];
$response = $client->get("browse/categories/{$categoryId}/playlists", $params);

foreach ($response['playlists']['items'] as $i => $item)
{
  echo "#$i\n";
  echo "name: {$item['name']}\n";
  echo "description: {$item['description']}\n";
  echo "uri: {$item['uri']}\n";
}

特定のカテゴリーのプレイリストを取得するには、下記URL

https://api.spotify.com/v1/browse/categories/{category_id}/playlists

に対してGETリクエストを送信すれば良い。パスのパラメータ category_id にはカテゴリーIDを指定する。

オプションのクエリパラメータとして、country パラメータに2文字の国名コードを指定すると、指定した国向けのプレイリストが得られる。

なお、特定の国向けに特別に存在するカテゴリーIDに対して country パラメータにそれとは違う国名コードを指定するとステータスコードコード 404 が返ってくる。例えば、日本向けに特別に存在するカテゴリーID j_tracks に対して country パラメータに US を指定すると、APIレスポンスのステータスコードとして 404 が返ってきてしまい、結果を得ることができない。無用なエラー処理を省くためには、カテゴリー一覧を取得したときの country パラメータの値とカテゴリーのプレイリストを取得するときの country パラメータの値は同一の国名コードに合わせたほうが無難といえる。

APIレスポンスとして返ってくるデータの playlists キー下にある items キーに指定したカテゴリーのプレイリスト情報が配列データとして入っている。上記のコードの例では、この配列データの各要素にある name キー、description キー、uri キーを参照し、プレイリスト名、プレイリストの説明文、プレイリストのURIを出力している。下記がその出力結果。


#0
name: Top Hits Japan
description: 世界中のトレンドと日本の最新ヒット曲をまとめてお届け。cover: あいみょん
uri: spotify:playlist:37i9dQZF1DXayDMsJG9ZBv
#1
name: Next Up
description: 前週のNew Releaseで大きく注目を浴びた楽曲。 cover: James Blake
uri: spotify:playlist:37i9dQZF1DWZvuOKNcLsjv
#2
name: Spotify Japan 急上昇チャート
description: Spotify Japanのデイリー急上昇チャート。9月17日付。
uri: spotify:playlist:37i9dQZF1DX9vYRBO9gjDe
...

Spotify Web API を利用しておすすめプレイリストを取得する

Spotify Web APIを利用しておすすめプレイリストを取得することができる。このプレイリスト情報は、Spotifyが作成したプレイリストが対象となる(ユーザーが作成したプレイリストは対象外)。このAPIリクエストの特徴として、日時を指定する timestamp パラメータが用意されており、指定した時間や曜日に応じて内容が変わる。

例えば、timestamp パラメータに 2020-09-16T09:00:00 のように朝9時を指定すると通勤や通学時向けのアップテンポな楽曲を集めたプレイリスト情報が得られる。朝だけでなく、昼や夕方、深夜の時間帯を指定すると、その時間帯に合わせたプレイリスト情報になる。また、曜日によっても内容が変わり、例えば土曜日の日時を指定すると「今週の〇〇を…」といったプレイリスト情報が得られる。
※月や季節、年、特定の日付に応じて内容が変わるかどうかは未確認。

下記はSpotify Web APIを利用しておすすめプレイリストを取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl --silent' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$params = [
  'country' => 'JP',
  'timestamp' => '2020-09-16T09:00:00',
];
$response = $client->get('browse/featured-playlists', $params);
var_dump($response);

おすすめプレイリストを取得するAPIリクエストは、下記URLに対して

https://api.spotify.com/v1/browse/featured-playlists

GETリクエストを送信することで実行できる。オプションのクエリパラメータとして、country パラメータに JP を指定すると、日本向けのプレイリスト情報を取得することができる。また、timestampyyyy-MM-ddTHH:mm:ss 形式(ISO 8601)で日時を指定することができ、記事の冒頭で紹介したように、このパラメータにより時間帯や曜日に合わせた情報を得ることができる。

Spotify Web API を利用して関連アーティスト情報を取得する

Spotify Web APIを利用して指定したアーティストに関連するアーティスト情報を取得することができる。関連アーティストというのは、類似するアーティストのことで、Spotifyがコミュニティの視聴履歴データを元に割り出している。また、特定のアーティストに対して、取得できる関連アーティストは最大20アーティストまでとなる。

下記は、関連アーティスト情報を取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$artistId = '64tJ2EAv1R6UaZqc4iOCyj'; // YOASOBI
$response = $client->get("artists/$artistId/related-artists", []);
var_dump($response);

関連アーティスト情報を取得するAPIリクエストは、下記URL

https://api.spotify.com/v1/artists/{id}/related-artists

に対してGETリクエストを行えば良い。このとき、パスのパラメータ id にアーティストIDを指定する。

APIレスポンスとして、指定したアーティストIDに関連するアーティスト情報が返される。その件数は最大で20件までとなる。

また、関連アーティスト情報は、レスポンスデータの artists キーに入っている。

Spotify Web API を利用してアーティストの人気の曲情報を取得する

Spotify Web APIを利用してアーティストの人気の曲情報を取得することができる。取得できるのは、人気度順にソートされた最大10曲から成る曲情報となる。

下記はSpotify Web APIを利用してアーティストの人気曲情報を取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$artistId = '64tJ2EAv1R6UaZqc4iOCyj';
$params = [
  'country' => 'JP'
];
$response = $client->get("artists/$artistId/top-tracks", $params);
var_dump($response);

アーティストの人気曲の情報は、下記URL

https://api.spotify.com/v1/artists/{id}/top-tracks

に対して、パスのパラメータ id にアーティストIDを指定しGETリクエストを送信すれば良い。また、このとき、必須のクエリパラメータとして、country パラメータに2文字の国名コードを指定する必要がある。

APIリクエスト実行後、人気曲の情報はレスポンスデータの tracks キーに配列データ(最大10曲)として保持されている。配列の各データには、曲情報に加え、アルバムとアーティスト情報も含まれている。曲名は name キー、再生可能なMP3形式の曲ファイル(30秒のプレビュー版)へのURLが preview_url キーに保持されている。曲の人気度は popularity キーの値を参照すれば良い。また、アルバムとアーティスト情報は、それぞれ album キーと artists キーに保持されている。

Spotify Web API を利用してランダムにアーティストを選んで情報を取得する方法

Spotify Web APIを利用してランダムにアーティストを選び情報を取得する方法を紹介する。

アーティストをランダムに選ぶAPIリクエストは、Spotify Web APIで直接提供されていないが、検索リクエストを工夫して利用することにより実現することができる。大まかには下記のように行う。

  1. 特定の条件でアーティストを検索するリクエストを行い、結果の総件数を取得する
  2. 結果の総件数の範囲内でランダムな整数を生成し、結果の中からアーティストを選択する

加えて、ランダムな整数を生成する上で、検索リクエスト時のクエリパラメータ offset の値が取り得る範囲を考慮する必要がある。

  • offset: 最小値は 0、最大値は 2000
    • 注意点として、offset の値は limit の値を含めて考える必要がある。limit = 20 のとき、offset の値は、offset = 0offset = 20offset = 40 のように limit の値に応じてインクリメントする必要がある。

特定の条件でアーティストの検索を行い、その結果の総件数が 2000 件内に収まる場合、総件数は offset の取り得る範囲内なので、limit1 にして、offset の値に 0 から 総件数 - 1 の範囲でランダムな整数を設定すれば、APIレスポンスとして返される結果の中から一つのアーティスト情報をランダムに選択できることになる。

検索結果の総件数が 2000 件より大きい場合は、limit の値は 1 のままで良いが、offset の取り得る範囲を超えるので、0 から 1999 の範囲でランダムな整数を生成する他ない。

下記が以上を踏まえて実装したランダムなアーティスト情報を取得するコード。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$params = [
  'q' => 'genre:"j-pop"',
  'type' => 'artist',
  'market' => 'JP',
  'limit' => 1,
];

// まずは、乱数生成に必要な総件数を取得するためにAPIリクエストを行う
$response = $client->get("search", $params);

$n = $response['artists']['total'];
echo "total: $n\n";

if ($n > 0)
{
  // offset に乱数をセットして、結果の中から
  // ランダムにアーティスト情報を取得する
  $params['offset'] = rand(0, min($n - 1, 1999));
  $response = $client->get("search", $params);

  $randomArtist = $response['artists']['items'][0];

  var_dump($randomArtist);
}

検索リクエストは、下記URL

https://api.spotify.com/v1/search

に対して、GETリクエストを行えば良い。このとき、必須のクエリパラメータとして q パラメータと type パラメータを指定する必要がある。

上記のコードでは、q パラメータに genre:"j-pop" を指定しジャンルを限定している。genre:"j-pop" year:2020genre:"j-pop" year:2015-2020 のようにして特定の年や年の範囲を指定することもできる。
q パラメータについての詳細は下記を参照のこと。
Search for an Item | Spotify for Developers

そして、type パラメータに artist を指定している。これによりアーティストを対象に検索を行うことができる。

また、オプションのクエリパラメータとして、marketJP を指定し、日本で利用可能なコンテンツを持つアーティストが対象になるようにしている。

結果のページネーションに利用する limitoffset パラメータは記事の冒頭で説明したように、limit には 1 を設定して、offset には検索結果の総件数に応じた乱数を設定し、検索結果の中からランダムに一つのアーティスト情報を取得するようにしている。

Spotify Web API を利用してアーティストのカタログ情報を取得する

Spotify Web APIを利用してアーティストのカタログ情報を取得することができる。フォロワー数、ジャンル、人気度といった詳細な情報を得ることができる。

下記はSpotify Web APIを利用してアーティストのカタログ情報を取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$artistId = '64tJ2EAv1R6UaZqc4iOCyj'; // YOASOBI
$response = $client->get("artists/$artistId", []);
var_dump($response);

アーティストのカタログ情報は、パスのパラメータ id にアーティストIDを指定し、下記のURLに対してGETリクエストを送信すれば良い。

https://api.spotify.com/v1/artists/{id}

APIリクエスト実行後、レスポンスデータの followers キー下に hreftotal キーがあり、total キーの値がフォロワー数を指す。href キーには、フォロワーの詳細情報を得るためのWeb APIのエンドポイントが入るが、現時点でまだサポートされていないため、値は常に null となる。

レスポンスデータの genres キーには、アーティストに関連付けられたジャンルのリストが保持されている。

レスポンスデータにある popularity キーは、アーティストの人気度を示すもので、この人気度はアーティストの全ての曲の人気度から計算される。0 から 100 までの値が入り、100 が最も人気があることを示す。

Spotify Web API を利用してアルバムのカタログ情報を取得する

Spotify Web APIを利用してアルバムのカタログ情報を取得することができる。前の記事で取り上げたニューリリース情報から得られるアルバム情報よりも詳細なものを取得することができ、主なものとしてアルバム内の曲情報を得ることができる。

下記はSpotify Web APIを利用してアルバムのカタログ情報を取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$params = [
  'market' => 'JP',
];
$albumId = '4nLIK2uFzYUJqLAfJZYgLx';
$response = $client->get("albums/$albumId", $params);
var_dump($response);

アルバムのカタログ情報は、下記URLに対してGETリクエストを送信することで得ることができる。

https://api.spotify.com/v1/albums/{id}

パスのパラメータ id には、アルバムIDを指定する。

また、APIリクエスト時のオプションのクエリパラメータとして market パラメータに2文字の国名コードを指定することができる。このパラメータを指定すると、Spotifyユーザーのプロフィール設定に登録された国情報により、アルバム内の特定の曲がそのユーザーの国では入手不可となる場合に、そのユーザーの国で利用可能なオリジナル曲の別の実体の曲データがあれば、その情報をAPIレスポンスに入れてくれる(公式ドキュメントでは、この機能を「Track Relinking」と呼んでいる)。
※Spotifyは、それぞれのマーケット(国)で入手可能な複数の実体の曲データを保持している。これはアルバム内の曲がそれぞれの国で別のライセンスで複数回リリースされた場合に一般的に起こる。
※Track Relinkingの詳細は下記を参照のこと
Track Relinking Guide | Spotify for Developers

APIリクエスト実行後、APIレスポンスの tracks キー下の items キーにアルバム内の曲のリスト情報が配列データとして保持されている。曲数は total_tracks キーに保持されている。

items キーに保持された各曲のデータには name キーがあり、曲名を得るにはこの値を参照すれば良い。また、preview_url キーには、MP3形式の楽曲(30秒のプレビュー版)へのURLが保持されている。

Spotify Web API を利用してニューリリース情報を取得する

Spotify Web APIを利用してニューアルバムのリリース情報を取得することができる。このニューリリース情報には、各アルバムの基本情報(アーティスト名、アルバム名、リリース日など)が含まれる。アルバム内の曲情報は含まれない。

下記は、Spotify Web APIを利用してニューリリース情報を取得するコードの例。


class SpotifyApiClient
{
  private $rootEndpoint = 'https://api.spotify.com/v1/';

  private $accessToken;

  public function __construct($ACCESS_TOKEN)
  {
    $this->accessToken = $ACCESS_TOKEN;
  }

  public function get($path, array $queryParams)
  {
    $url = $this->rootEndpoint . $path;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Authorization: Bearer {$this->accessToken}'" .
           " '$url'";

    echo "# $cmd\n";

    return shell_exec($cmd);
  }
}


$tokenFile = 'token_new.json';
$token = json_decode(file_get_contents($tokenFile), true);
$client = new SpotifyApiClient($token['access_token']);

$params = [
  'country' => 'JP',
  //'limit' => 1,
  //'offset' => 1,
];
$response = $client->get('browse/new-releases', $params);
var_dump($response);

ニューリリース情報は、下記URL

https://api.spotify.com/v1/browse/new-releases

に対して、GETリクエストを行えば取得することができる。

オプションのクエリパラメータとして、countrylimitoffset パラメータを指定することができる。

country パラメータには、2文字の国名コードを指定することができ、特定の国名コードを指定した場合、レスポンスとして返されるリリース情報をその国に関連するものに限定することができる。何も指定しない場合、全世界向けのニューリリース情報がレスポンスとして返される。上記のコードの例では JP(日本)を指定している。

limit パラメータは、レスポンスに含めるアルバム件数を指定するためのもので、デフォルト値は 20、最大値として 50 まで設定することができる。

offset パラメータは、結果のページネーションを行うためのもので、デフォルトでは 0 が設定され、最初の結果がレスポンスとして返される。以降の結果を取得していくには、この値を limit の値ずつインクリメントしていけば良い。例えば limit = 20 のとき、offset = 0 の次は offset = 20、その次は offset= 40 というようにインクリメントしていく。

APIリクエスト実行後、APIレスポンスの items キーにリクエストしたデータの本体であるニューリリース情報が保持されている。デフォルト(limit = 20)では、items キーに20件のアルバムの基本データ(詳細ではなく簡略版の情報)が含まれる。

Twitch API v5 を利用して人気のゲーム情報を取得する

Twitch API v5を利用して人気のゲーム情報を取得することができる。New Twitch APIでも可能だが、取得できるのは、現在の視聴数順にソートされたゲーム情報だけになる。v5はすでにdeprecatedなAPIとしてアナウンスされているが、ゲーム情報に加え、視聴数や配信チャンネル数も取得することができるため、New Twitch APIよりも利用価値が高い。

下記は、v5を利用して人気のゲーム情報を取得するコードの例。


class TwitchApi_v5_Client
{
  private $endpoint = 'https://api.twitch.tv/kraken/';

  private $oauthClientIdHeader;

  public function __construct($CLIENT_ID, $ACCESS_TOKEN = "")
  {
    $this->oauthClientIdHeader = "Client-ID: $CLIENT_ID";
  }

  public function get($resource, array $queryParams)
  {
    $url = $this->endpoint . $resource;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Accept: application/vnd.twitchtv.v5+json'" .
           " -H '{$this->oauthClientIdHeader}'" .
           " -X GET '$url'";

    echo "# $cmd\n";

    return exec($cmd);
  }
}


$CLIENT_ID = '_CLIENT_ID_';
$client = new TwitchApi_v5_Client($CLIENT_ID);

$params = [
  //'limit' => 100,
  //'offset' => 0,
];

$response = $client->get('games/top', $params);
var_dump($response);

v5で人気のゲーム情報を取得するには、下記のURLに対してGETリクエストを送信すれば良い。

https://api.twitch.tv/kraken/games/top

リクエスト時のクエリパラメータとして、limit パラメータを指定すると、APIレスポンスに含める結果の件数を変更することができる。デフォルトは 10 で10件のゲーム情報がレスポンスとして返される。最大値は 100 までとなる。

また、offset パラメータを指定することにより、レスポンスデータのページネーションを行うことができる。デフォルトでは、0 が設定され、1ページ目の結果がレスポンスとして返される。2ページ目以降の結果を取得するには、この値をインクリメントしていけば良い。

APIリクエスト実行後、レスポンスデータの top フィールドにゲーム情報(game オブジェクト)が含まれている。viewers プロパティがそのゲームの現在の視聴数、channels プロパティが現在配信しているチャンネル数を表す。現在の視聴数とチャンネル数は、New Twitch APIではレスポンスデータに含まれないため、これらのデータを取得したい場合は、v5を利用する必要がある。

New Twitch API を利用して動画情報を取得する

New Twitch APIを利用してユーザーに紐付いた動画情報やゲームに紐付いた動画情報を取得することができる。

下記はAPIを利用して動画情報を取得するコードの例。


class TwitchApiClient
{
  private $endpoint = 'https://api.twitch.tv/helix/';

  private $oauthClientIdHeader;
  private $oauthTokenHeader;

  public function __construct($CLIENT_ID, $ACCESS_TOKEN)
  {
    $this->oauthClientIdHeader = "Client-ID: $CLIENT_ID";
    $this->oauthTokenHeader = "Authorization: Bearer $ACCESS_TOKEN";
  }

  public function get($resource, array $queryParams)
  {
    $url = $this->endpoint . $resource;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H '{$this->oauthClientIdHeader}'" .
           " -H '{$this->oauthTokenHeader}'" .
           " -X GET '$url'";

    echo "# $cmd\n";

    return exec($cmd);
  }
}


$CLIENT_ID = '_CLIENT_ID_';
$ACCESS_TOKEN = '_ACCESS_TOKEN_';

$client = new TwitchApiClient($CLIENT_ID, $ACCESS_TOKEN);

$params = [
  //'user_id' => '19571641', // ninja
  'game_id' => '33214', // Fortnite
  'first' => 20,
  'period' => 'all',
  'sort' => 'views',
  'type' => 'all',
];

$page = 0;
do
{
  $response = $client->get('videos', $params);
  var_dump($response);
  $page++;

  if (isset($response['pagination']['cursor']))
    $params['after'] = $response['pagination']['cursor'];
  else
    break;

  if ($page >= 2)
    break;

} while(true);

動画情報を取得するには、下記のURLに対してGETリクエストを行えば良い。

https://api.twitch.tv/helix/videos

GETリクエストを行う際の必須クエリパラメータとして、user_id パラメータにユーザーIDを指定した場合は、そのユーザーに紐付いた動画情報、game_id パラメータにゲームIDを指定した場合は、そのゲームに紐付いた動画情報を取得することができる。上記のコードの例では、game_id にFortniteのゲームIDを指定している。

次に上記のコードで設定しているオプションのクエリパラメータを順に説明していく。

first パラメータに値を設定すると、APIレスポンスに含める動画情報の件数を指定することができる。デフォルト値は 20、最大 100 まで指定することができる。

period パラメータには、いつ作成された動画を取得対象にするか、その期間を指定できる。デフォルト値は all で全ての期間が対象となる。他には、dayweekmonth を指定することができる。

sort パラメータでは、レスポンスに含まれる動画情報リストのソート方法を指定できる。デフォルト値は time で新しい動画順にソートされる。views を指定すると視聴数(再生回数)が多い順にソートされる。他には trending も指定可能であるが、上記のコードを実行して確認した時点では、"503 Service Unavailable" で結果を取得することができなかった。

type パラメータでは、レスポンスに含める動画の種類を指定することができる。デフォルト値は all で全ての動画の種類がレスポンスに含まれる。upload を指定するとアップロード動画、archive を指定するとライブ配信のアーカイブ動画、highlight を指定するとダイジェスト動画に限定した結果を取得することができる。

APIリクエスト実行後、レスポンスデータの data フィールドにクエリパラメータの指定条件にマッチした動画情報リストが含まれている。また、APIリクエスト時に、レスポンスデータの pagination フィールドにある cursor プロパティの値を after パラメータの値に指定してリクエストを行うと、レスポンスデータの次の結果セットを取得することができる。

Twitch API v5 を利用してユーザー情報を取得する

Twitch API v5はすでにdeprecatedであるが、v5でユーザー情報を取得する方法を記載する。あえてv5でユーザー情報を取得する理由は、New Twitch APIで取得できるユーザー情報には、アカウント作成日時や更新日時が含まれていないが、Twitch API v5ではそれが取得可能なため。

下記はv5を利用してユーザー情報を取得するコード。


class TwitchApi_v5_Client
{
  private $endpoint = 'https://api.twitch.tv/kraken/';

  private $oauthClientIdHeader;

  public function __construct($CLIENT_ID, $ACCESS_TOKEN = "")
  {
    $this->oauthClientIdHeader = "Client-ID: $CLIENT_ID";
  }

  public function get($resource, array $queryParams)
  {
    $url = $this->endpoint . $resource;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Accept: application/vnd.twitchtv.v5+json'" .
           " -H '{$this->oauthClientIdHeader}'" .
           " -X GET '$url'";

    echo "# $cmd\n";

    return exec($cmd);
  }
}


$CLIENT_ID = '_CLIENT_ID_';
$client = new TwitchApi_v5_Client($CLIENT_ID);

$params = [
  'login' => 'ninja',
];

$response = $client->get('users', $params);
var_dump($response);

Twitch API v5でユーザー情報を取得するには、

https://api.twitch.tv/kraken/users

に対し、クエリパラメータとして、login パラメータにユーザー名を指定してGETリクエストを行えば良い。
※公式ドキュメントでは リクエストURLに user IDs と記載されていて紛らわしいが、ユーザーIDではなくユーザー名を指定する。

上記のコードを実行するとAPIレスポンスとして、下記のようなユーザー情報を取得することできる。
※実際はAPIレスポンスとしてJSONデータが返されるが、json_decode() を使って配列データに変換している。

レスポンスデータに含まれる created_atupdated_at がNew Twitch APIでは取得できない情報で、それぞれアカウントの作成日時、更新日時にあたる情報となる。


array(2) {
  ["_total"]=>
  int(1)
  ["users"]=>
  array(1) {
    [0]=>
    array(8) {
      ["display_name"]=>
      string(5) "Ninja"
      ["_id"]=>
      string(8) "19571641"
      ["name"]=>
      string(5) "ninja"
      ["type"]=>
      string(4) "user"
      ["bio"]=>
      NULL
      ["created_at"]=>
      string(27) "2011-01-16T04:31:20.024666Z"
      ["updated_at"]=>
      string(27) "2020-08-26T11:23:23.750014Z"
      ["logo"]=>
      string(109) "https://static-cdn.jtvnw.net/jtv_user_pictures/cef31105-8a6e-4211-a74b-2f0bbd9791fb-profile_image-300x300.png"
    }
  }
}

New Twitch API を利用してユーザー(チャンネル)のフォロワー数を取得する

New Twitch APIを利用してユーザー(チャンネル)のフォロワー数を取得する。Twitch API v5ではフォロワー数はチャンネルオブジェクトのプロパティの一つであったが、New Twitch APIではデータモデルが見直され、チャンネルオブジェクトはユーザーオブジェクトに統合された。よって、New Twitch APIでは、ユーザーリソースに対してリクエストを行うことによって、フォロワー数を取得することができる。

下記は、New Twitch APIでユーザーリソースに対してリクエストを行い、フォロワー数を取得するコードの例。


class TwitchApiClient
{
  private $endpoint = 'https://api.twitch.tv/helix/';

  private $oauthClientIdHeader;
  private $oauthTokenHeader;

  public function __construct($CLIENT_ID, $ACCESS_TOKEN)
  {
    $this->oauthClientIdHeader = "Client-ID: $CLIENT_ID";
    $this->oauthTokenHeader = "Authorization: Bearer $ACCESS_TOKEN";
  }

  public function get($resource, array $queryParams)
  {
    $url = $this->endpoint . $resource;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H '{$this->oauthClientIdHeader}'" .
           " -H '{$this->oauthTokenHeader}'" .
           " -X GET '$url'";

    echo "# $cmd\n";

    return exec($cmd);
  }
}


$CLIENT_ID = '_CLIENT_ID_';
$ACCESS_TOKEN = '_ACCESS_TOKEN_';

$client = new TwitchApiClient($CLIENT_ID, $ACCESS_TOKEN);

$params = [
  'to_id' => '19571641', // ninja
  'first' => 1,
];

$response = $client->get('users/follows', $params);
var_dump($response);

フォロワー数は、

https://api.twitch.tv/helix/users/follows

に対し、クエリパラメータとして to_id パラメータを付加してGETリクエストを行うことによって取得することができる。

to_id にはユーザーIDを指定する。上記のコードの例では、ユーザー名 ninja のユーザーIDを指定している。

APIレスポンスとして返ってくるデータは、totaldatapagination フィールドから構成され、total の値が取得したいフォロワー数に該当する。

data フィールドには、フォロワーのユーザー情報が含まれている。デフォルトでは20件のユーザー情報が含まれる。この件数は、APIリクエストを行う際のクエリパラメータとして first パラメータに値を設定することで変更できる。設定できる最大値は 100 まで。上記のコードの例では、フォロワー数を取得するのが主な目的なため、first1 を指定し、レスポンスに含めるデータ件数を抑制している。

pagination フィールドのデータは、結果のページネーションに利用するためのもの。data フィールドに含まれるユーザー情報の次の結果セットを取得したい場合、APIリクエスト時のクエリパラメータとして after パラメータに pagination フィールドの cursor の値を指定すれば良い。

Twitch API v5 を利用して人気の動画情報を取得する

Twitch API v5を利用して人気の動画情報を取得することができる。これは特定の期間における視聴数(再生回数)に基づいたもので、視聴数が多い順にソートされた動画情報がAPIレスポンスとして返ってくる。

Twitch API v5はすでにdeprecatedで、New Twitch APIを利用することが推奨されているが、New Twitch APIには現状、人気の動画情報をリクエストする手段が提供されていないので、v5を利用する。

下記は、v5を利用して人気の動画情報を取得するコード。


class TwitchApi_v5_Client
{
  private $endpoint = 'https://api.twitch.tv/kraken/';

  private $oauthClientIdHeader;

  public function __construct($CLIENT_ID, $ACCESS_TOKEN = "")
  {
    $this->oauthClientIdHeader = "Client-ID: $CLIENT_ID";
  }

  public function get($resource, array $queryParams)
  {
    $url = $this->endpoint . $resource;

    if (!empty($queryParams))
      $url .= '?' . http_build_query($queryParams);

    $response = $this->execCurlGET($url);
    sleep(1);

    return json_decode($response, true);
  }

  private function execCurlGET($url)
  {
    $cmd = 'curl' .
           " -H 'Accept: application/vnd.twitchtv.v5+json'" .
           " -H '{$this->oauthClientIdHeader}'" .
           " -X GET '$url'";

    echo "# $cmd\n";

    return exec($cmd);
  }
}


$CLIENT_ID = '_CLIENT_ID_';
$client = new TwitchApi_v5_Client($CLIENT_ID);

$params = [
  'language' => 'en,ja',
  'period' => 'all',
  'limit' => 20,
  'offset' => 0,
];

do
{
  $response = $client->get('videos/top', $params);
  var_dump($response);
  $params['offset']++;

  if ($params['offset'] >= 2)
    break;

} while($response);

Twitch API v5を利用して人気の動画情報を取得するには下記のURLに対してGETリクエストを送信すれば良い。

https://api.twitch.tv/kraken/videos/top

APIリクエストを送る際のクエリパラメータとして、上記のコードの例では、languageperiodlimitoffset パラメータを設定している。

language パラメータに言語コードを指定すると、APIレスポンスに含める結果を指定した言語に紐付いたものに限定させることができる。上記の例では、en,ja を指定し英語と日本語の動画に限定している。

period パラメータでは、人気の期間を指定することができる。この値には、weekmonthall のいずれかを指定できる。上記の例では、all を指定し全期間における累計の視聴数に基づいた結果を取得するようにしている。

limit パラメータは、APIレスポンスに含める動画件数を指定するもので、デフォルト値は 10、最大値として 100 を設定できる。今回の例では、20 を指定し、1回のリクエストあたり20件の結果を取得するようにしている。

offset パラメータは、結果のページネーションのためのもので、デフォルトでは 0 が設定される。このパラメータの値をインクリメントしていけば、次の結果を順に取得していくことができる。

Google APIs Client Library for PHP における YouTube サービスの実装の概要を確認する

YouTube Data API v3において定義されているリソースとPHPクライアントライブラリ (Google APIs Client Library for PHP) における実装がどのように対応しているか見ていきたい。

対応関係の概要だけでも知っておくと、APIリファレンスを読むとき、ドキュメント上での記述とPHPでアプリケーションを実装する際に必要なコードを頭の中で対応付けられるようになる。

APIリファレンスに記載されている通り、APIを利用して操作できるリソースには下記のものがある。

  • activities リソース
  • captions リソース
  • channelBanners リソース
  • channelSections リソース
  • channels リソース
  • commentThreads リソース
  • comments リソース
  • guideCategories リソース
  • i18nLanguages リソース
  • i18nRegions リソース
  • liveBroadcasts リソース(APIレファレンスに記載なし)
  • liveChatBans リソース(APIレファレンスに記載なし)
  • liveChatMessages リソース(APIレファレンスに記載なし)
  • liveChatModerators リソース(APIレファレンスに記載なし)
  • liveStreams リソース(APIレファレンスに記載なし)
  • members リソース
  • membershipsLevels リソース
  • playlistItems リソース
  • playlists リソース
  • search リソース
  • sponsors リソース(APIレファレンスに記載なし)
  • subscriptions リソース
  • superChatEvents リソース(APIレファレンスに記載なし)
  • thumbnails リソース
  • videoAbuseReportReasons リソース
  • videoCategories リソース
  • videos リソース
  • watermarks リソース

これらのリソースとPHPクライアントライブラリにおける実装の対応関係を見ていくために、簡単なコードを使って結果を確認していく。


まず、YouTube Data APIのリクエスト操作を行うには、下記のように Google_Service_YouTube オブジェクトを作成する。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

ここで下記のコードを実行すると、$youtube (Google_Service_YouTube オブジェクト) が持つプロパティと、そのクラスを確認することができる。


$propertyNames = [
  'activities',
  'captions',
  'channelBanners',
  'channelSections',
  'channels',
  'commentThreads',
  'comments',
  'guideCategories',
  'i18nLanguages',
  'i18nRegions',
  'liveBroadcasts',
  'liveChatBans',
  'liveChatMessages',
  'liveChatModerators',
  'liveStreams',
  'members',
  'membershipsLevels',
  'playlistItems',
  'playlists',
  'search',
  'sponsors',
  'subscriptions',
  'superChatEvents',
  'thumbnails',
  'videoAbuseReportReasons',
  'videoCategories',
  'videos',
  'watermarks',
];

foreach ($propertyNames as $propertyName)
{
  echo "property: ".'$youtube->'."$propertyName\n";

  if (property_exists($youtube, $propertyName))
  {
    echo "  ==> class       : " . get_class($youtube->$propertyName) . "\n";
    echo "  ==> parent class: " . get_parent_class($youtube->$propertyName) . "\n\n";
  }
  else
  {
    echo "  ==> not exists\n\n";
  }
}
[実行結果]

property: $youtube->activities
  ==> class       : Google_Service_YouTube_Resource_Activities
  ==> parent class: Google_Service_Resource

property: $youtube->captions
  ==> class       : Google_Service_YouTube_Resource_Captions
  ==> parent class: Google_Service_Resource

property: $youtube->channelBanners
  ==> class       : Google_Service_YouTube_Resource_ChannelBanners
  ==> parent class: Google_Service_Resource

property: $youtube->channelSections
  ==> class       : Google_Service_YouTube_Resource_ChannelSections
  ==> parent class: Google_Service_Resource

property: $youtube->channels
  ==> class       : Google_Service_YouTube_Resource_Channels
  ==> parent class: Google_Service_Resource

property: $youtube->commentThreads
  ==> class       : Google_Service_YouTube_Resource_CommentThreads
  ==> parent class: Google_Service_Resource

property: $youtube->comments
  ==> class       : Google_Service_YouTube_Resource_Comments
  ==> parent class: Google_Service_Resource

property: $youtube->guideCategories
  ==> class       : Google_Service_YouTube_Resource_GuideCategories
  ==> parent class: Google_Service_Resource

property: $youtube->i18nLanguages
  ==> class       : Google_Service_YouTube_Resource_I18nLanguages
  ==> parent class: Google_Service_Resource

property: $youtube->i18nRegions
  ==> class       : Google_Service_YouTube_Resource_I18nRegions
  ==> parent class: Google_Service_Resource

property: $youtube->liveBroadcasts
  ==> class       : Google_Service_YouTube_Resource_LiveBroadcasts
  ==> parent class: Google_Service_Resource

property: $youtube->liveChatBans
  ==> class       : Google_Service_YouTube_Resource_LiveChatBans
  ==> parent class: Google_Service_Resource

property: $youtube->liveChatMessages
  ==> class       : Google_Service_YouTube_Resource_LiveChatMessages
  ==> parent class: Google_Service_Resource

property: $youtube->liveChatModerators
  ==> class       : Google_Service_YouTube_Resource_LiveChatModerators
  ==> parent class: Google_Service_Resource

property: $youtube->liveStreams
  ==> class       : Google_Service_YouTube_Resource_LiveStreams
  ==> parent class: Google_Service_Resource

property: $youtube->members
  ==> class       : Google_Service_YouTube_Resource_Members
  ==> parent class: Google_Service_Resource

property: $youtube->membershipsLevels
  ==> class       : Google_Service_YouTube_Resource_MembershipsLevels
  ==> parent class: Google_Service_Resource

property: $youtube->playlistItems
  ==> class       : Google_Service_YouTube_Resource_PlaylistItems
  ==> parent class: Google_Service_Resource

property: $youtube->playlists
  ==> class       : Google_Service_YouTube_Resource_Playlists
  ==> parent class: Google_Service_Resource

property: $youtube->search
  ==> class       : Google_Service_YouTube_Resource_Search
  ==> parent class: Google_Service_Resource

property: $youtube->sponsors
  ==> class       : Google_Service_YouTube_Resource_Sponsors
  ==> parent class: Google_Service_Resource

property: $youtube->subscriptions
  ==> class       : Google_Service_YouTube_Resource_Subscriptions
  ==> parent class: Google_Service_Resource

property: $youtube->superChatEvents
  ==> class       : Google_Service_YouTube_Resource_SuperChatEvents
  ==> parent class: Google_Service_Resource

property: $youtube->thumbnails
  ==> class       : Google_Service_YouTube_Resource_Thumbnails
  ==> parent class: Google_Service_Resource

property: $youtube->videoAbuseReportReasons
  ==> class       : Google_Service_YouTube_Resource_VideoAbuseReportReasons
  ==> parent class: Google_Service_Resource

property: $youtube->videoCategories
  ==> class       : Google_Service_YouTube_Resource_VideoCategories
  ==> parent class: Google_Service_Resource

property: $youtube->videos
  ==> class       : Google_Service_YouTube_Resource_Videos
  ==> parent class: Google_Service_Resource

property: $youtube->watermarks
  ==> class       : Google_Service_YouTube_Resource_Watermarks
  ==> parent class: Google_Service_Resource

実行結果を見ると、例えば $youtube オブジェクトは、videos リソースに対応する videos プロパティを持ち、そのプロパティは Google_Service_YouTube_Resource_Videos クラスのオブジェクトであることが分かる。また、各プロパティに対応するクラスは、全て Google_Service_Resource クラスを親に持つことが分かる。

このことから、APIリファレンスに記載された videos リソースに関する説明は、PHPでは $youtube (Google_Service_YouTube オブジェクト) の videos プロパティに関する説明と解釈することができる。


次に、プロパティが持つメソッドを見ていきたい。下記のコードを実行すると、各プロパティが持つメソッドを確認することができる。


$methodNames = [
 'list',
 'insert',
 'update',
 'download',
 'delete',
 'markAsSpam',
 'setModerationStatus',
 'rate',
 'getRating',
 'reportAbuse',
 'set',
 'unset',
];

foreach ($propertyNames as $propertyName)
{
  echo "property: ".'$youtube->'."$propertyName\n";

  foreach ($methodNames as $methodName)
  {
    if (method_exists($youtube->$propertyName, $methodName))
    {
      echo "  ==> {$methodName}()\n";
    }
    else
    {
      $PropertyName = $propertyName;
      $PropertyName[0] = strtoupper($PropertyName[0]);

      $methodNamePropertyName = $methodName . $PropertyName;

      if (method_exists($youtube->$propertyName, $methodNamePropertyName))
      {
        echo "  ==> {$methodNamePropertyName}()\n";
      }
    }
  }
  echo "\n";
}
[実行結果]

property: $youtube->activities
  ==> listActivities()
  ==> insert()

property: $youtube->captions
  ==> listCaptions()
  ==> insert()
  ==> update()
  ==> download()
  ==> delete()

property: $youtube->channelBanners
  ==> insert()

property: $youtube->channelSections
  ==> listChannelSections()
  ==> insert()
  ==> update()
  ==> delete()

property: $youtube->channels
  ==> listChannels()
  ==> update()

property: $youtube->commentThreads
  ==> listCommentThreads()
  ==> insert()
  ==> update()

property: $youtube->comments
  ==> listComments()
  ==> insert()
  ==> update()
  ==> delete()
  ==> markAsSpam()
  ==> setModerationStatus()

property: $youtube->guideCategories
  ==> listGuideCategories()

property: $youtube->i18nLanguages
  ==> listI18nLanguages()

property: $youtube->i18nRegions
  ==> listI18nRegions()

property: $youtube->liveBroadcasts
  ==> listLiveBroadcasts()
  ==> insert()
  ==> update()
  ==> delete()

property: $youtube->liveChatBans
  ==> insert()
  ==> delete()

property: $youtube->liveChatMessages
  ==> listLiveChatMessages()
  ==> insert()
  ==> delete()

property: $youtube->liveChatModerators
  ==> listLiveChatModerators()
  ==> insert()
  ==> delete()

property: $youtube->liveStreams
  ==> listLiveStreams()
  ==> insert()
  ==> update()
  ==> delete()

property: $youtube->members
  ==> listMembers()

property: $youtube->membershipsLevels
  ==> listMembershipsLevels()

property: $youtube->playlistItems
  ==> listPlaylistItems()
  ==> insert()
  ==> update()
  ==> delete()

property: $youtube->playlists
  ==> listPlaylists()
  ==> insert()
  ==> update()
  ==> delete()

property: $youtube->search
  ==> listSearch()

property: $youtube->sponsors
  ==> listSponsors()

property: $youtube->subscriptions
  ==> listSubscriptions()
  ==> insert()
  ==> delete()

property: $youtube->superChatEvents
  ==> listSuperChatEvents()

property: $youtube->thumbnails
  ==> set()

property: $youtube->videoAbuseReportReasons
  ==> listVideoAbuseReportReasons()

property: $youtube->videoCategories
  ==> listVideoCategories()

property: $youtube->videos
  ==> listVideos()
  ==> insert()
  ==> update()
  ==> delete()
  ==> rate()
  ==> getRating()
  ==> reportAbuse()

property: $youtube->watermarks
  ==> set()
  ==> unsetWatermarks()

実行結果を見ると、list メソッド以外は、APIリファレンスに記載された通りの名前でメソッドが用意されている。list メソッドについては、listVideos のようにリソース名が付いた名前となっている。おそらく、これは、list() がPHPにおいて特別な意味を持つキーワードとして登録されているので、混乱を避けるためにこのようなメソッド名を採用したと考えられる。


最後にAPIレスポンスについて見ていきたい。下記のコードを実行するとレスポンスに含まれるプロパティと、そのクラスを確認することができる。


$channelId = "UCrXUsMBcfTVqwAS7DKg9C0Q"; // YouTube Japan

$params = [
  'id' => $channelId
];

$response = $youtube->channels->listChannels('snippet', $params);

echo "response\n";
echo "  ==> class              : " . get_class($response) . "\n";
echo "  ==> parent class       : " . get_parent_class($response) . "\n";
echo "  ==> parent parent class: " . get_parent_class(get_parent_class($response)) . "\n\n";

echo "response.pageInfo\n";
echo "  ==> class       : " . get_class($response['pageInfo']) . "\n";
echo "  ==> parent class: " . get_parent_class($response['pageInfo']) . "\n\n";

echo "// access as array\n";

foreach ($response['items'] as $item)
{
  echo "item\n";
  echo "  ==> class       : " . get_class($item) . "\n";
  echo "  ==> parent class: " . get_parent_class($item) . "\n\n";

  echo "item.snippet\n";
  echo "  ==> class       : " . get_class($item['snippet']) . "\n";
  echo "  ==> parent class: " . get_parent_class($item['snippet']) . "\n\n";
}

echo "// access with arrow operator\n";

foreach ($response->items as $item)
{
  echo "item.snippet\n";
  echo "  ==> class       : " . get_class($item->snippet) . "\n";
  echo "  ==> parent class: " . get_parent_class($item->snippet) . "\n\n";
}

echo "// just iterate over the object\n";

foreach ($response as $item)
{
  echo "item.snippet\n";
  echo "  ==> class       : " . get_class($item['snippet']) . "\n";
  echo "  ==> parent class: " . get_parent_class($item['snippet']) . "\n\n";
}
[実行結果]

response
  ==> class              : Google_Service_YouTube_ChannelListResponse
  ==> parent class       : Google_Collection
  ==> parent parent class: Google_Model

response.pageInfo
  ==> class       : Google_Service_YouTube_PageInfo
  ==> parent class: Google_Model

// access as array
item
  ==> class       : Google_Service_YouTube_Channel
  ==> parent class: Google_Model

item.snippet
  ==> class       : Google_Service_YouTube_ChannelSnippet
  ==> parent class: Google_Model

// access with arrow operator
item.snippet
  ==> class       : Google_Service_YouTube_ChannelSnippet
  ==> parent class: Google_Model

// just iterate over the object
item.snippet
  ==> class       : Google_Service_YouTube_ChannelSnippet
  ==> parent class: Google_Model

実行結果からAPIレスポンスに含まれるプロパティは、全て Google_Model を継承したクラスのオブジェクトであることが分かる。

Google_Model クラスは、ArrayAccess インターフェイスを実装したクラスとなっているため、アロー演算子を使わず配列としてオブジェクトのプロパティにアクセスすることが可能となっている。

Google_Collection クラスは Iterator インターフェイスを実装したクラスで、反復処理では自動的に items 配列を参照するようになっているので、例えば、foreach を使うとき、

foreach ($response['items'] as $item)

と明示的に items 配列を書かなくても、

foreach ($response as $item)

というように、単に $response オブジェクトに対して foreach を書くことができる。

YouTube Data API v3を利用してチャンネルのプロフィール情報を取得する

独自にYouTubeチャンネルのプロフィール情報ページを作成することを想定し、プロフィール情報ページは下記のデータから構成されるものと定義し、APIでこれらのデータを取得することを考えてみる。

  • チャンネルアイコン画像
  • チャンネルアート画像
  • チャンネル名
  • アップロード動画数
  • 登録者数
  • 動画再生回数
  • チャンネルに関連付けられた国
  • チャンネル作成日

これらのデータは、YouTube Data APIの channels リソースに含まれるプロパティと下記のように対応する。

  • snippet
    • snippet.thumbnails:チャンネルアイコン画像
    • snippet.title:チャンネル名
    • snippet.country:チャンネルに関連付けられた国
    • snippet.publishedAt:チャンネル作成日
  • statistics
    • statistics.videoCount:アップロード動画数
    • statistics.subscriberCount:登録者数
    • statistics.viewCount:動画再生回数
  • brandingSettings

これを踏まえて、APIを利用して上記のプロパティを取得するコードの例が下記。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

$json = file_get_contents("channelIds.json");
$channelIds = json_decode($json, true);

foreach (array_chunk($channelIds, 50) as $ids)
{
  $params = [
    'id' => implode(",", $ids),
    'maxResults' => 50,
  ];

  $response = $youtube->channels->listChannels('snippet,statistics,brandingSettings', $params);

  foreach ($response['items'] as $i => $item)
  {
    echo "#$i\n";
    echo "id         : {$item['id']}\n";
    echo "title      : {$item['snippet']['title']}\n";
    echo "country    : {$item['snippet']['country']}\n";
    echo "publishedAt: {$item['snippet']['publishedAt']}\n";

    echo "viewCount      : {$item['statistics']['viewCount']}\n";
    echo "subscriberCount: {$item['statistics']['subscriberCount']}\n";
    echo "videoCount     : {$item['statistics']['videoCount']}\n";

    foreach ($item['snippet']['thumbnails'] as $key => $img)
    {
      echo "$key: {$img['url']}\n";
    }

    foreach ($item['brandingSettings']['image'] as $key => $imgUrl)
    {
      if (!is_null($imgUrl))
      {
        echo "$key: $imgUrl\n";
      }
    }
  }
  sleep(1);
}

前述のプロフィール情報に必要なプロパティをリクエストするには、listChannels() メソッドの part 引数に snippetstatisticsbrandingSettings を指定すれば良い。

フィルタのパラメータとして、maxResults パラメータには、APIレスポンスに含める結果の件数を指定する。デフォルト値は 5、最大値は 50 となる。上記コードでは最大値 50 を指定している。また、id パラメータにチャンネルIDを指定する。カンマ区切りで複数のチャンネルIDを指定できる。上記のコードでは、maxResults パラメータに合わせて、カンマ区切りで一度に最大50のチャンネルIDを指定するようにしている。

YouTube Data API v3を利用してチャンネルの国情報を取得する

なぜか日本語版の公式ドキュメントには記載されていないが、英語版を確認すると、APIを利用してYouTubeチャンネルに関連付けられた国情報を取得できることが分かる。

channels リソースには brandingSettings プロパティがある。このプロパティ内の brandingSettings.channel.country プロパティにはチャンネルに関連付けられた国名コードが入っている。
※後述するが、snippet.country プロパティを参照しても良い。ただし、この値は brandingSettings.channel.country プロパティにセットした値が入っているだけのもの。

APIリクエストを行って、このプロパティを取得するコードの例が下記。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

$channelIds = [
  "UC_x5XG1OV2P6uZZ5FSM9Ttw", // Google Developers
  "UCrXUsMBcfTVqwAS7DKg9C0Q", // YouTube Japan
];

$params = [
  'id' => implode(",", $channelIds)
];

$response = $youtube->channels->listChannels('brandingSettings', $params);

foreach ($response['items'] as $i => $item)
{
  echo "#$i\n";
  echo "id     : {$item['id']}\n";
  echo "title  : {$item['brandingSettings']['channel']['title']}\n";
  echo "country: {$item['brandingSettings']['channel']['country']}\n\n";
}

listChannels() メソッドを使ってAPIリクエストを行う。part 引数には brandingSettings を指定し、フィルタのパラメータには、id パラメータに取得したいチャンネルIDを指定する。カンマ区切りで複数のIDを指定することができる。

そして、APIレスポンスとして返ってきたデータの中にある brandingSettings.channel.country プロパティの値を取得する。値は文字列で国名コードを表すものが入っている。

ただし、チャンネルによっては、brandingSettings.channel.country プロパティの値がセットされていないようで、NULL 値の場合がある。


次に、snippet.country プロパティを参照するバージョンのコードが下記。snippet.country プロパティの値には brandingSettings.channel.country プロパティにセットした値と同じものが入る。コードも、プロパティ名を変更するだけで本質的に違いはない。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

$channelIds = [
  "UC_x5XG1OV2P6uZZ5FSM9Ttw", // Google Developers
  "UCrXUsMBcfTVqwAS7DKg9C0Q", // YouTube Japan
];

$params = [
  'id' => implode(",", $channelIds)
];

$response = $youtube->channels->listChannels('snippet', $params);

foreach ($response['items'] as $i => $item)
{
  echo "#$i\n";
  echo "id     : {$item['id']}\n";
  echo "title  : {$item['snippet']['title']}\n";
  echo "country: {$item['snippet']['country']}\n\n";
}

YouTube Data API v3を利用してチャンネルの画像情報を取得する

APIを利用してYouTubeチャンネルに関連した画像情報を取得することができる。チャンネルに関連する主な画像として下記の2つがある。

  • チャンネルアイコン
  • チャンネルアート

チャンネルアイコンは、チャンネルのプロフィール画像で、縦横のサイズが等しい正方形または円形の画像となる。小、中、大の3種類の画像がある。

チャンネルアートは、チャンネルページ上部の背景/バナー画像として表示されるもので、各デバイス向けアプリケーション/画面解像度に合わせて複数の画像がある。

下記のコードは、これらの画像をAPIを利用してリクエストするもの。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

$channelId = "UCrXUsMBcfTVqwAS7DKg9C0Q"; // YouTube Japan

$params = [
  'id' => $channelId,
];

$response = $youtube->channels->listChannels('snippet,brandingSettings', $params);

foreach ($response['items'] as $i => $item)
{
  echo "channelId: {$item['id']}\n";

  foreach ($item['snippet']['thumbnails'] as $key => $img)
  {
    echo "$key ({$img['width']}px x {$img['height']}px):\n";
    echo "{$img['url']}\n";
  }

  foreach ($item['brandingSettings']['image'] as $key => $imgUrl)
  {
    if (!is_null($imgUrl))
    {
      // APIと関係ない、単に出力を見やすくするための処理、読み飛ばして良い
      $parts = preg_split('/(?=[A-Z])/', $key, -1, PREG_SPLIT_NO_EMPTY);
      array_pop($parts);
      array_pop($parts);
      $width = preg_replace('/^.+=w([0-9]+).+$/', '$1', $imgUrl);

      echo "$key (".implode(' ', $parts).", width={$width}px):\n";
      echo "$imgUrl\n";
    }
  }
}

チャンネルアイコンの画像情報は、snippet.thumbnails プロパティに格納されている。また、チャンネルアートの画像情報は、brandingSettings.image プロパティに格納されている。

※追記:brandingSettings.image プロパティは2020年9月9日に deprecated となっている。
https://developers.google.com/youtube/v3/revision_history#september-9,-2020

APIリクエストは listChannels() メソッドを使って行い、part引数に上記 snippetbrandingSettings の2つを指定する。フィルタのパラメータ指定では、id パラメータにチャンネルIDを指定すると、そのチャンネルの画像情報を取得できる。カンマ区切りでチャンネルIDを複数指定できる。

snippet.thumbnails プロパティには、defaultmediumhigh の3つキーがあり、それぞれに urlwidthheight の値が保持されている。

  • default
    • url: 小サイズ(デフォルト)の画像URL, width: 88, height: 88
  • medium
    • url: 中サイズの画像URL, width: 240, height: 240
  • high
    • url: 大サイズの画像URL, width: 800, height: 800

brandingSettings.image プロパティに格納されているデータには、各デバイス向けアプリケーション/画面解像度の画像URLが保持されている。代表的なものを挙げると下記となる。

  • bannerImageUrl
    • ウェブサイトのチャンネルページに表示される画像URL(サイズ 1060px x 175px)
  • bannerMobileImageUrl
    • モバイルアプリケーションのチャンネルページに表示される画像URL(サイズ 640px x 175px)
  • bannerTabletImageUrl
    • タブレットアプリケーションのチャンネルページに表示される画像URL(サイズ 1707px x 283px)
  • bannerTvImageUrl
    • テレビアプリケーションのチャンネルページに表示される画像URL(サイズ 2120px x 1192px)

また、画面解像度別には、モバイルアプリケーション向けを例にすると、bannerMobileMediumHdImageUrlbannerMobileHdImageUrl のように区分されて画像URLが保持されている。

YouTube Data API v3を利用して最も人気のある動画を取得する

APIを使ってYouTubeで最も人気のある動画を取得することができる。

地域や動画カテゴリを指定して取得することが可能で、下記は日本の音楽カテゴリで最も人気のある動画を取得する例。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

$client = new Google_Client();
$client->setDeveloperKey("_API_KEY_");
$youtube = new Google_Service_YouTube($client);

$params = [
  'chart' => 'mostPopular',
  'regionCode' => 'JP',
  'videoCategoryId' => '10', // 音楽
  'maxResults' => 50,
];

do {
  $response = $youtube->videos->listVideos('snippet', $params);

  foreach ($response['items'] as $i => $item)
  {
    echo "#$i\n";
    echo "id         : {$item['id']}\n";
    echo "channelTitle: {$item['snippet']['channelTitle']}\n";
    echo "title      : {$item['snippet']['title']}\n";
  }

  echo "\n";
  echo "# nextPageToken: {$response['nextPageToken']}\n";
  echo "# prevPageToken: {$response['prevPageToken']}\n";
  echo "# totalResults: {$response['pageInfo']['totalResults']}\n";
  echo "# resultsPerPage: {$response['pageInfo']['resultsPerPage']}\n\n";

  $pageToken = $response['nextPageToken'];
  $params['pageToken'] = $pageToken;
  sleep(1);

} while (!empty($pageToken));

listVideos() を呼ぶときのフィルタのパラメータとして chart パラメータに mostPopular を指定すると最も人気のある動画が返ってくる。上記のコードでは、その他に regionCodeJPvideoCategoryId10(音楽)を指定して、リクエスト対象が日本の音楽カテゴリになるようにしている。maxResults は、APIレスポンスに含める結果の動画件数を指定する。

動画タイトルなどの基本情報は listVideos()part 引数に snippet を指定すると得られる。APIレスポンスとして返ってくる snippet プロパティには下記の動画・基本情報が格納されている。

  • snippet.publishedAt:動画のアップロード日時
  • snippet.channelId:動画のチャンネルID
  • snippet.title:動画のタイトル
  • snippet.description:動画の説明
  • snippet.thumbnails:動画のサムネイル画像情報
  • snippet.channelTitle:動画のチャンネル名
  • snippet.tags:動画に付けられたタグ
    • 配列データ(動画にタグが付けられていない場合は NULL
  • snippet.categoryId:動画のカテゴリID

上記コードを実行すると、日本の音楽カテゴリで最も人気のある動画が人気上位から順に出力される。

なお、2ページ目以降の結果を取得するには、フィルタに pageToken パラメータを追加し、その値に nextPageToken の値(上記の実行結果の例では CDIQAA)を指定すると得られる。nextPageToken は、次のページ結果がある場合、APIレスポンスに含まれている。

YouTube Data API v3を利用したプレイリストのエクスポート/インポート機能のクォータ使用量

Googleは、APIによる各リクエストにコストを割り当ててクォータの使用量を計算している。コストは操作の種類ごとに下記のように設定されている。

※追記:Googleがクォータ・コストの割り当て方法の簡略化を行い、part パラメータに伴う追加コストが撤廃された。
https://developers.google.com/youtube/v3/revision_history#july-29,-2020

簡略化後は、part引数によらず、単純に各メソッドに割り当てられたコストがかかるだけになる。


※注意:これ以降の内容は、以前のpartパラメータにかかる追加コストを考慮に入れて、コストを計算したもの
  • リソースのIDを取得するだけの単純な読み取り操作のコストは 1 ユニット
  • リソースのパーツ(snippetstatus など、ただし id は除く)を取得する読み取り操作のコストはパーツ毎に 2 ユニット
  • リソースの書き込み操作のコストは 50 ユニット
  • 動画のアップロードのコストは 1600 ユニット

ここで、下記のプレイリストのエクスポート機能を想定したAPIリクエストのコストを計算してみる。

$youtube->playlistItems->listPlaylistItems('snippet', $params)

※フィルタのパラメータ $paramsmaxResults の値に 50 を設定、1回のリクエストで最大50件のプレイリストアイテム(プレイリスト内の動画情報)を取得

読み取り操作には、1 ユニットのコストがかかる。引数 partsnippet だけ指定しているので、読み取るパーツ数は1となる。パーツの読み取り操作は、パーツ毎に 2 ユニットなので、読み取り操作全体のコストは、

1 + 2 * 1
= 3

となり、上記APIリクエストは1回で 3 ユニットのコストがかかることになる。

1日あたりのクォータが 10,000、含まれる動画が50個以内のプレイリストを対象にすると、1日あたり 3,333 (=10,000/3) のプレイリスト情報を取得できる計算になる。


次に、下記のプレイリストのインポート機能を想定したAPIリクエストのコストを計算してみる。

プレイリストのインポートでは、下記2つのAPIリクエストが行われる。

  1. $youtube->playlists->insert('snippet,status', $youTubePlaylist, [])
  2. $youtube->playlistItems->insert('snippet', $playlistItem, [])

まず1番目のリクエストのコストから。

これはプレイリストを作成するためのもので、書き込み操作に該当する。よって、playlists->insert() は、書き込み操作として 50 ユニットのコストがかかる。

また、playlists->insert() の書き込み操作は、書き込みだけでなく、APIレスポンスとしてリソースを返す処理も実行される。つまり、リソースを返す処理に伴い読み取り操作のコストもかかることになる。読み取り操作には、1 ユニットのコストがかかる。引数 partsnippet,status を指定しているので、読み取るパーツ数は2となる。よって、playlists->insert() は、読み取り操作として、

1 + 2 * 2
= 5

のコストがかかる。

よって、playlists->insert() にかかる書き込みと読み取り操作のコストを合わせると、

50 + 5
= 55

これが1番目のAPIリクエストのコストとなる。

続いて、2番目のリクエストのコストを計算してみる。

これは作成したプレイリストにプレイリストアイテムを追加していく操作で、書き込み操作として、playlistItems->insert()50 ユニットのコストがかかる。これも同様にAPIレスポンスを返す処理に伴い読み取り操作が行われる。引数 partsnippet を指定しているので、読み取るパーツ数は1となることから、playlistItems->insert() は、読み取り操作として、

1 + 2 * 1
= 3

のコストがかかる。playlistItems->insert() にかかる書き込みと読み取り操作のコストを合わせると、

50 + 3
= 53

のコストがかかることになる。これはプレイリストアイテム1個あたりにかかるコストとなる。

そこで、プレイリストに15個のプレイリストアイテムを追加する場合を想定すると、

53 * 15
= 795

これが2番目のAPIリクエストのコストとなる。

プレイリストの作成、プレイリストアイテムの追加(15個)のコストを合わせると

55 + 795
= 850

これが1番目と2番目のAPIリクエストを合わせた総コストとなる。

1日あたりのクォータが 10,000、含まれる動画が10個のプレイリストをインポート対象とすると、1日あたり 11 (=10,000/850) のプレイリストをインポートできる計算になる。


エクスポートとインポートのコストを比較してみると、1日あたりの可能なエクスポート数は 3,333、インポート数は 11 となることから、書き込み操作のコストはかなり高いことがわかる。

クォータの使用量は、Google Cloud Platformの "IAM と管理" → "割り当て" から確認できる。

最後に、クォータ制限に引っかかると下記のようなエラーが返ってくる。これはプレイリスト作成で playlists->insert() による書き込み操作をリクエストしたときのもの。
※クォータ上限は 10,000 のはずなのだが、7700 ぐらいに達したぐらいで書き込み操作を伴うAPIリクエストが一切行えなくなった

Fatal error: Uncaught Google_Service_Exception: {
  "error": {
    "code": 500,
    "message": "Internal error encountered.",
    "errors": [
      {
        "domain": "youtube.api.v3.PlaylistInsertResponse.Error",
        "reason": "RATE_LIMIT_EXCEEDED"
      }
    ],
    "status": "INTERNAL"
  }
}

YouTube Data API v3を利用してプレイリストのインポート機能を実装する

YouTubeにはプレイリスト(再生リスト)のインポート機能がないので、YouTube Data API v3を利用して簡単なものを自作した。

プレイリストのインポート機能を実装するには、APIで挿入 (insert) 操作をリクエストする必要がある。

このAPIリクエストを実行するには、OAuth 2.0認証を行い、アプリケーション(今回の場合は自作インポート機能プログラム)によるユーザーアカウントへのアクセスが許可されなければならない。

また、このアクセス許可は、ユーザーのリソース操作全てを許可するわけではなく、スコープという仕組みを導入して許可する範囲を限定している。

プレイリストのインポート機能に必要な挿入 (insert) 操作を行う場合は、スコープ https://www.googleapis.com/auth/youtube が許可される必要がある。

OAuth 2.0認証のやり取りを行い、承認されたクライアントオブジェクトをセットアップするためのコードが下記になる。


require_once '/path/to/google-api-php-client/vendor/autoload.php';

require_once 'OAuthClient.php';

$CLIENT_ID = '_CLIENT_ID_';
$CLIENT_SECRET = '_CLIENT_SECRET_';
$REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob';
$TOKEN_FILENAME = "token.json";
$CODE = '_CODE_';

try
{
  $gclient = new Google_Client();
  $oauth = new OAuthClient($gclient, $CLIENT_ID, $CLIENT_SECRET, $REDIRECT_URI, $TOKEN_FILENAME, $CODE);
  $oauth->setScopes('https://www.googleapis.com/auth/youtube');
  $client = $oauth->getAuthorizedClient();
}
catch(Exception $e)
{
  switch($e->getCode())
  {
    case OAuthClient::EMPTY_CODE:
    case OAuthClient::INVALID_CODE:
      echo $e->getMessage() . "\n";
      echo $oauth->getAuthUrl() . "\n";
      exit;
    case OAuthClient::INVALID_TOKEN_FILE:
      echo $e->getMessage() . "\n";
      exit;
    default:
      throw $e;
  }
}

$youtube = new Google_Service_YouTube($client);

OAuth 2.0認証の一連の処理は OAuthClient クラスにまとめてある。このクラスの getAuthorizedClient() を呼べば、承認されたクライアントオブジェクトが返ってくる。詳細は前の記事で説明したので、それを参照のこと。
OAuth 2.0 認証で YouTube Data API v3 を利用する


ここからは本題のインポート機能について説明する。

インポート機能は次の3つの処理から成る。

  1. インポートファイルの読み込み
  2. プレイリスト作成
  3. プレイリストに動画を追加

まず、下記はインポートファイルの読み込みとプレイリストの作成を行う部分。


$importFileName = "import.tsv";

$videoIds = extractVideoIds($importFileName);

$playlistName = preg_replace('/^(.+)\.tsv$/', '$1', $importFileName);
echo "creating a playlist \"$playlistName\"...\n";

$playlistSnippet = new Google_Service_YouTube_PlaylistSnippet();
$playlistSnippet->setTitle($playlistName);
$playlistSnippet->setDescription("created with the YouTube Data API v3 [" . date('Y-m-d H:i:s') . "]");

$playlistStatus = new Google_Service_YouTube_PlaylistStatus();
$playlistStatus->setPrivacyStatus('private');

$youTubePlaylist = new Google_Service_YouTube_Playlist();
$youTubePlaylist->setSnippet($playlistSnippet);
$youTubePlaylist->setStatus($playlistStatus);

$playlistResponse = $youtube->playlists->insert('snippet,status', $youTubePlaylist, []);
$playlistId = $playlistResponse['id'];

echo "done.\n\n";


function extractVideoIds($filename)
{
  $videoIds = [];

  $file = file_get_contents($filename);

  if (!$file)
    exit("Error: Can't open file: $filename\n");

  echo "reading \"$filename\"...\n";

  foreach (str_getcsv($file, "\n") as $row)
  {
    if (empty($row))
      continue;

    $cols = str_getcsv($row, "\t");

    $videoId = preg_replace('|^https://www.youtube.com/watch\?v=(.+)$|', '$1', $cols[0]);
    $videoIds[] = $videoId;
  }

  echo "done.\n\n";

  return $videoIds;
}

インポートできるファイルは、下記のようなYouTubeの動画URLとタイトルが TSV(タブ区切り)形式で保存されたファイルを想定している。


YouTube動画URL1	動画タイトル1
YouTube動画URL2	動画タイトル2
YouTube動画URL3	動画タイトル3
...

このファイルを読み込んで動画IDだけ抽出する。

続いてプレイリストの作成では、まず、snippet プロパティと status プロパティの値を保持する PlaylistSnippetPlaylistStatus オブジェクトをそれぞれ作成する。

PlaylistSnippet オブジェクトの作成では、snippet プロパティ内の snippet.title プロパティと snippet.description(プレイリストの説明)の値を setTitle()setDescription() でそれぞれセットする。上記のコードの例では、title にはインポートファイルのファイル名、description には文字列 created with the YouTube Data API v3 とそれにタイムスタンプを付加したものをセットしている。

PlaylistStatus オブジェクトの作成では、status プロパティ内の status.privacyStatus プロパティの値をセットする。有効な値は、publicprivateunlisted の3つで、デフォルトは public となる。上記のコードの例では、private をセットし、作成するプレイリストは非公開のものとして設定している。

PlaylistSnippetPlaylistStatus オブジェクトを作成したら、それらを Playlist オブジェクト $youTubePlaylistsetSnippet()setStatus() でそれぞれセットする。そして、$youtube->playlists->insert('snippet,status', $youTubePlaylist, []) でAPIリクエストを行い、プレイリストの作成が完了する。insert() の引数 'snippet,status' は、書き込み操作対象となるプロパティを特定するものである。

APIレスポンスに作成されたプレイリストIDが含まれているのでそれを取得する。

次に、このIDを使って、プレイリストに動画をインポートしてプレイリストを完成させていく。


foreach ($videoIds as $i => $videoId)
{
  echo "$i: videoId: $videoId ";

  $resourceId = new Google_Service_YouTube_ResourceId();
  $resourceId->setVideoId($videoId);
  $resourceId->setKind('youtube#video');

  $playlistItemSnippet = new Google_Service_YouTube_PlaylistItemSnippet();
  $playlistItemSnippet->setPlaylistId($playlistId);
  $playlistItemSnippet->setResourceId($resourceId);

  $playlistItem = new Google_Service_YouTube_PlaylistItem();
  $playlistItem->setSnippet($playlistItemSnippet);
  $playlistItemResponse = $youtube->playlistItems->insert('snippet', $playlistItem, []);

  echo "inserted.\n";
}

echo "\ndone.\n";

プレイリストはプレイリストアイテムから構成され、インポートする動画一つ一つに対応するプレイリストアイテムを作成して、それらをプレイリストに挿入していくのが主な処理となる。

プレイリストアイテムの作成手順は前述のプレイリスト作成と同様で、プレイリストアイテムの snippet プロパティの値を保持する PlaylistItemSnippet オブジェクトを作成し、それを PlaylistItem オブジェクトの setSnippet() に渡してセットし、PlaylistItem オブジェクト $playlistItem をセットアップする。そして、$youtube->playlistItems->insert('snippet', $playlistItem, []) でAPIリクエストを行い、プレイリストにプレイリストアイテムを挿入し、動画一つのインポートが完了する。

違う点は、プレイリストアイテムとプレイリストの紐付け、また、プレイリストアイテムと動画IDを紐付けるために ResourceId オブジェクトを作成する必要があるというところ。

プレイリストアイテムとプレイリストの紐付けは、PlaylistItemSnippet オブジェクトの setPlaylistId() にプレイリストIDを渡して行う。

プレイリストアイテムと動画IDの紐付けは、ResourceId オブジェクトを作成し、setVideoId() で動画IDをセット、setKind() でリソースタイプをセットする。リソースタイプは動画の場合、youtube#video となる。そして、ResourceId オブジェクトを PlaylistItemSnippet オブジェクトの setResourceId() に渡し、プレイリストアイテムと動画IDが紐付けられる。