AI×Instagramでコンテンツ自動化！ベトナム風景の自動生成＆投稿システム


## TL;DR
Google Apps Script (GAS) を利用して、DALL·Eによるベトナム風景の自動生成してInstagramへの自動投稿を行うシステムを構築しました。

作成したアカウントはこちらです。
https://www.instagram.com/ai_vietnam/


## 背景
多くのインフルエンサーや企業が、Instagramの運用に手間をかけています。
しかし、AIを活用することで、コンテンツ生成と投稿を自動化し、定期的に新しい画像を提供することが可能になります。
特に、DALL·Eのような生成AIを使用すると、無限にバリエーション豊かな画像を生成でき、Instagramに毎日投稿することが手軽に実現できます。

今回は、ベトナムの風景をテーマにした自動生成コンテンツの投稿システムを作成しました。
このシステムは、Google Apps ScriptとDALL·E、Instagram Graph APIを組み合わせて、完全自動でInstagramに投稿できる仕組みです。

## システム概要
このシステムは次のようなステップで動作します：

1. プロンプト生成: Googleスプレッドシートからランダムな自然要素、天気、時間帯、文化的要素を抽出し、DALL·Eに渡すプロンプトを自動生成します。
2. AIによる画像生成: DALL·E APIを使い、生成されたプロンプトを基に画像を作成します。
3. Google Driveへの保存: 生成された画像をGoogle Driveに保存し、アクセス可能なURLを取得します。
4. キャプション生成: ChatGPTを利用して、生成された画像に最適なInstagram用のキャプションを作成します。
5. Instagramへの自動投稿: 最後に、Instagram Graph APIを使い、生成された画像とキャプションをInstagramに自動投稿します。

```mermaid
graph TD
    A[Google Spreadsheet] -->|ランダムプロンプト生成| B[Google Apps Script]
    B -->|プロンプト送信| C[DALL·E API]
    C -->|画像生成| D[Google Drive]
    D -->|画像URL取得| E[Google Apps Script]
    E -->|プロンプト送信| F[ChatGPT API]
    F -->|キャプション生成| E
    E -->|画像URLとキャプションをInstagramに送信| G[Instagram Graph API]
    G -->|投稿成功| H[Instagram]
    G -->|キャプション付きで投稿完了| I[投稿がInstagramに反映される]

    subgraph API連携
        C
        F
        G
    end

    subgraph データストレージ
        D
        A
    end

```

## 必要なツールとAPI
このシステムの実現には以下のツールやAPIが必要です。

- Google Apps Script: GoogleのスプレッドシートとDrive APIにアクセスするためのスクリプト環境。
- DALL·E API: OpenAIが提供する画像生成API。
- Instagram Graph API: Instagramに自動投稿を行うためのAPI。Facebook for Developersを通じて使用します。
- Google Drive: 生成された画像を保存し、Instagramに投稿するための公開URLを取得するために使用。


## 実装手順
### 1. Google Apps Scriptのセットアップ
まず、Googleスプレッドシートを作成し、要素（自然、天気、時間帯、文化など）をリストとして入力します。次に、Google Apps Scriptを開き、スクリプトを書く準備をします。

### 2. プロンプトの生成
プロンプト生成のために、スプレッドシートのデータからランダムに要素を選び、それをもとにDALL·E用のプロンプトを作成します。

```javascript
function generateRandomPrompt() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');  // シート名を確認
  var lastRow = sheet.getLastRow();  // リストの最後の行を取得
  var natureElement = sheet.getRange(getRandomRow(lastRow), 1).getValue();  // 自然要素
  var weatherElement = sheet.getRange(getRandomRow(lastRow), 2).getValue();  // 天気
  var timeOfDayElement = sheet.getRange(getRandomRow(lastRow), 3).getValue();  // 時間帯
  var culturalElement = sheet.getRange(getRandomRow(lastRow), 4).getValue();  // 文化要素

  // ランダムプロンプトの生成
  return `Create a ${weatherElement} ${timeOfDayElement} scene featuring ${natureElement} with ${culturalElement} in the background.`;
}
```


別途Googleスプレッドシートでプロンプトの要素を用意しておきます。
各列からランダムで単語を一つ決定して組み合わせることで、生成される画像に幅を持たせています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526943/ae7696a4-8e12-9e0c-6d8b-601cd3a2ef31.png)


### 3\. DALL·E APIで画像生成
DALL·E APIにリクエストを送り、生成された画像のURLを取得します。

```javascript
function callDallEAPI(prompt) {
  var apiKey = PropertiesService.getScriptProperties().getProperty("OPEN_AI_API_KEY");
  var url = 'https://api.openai.com/v1/images/generations';
  var options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ' + apiKey,
      'Content-Type': 'application/json'
    },
    'payload': JSON.stringify({
      'model': 'dall-e-3',
      'prompt': prompt,
      'num_images': 1,
      'size': '1024x1024'
    })
  };

  var response = UrlFetchApp.fetch(url, options);
  var json = response.getContentText();
  var data = JSON.parse(json);
  return data.data[0].url;
}
```



例えば、こんな感じで生成されます。

```
Create a rainy sunrise scene featuring forest with village markets in the background.
```

![Create a rainy sunrise scene featuring forest with.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526943/c056822b-5a35-ba85-b72f-4c93f2eb736d.png)


### 4\. Google Driveに保存
生成された画像をGoogle Driveに保存し、共有リンクを取得します。

```javascript
function saveImageToDrive(imageUrl, prompt) {
  var folder = DriveApp.getFolderById('YOUR_GOOGLE_DRIVE_FOLDER_ID');
  var imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
  var file = folder.createFile(imageBlob);
  file.setName(prompt.substring(0, 50) + ".png");
  return file.getUrl();  // Google Drive上のファイルURLを返す
}
```

### 5\. Instagram Graph APIで投稿
最後に、Instagram Graph APIを使い、Google Driveから取得した画像URLと生成されたキャプションを使ってInstagramに自動投稿します。

```javascript
function postToInstagram(imageUrl, caption) {
  var mediaCreateUrl = 'https://graph.facebook.com/v17.0/' + INSTAGRAM_ACCOUNT_ID + '/media';
  var payload = {
    'image_url': imageUrl,
    'caption': caption,
    'access_token': ACCESS_TOKEN
  };

  var options = {
    'method': 'post',
    'payload': payload
  };

  var response = UrlFetchApp.fetch(mediaCreateUrl, options);
  var mediaResponse = JSON.parse(response.getContentText());
  var mediaId = mediaResponse.id;

  var publishUrl = 'https://graph.facebook.com/v17.0/' + INSTAGRAM_ACCOUNT_ID + '/media_publish';
  var publishPayload = {
    'creation_id': mediaId,
    'access_token': ACCESS_TOKEN
  };

  var publishOptions = {
    'method': 'post',
    'payload': publishPayload
  };

  UrlFetchApp.fetch(publishUrl, publishOptions);
}
```

Instagram Graph APIを使用するには、アクセストークンとアカウントIDが必要なのですが、これがとんでもなく面倒でした。こちらのサイトを参考にしてください。

https://tkstock.site/2023/03/08/%E3%80%902023%E5%B9%B4%E7%89%88%E3%80%91instagram-graph-api%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E6%96%B9/




## 最後に
自動投稿は思ったよりハードル低いなと思いました。
Instagram Graph APIのアクセストークン取得は手順がややこしいので、ここが一番時間かかりましたが、
コーディング自体はChatGPTにお願いしたので、30分くらいでできました。

天気予報のAPIをつなげて、今日の天気を反映した画像とかにしても面白いかなと思いました。