YouTubeライブ番組予約をXで告知補助するツールを作る

YouTubeチャンネルでライブ番組を予約した際に、自動で内容を取得して **X（旧Twitter）** に告知投稿を補助する PowerShell スクリプトを作成しました。
毎回手作業するのが面倒だったので・・・。

## 🎯 目的

* **未来のYouTubeライブイベント**のみを対象に、次回のライブ配信を検出
* ライブの **タイトル・概要・URL** を取得
* Twitterの投稿フォームを自動でブラウザに開き、**ワンクリックで告知投稿できる状態にする**

---

## 🧰 使用ツール

* [`yt-dlp`](https://github.com/yt-dlp/yt-dlp)（YouTube動画の情報を取得）
* PowerShell（スクリプトロジック）
* Webスクレイピング（HTMLから概要・タイトル取得）
* 任意のブラウザ（Twitterの投稿画面を開く）
* Windowsバッチ（起動補助）

---

## 💡 機能概要

* 対象チャンネルの `@ユーザー名/streams` ページを解析
* `yt-dlp` を使って最大10件のライブ配信情報を取得
* 各動画IDのページを開き、HTMLから `<meta>` や JSONスニペットを使って **タイトルと概要** を抽出
* `概要文` は特定の区切り文字（例：`《クレジット》`）でトリミング
* 結果を **Twitter投稿用のテキスト** に整形し、投稿画面を開く

---

## 💻 実装コード

### PowerShell スクリプト：`YouTubeLiveTweet.ps1`
(文字コードをUTF-8「BOM付き」で保存して下さい！)
```powershell
# 必要なモジュールのインポートと初期設定
$ErrorActionPreference = "Stop"
$youtubeChannelUrl = "https://www.youtube.com/@your_channel_name/streams"
# yt-dlpの絶対パスを設定（環境に応じて変更してください）
$ytDlpPath = "C:\programs\yt-dlp\yt-dlp.exe"

# 概要文の切り出し用文字列
$descriptionCutoff = "《クレジット》"
# 現在の日時（UNIXタイムスタンプ用）
$currentUnixTime = [int64]((Get-Date).ToUniversalTime() - (Get-Date "1970-01-01")).TotalSeconds

# yt-dlpでライブイベント情報を取得（最大10件）
function Get-LiveEvents {
    param (
        [string]$url
    )
    try {
        # yt-dlpでJSON形式の情報を取得、最大10件に制限
        $command = "& `"$ytDlpPath`" --dump-json --flat-playlist --no-warnings --playlist-items 1-10 `"$url`""
        $jsonOutput = Invoke-Expression $command | ForEach-Object { ConvertFrom-Json $_ }
        return $jsonOutput
    }
    catch {
        Write-Error "yt-dlpでの情報取得に失敗しました: $_"
        exit 1
    }
}

# HTMLからタイトルと概要を取得
function Get-EventDetails {
    param (
        [string]$videoId
    )
    $videoUrl = "https://www.youtube.com/watch?v=$videoId"
    try {
        # WebページのHTMLを取得
        $response = Invoke-WebRequest -Uri $videoUrl -UseBasicParsing
        $htmlContent = $response.Content

        # タイトルの抽出（<meta name="title">タグから）
        $titlePattern = '<meta name="title" content="([^"]+)"'
        if ($htmlContent -match $titlePattern) {
            $title = $matches[1]
        }
        else {
            $title = "タイトルが見つかりませんでした"
        }

        # 概要の抽出
        $descriptionPattern = 'attributedDescription":{"content":"([^"]+)"'
        if ($htmlContent -match $descriptionPattern) {
            $description = $matches[1]
            # 概要文を指定文字列の手前まで切り出し
            $cutoffIndex = $description.IndexOf($descriptionCutoff)
            if ($cutoffIndex -ge 0) {
                $description = $description.Substring(0, $cutoffIndex).Trim()
            }
            # \nを実際の改行に置換
            $description = $description.Replace('\n', "`n")
        }
        else {
            $description = "概要が見つかりませんでした"
        }

        return @{
            Title       = $title
            Description = $description
            Url         = $videoUrl
        }
    }
    catch {
        Write-Warning "ビデオID $videoId の詳細取得に失敗しました: $_"
        return $null
    }
}

# Twitter投稿用のテキストを生成
function Format-TwitterPost {
    param (
        [hashtable]$event
    )
    # タイトル\n概要文\nURLの形式で整形
    $post = "$($event.Title)`n$($event.Description)`n$($event.Url)"
    return $post
}

# Twitter投稿リンクを生成してブラウザで開く
function Post-ToTwitter {
    param (
        [string]$text
    )
    $encodedText = [Uri]::EscapeDataString($text)
    $twitterUrl = "https://twitter.com/intent/tweet?text=$encodedText"
    Start-Process $twitterUrl
}

# メイン処理
Write-Host "YouTubeライブイベント情報を取得中（最大10件）..."
$liveEvents = Get-LiveEvents -url $youtubeChannelUrl

if (-not $liveEvents) {
    Write-Host "ライブイベントが見つかりませんでした。"
    exit 0
}

# 未来のイベントIDを格納する配列
$futureEventIds = @()

# 未来のイベントを特定
foreach ($event in $liveEvents) {
    $videoId = $event.id
    $releaseTimestamp = $event.release_timestamp

    if (-not $videoId) {
        Write-Warning "ビデオIDが見つかりませんでした。スキップします。"
        continue
    }

    if (-not $releaseTimestamp) {
        Write-Warning "ビデオID $videoId にrelease_timestampが見つかりませんでした。スキップします。"
        continue
    }

    # release_timestampが現在よりも未来かチェック
    if ($releaseTimestamp -gt $currentUnixTime) {
        $futureEventIds += $videoId
    }
}

if (-not $futureEventIds) {
    Write-Host "未来のライブイベントが見つかりませんでした。"
    exit 0
}

# 最後の未来イベント（直近の未来イベント）を取得
$lastFutureVideoId = $futureEventIds | Select-Object -Last 1
Write-Host "直近の未来のライブイベントを検出（ビデオID: $lastFutureVideoId）"

# イベントの詳細を取得
$eventDetails = Get-EventDetails -videoId $lastFutureVideoId
if (-not $eventDetails) {
    Write-Host "未来のライブイベントの詳細を取得できませんでした。"
    exit 0
}

Write-Host "未来のライブイベントを検出: $($eventDetails.Title)"

# Twitter投稿用のテキストを生成
$twitterPost = Format-TwitterPost -event $eventDetails
Write-Host "Twitter投稿内容:`n$twitterPost"

# Twitter投稿リンクを開く
Post-ToTwitter -text $twitterPost

Write-Host "処理が完了しました。"
```

### バッチ起動ファイル：`YouTubeLiveTweet.bat`

```bat
@echo off
powershell -ExecutionPolicy Bypass -File ".\YouTubeLiveTweet.ps1" %*
pause
```

---

## 📝 実行前の準備

1. **`yt-dlp.exe` をダウンロード**
   [https://github.com/yt-dlp/yt-dlp/releases](https://github.com/yt-dlp/yt-dlp/releases) から入手して、任意のフォルダに配置。

2. **スクリプト内の `$ytDlpPath` を実環境に合わせて修正**

   ```powershell
   $ytDlpPath = "C:\programs\yt-dlp\yt-dlp.exe"
   ```

3. **対象のYouTubeチャンネルURLを `$youtubeChannelUrl` に設定**

---

## ✅ 実行例

* 実行すると、次のような出力が表示され、ブラウザでTwitter投稿画面が開きます：

```
YouTubeライブイベント情報を取得中（最大10件）...
直近の未来のライブイベントを検出（ビデオID: XXXX）
未来のライブイベントを検出: 【配信タイトル】
Twitter投稿内容:
【配信タイトル】
【概要抜粋】
https://www.youtube.com/watch?v=XXXX
```

---

## 🔒 注意点

* Webスクレイピングを行っているため、YouTubeの仕様変更により動作しなくなる可能性があります。
* `Twitter API` は使っておらず、**あくまで投稿画面を開くだけ** なので認証不要で手軽です。
---

## 🏁 おわりに

YouTube配信者や応援アカウントが **ライブの告知を忘れずに手軽に投稿する** のをサポートするスクリプトです。ChatGPT,Grokに補助してもらいながら作りました。

応用として、BlueskyやMisskeyなど複数サイトの投稿画面を開くのもよいかもしれませんね。修正して試してみてください

---