毎朝決まった時刻に発生する数分の手作業は、自動化の最有力候補です。
今回は「予約公開されるYouTube動画を、公開されたタイミングで紹介サイトへ反映する」という運用を、YouTube Data API・OAuth・Windowsのタスクスケジューラを組み合わせて完全自動化した実例を、技術寄りに解説します。AI(Claude)と対話しながら15分ほどで組み上げた流れと、要所の勘どころ(ブランドアカウントの扱いや設計判断)が中心です。
やりたいこと

題材は、ある音楽配信企画です。
全7曲の動画曲を、YouTubeの予約公開(scheduled)で毎朝8:00に1曲ずつ自動公開していきます。一方、それを紹介する静的サイト(GitHub Pages)側には各曲の枠があり、公開前は「準備中」のプレースホルダ、公開後は実際のプレーヤー埋め込みに差し替える――この差し替えが毎朝の手作業でした。
つまり必要なのは、(1) その日に公開済みになった動画を判定し、(2) サイトのHTMLを書き換えて、(3) git push する、という3ステップを毎朝自動で回す仕組みです。
Google Cloud と OAuth のセットアップ
YouTubeの動画情報をプログラムから読み書きするには YouTube Data API v3 を使います。手順は概ね次の通りです。
- Google Cloud Console でプロジェクトを作成し、「YouTube Data API v3」を有効化する(これを忘れると最初のAPIコールが
accessNotConfiguredで弾かれる)。 - OAuth同意画面を構成。自分のチャンネルを操作するだけでも、書き込み系スコープ
youtube.force-sslはユーザー認可(OAuth 2.0)が必須。User Typeを「外部」にし、自分のアカウントをテストユーザーに追加する。 - 認証情報として「OAuthクライアントID(デスクトップアプリ)」を作成し、
client_secret.jsonをダウンロード。 - 初回だけブラウザ認可フローを通すと
token.json(アクセストークン+リフレッシュトークン)が生成され、以後はこれを使い回す。
ここまでで「APIキーだけで済むだろう」と思いがちですが、自分のチャンネルの非公開情報(予約公開中の動画など)にアクセスするにはOAuthが要るのがポイントです。APIキーは公開データの読み取り専用と割り切るのが安全です。
ブランドアカウントで「1アカウント複数チャンネル」を使い分ける

YouTubeにはブランドアカウントという仕組みがあり、1つのGoogleアカウントで複数のチャンネルを保有・管理できます。個人用チャンネルとは別に、作品やプロジェクトごとにチャンネルを分けられる正規の機能です。しかも各チャンネルはAPI(=Claude Codeからの操作)で個別に扱えるため、動画のアップロードもタイトル変更もチャンネル単位で自動化でき、複数チャンネル運用と相性が良いのが魅力です。
実装で押さえておきたいのは認証(OAuth)まわりの仕様です。channels.list(part=..., mine=true) は認可トークンが紐づくチャンネルを返すため、複数チャンネルを持つアカウントでは、OAuthの認可フローで表示される「チャンネルを選択」画面で操作対象のチャンネルを選んでおくのがポイントです。これさえ理解すれば、チャンネルごとにトークンを分けて、それぞれを独立に自動運用できます(最初に個人用チャンネルが返ってきても、再認可で対象を選び直せば切り替わります)。
運用上の注意 ― テスト公開状態だとリフレッシュトークンが7日で失効
OAuth同意画面を「テスト」状態のまま運用すると、発行されたリフレッシュトークンは約7日で失効します。短期間のジョブなら問題ありませんが、恒久運用するなら同意画面を「本番(公開)」に切り替えるか、失効時に再認可する運用を前提に設計しておく必要があります。自動化を“仕込んで放置”する場合に効いてくる落とし穴です。
公開検知とサイト反映のロジック
核心は「公開済みかどうか」の判定です。アップロード済みでも予約公開中の動画は privacyStatus = private+publishAt(公開予定時刻)を持つため、videos.list(part="status") を見て privacyStatus == "public" のものだけを反映対象にします。これで「まだ公開されていない動画を誤って埋め込む」事故を防げます。
# 1. OAuth(token.json を再利用。無ければブラウザ認可)
yt = get_service()
# 2. 公開済み動画だけ抽出(予約公開中の private は除外)
published = {v.id for v in uploads if v.status.privacyStatus == "public"}
# 3. サイトHTMLを冪等に書き換え
# 「準備中」プレースホルダ → プレーヤー埋め込み
# 既に反映済みならスキップ。変更があれば git commit & push
# 全曲反映し終えたら、自分のスケジュールタスクを自己削除
書き換えは冪等に設計するのがコツです。該当トラックが「準備中」の正規表現にマッチした時だけ差し替えるので、何度実行しても二重反映や差し戻しが起きません。差分があったときだけ git commit & push し、GitHub Pagesの再ビルドに任せます。
なぜクラウドSaaSでなく「ローカルのタスクスケジューラ」なのか

自動化というとGAS・各種iPaaS・サーバーレス関数などクラウド側を思い浮かべがちです。しかし今回、書き換える対象(サイトのソース)も、git pushの認証情報も、OAuthのトークンもすべてローカルPC上にありました。これらをクラウドのジョブから触らせるには、リポジトリのホスティング・シークレット管理・CI連携……と一気に大掛かりになります。
対象が手元で完結しているなら、Windows標準のタスクスケジューラで十分です。今回は次のように設定しました。
- 毎朝8:05(公開の5分後)に実行。実行ユーザーの権限で動くので、保存済みのgit認証情報(資格情報マネージャー)をそのまま使える。
StartWhenAvailableを有効化。8:05にPCがスリープ/オフでも、次回起動時に取りこぼし実行される。EndBoundaryで公開期間の翌日に自動失効。さらにスクリプト側でも「全曲反映後はタスク自身をschtasks /Deleteで消す」自己終了を実装し、二重に後始末。
月額0円、外部にデータも出ず、PowerShellの Register-ScheduledTask 数行で登録できます。「流行りの基盤」ではなく「要件に合う最小の道具」を選ぶ、という判断です。
AIと“壁打ち”で組むということ

面白かったのは、セットアップ中の細かな詰まり(APIの有効化もれや、複数チャンネルでの認可対象の選択など)を、AIとの対話でその場で切り分けて解消できたことです。エラーメッセージを渡す→原因仮説を出す→確認する、という往復を数回回すだけで抜けられました。AIは万能の魔法ではなく、文脈を正確に渡すほど精度が上がる“非常に優秀な新人”です。
完全な丸投げよりも、設計判断(クラウドかローカルか、冪等性をどう担保するか)を人間が握り、実装と切り分けをAIに高速で回させる分業が、こうした自動化では一番速いと感じます。
まとめ
結果、翌朝から「動画が予約公開される→サイトに自動反映される」が人手ゼロで回り、全曲反映後は仕組み自体が後始末をして消えるところまで作り切れました。ポイントを再掲します。
- 自分のチャンネルの非公開情報を扱うなら、APIキーでなくOAuth(
youtube.force-ssl)。ブランドアカウントを使えば1アカウントで複数チャンネルを個別に自動運用でき、認可時に対象チャンネルを選ぶのがコツ。 - 公開判定は
privacyStatus == "public"。予約公開中の動画を誤って埋め込まない。 - 対象がローカル完結なら、クラウドよりタスクスケジューラ+スクリプトが速く・安く・安全。
「毎日決まった時刻にやっている小さな作業」は、たいてい同じ型で自動化できます。
まずは1つ、API設定とローカルスケジューラの組み合わせから試してみてください。

