タイトル: YouTube Data API (v3)
SEOタイトル: YouTube Data API v3 入門 — 認証・主要エンドポイント・クォータ・サンプルコード
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>事前準備</strong>: Google Cloud Console でプロジェクト作成 → <strong>YouTube Data API v3</strong> 有効化 → 認証情報作成(API キー or OAuth クライアント ID)</li><li><strong>API キー</strong>: 公開データ読み取り専用(動画情報・検索など)。<strong>OAuth 2.0</strong>: 自分のチャンネル操作(アップロード・コメント投稿)に必要</li><li>主要エンドポイント: <code>videos.list</code> / <code>search.list</code> / <code>channels.list</code> / <code>playlistItems.list</code> / <code>commentThreads.list</code></li><li><strong>クォータ制限</strong>: デフォルト 10,000 ユニット/日。<code>search.list</code> = 100、<code>videos.list</code> = 1 と非常に偏る</li><li><strong>part パラメータ</strong>: 取得フィールドを指定(<code>snippet,statistics,contentDetails</code>)。多いほどレスポンスが膨らむ</li><li>JS から呼ぶ場合は <strong>gapi クライアントライブラリ</strong>。サーバ側は <code>google-api-php-client</code> / <code>google-api-python-client</code></li></ul></td></tr></table>
<h2>事前準備: Google Cloud Console</h2>
<ol>
<li><a href="https://console.cloud.google.com/">Google Cloud Console</a> にアクセス</li>
<li>新規プロジェクト作成 (または既存プロジェクト選択)</li>
<li>左メニュー <strong>API とサービス → ライブラリ</strong></li>
<li><strong>YouTube Data API v3</strong> を検索 → 有効化</li>
<li><strong>認証情報</strong> → <strong>+ 認証情報を作成</strong>:
<ul>
<li><strong>API キー</strong>: 公開データ読み取り用。すぐ発行</li>
<li><strong>OAuth クライアント ID</strong>: ユーザー認可が必要な操作用。同意画面の設定が必要</li>
</ul>
</li>
<li>API キーは <strong>HTTP リファラ制限 / IP 制限</strong>を設定してリーク対策</li>
</ol>
<h2>主要エンドポイント</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>エンドポイント</th><th>用途</th><th>クォータコスト</th></tr></thead>
<tbody>
<tr><td><code>videos.list</code></td><td>動画情報取得(指定 ID)</td><td>1</td></tr>
<tr><td><code>search.list</code></td><td>キーワード検索</td><td><strong>100</strong></td></tr>
<tr><td><code>channels.list</code></td><td>チャンネル情報</td><td>1</td></tr>
<tr><td><code>playlists.list</code></td><td>再生リスト一覧</td><td>1</td></tr>
<tr><td><code>playlistItems.list</code></td><td>再生リスト内動画</td><td>1</td></tr>
<tr><td><code>commentThreads.list</code></td><td>コメント取得</td><td>1</td></tr>
<tr><td><code>videos.insert</code></td><td>動画アップロード</td><td>1,600</td></tr>
<tr><td><code>liveBroadcasts.list</code></td><td>ライブ配信</td><td>1</td></tr>
</tbody>
</table>
<h2>JavaScript (ブラウザ) からの呼び出し</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><script src="https://apis.google.com/js/api.js"></script>
<script>
const API_KEY = 'YOUR_API_KEY';
async function init() {
await gapi.load('client', async () => {
await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest'],
});
searchVideos('Laravel');
});
}
async function searchVideos(query) {
const res = await gapi.client.youtube.search.list({
part: 'snippet',
q: query,
type: 'video',
maxResults: 10,
order: 'relevance', // date / rating / viewCount / relevance
});
res.result.items.forEach(item => {
console.log(item.id.videoId, item.snippet.title);
});
}
init();
</script></code></pre>
<h2>シンプルな HTTP リクエスト</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash"># API キーで動画情報取得
curl "https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id=dQw4w9WgXcQ&key=YOUR_API_KEY"
# 検索
curl "https://www.googleapis.com/youtube/v3/search?part=snippet&q=Laravel&type=video&maxResults=5&key=YOUR_API_KEY"
# チャンネル情報
curl "https://www.googleapis.com/youtube/v3/channels?part=snippet,statistics&forHandle=@GoogleDevelopers&key=YOUR_API_KEY"</code></pre>
<h2>PHP からの呼び出し</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php
// composer require google/apiclient
require __DIR__ . '/vendor/autoload.php';
$client = new Google\Client();
$client->setDeveloperKey('YOUR_API_KEY');
$youtube = new Google\Service\YouTube($client);
// 検索
$response = $youtube->search->listSearch('snippet', [
'q' => 'Laravel チュートリアル',
'type' => 'video',
'maxResults' => 10,
'order' => 'viewCount',
'regionCode' => 'JP',
]);
foreach ($response->items as $item) {
echo $item->id->videoId . ' — ' . $item->snippet->title . "\n";
}
// 動画詳細
$videos = $youtube->videos->listVideos('snippet,statistics,contentDetails', [
'id' => 'dQw4w9WgXcQ',
]);
foreach ($videos->items as $v) {
echo $v->snippet->title . "\n";
echo "views: " . $v->statistics->viewCount . "\n";
echo "duration: " . $v->contentDetails->duration . "\n"; // ISO 8601 PT4M13S
}</code></pre>
<h2>part パラメータの主な値</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>part 値</th><th>含まれる情報</th></tr></thead>
<tbody>
<tr><td><code>snippet</code></td><td>タイトル、説明、サムネ、公開日、チャンネル名</td></tr>
<tr><td><code>statistics</code></td><td>視聴数、いいね数、コメント数</td></tr>
<tr><td><code>contentDetails</code></td><td>動画長さ (ISO 8601)、画質、字幕有無、年齢制限</td></tr>
<tr><td><code>status</code></td><td>公開状態、組込許可、ライセンス</td></tr>
<tr><td><code>player</code></td><td>埋込用 iframe HTML</td></tr>
<tr><td><code>topicDetails</code></td><td>Wikipedia トピック関連</td></tr>
</tbody>
</table>
<p>カンマ区切りで複数指定: <code>part=snippet,statistics,contentDetails</code>。<strong>必要なものだけにしてクォータ節約</strong>。</p>
<h2>クォータ管理</h2>
<ul>
<li>デフォルト <strong>10,000 ユニット/日</strong>。日本時間 16:00 / 17:00 (PST 0:00) にリセット</li>
<li><code>search.list</code> は <strong>1 リクエスト = 100 ユニット</strong>。100 回叩くと枯渇</li>
<li>不足する場合は <strong>クォータ拡張申請</strong>(フォーム提出 → 数週間レビュー)</li>
<li>節約テク: <code>fields</code> パラメータで返却フィールドを絞る、<strong>結果キャッシュ</strong>、ID 既知なら <code>videos.list</code>(コスト 1)に切替</li>
</ul>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-text"># fields パラメータ例 — 必要だけ取り出す
?part=snippet,statistics
&fields=items(id,snippet/title,statistics/viewCount)</code></pre>
<h2>OAuth が必要な操作</h2>
<p>自分のチャンネルへの<strong>動画アップロード</strong>、<strong>プレイリスト編集</strong>、<strong>コメント投稿</strong>は API キーでは不可。OAuth 2.0 認可フローが必要です:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php
$client = new Google\Client();
$client->setClientId('CLIENT_ID');
$client->setClientSecret('CLIENT_SECRET');
$client->setRedirectUri('http://localhost/oauth2callback.php');
$client->addScope(Google\Service\YouTube::YOUTUBE_UPLOAD);
if (!isset($_GET['code'])) {
header('Location: ' . $client->createAuthUrl());
exit;
}
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$client->setAccessToken($token);
// これで OAuth 必須 API も呼べる
$youtube = new Google\Service\YouTube($client);
// $youtube->videos->insert(...)</code></pre>
<h2>FAQ</h2>
<p><strong>Q: API キーが漏洩した</strong><br />
A: Cloud Console から即座に削除し、新規発行。リファラ制限 / IP 制限を必ず設定。フロントエンド埋込は最小限の権限のみ。</p>
<p><strong>Q: search.list でフィルタしたら結果がおかしい</strong><br />
A: <code>order=relevance</code> がデフォルト。再現性が必要なら <code>order=date</code> + 日付フィルタ。<code>publishedAfter</code> / <code>publishedBefore</code> は <strong>RFC 3339</strong> 形式。</p>
<p><strong>Q: クォータが枯渇したらどうなる</strong><br />
A: <code>quotaExceeded</code> エラーで全リクエストが失敗。翌日リセットまで待つか、別プロジェクトの API キーを発行。長期的にはキャッシュ / バックエンド集約が必須。</p>