公開日:

森田 嶺

【応用編】Gemini Enterprise APIでノートブック音声解説の生成を自動化する

【応用編】Gemini Enterprise APIでノートブック音声解説の生成を自動化するサムネイル画像

前回は、「Gemini Notebook Enterprise APIで何ができるのか?」について、具体的なユースケースを交えて解説しましたが、今回はAPIを使った自動化方法について解説します。

【基本編】Gemini Notebook Enterprise APIで何ができるのか?サムネイル画像
 

Notebook Enterprise APIでできることの振り返り

詳しくは、前回の記事を参考いただくとして、Notebook Enterprise APIでできることは主に3つのリソースに対する操作です。

  • ノートブック
  • ソース
  • 音声解説

ノートブックの作成やソースの登録などは、APIがあるのであれば「まぁ使えるよね」と想像がつくと思いますが、一番のポイントはAudio OverviewがAPIで生成できるところです。

今回作りたい仕組み

Notebook Enterprise APIの実用性を理解していただくために、日常でNotebookの音声解説が役立つケースを考えてみました。ビジネスパーソンが、毎朝通勤中に聴くことができる学習音声を自動作成するユースケースです。

  1. 複数のRSSから生成AI関連ニュースを取得する
  2. 取得した記事をGoogle ドキュメントにまとめる
  3. Gemini Notebook Enterpriseのノートブックを作成する
  4. Google ドキュメントをノートブックのソースとして追加する
  5. Audio Overview(音声解説)を生成する
  6. 作成したノートブックをGmailで通知する

Gemini Notebook Enterprise APIの使い所は、上記の赤枠部分(③④⑤)です。

GASとNotebook Enterprise APIで仕組みを構築

今回の要件は重いバッチ処理を実行するわけではありません。というわけで、ローコードで簡易的なコードを実行できるGoogle Apps Script(以下GAS)とNotebook Enterprise APIを組み合わせて、前述した仕組みを構築してみようと思います。

最初のセットアップ

まずはAPIを利用するための環境を準備します。

Gemini Notebook Enterprise APIが利用できる前提条件は以下の通りです。

  • Google Cloudプロジェクトの作成
  • 課金の有効化
  • Discovery Engine API
  • Notebook Enterpriseライセンスの付与

Discovery Engine APIを有効化する

Google Cloud Consoleから、今回利用するGoogle Cloudプロジェクトを選択します。その上で「APIとサービス」からDiscovery Engine APIを有効化してください。

Notebookの作成やソースの登録、Audio Overviewの生成など、今回使用するAPIは discoveryengine.googleapis.com のエンドポイントに対してリクエストを送信するからです。

Cloud NotebookLM Userロールを付与する

次に、GASを実行するユーザーへIAMロールを設定します。Google Cloud Consoleの「IAM」から対象ユーザーを追加し、Cloud NotebookLM Userを付与します。

ロールIDは次の通りです。

roles/discoveryengine.notebookLmUser

また、これは注意ポイントですが、Notebookを別のユーザーへ共有する場合、共有先ユーザーについてもCloud NotebookLM Userロールが必要です。 Notebook Enterpriseでは、共有先ユーザーについても、ライセンスの購入が必要だからです。

ライセンスを確認する

IAMロールだけではGemini Notebook Enterpriseを利用できません。対象ユーザーにはGemini Notebook Enterpriseのライセンスも必要です。

注意したいのが、ライセンスとマルチリージョンの関係です。Gemini Notebook Enterpriseのライセンスはマルチリージョン単位で管理されます。例えば usglobal の両方のNotebookへアクセスさせたい場合、それぞれに対応したライセンスが必要です。 そのため、後述するAPIのLOCATIONとライセンスのリージョンは事前に整理しておくことをおすすめします。

ここまでの設定で、Notebook Enterprise APIを利用するための事前準備は完了です。

GASプログラムの実装

事前準備が完了したら、いよいよ実装を開始していきます。

GASプロジェクトの基本設定

まずは、新規でGASプロジェクトを作成し、「プロジェクトの設定」で

「appsscript.json」マニフェスト ファイルをエディタで表示する」にチェックを入れます。

すると、appsscript.jsonが自動的に出現するので、以下のコードをそのまま貼り付けます。これらのURLは、今回の自動化の仕組みに必要なAPIスコープになります。

{

"timeZone": "Asia/Tokyo",

"dependencies": {},

"exceptionLogging": "STACKDRIVER",

"runtimeVersion": "V8",

"oauthScopes": [

"https://www.googleapis.com/auth/cloud-platform",

"https://www.googleapis.com/auth/script.external_request",

"https://www.googleapis.com/auth/script.scriptapp",

"https://www.googleapis.com/auth/script.send_mail",

"https://www.googleapis.com/auth/gmail.send",

"https://www.googleapis.com/auth/documents",

"https://www.googleapis.com/auth/drive"

]

}

GASプログラムの実装

最初に結論となるプログラムを貼り付けます。尚、以下はGemini 3.7 Flashによって生成しています。まずは、全体的な流れがなんとなく理解できれば良いと思います。

/**

* ============================================================

* Notebook Enterprise × 生成AI最新ニュース自動収集 GAS

* ============================================================

*

* 機能:

* 1. 複数のRSSフィードから生成AIの最新ニュースを収集し、各記事の本文テキストを抽出

* 2. 本文テキストをまとめたGoogleドキュメントを自動作成

* 3. Notebook Enterprise APIでノートブックを新規作成

* 4. 作成したGoogleドキュメントをノートブックのソースとして登録

* 5. 作成したノートブックを指定アカウントに自動共有

* 6. ノートブックから音声解説(Audio Overview)を自動生成

* 7. Gmailで指定メールアドレスにノートブックURL・GoogleドキュメントURL等を通知

*

* 必要な前提条件:

* - Notebook Enterprise ライセンス (Gemini Enterprise / Education Premium)

* - Google Cloud プロジェクトで Discovery Engine API を有効化

* - 実行アカウントに roles/discoveryengine.notebookLmUser IAMロールを付与

* - 共有先アカウントに roles/discoveryengine.notebookLmUser IAMロールを付与

* - Gmail 送信権限 / Google ドキュメント・Drive 操作権限

*

* セットアップ手順:

* 1. 下記 CONFIG の各値を自分の環境に合わせて設定する

* 2. スクリプトエディタで appsscript.json を表示し、OAuthスコープを確認する

* 3. setupDailyTrigger() を一度だけ手動実行してトリガーを登録する

* 4. main() を手動実行して動作確認する

* ============================================================

*/

 

// ============================================================

// 設定セクション(必ず自分の環境に合わせて変更してください)

// ============================================================

const CONFIG = {

// Google Cloud プロジェクト番号(数値)

// Cloud Console の「プロジェクト情報」から確認できます

GCP_PROJECT_NUMBER: '<プロジェクト番号>',

 

// ノートブックのロケーション(通常は 'global' または 'us')

NOTEBOOK_LOCATION: 'us',

 

// APIエンドポイントのリージョン: 'us', 'eu', または 'global'

ENDPOINT_LOCATION: 'us',

 

// 通知先 & 共有先メールアドレス

NOTIFICATION_EMAIL: '通知先のメールアドレス',

 

// ノートブック共有時のロール ('PROJECT_ROLE_WRITER' または 'PROJECT_ROLE_READER')

SHARE_ROLE: 'PROJECT_ROLE_WRITER',

 

// 1回の実行で取得するニュース件数の上限

MAX_NEWS_ITEMS: 10,

 

// ニュース収集対象のRSSフィード一覧

RSS_FEEDS: [

{

name: 'Google News (日本語)',

url: 'https://news.google.com/rss/search?q=%E7%94%9F%E6%88%90AI+OR+%E7%94%9F%E6%88%90%E7%9A%84AI+OR+LLM&hl=ja&gl=JP&ceid=JP:ja',

lang: 'ja'

},

{

name: 'Google News (英語)',

url: 'https://news.google.com/rss/search?q=generative+AI+OR+LLM+OR+ChatGPT+OR+Gemini&hl=en-US&gl=US&ceid=US:en',

lang: 'en'

},

{

name: 'OpenAI Blog',

url: 'https://openai.com/news/rss.xml',

lang: 'en'

},

{

name: 'Google DeepMind Blog',

url: 'https://deepmind.google/discover/blog/feed/',

lang: 'en'

}

],

 

// ノートブック名・ドキュメント名のプレフィックス

NOTEBOOK_TITLE_PREFIX: '生成AI最新ニュース',

 

// スクリプトプロパティのキー(重複実行防止用)

PROP_LAST_RUN: 'LAST_RUN_DATE'

};

 

// ============================================================

// メインエントリーポイント

// ============================================================

 

/**

* メイン関数 - GASトリガーから毎日呼び出されます

* 手動実行でもデバッグできます

*/

function main() {

Logger.log('=== Notebook ニュースボット 開始 ===');

const startTime = new Date();

 

try {

const today = Utilities.formatDate(startTime, 'Asia/Tokyo', 'yyyy-MM-dd');

const baseTitle = CONFIG.NOTEBOOK_TITLE_PREFIX + ' ' + today;

 

// --- Step 1: ニュース収集&本文抽出 ---

Logger.log('[Step 1] RSSフィードからニュースを収集し、本文テキストを抽出中...');

const articles = fetchAiNews(CONFIG.MAX_NEWS_ITEMS);

 

if (articles.length === 0) {

const msg = '収集できたニュース記事が0件でした。RSSフィードの設定を確認してください。';

Logger.log('[WARN] ' + msg);

sendErrorToGmail(msg);

return;

}

Logger.log('[Step 1] ' + articles.length + ' 件の記事・本文を取得完了');

 

// --- Step 2: Google ドキュメントの作成 ---

Logger.log('[Step 2] 本文テキストをまとめたGoogleドキュメントを作成中...');

const docInfo = createNewsDocument(baseTitle + ' (記事まとめ)', articles);

Logger.log('[Step 2] Googleドキュメント作成完了: ID = ' + docInfo.id);

 

// --- Step 3: ノートブック作成 ---

Logger.log('[Step 3] Notebook Enterprise ノートブックを作成中...');

const notebook = createNotebook(baseTitle);

Logger.log('[Step 3] ノートブック作成完了: ID = ' + notebook.name);

 

// --- Step 4: 作成したGoogleドキュメントをノートブックのソースとして登録 ---

Logger.log('[Step 4] Googleドキュメントをノートブックのソースとして登録中...');

addGoogleDocSourceToNotebook(notebook.name, docInfo.id);

Logger.log('[Step 4] ソース登録完了');

 

// --- Step 5: ノートブックの共有設定 ---

Logger.log('[Step 5] ノートブックを共有中: ' + CONFIG.NOTIFICATION_EMAIL);

shareNotebook(notebook.name, CONFIG.NOTIFICATION_EMAIL);

 

// --- Step 6: 音声解説(Audio Overview)の自動生成 ---

Logger.log('[Step 6] 音声解説(Audio Overview)の生成をトリガー中...');

Utilities.sleep(3000); // ソース登録の反映を待機

generateAudioOverview(notebook.name);

 

// ノートブックのURLを構築

const notebookId = notebook.name.split('/').pop();

const notebookUrl = buildNotebookUrl(notebookId);

 

// --- Step 7: Gmail に通知 ---

Logger.log('[Step 7] Gmailに通知メールを送信中: ' + CONFIG.NOTIFICATION_EMAIL);

sendToGmail(articles, notebookUrl, baseTitle, docInfo.url, startTime);

Logger.log('[Step 7] Gmail通知完了');

 

// 最終実行日をプロパティに記録

PropertiesService.getScriptProperties().setProperty(CONFIG.PROP_LAST_RUN, today);

 

const elapsed = (new Date() - startTime) / 1000;

Logger.log('=== 完了 (所要時間: ' + elapsed.toFixed(1) + '秒) ===');

 

} catch (e) {

const errMsg = 'エラーが発生しました: ' + e.message + '\n' + (e.stack || '');

Logger.log('[ERROR] ' + errMsg);

sendErrorToGmail(errMsg);

throw e;

}

}

 

// ============================================================

// Step 1: ニュース収集&本文抽出

// ============================================================

 

/**

* 複数のRSSフィードから生成AIの最新ニュースを収集し、各記事の本文テキストを抽出する

* @param {number} maxItems 取得する最大件数

* @returns {Array<{title: string, url: string, source: string, pubDate: string, content: string}>}

*/

function fetchAiNews(maxItems) {

const allArticles = [];

const seenUrls = {};

 

for (const feed of CONFIG.RSS_FEEDS) {

try {

Logger.log(' フィード取得中: ' + feed.name);

const articles = fetchRssFeed(feed);

for (const article of articles) {

// URL重複チェック

if (!seenUrls[article.url]) {

seenUrls[article.url] = true;

allArticles.push(article);

}

}

Logger.log(' ' + feed.name + ': ' + articles.length + ' 件取得');

} catch (e) {

Logger.log(' [WARN] ' + feed.name + ' の取得に失敗: ' + e.message);

// 1つのフィードが失敗しても続行

}

}

 

// 公開日の新しい順にソートしてmaxItems件に絞る

allArticles.sort(function(a, b) {

return new Date(b.pubDate) - new Date(a.pubDate);

});

const targetArticles = allArticles.slice(0, maxItems);

 

// 各記事の本文テキストを取得

Logger.log(' 各記事の本文テキストを取得中 (' + targetArticles.length + '件)...');

for (const [k, item] of targetArticles.entries()) {

Logger.log(' [' + (k + 1) + '/' + targetArticles.length + '] 本文取得: ' + item.title.substring(0, 30) + '...');

item.content = fetchArticleContent(item);

// レートリミット配慮

Utilities.sleep(300);

}

 

return targetArticles;

}

 

/**

* 単一のRSSフィードを取得してパースする

* @param feed

* @returns {Array<{title: string, url: string, source: string, pubDate: string, description: string}>}

*/

function fetchRssFeed(feed) {

const response = UrlFetchApp.fetch(feed.url, {

muteHttpExceptions: true,

followRedirects: true

});

 

if (response.getResponseCode() !== 200) {

throw new Error('HTTPエラー: ' + response.getResponseCode());

}

 

const xml = response.getContentText('UTF-8');

const doc = XmlService.parse(xml);

const root = doc.getRootElement();

const ns = root.getNamespace();

 

let items = [];

try {

const channel = root.getChild('channel', ns) || root.getChild('channel');

if (channel) {

// RSS 2.0

items = channel.getChildren('item');

} else {

// Atom形式

items = root.getChildren('entry', root.getNamespace());

}

} catch (e) {

Logger.log(' XMLパースエラー (' + feed.name + '): ' + e.message);

return [];

}

 

const articles = [];

for (const item of items) {

try {

// タイトル取得

const titleEl = item.getChild('title') || item.getChild('title', item.getNamespace());

const title = titleEl ? titleEl.getValue().trim() : '(タイトルなし)';

 

// URL取得

let url = '';

const linkEl = item.getChild('link') || item.getChild('link', item.getNamespace());

if (linkEl) {

url = linkEl.getValue().trim();

// Atom の 形式に対応

if (!url) {

const hrefAttr = linkEl.getAttribute('href');

if (hrefAttr) url = hrefAttr.getValue();

}

}

 

// Google News の場合は guid にURLが入ることがある

if (!url) {

const guidEl = item.getChild('guid');

if (guidEl) url = guidEl.getValue().trim();

}

 

if (!url || !title) continue;

 

// 公開日取得

const pubDateEl = item.getChild('pubDate') || item.getChild('published') || item.getChild('updated');

const pubDate = pubDateEl ? pubDateEl.getValue().trim() : new Date().toISOString();

 

// 概要(フォールバック用)

const descEl = item.getChild('description') || item.getChild('summary');

const description = descEl ? descEl.getValue().trim() : '';

 

articles.push({

title: title,

url: url,

source: feed.name,

pubDate: pubDate,

description: description

});

} catch (e) {

// 個別アイテムのパース失敗は無視して続行

}

}

 

return articles;

}

 

/**

* 記事URLにアクセスして本文テキストを抽出する

* @param article

* @returns {string} 本文テキスト

*/

function fetchArticleContent(article) {

try {

const response = UrlFetchApp.fetch(article.url, {

muteHttpExceptions: true,

followRedirects: true,

headers: {

'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'

}

});

 

if (response.getResponseCode() !== 200) {

Logger.log(' [WARN] 本文取得HTTPエラー (' + response.getResponseCode() + '): ' + article.title);

return cleanHtmlToText(article.description) || '(本文の取得に失敗しました)';

}

 

const html = response.getContentText('UTF-8');

let text = cleanHtmlToText(html);

 

// テキストが極端に短い場合は description をフォールバック

if (!text || text.length < 100) {

if (article.description) {

text = cleanHtmlToText(article.description);

}

}

 

// ドキュメント肥大化防止のため最大5,000文字でトリミング

if (text.length > 5000) {

text = text.substring(0, 5000) + '\n\n...(以下省略)';

}

 

return text || '(本文なし)';

} catch (e) {

Logger.log(' [WARN] 本文取得エラー (' + article.title + '): ' + e.message);

return cleanHtmlToText(article.description) || '(本文取得中にエラーが発生しました)';

}

}

コードレベルの説明

CONFIGデータの重要ポイント

今回のコードでは、最初にCONFIGオブジェクトへ環境ごとの設定をまとめています。

const CONFIG = {

// Google Cloud プロジェクト番号(数値)

// Cloud Console の「プロジェクト情報」から確認できます

GCP_PROJECT_NUMBER: '<プロジェクト番号>',

 

// ノートブックのロケーション(通常は 'global' または 'us')

NOTEBOOK_LOCATION: 'us',

 

// APIエンドポイントのリージョン: 'us', 'eu', または 'global'

ENDPOINT_LOCATION: 'us',

 

...

特に重要なのが GCP_PROJECT_NUMBER です。ここで設定するのはプロジェクトIDではなく、Google Cloudの「プロジェクト番号」です。

また、ENDPOINT_LOCATION はAPIへアクセスするマルチリージョンを指定します。設定できるのは useuglobal のいずれかになります。今回のサンプルでは us を使用していますが、自社環境に合わせて設定してください。

GASからAPIを呼び出す仕組み

Gemini Notebook Enterpriseには、GAS専用のサービスが用意されているわけではありません。そのため今回は UrlFetchApp を使用してREST APIへ直接HTTPリクエストを送信します。

認証には次のコードを利用します。

const token = ScriptApp.getOAuthToken();

ScriptApp.getOAuthToken() では、GASを実行しているユーザーのOAuth 2.0アクセストークンを取得できます。取得したトークンをAuthorizationヘッダーへ設定します。

headers: {

'Authorization': 'Bearer ' + token

}

GASからGoogle APIを直接呼び出す方法として、ScriptApp.getOAuthToken() で取得したアクセストークンをAuthorizationヘッダーへ設定する方法を公式ドキュメントで案内しています。

また、UrlFetchApp の利用には https://www.googleapis.com/auth/script.external_request スコープが必要です。appsscript.jsonでOAuthスコープを明示的に設定している環境では、この点も確認してください。 ここまで設定できれば、Notebook Enterprise APIをGASから呼び出す準備は完了です。

ノートブックを自動作成する

ここから実際の処理を見ていきます。最初に実行するのがNotebookの作成です。Notebookを新規作成する場合は、notebooks.create メソッドを使用します。

APIのURLは次の形式です。

https://us-discoveryengine.googleapis.com/v1alpha/

projects/{PROJECT_NUMBER}/locations/{LOCATION}/notebooks

GASでは、POSTリクエストの本文としてNotebookのタイトルを渡します。

const payload = {

title: title

};

const options = {

method: 'POST',

contentType: 'application/json; charset=UTF-8',

headers: {

'Authorization': 'Bearer ' + token

},

payload: JSON.stringify(payload)

};

そして UrlFetchApp.fetch() でAPIを実行します。

const response = UrlFetchApp.fetch(endpoint, options);

成功すると作成されたNotebookの情報が返ってくるため、以降の処理ではレスポンスに含まれるリソース名を利用します。今回のコードでは日付を付けて、以下タイトルのNotebookを毎日作成しています。

生成AI最新ニュース 2026-09-10

Notebookを定期生成する場合、日付や部署名、プロジェクト名などをタイトルへ組み込んでおくと、後から確認しやすくなります。

Google ドキュメントをNotebookのソースへ登録する

Notebookだけ作成しても、まだAudio Overviewは作成できません。次に音声解説の材料となるソースを追加します。今回のサンプルでは、RSSから取得した記事本文を一つのGoogle ドキュメントへまとめ、そのファイルをNotebookへ登録しています。

Notebookへ複数のソースを登録するためのAPIとして、Googleは notebooks.sources.batchCreate を提供しています。 Google ドキュメントを追加する場合は、次のようなデータを送信します。

const payload = {

userContents: [

{

googleDriveContent: {

documentId: docId,

mimeType: 'application/vnd.google-apps.document'

}

}

]

};

documentId にはGoogle ドキュメントのファイルIDを指定します。Google ドキュメントの場合、MIMEタイプは次の値です。

application/vnd.google-apps.document

Google スライドの場合は、以下のMIMEタイプを指定します。

application/vnd.google-apps.presentation

現在のAPIではGoogle Driveファイルだけではなく、テキスト、Webコンテンツ、動画などもソースとして扱えます。

つまり今回のように必ずGoogle ドキュメントを中継する必要があるわけではありません。一方で、複数の記事本文を一つのGoogle ドキュメントへまとめておけば、実際にNotebookへ投入された情報を人間が後から確認しやすくなります。自動化処理の内容を確認するという意味でも、今回のような構成にはメリットがあります。

Notebookを他のユーザーへ共有する

作成したNotebookを自分だけではなく別のユーザーも利用する場合は、notebooks.share を呼び出します。

リクエストするURLは次のような形式です。

https://{CONFIG.ENDPOINT_LOCATION}-discoveryengine.googleapis.com/v1alpha/notebooks/{NOTEBOOK_ID}:share

共有先にはメールアドレスと権限を指定します。

accountAndRoles: [

{

email: email,

role: 'PROJECT_ROLE_WRITER'

}

]

現在のAPIでは、PROJECT_ROLE_WRITER のほかに閲覧者となる PROJECT_ROLE_READER などが定義されています。

また、現在のAPIリファレンスでは notifyViaEmail もリクエスト項目として定義されています。共有通知をNotebook Enterprise側から送信する場合は、この設定もAPI仕様に合わせて追加してください。 社内への情報配信であれば閲覧だけ必要なユーザーにはREADER、Notebook自体を編集させたいユーザーにはWRITERというように、用途に応じて分けるのが良いでしょう。

Audio Overview(音声解説)をAPIから生成する

いよいよ今回の中心となるAudio Overviewを生成します。

Googleは現在、Notebookの内容からAudio Overviewを生成する notebooks.audioOverviews.create メソッドを提供しています。

エンドポイントは次の形式です。

POST

https://{ENDPOINT_LOCATION}-discoveryengine.googleapis.com/v1alpha/

projects/{PROJECT_NUMBER}/locations/{LOCATION}/notebooks/{NOTEBOOK_ID}/audioOverviews

現在の公式ドキュメントでは、例えば次の情報を指定できます。

var payload = {

sourceIds: [

{

id: sourceId

}

],

episodeFocus: '今日の重要なニュースを分かりやすく解説してください',

languageCode: 'ja'

};

sourceIds では音声解説に利用するソースを指定し、episodeFocus ではAudio Overviewで特に取り上げてほしいテーマを指定できます。また languageCode で生成言語を設定できます。

これを通常のAPIリクエストと同じようにPOSTします。

var options = {

method: 'POST',

contentType: 'application/json; charset=UTF-8',

headers: {

'Authorization': 'Bearer ' + token

},

payload: JSON.stringify(payload)

};

UrlFetchApp.fetch(endpoint, options);

これだけでAudio Overviewの生成処理を開始できます。ただし、ここの処理には、いくつか重要な注意点があります。

Audio Overviewを作成するためには、事前にNotebookへデータソースを追加しておく必要があります。また、一つのNotebookが同時に持てるAudio Overviewは一つです。すでにAudio Overviewが存在するNotebookに対して新たに作成しようとすると、そのままでは作成できません。 そのため、今回のサンプルのように毎日Notebook自体を新規作成する構成がベターです。

なお、2026年9月時点でNotebook Enterprise APIのこれらの機能はPreview版です。そのため、仕様は今後も変更される可能性があるため、業務システムへ組み込む場合は、この点を理解した上で利用する必要があります。

最後にGmailでNotebookのURLを通知する

Audio Overviewの生成リクエストを送ったら、最後に作成したNotebookのURLを利用者へ通知します。

今回のサンプルでは、

GmailApp.sendEmail(

CONFIG.NOTIFICATION_EMAIL,

subject,

plainText,

{

htmlBody: htmlBody,

name: 'Notebook ニュースボット'

}

);

という形でメールを送信しています。

メールにはNotebookのURLだけではなく、元データとなったGoogle ドキュメントのURLや、収集したニュース記事一覧も掲載しています。こうしておけば、利用者は通知メールからNotebookを開き、その日のAudio Overviewを確認できます。

今回の処理ではAudio Overviewの生成を開始した直後にメールを送っているため、メール受信時点ではまだ生成中の場合があります。この点はメール本文でも明示しておくと分かりやすいでしょう。

GASの時間主導型トリガーを設定して完全自動化する

ここまでの処理が動作すれば、最後は定期実行です。

今回のサンプルではGASの時間主導型トリガーを作成し、main() を毎日実行する構成にしています。

ScriptApp.newTrigger('main')

.timeBased()

.everyDays(1)

.atHour(8)

.create();

初回のみトリガー設定用の関数を手動実行しておけば、それ以降は人間がNotebookを作成する必要はありません。 毎朝RSSからニュースを取得し、Google ドキュメントを作成し、Notebookへ登録し、Audio Overviewの生成を開始し、最後に利用者へメールを送信するところまで自動化できます。

まとめ

Audio Overviewというと、Notebookへ資料を入れた後に人間がボタンを押して生成する機能というイメージを持っている方も多いと思います。しかしNotebook Enterprise APIを利用すると、その前段階にあるNotebookの作成やソース登録からプログラムで実行できます。

今回紹介したニュース収集は、一例にすぎません。例えば、毎週作成される営業レポートをNotebookへ自動登録して営業会議前に音声解説を生成したり、社内研修資料をNotebookへ投入して移動中に聞ける音声コンテンツを作ったりすることも可能です。

特に重要なのは、Audio Overviewだけを自動化するのではなく、「情報が発生する場所」からNotebookまでを一つの処理として設計することです。

GASを組み合わせればGoogle ドライブ、Google ドキュメント、GmailなどGoogle Workspace上のデータとNotebook Enterprise APIを接続できます。Notebookを単体の情報整理ツールとして利用するだけではなく、社内に蓄積されている情報を定期的にNotebookへ届け、さらに音声へ変換する仕組みまで作れるようになったことは、Notebook Enterprise APIの非常に面白いポイントではないでしょうか。

今後は、部署ごとにNotebookを自動生成したり、特定フォルダへ追加されたファイルを自動的にNotebookへ登録したりするなど、さらに実務に近い自動化にも発展させられそうです。

森田 嶺
森田 嶺
大学卒業後、 AWS や Google Cloud 等、主にクラウドを基盤とした新規サービス開発の経験を経て、YOSHIDUMIに入社。Google ドライブ拡張サービス「Cmosy Pocket」「共有ドライブマネージャー」等、 Google Cloud を活用した自社サービスの開発に従事。現在、 Google 等が提供する生成AIを活用したサービスを開発中。https://x.com/r__morita
Gemini・Notebookで変革! Google Workspaceで始めるAIファーストの働き方 〜「うちの会社でもできる」成長企業のための効果的な導入移行へのアプローチ〜

14:00-15:00 オンライン

Gemini・Notebookで変革! Google Workspaceで始めるAIファーストの働き方 〜「うちの会社でもできる」成長企業のための効果的な導入移行へのアプローチ〜

詳細はこちら

「閉じた」共有ドライブの利便性を最大化する! Cmosy Pocketで実現する、安全・快適な外部コラボレーション術セミナー

14:00-15:00 オンライン

「閉じた」共有ドライブの利便性を最大化する! Cmosy Pocketで実現する、安全・快適な外部コラボレーション術セミナー

詳細はこちら

Geminiの各機能、どう活かす?日常業務を加速する活用術と全社展開へのステップセミナー

14:00-15:00 オンライン

Geminiの各機能、どう活かす?日常業務を加速する活用術と全社展開へのステップセミナー

詳細はこちら

オンラインセミナー開催中

お申込みはこちらをCheck!