Google 翻訳に翻弄される日々

この記事は [Qiita IoTLT Advent Calendar 2020](https://qiita.com/advent-calendar/2020/iotlt) の 21 日目の記事です。

Google 翻訳に翻弄されっぱなしなので、備忘録的にそれを書きます。
何かを作った話じゃないです。ポエムっぽくてごめんなさい。

# 予備知識
個人的に esp8266/esp32 向けのライブラリーを公開しています。

  - horihiro / esp8266-google-tts<br>
    https://github.com/horihiro/esp8266-google-tts
  - Google 翻訳を使って、ESP8266 で TextToSpeech するライブラリ<br>
    https://qiita.com/horihiro/items/d64b699d06605ad44646

上の Qiita 記事にも書いていますが、node.js 用モジュールの [google-tts-api](https://github.com/zlargon/google-tts) の ~~パクリ~~ ポーティングです。

このライブラリーは (当然パクリ元の[google-tts-api](https://github.com/zlargon/google-tts) も) 、Google 翻訳ページ内の TTS の仕組みを使っています。

この 🔊 をクリックしたときの動きです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90361/d0ec292f-f428-35b5-b343-4980aaced58d.png)

このページでは、入力された (もしくは翻訳後の) 文字列とページに埋め込まれた `tkk` とかいう謎値をもとにトークンを計算し、そこから mp3 ファイルの URL を構築しています (ました)。

# それはいつも突然やってくる
はい、Google 翻訳の I/F 変更はいつも突然です。

過去にも、ページに埋め込まれた `tkk` が、それまで大文字だったものが小文字に変わったことで動かなくなったこともありました。

そして、11月上旬、Google がまたやってくれました。

## きっかけ
この issue です。「2，3回実行したらハングアップするんだけど」と。

  - Library fails to get URL the second or third time.<br>
    https://github.com/horihiro/esp8266-google-tts/issues/10

2, 3 回、というのが、またいやらしい。

## 調査
しょうがないので調べます。

Google 翻訳のページを開いて、開発者ツールとにらめっこして、ページのソースを見てみます。

  ＿人人人人人人人＿
  ＞ `tkk` がない！ ＜
  ￣Y^Y^Y^Y^Y^Y￣

そりゃ動かんわけです。

でもやばい。
mp3 の URL 構築方法が変わったか？どういう URL になったのか？

ネットワーク タブで HTTP リクエストを漁ってみると驚愕の事実が。

  ＿人人人人人人人人人人人人人人人＿
  ＞ mp3 へのリクエストがない！！ ＜
  ￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣

え！？Google さん、どうやって再生しているの？これ。
詰んだ。。。完全に詰んだ。。。

## でもなぜ 「2，3 回は動く」？？
絶望を紛らわすため、いったん視点を変えて「2，3 回は動く」に着目してみます。

何度か Google 翻訳のページをリロードしてみると、見た目が全く同じな 2 種類のページがランダムで表示されていることがわかりました ( 11 月上旬時点)。
従来の `tkk` パラメータがあるページと、ないページ。

なるほど。見えてきました。

  - たまたま最初の 2, 3 回は従来のページに当たって再生できた。
  - その後、新しい (`tkk` がない) ページに当たってしまい、`tkk` が見つからずハングアップ (はい、ここはバグです 🙇‍♂️）

て流れか。

## 対策を考える

数時間、開発ツールとにらめっこしてると以下のことがわかりました。

  - 新しいページでは、mp3 の URL を作るのではなく、mp3 ファイル自体 (base64 encoded) をダウンロードしている
  - 従来ページと新しいページで、レスポンス ヘッダー `Server` の値が変わっている

まっとうな対応なら、mp3 ファイル本体を返す実装にするのでしょうが、esp8266/32 のようなマイコンでのメモリー管理に自信がないので、あまり大きなデータを渡すライブラリーもあまり作りたくありません。

というわけで、少なくとも従来ページはまだ生きているので、レスポンス ヘッダー `Server` を見て、新しいページにアクセスしてしまった場合は接続を切ってリトライ (デフォルトでは 10 回) 、従来ページにアクセスできたとわかれば処理を続行、という実装にし、修正版を無事リリースしましたとさ。

めでたしめでたし。

ご高覧賜りありがとうございました。
ほりひろ先生の次回作にご期待ください。
<br>
<br>
<br>
<br>
<br>
<br>
とかすんなり終われば幸せだったのですが。

# 悪夢再び
上の修正版のリリースが 11 月半ばの話。その直後、12 月頭に新たな issue が。。。

  - Failed to connect to Google Translate. trying again...<br>
    https://github.com/horihiro/esp8266-google-tts/issues/12

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90361/9fe75d5d-c86c-8a3c-4e5e-8a08b5a3c9bc.png)


修正版で実装したリトライを何度しても従来ページにつながらず、デフォルトの 10 回に達してエラー、という状況。
どうやら、Google は従来ページは完全に閉じてしまったようで、何度アクセスしても `tkk` が取れません。

誰か Google に「手加減」を教えてあげてください。完全に言いがかりなんですが。

実は最初の issue への [コメント](https://github.com/horihiro/esp8266-google-tts/issues/10#issuecomment-723540589) に、「これだったら動くよー」暫定策も書かれていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90361/a16b9497-ba0e-4888-966f-78c1476140ea.png)

このコメントの時点では、

  - 従来のページは生きていて、大体半々で (ほりひろ調べ) でアクセスできていた。<br>
    -> なので、当時はリトライで何とかなった。
  - issue コメントに記載された暫定策は、一度 Google に閉じられた方法だったと記憶している。<br>
    -> またいつ閉じられても不思議じゃない、という不安感があった

ということもあり、採用を見送ったのですが、この暫定策よりも先に従来のページの方が閉じられてしまいました。
完全に読み誤りました。

おとなしく暫定策を実装したものを、つい先日 (12/19) 1.0.10 としてリリースしました。

コードを見たらわかるのですが、このライブラリー、もはや URL Encode と文字列連結しかしてないんですよね。
ここまで仕事してないと、ライブラリー化する意味があるのか疑問に思っています。

# 最後に

というわけで、ご利用者様にはバージョンを挙げて試してもらいたいのです。
ただ、この実装が最後の砦、という雰囲気があるので、この方法を閉じられたら、いよいよ「来世にご期待ください」になってしまいます。

以下、学びというか再認識というか。

  - 公開したものを使ってくれる人がいるのは嬉しい<br>
    issue でも `First of all, I'd like to say thanks for your library.` とか書かれると嬉しい
  - ただし外の何かに依存した作りになっている場合、それの気分次第で全部が作り直しになる可能性がある<br>
    このケースでいうと Google の気分次第
  - issue 対応の英語は、チョー適当でもなんとかなる


以上です。
ご高覧賜りありがとうございました (2回目)。