✍️

GoogleスライドでもSpeaker Deckで日本語フォントを崩さないアップロード手順

2023/12/23に公開

こんにちは、AWS Community Builder 兼 AWS User Group Leaders 兼 Amplify Japan User Group運営メンバーの池田 @ikenyal です。株式会社GENDA でEMをしつつ、株式会社ZINE で取締役CTOをしています。

登壇資料や外部公開するスライドをアップロードできるサービスはいくつもありますが、その中でも、Speaker Deckを主に利用しています。しかし、Speaker DeckではGoogleスライドとの相性に悩まされることがあります。日本語フォントを含んだスライドの場合、フォントやデザインが崩れた状態でSpeaker Deckにアップロードされる事象にしばしば遭遇したため、その回避策をまとめました。

Speaker Deckで遭遇する日本語の白抜き文字

Speaker Deckで、以下の「これは太字」のような白抜き状態の日本語フォントになっている事象を見かけたことが一度はあるのではないでしょうか。

このサンプルスライドはGoogleスライドで作成したものです。もちろん、Googleスライド上では、以下のようにきれいなフォントの状態で表示されています。

そして、GoogleスライドからPDFを出力した段階でも、以下のようにきれいな状態は維持されています。

ということは、Speaker DeckがPDFファイルを取り込んで処理する際に、日本語フォントが意図しない状態になっていると言えそうです。

いろいろと情報を調べていくと、Speaker Deckできれいに表示できる日本語フォントの種類は限られているようです。つまり、一番簡単な解決策としては「Speaker Deckでもきれいに表示される日本語フォントのみでスライドを作る」というものでしょう。

しかし、常に同じスライドのテーマを使っていれば問題ないですが、それでは普段とは違うテーマを使いにくくなってしまします。そして、何より使えるフォントが最初に限定されてしまうことは、デザインの制限になるとも言えます。

それならば、PDF内のフォントが問題なのであれば、フォントという概念のない画像として扱ってSpeaker Deckに読み込ませればいいんじゃないか、という発想に行き着きました。

手動でGoogleスライドから画像を出力するのは大変

Googleスライドから画像を出力すれば後はアップロードするだけ、と言いたいのですが、スライド全ページの画像出力も一筋縄ではいかない点がありました。

そもそも、ブラウザからGoogleスライドを操作していくと、画像のエクスポートはできるのですが、スライド1枚ずつエクスポートしないといけない仕様になっています。そのため、スライドの枚数分だけ手動でダウンロードしなければならず、運用フローとするのは気が引けます。さらに、ダウンロードできる画像のサイズも大きくないので、Speaker Deckにアップロードして大きく表示するには解像度が足りない状況でした。

手動ではどうしようもないので、スクリプトで対応することにしました。ただし、全工程を自動化しなくても、一部の手順だけ自動化できれば十分だという判断をし、以下の手順を定めています。なお、画像出力がjpgやpngだと画質が足りなくなるので、svgで出力させるようにしています。

スクリプトでGoogleスライドから画像ファイルを出力

ここでは、スプレッドシートでApps Scriptを利用し、Googleスライドの内容を画像としてGoogleドライブへ配置する流れを紹介します。

1. Googleスライドを配置したGoogleドライブのフォルダにスプレッドシートを配置

まず、Speaker DeckにアップロードしたいGoogleスライドを、Googleドライブの任意の場所に配置し、同じ場所にスプレッドシートを作成します。

2. スプレッドシートのApps Scriptを記載

用意したスプレッドシートにApps Scriptを記載していきます。これは初回に一度作成してしまえば、2度目以降はスクリプトを実行するだけで画像ファイルを出力できるようになります。


なお、ソースコードは後述します。

3. スクリプトを保存し、権限を付与

上記のスクリプトを保存し、実行をします。初回にはアクセス権限を求められるので付与します。






4. Apps Scriptで createPresentationSvgFileを実行

スクリプトに記載したcreatePresentationSvgFileを実行します。この実行はスライドの枚数にもよりますが、完了まで数分かかります。Googleスライドの枚数分のログが出力されていくので、実行完了の表示が出るまで待ちます。

5. Googleドライブに出力された画像をダウンロード

Googleドライブの同一フォルダに画像ファイル、今回だとsvgファイルがスライド枚数分出力されるので、すべてダウンロードします。なお、この画像ファイルはGoogleドライブ上には不要なので、Googleドライブのフォルダからは削除しておきます。また、Googleドライブから複数ファイルを同時にダウンロードした場合、zipファイルでダウンロードされるので解凍しておきます。

6. ダウンロードしたファイルから不要なページを削除

スライドの中にアップロードしたくないページがある場合は、ダウンロードした画像のなかから該当ページのsvgファイルを削除しておきます。なお、Macでsvgファイルを確認するには Gapplin 等のアプリで開くことが可能です。

Apps Scriptの内容

function createPresentationSvgFile() {
  // Googleスライドの情報を取得
  //   GoogleスライドのURL https://docs.google.com/presentation/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit#slide=id.abcd123456789_1_23
  //   の「xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx」に該当する部分を記載
  const presentation = SlidesApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');

  // Googleスライドのスライド情報を取得
  const slides = presentation.getSlides();

  // GoogleスライドのIDを取得
  const presentationId = presentation.getId();

  // Googleスライドのファイル名を取得
  const fileName = presentation.getName();
  
  // 出力形式を指定
  const format = 'svg';
  
  // ファイル名に付与する通し番号の初期値
  var page_num = 1;

  // スライド1枚ずつ、上記で指定の出力形式でファイルをダウンロード
  slides.forEach(function (slide) {
    // スライドのオブジェクトIDを取得
    const page_id = slide.getObjectId();

    // スライドを指定形式で出力する関数 convertPresentationToSpecifiedFormat を実行
    convertPresentationToSpecifiedFormat(fileName, presentationId, page_id, page_num, format);

    // ファイル名に通し番号を付与
    page_num += 1;
  });
}

// スライドを指定形式で出力する関数
function convertPresentationToSpecifiedFormat(file_Name, presentation_id, page_id, page_num, format) {
  // ダウンロードURLを組み立て
  const url = "https://docs.google.com/presentation/d/" + presentation_id + "/export/" + format + "?id=" + presentation_id + "&pageid=" + page_id;
  
  // HTTPリクエストに必要なオプションを指定
  const options = {
    method: "get",
    headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
    muteHttpExceptions: true
  };
  console.log(url)

  // HTTPリクエストを実施(エラーコード 429のリクエスト過多判定を回避しつつ
  var response = null;
  var maxRetries = 5;
  for (var i = 0; i < maxRetries; i++) {
    response = UrlFetchApp.fetch(url, options);
    if (response.getResponseCode() == 200) break;
    response = null;
    Utilities.sleep(5000);
  }
  if (!response) throw new Error("Values cannot be retrieved.");

  // HTTPリクエストの結果が正常な場合はファイル出力
  if (response.getResponseCode() === 200) {
    // ファイルが格納されているフォルダを取得
    const parentFolder = DriveApp.getFileById(presentation_id).getParents();
    const folder = parentFolder.next();

    // 対象フォルダにファイル作成
    return folder.createFile(response.getBlob()).setName((file_Name + page_num + "." + format).replace(' ', '-'));
  } else {
    console.log(response.getResponseCode())
  }
}

svgファイルをPDFへ一括変換

ダウンロードしたsvgファイルを、コマンドでPDFに変換します。

1. librsvgのインストール

初回のみ、librsvg をインストールします。

brew install librsvg

2. svgファイルをダウンロードしたディレクトリに移動

先程Googleドライブからダウンロードしたsvgファイルの配置場所を作業ディレクトリとします。

cd {該当ディレクトリのパス}

3. 出力先にするpdfディレクトリを作成

コマンドでPDFを出力する先のディレクトリを作成します。

mkdir pdf

4. PDFへの変換を実行

保存されているsvgファイルをコマンドですべてPDF出力します。

find ./ -type f -name '*.svg' | xargs -I{} sh -c 'rsvg-convert -f pdf -o "./pdf/$(basename {} .svg).pdf" {}'

5. コマンドで変換に失敗したページがあれば手動で変換

ページの内容にによってエラーになる場合もあります。その場合は、上記で紹介したGapplin等で該当のsvgファイルを開き、ファイル→書き出す でPDFを出力し、上記のpdfディレクトリに配置します。

6. PDFファイルの結合

Macの場合、FinderでpdfディレクトリにあるすべてのPDFを選択し、右クリックから クイックアクション→ PDFを作成 で結合したPDFを出力します。なお、カーソルが1枚目のPDFを選択した状態でないと順番がずれるようです。しかし、順番がずれてしまっても、結合されたPDFを開いて手動で順番を入れ替えて保存すれば問題ありません。

7. Speaker Deckにアップロード

出力されたPDFの中身を確認し、問題なければSpeaker Deckにアップロードします。

これでSpeaker Deckにどんな日本語でもきれいに表示できる

以上の手順により、日本語フォントの種類を問わず、きれいなフォントの状態でスライドをSpeaker Deckにアップロードできるようになりました。

Discussion