Google DriveからInstagramリール投稿
このモジュールで学ぶこと
- Cloudinaryを使った動画ホスティングの設定方法
- Google Driveから動画を検索してCloudinaryにアップロードする方法
- Instagram Graph APIでリール動画を投稿する方法
- 動画ファイルの存在確認とループ処理の実装方法
学習目標
このモジュールを終えると、以下のことができるようになります:
- Cloudinaryアカウントを作成し、Upload Presetを設定できる
- postsシートからDRAFT状態の投稿を取得し、対応する動画ファイルを検索できる
- Cloudinary経由でInstagramリールを自動投稿できる
- 投稿完了後にpostsシートのステータスを更新できる
目次
- セクション1: なぜCloudinaryが必要なのか
- セクション2: Cloudinaryアカウントの設定
- セクション3: ワークフローの全体像
- セクション4: ワークフローの構築
- セクション5: Cloudinaryアップロードの設定
- セクション6: Instagram投稿処理
- セクション7: postsシートの更新
- セクション8: 動作確認
- ワークフローJSONダウンロード
- トラブルシューティング
- まとめ
- 参考資料
- よくある質問
事前準備
必要なもの
- Module 09で作成した動画ファイルがGoogle Driveに保存されていること
- postsシートにDRAFT状態のデータがあること
- Instagram APIアクセストークン(Module 02で取得済み)
確認事項
Google Driveに以下のようなフォルダ構成があることを確認してください。
n8n-instagram/
├── 202512Instagram投稿A/
│ ├── POST-xxx.mp4
│ └── POST-yyy.mp4
├── 202512Instagram投稿B/
│ └── ...
└── ...
重要: 動画ファイル名はPOST-で始まり、postsシートのpost_idと一致している必要があります。
セクション1: なぜCloudinaryが必要なのか
Google DriveのURLは直接使えない
2025年1月以降、Instagram Graph APIではGoogle DriveのURLを直接使用できなくなりました。
エラー例:
Error in loading https://drive.google.com/uc?export=download&id=xxx
500 Internal Server Error
原因:
- Google DriveのURLはリダイレクトを含む
- 認証トークンが必要
- HTMLラッパーを含む場合がある
解決策: Cloudinaryを経由してアップロード
Cloudinaryとは
Cloudinaryは画像・動画のホスティングサービスです。無料プランでも以下が利用可能です:
- 月25クレジット
- 1GBストレージ = 1クレジット
- 1GB帯域幅 = 1クレジット
Instagram投稿用には十分な容量です。
チェックポイント
- Google DriveのURLが直接使えない理由を理解した
- Cloudinaryの役割を理解した
セクション2: Cloudinaryアカウントの設定
Step 1: Cloudinaryアカウント作成
- Cloudinaryにアクセス
- 「Sign Up For Free」をクリック
- 必要情報を入力してアカウント作成
Step 2: ダッシュボードの確認
ログインするとダッシュボードが表示されます。

以下の情報を確認してください:
- Cloud Name:
あなたのCloud Name(APIのURLで使用) - 使用量の表示(Media files, Bandwidth, Transformations, AI Usage)
Step 3: Upload Presetの作成
Upload Presetを使うと、API KeyなしでHTTP POSTでアップロードできます。
- 左メニューから「Settings」をクリック
- 「Upload」タブを選択
- 「Upload presets」セクションを確認

- 「Add upload preset」をクリック
- 以下の設定を入力:
| 設定項目 | 値 |
|---|---|
| Upload preset name | instagram_reel |
| Signing Mode | Unsigned |
| Folder | instagram(任意) |

重要: Signing Modeは必ず「Unsigned」を選択してください。これにより、API Keyなしでアップロードできるようになります。
- 「Save」をクリック
Step 4: 設定の確認
Upload Preset一覧に作成したプリセットが表示されます。

instagram_reelがリストに表示されている- Signing Modeが「Unsigned」になっている
チェックポイント
- Cloudinaryアカウントを作成できた
- Cloud Nameを確認できた
- Upload Preset「instagram_reel」を作成できた
- Signing Modeが「Unsigned」になっている
セクション3: ワークフローの全体像
ワークフロー構成図
[Manual Trigger]
↓
[Get DRAFT Posts] ← postsシートからDRAFT全件取得
↓
[Loop] ← 1件ずつ処理
↓
[Get Category from Pattern] ← content_jsonからカテゴリ判定
↓
[Search Category Folder] ← Driveでカテゴリフォルダを検索
↓
[Search Video File] ← フォルダ内でpost_idの動画を検索
↓
[IF File Exists] ← 動画があるか確認
├── Yes → [Upload to Cloudinary] → [Instagram投稿処理] → 終了
└── No → [Loop]へ戻る(次のDRAFTを試す)
ポイント
- ループ処理: postsシートに複数のDRAFTがある場合、動画ファイルがあるものを見つけるまで順番に試します
- alwaysOutputData: フォルダやファイルが見つからない場合でもワークフローが停止しないよう設定します
- 1件だけ投稿: 動画が見つかったら1件だけ投稿して終了します
セクション4: ワークフローの構築
Step 1: 新しいワークフローを作成
- n8nダッシュボードで「Create new workflow」をクリック
- ワークフロー名を「Instagram Reel Post」に変更
Step 2: Manual Triggerを追加
- 「+」ボタンをクリック
- 「Manual Trigger」を選択
Step 3: Get DRAFT Postsノードを追加
- 「+」ボタンをクリックして「Google Sheets」を検索
- 以下の設定を行う:
| 設定項目 | 値 |
|---|---|
| Resource | Sheet |
| Operation | Get row(s) in sheet |
| Document | n8n-test(あなたのスプレッドシート) |
| Sheet | posts |
| Filter | status = DRAFT |
Step 4: Loopノードを追加
- 「+」ボタンをクリックして「Split In Batches」を検索
- 以下の設定を行う:
| 設定項目 | 値 |
|---|---|
| Batch Size | 1 |
Step 5: Get Category from Patternノードを追加
- 「+」ボタンをクリックして「Code」を検索
- 以下のコードを入力:
const item = $input.first();
const contentJson = JSON.parse(item.json.content_json || '{}');
const pattern = contentJson.pattern || '';
// patternからカテゴリを判定
const patternToCategory = {
'versus': 'A',
'instant_hack': 'B',
'secret_feature': 'C',
'warning': 'D',
'ranking': 'E'
};
const category = patternToCategory[pattern] || 'A';
// フォルダ名を生成(例: 202512Instagram投稿A)
const now = new Date();
const yearMonth = now.getFullYear().toString() + String(now.getMonth() + 1).padStart(2, '0');
const folderName = `${yearMonth}Instagram投稿${category}`;
return [{
json: {
...item.json,
category: category,
folder_name: folderName,
pattern: pattern
}
}];
このコードは:
- postsシートの
content_jsonからpatternを取得 - patternに応じてカテゴリ(A〜E)を判定
- 年月とカテゴリからフォルダ名を生成(例:
202512Instagram投稿A)
Step 6: Search Category Folderノードを追加
- 「+」ボタンをクリックして「Google Drive」を検索
- 以下の設定を行う:
| 設定項目 | 値 |
|---|---|
| Resource | File/Folder |
| Operation | Search files and folders |
| Query String | {{ $json.folder_name }} |
| Folder ID | あなたの親フォルダID(n8n-instagramフォルダ) |
- 重要: ノード設定で「Always Output Data」をONにする
- 右上の「︙」メニューから「Settings」を開く
- 「Always Output Data」のトグルをON
Step 7: Search Video Fileノードを追加
- 「+」ボタンをクリックして「Google Drive」を検索
- 以下の設定を行う:
| 設定項目 | 値 |
|---|---|
| Resource | File/Folder |
| Operation | Search files and folders |
| Query String | {{ $('Get Category from Pattern').item.json.post_id }} |
| Folder ID | {{ $json.id }}(前のノードで取得したフォルダID) |
- 重要: 「Always Output Data」をONにする
Step 8: IF File Existsノードを追加
- 「+」ボタンをクリックして「IF」を検索
- 以下の条件を設定:
| 設定項目 | 値 |
|---|---|
| Value 1 | {{ $json.id }} |
| Operation | is not empty |
接続:
- True(ファイルあり) → Upload to Cloudinary へ
- False(ファイルなし) → Loop へ戻る
チェックポイント
- Get DRAFT Postsでpostsシートからデータを取得できた
- Loopノードで1件ずつ処理できた
- Get Category from Patternでカテゴリを判定できた
- Search Category FolderでDriveのフォルダを検索できた
- Search Video Fileで動画ファイルを検索できた
- IF File Existsで分岐できた
セクション5: Cloudinaryアップロードの設定
Step 1: Upload to Cloudinaryノードを追加
- IF File Existsの「True」出力から「+」をクリック
- 「HTTP Request」を検索して追加
- 以下の設定を行う:
| 設定項目 | 値 |
|---|---|
| Method | POST |
| URL | https://api.cloudinary.com/v1_1/YOUR_CLOUD_NAME/video/upload |
| Body Content Type | Form-Data |
YOUR_CLOUD_NAMEはCloudinaryダッシュボードで確認したCloud Nameに置き換えてください。
- Body Parametersに以下を追加:
| Name | Value |
|---|---|
| file | https://drive.google.com/uc?export=download&id={{ $json.id }} |
| upload_preset | instagram_reel |

Step 2: 動作確認
ノードをテスト実行すると、Cloudinaryにアップロードされ、以下のような結果が返ります:
{
"secure_url": "https://res.cloudinary.com/xxx/video/upload/v1234567890/xxx.mp4",
"public_id": "xxx",
"format": "mp4",
...
}
secure_urlがInstagram APIに渡すURLになります。
チェックポイント
- HTTP RequestノードでCloudinaryのURLを設定できた
- Body Parametersにfileとupload_presetを追加できた
- テスト実行でsecure_urlが取得できた
セクション6: Instagram投稿処理
Step 1: Get User IDノードを追加
- Upload to Cloudinaryの出力から「+」をクリック
- 「HTTP Request」を追加
- 以下の設定:
| 設定項目 | 値 |
|---|---|
| Method | GET |
| URL | https://graph.instagram.com/v20.0/me |
- Query Parametersに以下を追加:
| Name | Value |
|---|---|
| fields | user_id,username |
| access_token | YOUR_ACCESS_TOKEN |

Step 2: Create Reel Containerノードを追加
- 「HTTP Request」を追加
- 以下の設定:
| 設定項目 | 値 |
|---|---|
| Method | POST |
| URL | https://graph.instagram.com/v20.0/{{ $json.user_id }}/media |
- Query Parametersに以下を追加:
| Name | Value |
|---|---|
| media_type | REELS |
| video_url | {{ $('Upload to Cloudinary').item.json.secure_url }} |
| caption | {{ $('Get Category from Pattern').item.json.caption }}\n\n{{ $('Get Category from Pattern').item.json.hashtags }} |
| share_to_feed | true |
| access_token | YOUR_ACCESS_TOKEN |

Step 3: Wait 15sノードを追加
動画のアップロード処理には時間がかかるため、待機時間を設けます。
- 「Wait」ノードを検索して追加
- Amount:
15(秒)
Step 4: Check Container Statusノードを追加
- 「HTTP Request」を追加
- 以下の設定:
| 設定項目 | 値 |
|---|---|
| Method | GET |
| URL | https://graph.instagram.com/{{ $('Create Reel Container').item.json.id }} |
- Query Parametersに以下を追加:
| Name | Value |
|---|---|
| fields | status_code |
| access_token | YOUR_ACCESS_TOKEN |

ステータスがFINISHEDになれば投稿可能です。
Step 5: Publish Reelノードを追加
- 「HTTP Request」を追加
- 以下の設定:
| 設定項目 | 値 |
|---|---|
| Method | POST |
| URL | https://graph.instagram.com/v20.0/{{ $('Get User ID').item.json.user_id }}/media_publish |
- Query Parametersに以下を追加:
| Name | Value |
|---|---|
| creation_id | {{ $('Create Reel Container').item.json.id }} |
| access_token | YOUR_ACCESS_TOKEN |
チェックポイント
- Get User IDでuser_idを取得できた
- Create Reel Containerでcontainer_idを取得できた
- Wait 15sで待機時間を設けた
- Check Container StatusでFINISHEDを確認できた
- Publish Reelで投稿IDを取得できた
セクション7: postsシートの更新
Step 1: Edit Fieldsノードを追加
- 「Edit Fields」を検索して追加
- 以下のフィールドを設定:
| フィールド名 | 値 |
|---|---|
| post_id | {{ $('Get Category from Pattern').item.json.post_id }} |
| status | PUBLISHED |
| ig_post_id | {{ $json.id }} |
| published_at | {{ $now.toISO() }} |
Step 2: Update Posts Sheetノードを追加
- 「Google Sheets」を追加
- 以下の設定:
| 設定項目 | 値 |
|---|---|
| Resource | Sheet |
| Operation | Append or update row in sheet |
| Document | n8n-test |
| Sheet | posts |
| Matching Columns | post_id |
- Values to Sendで以下を設定:
- post_id:
{{ $json.post_id }} - status:
{{ $json.status }} - ig_post_id:
{{ $json.ig_post_id }} - published_at:
{{ $json.published_at }}
- post_id:
チェックポイント
- Edit Fieldsで更新データを整形できた
- Update Posts Sheetでpostsシートを更新できた
- statusがPUBLISHEDに変更された
- ig_post_idとpublished_atが記録された
セクション8: 動作確認
Step 1: テストデータの準備
- postsシートにDRAFT状態のレコードがあることを確認
- Google Driveに対応する動画ファイルがあることを確認
- ファイル名が
POST-xxx形式 - 対応するカテゴリフォルダに保存されている
- ファイル名が
Step 2: ワークフロー全体図の確認
完成したワークフローは以下のようになります。

Step 3: 実行テスト
- 「Execute Workflow」をクリック
- 各ノードが順番に実行されることを確認
- 最終的にInstagramに投稿されることを確認
- postsシートのstatusがPUBLISHEDに更新されることを確認
チェックポイント
- ワークフローがエラーなく完了した
- Instagramにリールが投稿された
- postsシートのstatusがPUBLISHEDになった
ワークフローJSONダウンロード
以下のJSONファイルをダウンロードしてn8nにインポートできます。
インポート後に変更が必要な箇所:
| プレースホルダー | 変更内容 |
|---|---|
YOUR_SPREADSHEET_ID | あなたのスプレッドシートID |
YOUR_POSTS_SHEET_GID | postsシートのGID |
YOUR_PARENT_FOLDER_ID | Google Driveの親フォルダID |
YOUR_CLOUD_NAME | CloudinaryのCloud Name |
YOUR_UPLOAD_PRESET | Cloudinaryのupload preset名 |
YOUR_INSTAGRAM_ACCESS_TOKEN | Instagram APIアクセストークン |
また、Google SheetsとGoogle Driveのクレデンシャルを設定してください。
トラブルシューティング
「Error in loading https://drive.google.com/...」エラー
症状: Create Reel Containerで500 Internal Server Errorが発生
原因: Google DriveのURLをInstagram APIに直接渡している
解決方法: Cloudinary経由でアップロードしてください(本モジュールの方法)
「RangeError: Invalid string length」エラー
症状: n8nで大きな動画をダウンロードしようとするとエラー
原因: n8nのメモリ制限
解決方法: Google DriveのURLをCloudinaryに直接渡して、Cloudinaryにダウンロードさせてください(本モジュールの方法)
ループが途中で止まる
症状: 数件処理した後、ワークフローが「成功」で終了する
原因: Search Category FolderまたはSearch Video Fileの「Always Output Data」がOFFになっている
解決方法:
- 両方のノードの設定を開く
- 「Settings」で「Always Output Data」をONにする
Container StatusがFINISHEDにならない
症状: Check Container StatusでIN_PROGRESSのまま
原因: 動画のアップロード処理に時間がかかっている
解決方法:
- Wait時間を増やす(15秒→30秒)
- またはリトライループを追加する
アクセストークンが無効
症状: 「Invalid OAuth access token」エラー
原因: アクセストークンの有効期限切れ
解決方法: Module 02の手順でアクセストークンを再取得してください
まとめ
このモジュールで学んだこと
- Cloudinaryを使った動画ホスティングの設定方法
- Google DriveのURLをInstagram APIで直接使えない理由と解決策
- postsシートからDRAFTを取得し、対応する動画を検索する方法
- ループ処理と「Always Output Data」オプションの使い方
- Instagram Graph APIでリール動画を投稿する手順
- 投稿完了後のシート更新処理
次のステップ
これでn8n講座は完了です!
構築したシステムの全体像:
- Module 01-04: 環境構築とAPI設定
- Module 05-06: シートからInstagram投稿
- Module 07-08: AIでコンテンツ自動生成
- Module 09: Canvaで動画素材を一括生成
- Module 10: 動画をInstagramリールとして投稿
これにより、AIによる企画生成から動画素材化、Instagram投稿まで、大部分の作業を自動化できるようになりました。
参考資料
- Instagram Graph API - Reels Publishing
- Cloudinary Upload API
- n8n Community - Google Drive links are no longer accepted
よくある質問
Q: Cloudinary無料プランで足りますか? A: 月に数十件程度の投稿であれば十分です。動画1本あたり約10-50MBで、月25クレジット(約25GB相当)利用可能です。
Q: Container StatusのチェックにIFノードを追加すべきですか? A: 動画が短い(15秒以下)場合は15秒の待機で通常は十分です。長い動画の場合はリトライループの追加を推奨します。
Q: 複数投稿を一度に実行できますか? A: 現在のワークフローは1件ずつ投稿する設計です。Instagram APIのレート制限もあるため、複数投稿する場合は間隔を空けて実行してください。
Q: 投稿がいつまでもFINISHEDにならない場合は? A: 動画のフォーマットや解像度に問題がある可能性があります。Instagram推奨の形式(MP4、H.264、1080x1920、9:16)を確認してください。