4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【GAS】画像から文字を起こすLINEbotに翻訳機能を追加(言語サポート全部乗せ)

Last updated at Posted at 2021-01-16

概要

先日、画像を送ると文字に起こしてくれるLINEbotを作成して便利に使っていたんだけど、ついでに翻訳してくれたらなぁ~ってのが今回。

Qiita記事:【GAS】画像を送ると文字に起こすLINEbot【OCR】

上記リンク先で紹介したコードに少し足したら作れたので、追記部分を紹介するのがこの記事。

実行結果

画像送信
  ↓
文字起こし
  ↓
言語コード送信※
  ↓ ↑
翻訳(繰り返しOK)

LINEbotで画像から文字起こしするたびにスプレッドシートに起こした文字が記録され、言語コードを受け取ると記録された文字を翻訳する設計。

※Googleの翻訳機能でサポートされてる言語は何でも行けるようにしてみた^^)b

Translation API:言語サポート

そんなわけで、洋酒のラベルをLINEbotに送信。
image.png
ここまでは前と同じ。文字起こしされても私には読めない^^;

と言うことで、日本語(言語コード:ja)に翻訳!
image.png
なんかちょっと変だけど、翻訳精度はGoogle翻訳に依存。

韓国語(ko)
image.png

マラヤーラム文字(ml)
image.png
もちろん韓国語やマラヤーラム文字が読めるわけではない( ´_ゝ`)デザインがクール

コード

全文掲載。追加したのは4ヶ所(量は少し)、コード内で軽く触れつつ後程説明。その他の部分の説明は前の記事を参照。

var TOKEN = "xxxxxxxxxxxxxxxxxxxx";
var replyURL = "https://api.line.me/v2/bot/message/reply";

//追加コード①:スプレッドシートを定義
var sheet = SpreadsheetApp.openById('シートID').getSheetByName('シート名');

function doPost(event) {

  var json = JSON.parse(event.postData.contents);
  var replyToken = json.events[0].replyToken;
  var type = json.events[0].message.type;
  var messageId = json.events[0].message.id;

  //追加コード②:メッセージがテキストだった場合
  if (type === "text"){

    //言語コードを受け取るためにメッセージを取得
    var userMessage = json.events[0].message.text;
  
    //A1セルを取得(文字起こし前なら空欄)
    var origText = sheet.getRange('A1').getValue();
  
    //A1セルが空欄でなければ翻訳する ※追加コード④へ
    if(origText){
      translationText(userMessage, origText, replyToken);
    }

  }
  
  if (type !== "image"){
    replyBot(replyToken);
    return;
  }

  var imageURL = "https://api-data.line.me/v2/bot/message/" + messageId + "/content";
  var image = getImage(imageURL);
  
  //var folder = DriveApp.getFolderById("1gTJgvoX5ldwB69oPRelKEY-89dxGa_Ru");
  //folder.createFile(image);
  
  var ocrText = getText(image);
  
  //追加コード③:起こした文字を記録
  sheet.getRange('A1').setValue(ocrText);
  
  replyText(ocrText,replyToken);
}


//追加コード④:翻訳してLINEで返信
function translationText(lang, origText, replyToken) {
  
  //ターゲット言語が無効の場合return
  try{
    var transText = LanguageApp.translate(origText, "", lang);
  }catch(e){
    return;
  }
  
  //メッセージ作成・送信
  var payload = JSON.stringify({
      "replyToken": replyToken,
      "messages": [{
        "type": "text",
        "text": transText
      }]
  });
  UrlFetchApp.fetch(replyURL, {
      "headers": {
        "Content-Type": "application/json; charset=UTF-8",
        "Authorization": "Bearer " + TOKEN,
      },
      "method": "post",
      "payload": payload
  });
  return;
}


//画像でも翻訳リクエストでもない場合 画像を求めるメッセージを返す
//出来心で少し改変したので後程説明
function replyBot(replyToken) {

  var title = '画像を送ってね';
  var text  = '画像を送ると文字に起こすよ。\n翻訳するには文字起こし後に言語コードを送信。';
  
  var payload = JSON.stringify({
      "replyToken": replyToken,
      "messages": [{
        "type": "template",
        "altText": "ヒント",
        "template": {
          "type": "buttons",
          "title": title,
          "text": text,
          "actions": [
            {
              "type": "uri",
              "label": "カメラを起動する",
              "uri":"https://line.me/R/nv/camera/",
            },
            {
              "type": "uri",
              "label": "画像を選択する",
              "uri":"https://line.me/R/nv/cameraRoll/single",
            },
            {
              "type": "uri",
              "label": "サポート言語を見る",
              "uri":"https://cloud.google.com/translate/docs/languages",
            }
          ]
        }
      }]
  });
  UrlFetchApp.fetch(replyURL, {
        "headers": {
        "Content-Type": "application/json; charset=UTF-8",
        "Authorization": "Bearer " + TOKEN,
      },
      "method": "post",
      "payload": payload
  });
  return;
}


//投稿から画像を取得(変更無し)
function getImage(imageURL) {

  var image = UrlFetchApp.fetch(imageURL, {
       "headers": {
         "Content-Type": "application/json; charset=UTF-8",
         "Authorization": "Bearer " + TOKEN,
       },
       "method": "get"
  }).getBlob();
  
  return image;
}


//画像を文字に起こす(変更無し)
function getText(image) {
  
  var title = image.getName();
  var mimeType = image.getContentType();
  
  var resource = {title: title, mimeType: mimeType};
  var fileId = Drive.Files.insert(resource, image, {ocr: true}).id;
  
  var document = DocumentApp.openById(fileId);
  var ocrText = document.getBody().getText().replace("\n", "");
  Drive.Files.remove(fileId);
  
  return ocrText;
}


//起こした文字をLINEで返信(変更無し)
function replyText(ocrText,replyToken) { 

  var replyURL = "https://api.line.me/v2/bot/message/reply"; 
  
  var payload = JSON.stringify({ 
      "replyToken": replyToken, 
      "messages": [{ 
        "type": "text", 
        "text": ocrText 
      }] 
  }); 
  UrlFetchApp.fetch(replyURL, { 
      "headers": { 
        "Content-Type": "application/json; charset=UTF-8", 
        "Authorization": "Bearer " + TOKEN, 
      }, 
      "method": "post", 
      "payload": payload 
  }); 
  return; 
}

解説

まずは追加コード①でスプレッドシートを定義。

前のコードではテキスト判定は行わなかったけど、今回は「追加コード②」でテキスト判定を行っている。テキストでなく画像であれば文字起こし→「追加コード③」でスプレッドシートへ記録。

テキストメッセージが送られてきたら、それをA1セルの文字と一緒に「追加コード④」へ送る。「追加コード④」では、テキストメッセージを言語コードとして.translateメソッドでA1セルを翻訳。(翻訳前の言語を指定する部分を空欄にしているので、言語は自動で判定。)

翻訳先の言語コードがサポートされていないコードや関係ないテキストだった場合、通常ならエラーになってスクリプトが停止してしまうけどtry...catch文で停止回避、翻訳エラーの場合はreturnさせる。

これでサポートされている言語を全部使える^^

returnされたのであれば、メッセージタイプは画像ではないので画像を求めるメッセージを返す。
image.png
前のままでも使えたけど、カメラ起動・カメラロール・言語サポートリンクのボタンテンプレートを返すようにした。

おしまい

4
5
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?