Youtubeの動画をダウンロードして作業用のプレイリストを作りたい！！！

# YouTube Premium代替！Google ColabでYouTube動画を自動ダウンロード→Google Drive保存する方法

## はじめに

作業用BGM動画を垂れ流すのが好きなのですが、外出先での通信制限や電波の悪さが気になることってありませんか？

- **YouTube Premiumにどうしても入りたくない**
- **外出先でモバイルデータを使わずに動画を見たい**
- **作業用に動画をオフラインで楽しみたい**

そんな悩みを解決するため、Google Colabを使って**YouTube動画を自動ダウンロード→Google Driveに保存→iPhoneで視聴**する方法をAIで作ってみました。

## できること

✅ **YouTubeプレイリストの一括ダウンロード**（480p固定で軽量化）  
✅ **Bot判定回避機能付き**で安定動作  
✅ **Google Driveに自動保存**でiPhoneからすぐアクセス  
✅ **ファイル名に番号付け**で順番通りの再生が可能  
✅ **自分の端末にアプリ不要**（Google Colab完結）

## 環境・必要なもの

- Googleアカウント（Google Colab・Google Drive用）
- YouTube動画・プレイリストのURL
- cookies.txt（限定公開動画の場合のみ）

## 実装コード

以下のコードをGoogle Colabにコピペするだけです：

```python
# YouTube動画ダウンロード→Google Drive保存スクリプト（Google Colab用・480p固定）

# 必要なパッケージのインストール
!pip install yt-dlp

# スクリプト本体
from __future__ import unicode_literals
import yt_dlp
import os
import shutil
import time
from datetime import datetime
from google.colab import drive

def get_cookies_instructions():
    """cookies.txtの作成手順を表示"""
    print("\n" + "="*60)
    print("🍪 cookies.txt作成手順（推奨）")
    print("="*60)
    print("1. ブラウザでYouTubeにログイン")
    print("2. 以下のいずれかの方法でcookiesを取得:")
    print("   📱 Chrome拡張機能「Get cookies.txt LOCALLY」を使用")
    print("   📱 Firefox拡張機能「cookies.txt」を使用")
    print("   🔧 開発者ツールから手動で取得")
    print("3. 取得したcookies.txtをGoogle Colabにアップロード")
    print("4. ファイルを/content/cookies.txtに配置")
    print("5. このスクリプトを再実行")
    print("="*60)

def mount_google_drive():
    """Google Driveをマウント"""
    print("\n📁 Google Driveに接続中...")
    try:
        drive.mount('/content/drive')
        print("✅ Google Drive接続成功")
        return True
    except Exception as e:
        print(f"❌ Google Drive接続失敗: {str(e)}")
        return False

def create_gdrive_folder():
    """Google Drive内にYouTube動画用フォルダを作成"""
    now = datetime.now()
    folder_name = f"YouTube_Videos_{now.strftime('%Y%m%d_%H%M')}"
    gdrive_folder = f"/content/drive/MyDrive/{folder_name}"
    
    os.makedirs(gdrive_folder, exist_ok=True)
    print(f"📂 Google Driveフォルダを作成: {folder_name}")
    return gdrive_folder, folder_name

def main():
    # 開始時刻を記録
    start_time = time.time()
    
    print("🎬 YouTube動画ダウンロード→Google Drive保存ツール（480p固定）")
    print("📝 Bot判定回避機能付き")
    print("=" * 50)
    
    # Google Driveマウント
    if not mount_google_drive():
        print("Google Driveの接続が必要です。再実行してください。")
        return
    
    # cookies作成手順を表示するか確認
    print("\n❓ cookies.txtの作成方法を確認しますか？ (y/n)")
    show_help = input().strip().lower()
    if show_help in ['y', 'yes']:
        get_cookies_instructions()
    
    # 再生リストのリンクを入力
    print("\nYouTubeの再生リストのリンクを入力してください")
    print("（例: https://youtube.com/playlist?list=xxxxxx）")
    print("（個別動画のURLでも対応）")
    playlist_url = input("URL: ").strip()
    
    if not playlist_url:
        print("❌ URLが入力されていません。")
        return
    
    # Google Driveフォルダを作成
    gdrive_folder, folder_name = create_gdrive_folder()
    
    # 一時ダウンロードディレクトリの設定
    download_dir = '/content/temp_downloads'
    if os.path.exists(download_dir):
        shutil.rmtree(download_dir)
    os.makedirs(download_dir, exist_ok=True)
    
    # cookies.txtの存在確認（オプション）
    cookies_path = '/content/cookies.txt'
    use_cookies = os.path.exists(cookies_path)
    if use_cookies:
        print("✅ cookies.txtを使用します（限定公開動画もダウンロード可能）")
    else:
        print("ℹ️ cookies.txtなしで実行します（公開動画のみダウンロード可能）")
    
    # ダウンロードオプションの設定（480p固定・Bot回避対応）
    ydl_opts = {
        'format': 'best[height<=480][ext=mp4]/best[height<=480]/worstvideo[height>=480]+bestaudio/worst[height>=480]',
        'outtmpl': f'{download_dir}/%(playlist_index)03d_%(title)s.%(ext)s',  # 番号付きファイル名
        'ignoreerrors': True,
        'merge_output_format': 'mp4',
        'writeinfojson': False,
        'no_warnings': False,
        'extract_flat': False,
        # Bot回避設定
        'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'referer': 'https://www.youtube.com/',
        'headers': {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'ja,en-US;q=0.5',
            'Accept-Encoding': 'gzip, deflate',
            'DNT': '1',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
        },
        'sleep_interval': 1,
        'max_sleep_interval': 5,
        'sleep_interval_requests': 1,
        'extractor_retries': 3,
        'fragment_retries': 3,
        'postprocessors': [{
            'key': 'FFmpegVideoConvertor',
            'preferedformat': 'mp4',
        }]
    }
    
    # クッキーがある場合のみ追加
    if use_cookies:
        ydl_opts['cookiefile'] = cookies_path
    
    # プレイリスト情報の取得とダウンロード
    print("\n🔍 動画情報を取得中...")
    try:
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            print("⏳ Bot判定回避のため少し待機...")
            time.sleep(2)
            
            info_dict = ydl.extract_info(playlist_url, download=False)
            
            if info_dict is None:
                print("❌ 動画情報の取得に失敗しました。")
                print("💡 対処法:")
                print("   1. 別のプレイリストで試してみる")
                print("   2. 個別動画URLで試してみる")
                print("   3. cookies.txtを用意する")
                return
            
            # プレイリストの場合
            if '_type' in info_dict and info_dict['_type'] == 'playlist':
                print(f"📝 プレイリスト名: {info_dict.get('title', '不明')}")
                entries = info_dict.get('entries', [])
                valid_entries = [e for e in entries if e is not None]
                print(f"📊 動画数: {len(valid_entries)}本")
                
                if len(valid_entries) == 0:
                    print("❌ ダウンロード可能な動画がありません。")
                    return
                else:
                    print("✅ プレイリスト情報の取得に成功")
            else:
                print(f"📝 動画タイトル: {info_dict.get('title', '不明')}")
                print("✅ 個別動画として処理します")
            
            # ダウンロード実行
            print("\n⬇️ ダウンロード開始...")
            print("🤖 Bot判定回避のため、ゆっくりダウンロードします")
            ydl.download([playlist_url])
            
    except Exception as e:
        error_msg = str(e)
        print(f"❌ エラーが発生しました: {error_msg}")
        
        if "Sign in to confirm you're not a bot" in error_msg:
            print("\n🤖 Bot判定エラーが発生しました")
            print("🔧 解決策:")
            print("   1. cookies.txtを用意する（最も確実）")
            print("   2. 時間を空けて再実行する")
            print("   3. 別のプレイリストで試す")
            print("   4. 個別動画URLで試す")
        elif "Private video" in error_msg or "Video unavailable" in error_msg:
            print("\n🔒 限定公開動画エラー")
            print("💡 限定公開動画の場合は、cookies.txtを用意してください。")
        elif "HTTP Error 429" in error_msg:
            print("\n⏰ レート制限エラー")
            print("   しばらく待ってから再実行してください。")
        
        return
    
    # ダウンロードされたファイルの確認
    mp4_files = [f for f in os.listdir(download_dir) if f.endswith('.mp4')]
    
    if not mp4_files:
        print("❌ ダウンロードされた動画ファイルがありません。")
        if not use_cookies:
            print("💡 限定公開動画の場合は、cookies.txtを用意してください。")
        return
    
    print(f"\n✅ {len(mp4_files)}本の動画がダウンロードされました。")
    
    # Google Driveに移動
    print(f"\n📤 Google Driveに移動中...")
    print(f"📂 保存先: {folder_name}")
    
    moved_files = []
    total_size = 0
    
    for i, filename in enumerate(mp4_files, 1):
        src_path = os.path.join(download_dir, filename)
        dst_path = os.path.join(gdrive_folder, filename)
        
        try:
            # ファイルサイズを取得
            file_size = os.path.getsize(src_path) / (1024 * 1024)  # MB
            total_size += file_size
            
            # Google Driveに移動
            shutil.move(src_path, dst_path)
            moved_files.append(filename)
            
            print(f"  {i}/{len(mp4_files)}: {filename[:40]}{'...' if len(filename) > 40 else ''} ({file_size:.1f}MB)")
            
        except Exception as e:
            print(f"❌ 移動失敗: {filename} - {str(e)}")
    
    # 結果表示
    if moved_files:
        print(f"\n✅ Google Driveへの移動完了！")
        print(f"📊 移動ファイル数: {len(moved_files)}本")
        print(f"📦 合計サイズ: {total_size:.1f} MB")
        print(f"📂 Google Driveパス: MyDrive/{folder_name}")
        print(f"🎯 解像度: 480p固定")
        
        print(f"\n📱 iPhoneでの確認方法:")
        print(f"1. Google DriveアプリまたはiPhoneの「ファイル」アプリを開く")
        print(f"2. 「{folder_name}」フォルダを確認")
        print(f"3. 動画を個別にダウンロードまたは直接再生")
        
        # プレイリスト作成の提案
        print(f"\n💡 iPhoneでの連続再生方法:")
        print(f"   - VLCなどの動画プレイヤーアプリを利用")
        print(f"   - ファイル名の番号順で自動再生される場合が多いです")
        
    else:
        print("❌ Google Driveへの移動に失敗しました。")
    
    # 一時フォルダのクリーンアップ
    if os.path.exists(download_dir):
        shutil.rmtree(download_dir)
        print("\n🧹 一時ファイルをクリーンアップしました")
    
    # 実行時間の表示
    end_time = time.time()
    elapsed_time = end_time - start_time
    minutes = int(elapsed_time // 60)
    seconds = int(elapsed_time % 60)
    print(f"\n⏱️ 作業時間: {minutes}分{seconds}秒")
    print(f"🎉 Google Driveへの保存が完了しました！")

# スクリプト実行
main()
```

## 使い方（3ステップ）

### 1. Google Colabでの実行

1. [Google Colab](https://colab.research.google.com/)にアクセス
2. 新しいノートブックを作成
3. 上記のコードをコピペして実行

### 2. 動画のダウンロード

1. Google Driveへのアクセス許可を与える
2. YouTubeのプレイリストまたは動画URLを入力
3. 自動でダウンロード→Google Driveに保存

### 3. iPhoneでの視聴

1. **Google Driveアプリ**または**iPhoneの「ファイル」アプリ**を開く
2. 作成されたフォルダ（例：`YouTube_Videos_20250623_1430`）を確認
3. **VLCプレイヤー**などで連続再生

## トラブルシューティング

### Bot判定エラーが出る場合

**原因**: YouTubeがbotと判定している  
**解決策**:
- cookies.txtを用意する（最も確実）
- 時間を空けて再実行
- 別のプレイリストで試す

### cookies.txtの作成方法

限定公開動画や安定性向上のため、cookies.txtの利用を推奨します：

1. ブラウザでYouTubeにログイン
2. Chrome拡張機能「**Get cookies.txt LOCALLY**」をインストール
3. YouTubeページでクリックしてcookies.txtをダウンロード
4. Google Colabにアップロード（`/content/cookies.txt`に配置）

## 応用・カスタマイズ

### 解像度を変更したい場合

`format`パラメータを変更：

```python
# 720p固定の場合
'format': 'best[height<=720][ext=mp4]/best[height<=720]'

# 最高画質の場合
'format': 'best[ext=mp4]/best'
```

### 音声のみダウンロードしたい場合

```python
# 音声のみ（MP3）
'format': 'bestaudio[ext=m4a]/bestaudio/best[ext=m4a]'
'outtmpl': f'{download_dir}/%(playlist_index)03d_%(title)s.%(ext)s'
```

## 注意事項・免責事項

- **著作権**: 個人利用の範囲内で使用してください
- **利用規約**: YouTubeの利用規約を確認の上ご利用ください
- **責任**: 本ツールの使用により生じた問題について、作者は責任を負いません
- **教育目的**: プログラミング学習・技術検証目的での紹介です

## まとめ

YouTube Premiumに入らずとも、Google Colabを活用することで：

✅ **作業効率UP**: プレイリスト一括ダウンロード  
✅ **通信費節約**: オフライン視聴でデータ使用量削減  
✅ **環境不問**: 自分の端末にアプリ不要  
✅ **高い自由度**: 解像度・形式のカスタマイズ可能

プログラミング初心者でも簡単に使えるので、ぜひ試してみてください！

---

**この記事が役に立った方は、いいね・ストックしていただけると嬉しいです！**  
改善点や質問があれば、コメントでお気軽にどうぞ 🚀