「Google Apps Script」カテゴリーアーカイブ

【Google Apps Script】Youtube動画の公開/非公開を切り替える

最近知ったのですが、Google Apps Scriptというのがあって、Googleドライブ上に作成したドキュメントやGoogleの各サービスをjavaScriptペースでハンドリングできるらしい。

【参考】
ASCII.jp:Web制作をちょっと便利にするGoogle Apps Script入門

※わかりやすいですが、ちょっと古い記事なのでメニューの場所などが現在のものと違っていたりします。

ちょうど必要があって、Youtube動画の公開/非公開を切り替えるスクリプトを考えてみました。

まず近そうなもので参考にしたのはこの辺。

【参考】
GoogleAppsScript – 公開されたGASのYouTubeAPIを少し使ってみた。 – Qiita
GoogleAppsScript – GASでYouTubeの自分の再生リストを全て非公開にする。 – Qiita

※参考ページにもありますが、YoutubeのAPIは拡張サービスという位置付けで、YouTube Data APIの有効化と承認が必要になります。

基本的にはYoutube Data APIをそのままJavaScriptの書式で書けばいいということなんですが、リストの取り方が・・・

Channels(チャンネル)
Playlists(再生リスト)
PlaylistItems(再生リストの項目)
Videos(動画)

といくつかあって、公開/非公開の切替は動画IDが必要になるのだけれど、確認した限りでは動画IDを含んだ結果を返すものは、

・PlaylistItems(再生リストの項目)
・Videos(動画)

の2つみたいです。

ただPlaylistItems(再生リストの項目)でのリスト取得も、Videos(動画)でのリスト取得もidまたはplaylistidが必要になります。Playlistは必ず作成するとは限らないし、Channels(チャンネル)から辿っていくのも大変そうだしと思ってAPIを見ていたら、Search(検索)のリスト取得に「forMine」という自分のIDに紐付いたものだけを検索するフィルタがあったので、これを使うことにしました。

とりあえず自分のIDに紐付いた動画idを取得して、スプレッドシートに書き出すのはこんな感じ。

//---自分のvideoを検索する
function searchMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', 
                                     {maxResults: 50,
                                      forMine: true,
                                      order: "date",
                                      type: "video",
                                      pageToken: nextToken});
    
    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
  
  if (arrayId.length > 0){
    getMyVideoList(arrayId);
  }
 
  Browser.msgBox("動画一覧を取得しました。");
}

//---videoの詳細情報を取得
function getMyVideoList(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  var arrayStatus = [];
  
  var sheetId = '**********************************';
  var spreadsheet = SpreadsheetApp.openById(sheetId);
  var newsheet = SpreadsheetApp.openById(sheetId).getSheetByName('動画リスト');
  newsheet.getRange(1, 1).setValue('id');
  newsheet.getRange(1, 2).setValue('タイトル');
  newsheet.getRange(1, 3).setValue('作成日');
  newsheet.getRange(1, 4).setValue('公開/非公開/限定公開');
  
  var count = 2;
  
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});

    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
);
      
      arrayStatus.push(item.snippet.title + ";" + item.status.privacyStatus);
      
      newsheet.getRange(count, 1).setValue(item.id);
      newsheet.getRange(count, 2).setValue(item.snippet.title);
      newsheet.getRange(count, 3).setValue(item.snippet.publishedAt);
      newsheet.getRange(count, 4).setValue(item.status.privacyStatus);
      count++;
    }

    nextToken = playlistResponse.nextPageToken;

  }
}

検索で取得できるリストの項目数は最大50件で、続きがある場合は「nextPageToken」に何かしらの値が入ってくるようなので、値がある場合は処理を繰り返しています。で、リストを取得するごとに配列(arrayId)に動画id(item.id.videoId)を保存しておいて、検索が終わったらまとめてスプレッドシートに書き出しています。

また「var sheetId = ‘**********************************’;」にはスプレッドシートのidを指定するのですが、これは・・・

function checkId(){
  Logger.log(SpreadsheetApp.getActiveSpreadsheet().getId());
}

を実行してログの出力結果から取得するか、スプレッドシートのURLの・・・

https://docs.google.com/spreadsheets/d/**********/edit#gid=xxxxxxxx

「**********」の部分から取得できます。この例だと「**********」というidのスプレッドシートの「動画リスト」という名前のタブのシートを指定していることになります。

続いて、動画を全部非公開にするのはこんな感じ。

//---自分のvideoを非公開にする
function setPrivateMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', 
                                     {maxResults: 50,
                                      forMine: true,
                                      order: "date",
                                      type: "video",
                                      pageToken: nextToken});
    
    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
  
  if (arrayId.length > 0){
    updatePrivacyStatus_private(arrayId);
  }
  Browser.msgBox("全ての動画を非公開にしました。");
}

//---VideoのprivacyStatusをprivateに変更する
function updatePrivacyStatus_private(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});

    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
      if(item.status.privacyStatus != "private") {
        item.status.privacyStatus = "private";
        var updateRes = YouTube.Videos.update(item, "status,snippet");
      }

    }

    nextToken = playlistResponse.nextPageToken;

  }
}

スプレッドシートに書き出す代わりに、ステータス(item.status.privacyStatus)が非公開(private)でないものを非公開に更新しています。

最後に全て公開するにはこうします。

//---自分のvideoを公開する
function setPublicMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', 
                                     {maxResults: 50,
                                      forMine: true,
                                      order: "date",
                                      type: "video",
                                      pageToken: nextToken});
    
    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
  
  if (arrayId.length > 0){
    updatePrivacyStatus_public(arrayId);
  }
  Browser.msgBox("全ての動画を公開しました。");
}

//---VideoのprivacyStatusをpublicに変更する
function updatePrivacyStatus_public(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});

    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];

      if(item.status.privacyStatus != "public") {
        item.status.privacyStatus = "public";
        var updateRes = YouTube.Videos.update(item, "status,snippet");
      }

    }

    nextToken = playlistResponse.nextPageToken;

  }
}

こちらではステータス(item.status.privacyStatus)が公開(public)でないものを公開に更新しています。

ちなみに処理が終わったのを確認するために「Browser.msgBox();」でポップアップを表示しているのですが、これを処理の途中で挟むと、処理が途中までしか実行されないということがありました。原因はよくわからないですが、あくまで確認用ということで余り使わない方がいいかも。

それからログ書きだし(Logger.log())はAPIの呼び出しごとにリセットされるようで、スクリプトエディタの表示>ログで確認しても最後のAPIの分しか書き出されていません。ASのtrace()やJSのconsole.log()のイメージで使うには、一回変数に入れてから最後に書き出すしかなさそうです。