GAS×YouTube自動化!クォータ節約実装術
自治体や地元の事業者で公式YouTubeチャンネルを運営している際、更新情報の管理やWeb・アプリへの転記作業に手間を感じていませんか?
本記事では、Google Apps Script(GAS)とYouTube Data API v3を活用し、指定チャンネルの最新動画情報をGoogleスプレッドシートへ自動挿入・蓄積する完全決定版コードを解説します。
単にAPIを呼び出すだけでなく、検索時と詳細取得時で役割分担を行い、APIクォータ(利用制限上限)の消費量を激減させる実践的なテクニックをまとめました。
【概要】GAS×YouTube APIで動画情報を自動集約するメリット
GASとYouTube Data API v3を連携させることで、公式チャンネルの動画更新監視からデータ格納までの全プロセスを全自動化できます。
手動での転記作業をゼロにするだけでなく、ノーコードツール(Glideなど)のデータソースとしても即座に活用可能です。
| 課題・従来の手順 | 本手法(GAS自動化)での解決策 | 導入効果 |
|---|---|---|
| 動画投稿のたびにスプレッドシートを手動更新 | トリガー実行で24時間自動検知・自動書き込み | 更新モレ・手入力ミスの完全排除 |
| APIクォータ(1日10,000ユニット)の上限超過 | Search.list(IDのみ)+ Videos.list(一括取得)の2段階設計 | クォータ消費を約9割カット |
| 重複データや古いログの蓄積 | 最新行(2行目)への挿入 + 重複URLチェック&保持行数制限 | 常に最新データのみを最適化保持 |
主な活用シーン(秋田・東北の自治体DX・地域DX)
- 自治体広報: 広報課YouTubeチャンネルの更新情報を広報ポータルサイトへ同期
- 地域観光・イベント: 観光協会のPR動画一覧を市民向けポータルアプリに自動反映
- 社内ナレッジ: 自社動画マニュアルの公開状況をスプレッドシートで一元管理
実装コードと主要ロジックの解説
以下がYouTube動画の最新情報を取得し、スプレッドシートへ安全かつ効率的に書き込む全コードです。
/**
* ====================================================================
* Utility Module for GAS / Civic Tech Akita
* Copyright (c) Civic Tech Akita (https://akita-csmedia.com/)
*
* 本モジュールは Civic Tech Akita の留保知的財産権(自社資産)です。
* ライセンス・実装に関するお問い合わせ: https://akita-csmedia.com/?page_id=1476
* ====================================================================
*/
/**
* 機能: 市政情報・地域情報集約(YouTube更新)
* 動画詳細を「id,snippet」パートで明示的に取得する最終安定版
*/
function updateYouTube() {
// 設定値の読み込み(PropertiesService等での管理を推奨)
const properties = PropertiesService.getScriptProperties();
const channelId = properties.getProperty('YOUTUBE_CHANNEL_ID');
const sheetName = properties.getProperty('SHEET_YT_NAME') || 'YouTubeData';
const maxHistoryRows = parseInt(properties.getProperty('MAX_HISTORY_ROWS') || '100', 10);
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
if (!sheet) {
console.error("対象のスプレッドシートが見つかりません: " + sheetName);
return;
}
// 1. まず動画IDのリストを取得(ここではIDだけに限定してクォータ節約)
const searchResults = YouTube.Search.list('id', {
channelId: channelId,
maxResults: 10,
order: 'date',
type: 'video'
});
if (!searchResults.items || searchResults.items.length === 0) {
console.warn("動画が見つかりませんでした");
return;
}
// 動画IDをカンマ区切りの文字列として抽出
const videoIds = searchResults.items.map(item => item.id.videoId).join(',');
// 2. Videos.listで「snippet」を一括取得(ID指定で詳細をまとめる)
const videoDetails = YouTube.Videos.list('id,snippet', {
id: videoIds
});
// 既存データ(C列: URL)の取得で重複判定の準備
const lastRow = sheet.getLastRow();
const existingUrls = lastRow > 1 ? sheet.getRange(2, 3, lastRow - 1, 1).getValues().flat() : [];
// 3. ループ内で重複チェックを行いながら最新行(2行目)へ挿入
videoDetails.items.forEach(item => {
const videoId = item.id;
const title = item.snippet.title;
const url = 'https://www.youtube.com/watch?v=' + videoId;
// 概要欄。万が一空の場合の対策として代替文字を挿入
const description = item.snippet.description || "(概要欄なし)";
const publishedAt = new Date(item.snippet.publishedAt);
if (!existingUrls.includes(url)) {
// 常に2行目に差し込むことで降順(新しい順)を維持
sheet.insertRowBefore(2);
// 列A:日付, B:タイトル, C:URL, D:概要欄
sheet.getRange(2, 1, 1, 4).setValues([[publishedAt, title, url, description]]);
console.log("追加成功: " + title);
}
});
// データ保持制限(規定行数を超えた古いログを削除する別関数の呼び出し)
if (typeof rotateData === 'function') {
rotateData(sheet, maxHistoryRows);
}
Step 1. YouTube.Search.list で動画IDのみを取得(軽量化)
YouTube.Search.list メソッドを呼び出す際、第1引数のパート指定を 'id' のみに絞り込むことが極めて重要です。
snippet(タイトルや概要欄などの詳細情報)を含めて検索 API を叩くと、APIの消費クォータが膨れ上がります。まずは動画の存在確認とID(videoId)の抽出だけに用途を絞ることで、検索フェーズの負荷を最小化しています。
Step 2. YouTube.Videos.list で id,snippet を一括取得(クォータ節約)
ステップ1で取得した複数の videoId をカンマ区切り(video1,video2,video3...)で結合し、YouTube.Videos.list へ1回のAPIリクエストでまとめて送信します。
個別にループで詳細を取得すると「10件=10回リクエスト」となりますが、この方式であれば「1回のリクエスト」で10件分のタイトル・概要欄・投稿日時(snippet)を取得できます。クォータ節約の観点から最も効果的な設計パターンです。
Step 3. 重複チェックとスプレッドシート最新行への挿入
重複書き込みを防止するため、スプレッドシートのC列(URL一覧)を事前取得して existingUrls アレイを作成します。
新規動画のみに対して sheet.insertRowBefore(2) を実行し、見出し行直下(2行目)にデータを挿入します。これにより、ソート処理を行わなくても常に「最新投稿が一番上」に来るデータ構造を維持できます。
運用時の注意点とセキュリティ対策
プログラミングおよび実際の運用環境においては、API制限と認証情報の取り扱いに十分な配慮が必要です。
1. APIクォータ(利用制限)の管理
YouTube Data API v3 には、デフォルトで「1日あたり10,000ユニット」の利用上限(クォータ)が設定されています。
- Search.list: 1回の呼び出しで約100ユニット消費
- Videos.list: 1回の呼び出しで約1ユニット消費
1時間ごとの定時トリガーを設定した場合、1日24回の実行で Search.list だけでも 2,400ユニット を消費します。本コードのように呼び出し回数と取得パートを最適化することが、制限回避の必須条件となります。
2. PropertiesService(スクリプトプロパティ)の活用
コード内に YOUTUBE_CHANNEL_ID や設定値をハードコーディングすることは、セキュリティリスクおよびメンテナンス性の低下につながります。
GASのエディタ画面にある 「プロジェクトの設定」>「スクリプト プロパティ」 を使用し、安全に管理してください。
// 安全な読み込み例
const properties = PropertiesService.getScriptProperties();
const channelId = properties.getProperty('YOUTUBE_CHANNEL_ID')
発展・応用例(Glideと連携した情報配信アプリへの拡張)
本スクリプトで集約したGoogleスプレッドシートのデータは、そのままノーコードアプリ作成ツール「Glide」のデータソースとして接続可能です。
活用ステップ
- Glideのデータソースに連携:
本GASが書き込むスプレッドシートをGlideに接続。 - カードビューでレイアウト作成:
タイトル、公開日時、概要欄を綺麗にレイアウトし、タップでYouTubeが開く、またはアプリ内で再生できるUIを作成。 - 地域ポータルアプリへの組み込み
秋田県内の市政ニュース、防災情報動画、地域イベントPR動画などを、市民や観光客がスマホから快適に視聴できるネイティブアプリ感覚のWebアプリを数時間で構築できます。
よくある質問(FAQ)
-
YouTube Data APIをGASで使うための事前準備は?
-
GCP(Google Cloud Platform)でのAPI有効化、またはGASの「拡張サービス」追加が必要です。
最も簡単な方法は、GASエディタの左メニュー「拡張サービス」で「YouTube Data API v3」を選択して追加することです。GCPコンソールで認証キーを発行して UrlFetchApp で通信する方法もありますが、拡張サービスを利用すれば認証処理が自動化されます。
-
定時トリガーで自動実行するとエラーになることがあります。
-
主な原因はAPIのレートリミットまたはネットワーク瞬断です。
GASのトリガー機能で「時間駆動型(例: 1時間ごと)」を設定する際、コード全体を try-catch 文で囲み、エラー発生時には管理者へメール通知(GmailApp.sendEmail)やログ出力(console.error)を行うエラーハンドリングを実装しておくことを推奨します。
-
ショート動画(YouTube Shorts)も取得されますか?
-
はい、通常の動画と同様に取得されます。
もしショート動画を除外したい場合は、item.snippet.title や動画の再生時間(contentDetails.duration)を判別するロジックをステップ2のループ内に追加してください。
まとめ
YouTube Data API v3 と GAS を組み合わせることで、クォータを意識した堅牢な動画自動集約システムを簡単に構築できます。さらにノーコードツール「Glide」と組み合わせることで、収集したデータを魅力的な地域ポータルや社内アプリへ素早く昇華させることが可能です。
「自社や自治体のYouTube・各種SNSデータを集約したい」「Glideを活用して業務効率化アプリを作りたいが開発リソースが足りない」とお悩みの方は、ぜひ Civic Tech Akita へお気軽にご相談ください。
