[GCP] Python3 x google-cloud-speechで音声認識を実装する

GCPでCloud Speech-to-Text APIを有効化します。

GCPユーザの認証データの*.jsonを取得します。

audio.rawはこちらからお借りします。
https://github.com/googleapis/java-speech/tree/master/samples/install-without-bom/resources

$ pip3 install google-cloud-speech

main.py

import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "hpscript.json"
from google.cloud import speech
import io

def transcribe_file(speech_file):
	
    client = speech.SpeechClient()

    with io.open(speech_file, "rb") as audio_file:
        content = audio_file.read()

    audio = speech.RecognitionAudio(content=content)
    config = speech.RecognitionConfig(
        encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
        sample_rate_hertz=16000,
        language_code="en-US",
    )
    response = client.recognize(config=config, audio=audio)

    for result in response.results:
        print(u"Transcript: {}".format(result.alternatives[0].transcript))

if __name__ == '__main__':
	transcribe_file('audio.raw')

$ python3 main.py
Transcript: how old is the Brooklyn Bridge

うーむ、なんだこれは

[AWS ALB] EC2で最初の接続だけ異常に重い時

EC2で最初の接続だけ異常に重く、一度接続すると、サクサク動く。
何故だ?curlで計測したところ、以下の様に最初の接続に130秒もかかっている。

$ curl ‘https://*.com/login’ -H ‘Accept-Encoding: gzip, deflate, sdch’ ept-Language: en-US,en;q=0.8,ja;q=0.6′ -H ‘Upgrade-Insecure-Requests: 1’ -H ‘User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36’ -H ‘Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8’ -H ‘Connection: keep-alive’ –compressed -o /dev/null -w “%{time_starttransfer}\n” -s
130.982826

最初、メモリが問題かと思って、増設し、さらにswapもつけたが、それでも変わらない。

$ df
ファイルシス 1K-ブロック 使用 使用可 使用% マウント位置
devtmpfs 492676 0 492676 0% /dev
tmpfs 503444 0 503444 0% /dev/shm
tmpfs 503444 524 502920 1% /run
tmpfs 503444 0 503444 0% /sys/fs/cgroup
/dev/xvda1 18862060 13096136 5765924 70% /
tmpfs 100692 0 100692 0% /run/user/1000

$ free
total used free shared buff/cache available
Mem: 1006892 713376 72396 352 221120 154016
Swap: 1048572 768 1047804

明らかにおかしいと思ったら、2つのsubnetのうち1つがinternet gatewayにアタッチされていなかったのが原因。

AWS Elastic Load Balancing: Seeing extremely long initial connection time
https://stackoverflow.com/questions/35523421/aws-elastic-load-balancing-seeing-extremely-long-initial-connection-time

ALBだとAZで2つのsubnetの設定が必要だが、今回はインスタンスは1つしか使わないので、internet gatewayには1つしかアタッチしてなかった。もう一つのpublic subnetをigwにアタッチしたところ、0.63msに改善

$ curl ‘https://*.com/login’ -H ‘Accept-Encoding: gzip, deflate, sdch’ -H ‘Accept-Language: en-US,en;q=0.8,ja;q=0.6’ -H ‘Upgrade-Insecure-Requests: 1’ -H ‘User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36’ -H ‘Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8’ -H ‘Connection: keep-alive’ –compressed -o /dev/null -w “%{time_starttransfer}\n” -s
0.638270

メモリの問題じゃなかったああああああああああああああああああ 
なんてこったい

[Laravel x Python] exec($command, $output)のトラブルシューティング

execコマンドがvagrantのamazon linux2では問題なく動作するのに、ec2にデプロイして実行すると反応しない。
execコマンドだとダメそうなので、SymphonyのProcessでやってみたが、それでもダメ。
NLPは最も肝となる処理なので諦めるわけにはいかん、とトラブルシューティングを丸一日。Webの記事を探しまくるも一向に解決せず。

該当のcontroller

            $input = $request->input;
            $replace_input = str_replace(" ", "\ ", $input);
            $path = app_path() . "/python/main.py";
            // $command = "python3 " . $path . " ".$replace_input;
            // exec($command, $output);
            $process = new Process(["python3", $path, $replace_input]);
            $process->run();
            $output = $process->getOutput();
            dd($output);

結論から言うと、ProcessFailedExceptionでエラー原因を表示させたらわかった。sudu pip3でpandas, sklearn, MeCabなどをインストールすればよかった。

use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
// 省略

            $process = new Process(["python3", $path, $replace_input]);
            $process->run();
            if (!$process->isSuccessful()) {
                throw new ProcessFailedException($process);
            }

エラーが起きたら、まず、Exceptionで原因を調べるのが早いですね。
laravelでpythonの処理は変則的なので、かなり焦りました。
もっと上達してええええええええええええ

[AWS EC2] mecab-ipadic-neologd で std::bad_alloc

EC2にMecabを入れます。

ssh ec2-user@18.179.118.214 -i ~/.ssh/aws-dev.pem

$ sudo yum update -y
$ sudo yum groupinstall -y “Development Tools”

$ wget ‘https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE’ -O mecab-0.996.tar.gz
$ tar xzf mecab-0.996.tar.gz
$ cd mecab-0.996
$ ./configure
$ make
$ make check
$ sudo make install
$ cd –
$ rm -rf mecab-0.996*

$ git clone –depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a -y
terminate called after throwing an instance of ‘std::bad_alloc’
what(): std::bad_alloc
/home/ec2-user/mecab-ipadic-neologd/bin/../libexec/make-mecab-ipadic-neologd.sh: 525 行: 24919 Aborted ${MECAB_LIBEXEC_DIR}/mecab-dict-index -f UTF8 -t UTF8

8.0G中、7.6G使用しており、メモリが足りなくなっています。
$ df -hT
ファイルシス タイプ サイズ 使用 残り 使用% マウント位置
devtmpfs devtmpfs 482M 0 482M 0% /dev
tmpfs tmpfs 492M 0 492M 0% /dev/shm
tmpfs tmpfs 492M 460K 492M 1% /run
tmpfs tmpfs 492M 0 492M 0% /sys/fs/cgroup
/dev/xvda1 xfs 8.0G 7.6G 455M 95% /
tmpfs tmpfs 99M 0 99M 0% /run/user/1000

memoryが足りないのでebsのボリュームを8Gから15Gにあげます。

$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 15G 0 disk
└─xvda1 202:1 0 8G 0 part /

$ sudo xfs_growfs /dev/xvda1
data blocks changed from 2096635 to 3931643

$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
devtmpfs 482M 0 482M 0% /dev
tmpfs 492M 0 492M 0% /dev/shm
tmpfs 492M 460K 492M 1% /run
tmpfs 492M 0 492M 0% /sys/fs/cgroup
/dev/xvda1 15G 7.6G 7.5G 51% /
tmpfs 99M 0 99M 0% /run/user/1000

$ ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a -y
[install-mecab-ipadic-NEologd] : Finish..

$ echo すもももももももものうち | mecab
すもももももももものうち 名詞,固有名詞,一般,*,*,*,すもももももももものうち,スモモモモモモモモノウチ,スモモモモモモモモノウチ
EOS

>>> import MeCab
>>> tagger = MeCab.Tagger(‘-Ochasen -d/usr/local/lib/mecab/dic/mecab-ipadic-neologd’)
>>> print(tagger.parse(‘すもももももももものうち’))
すもももももももものうち スモモモモモモモモノウチ すもももももももものうち 名詞-固有名詞-一般
EOS

MeCabが使えないと色々と前提が崩れるところやったわ

[AWS] Lambdaの基本機能

tutorialの”Introduction to AWS Lambda”で学んでいきます。

S3でbucketを作ります。
images-1357-4563
images-1357-4563-resized

HappyFace.jpeg

bucketのimages-1357-4563にuploadします。
Lambdaのcreate function

function name: Create-Thumbnail
runtime: Python 3.7 *tutorialはpython3.8で実行するとエラーになります。
Permissions: use an existing role
L lambda execution role

Add Trigger
S3
bucket: images-1357-4563
event type: All object create events

upload file
https://s3-us-west-2.amazonaws.com/us-west-2-aws-training/awsu-spl/spl-88/2.3.15.prod/scripts/CreateThumbnail.zip

Runtime setting: CreateThumbnail.handler

Test event: New event
template: s3-put

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "us-west-2",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "images-1357-4563",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "arn:aws:s3:::images-1357-4563"
        },
        "object": {
          "key": "HappyFace.jpeg",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

Execution result: succeeded
S3で確認するとリサイズされていることがわかります。

monitor, cloudwatchで確認できます。

add triggerは基本的にAWSでのサービスなんですね。

一周回って動きの流れは理解したが、アプリケーション側のイベントとは概念が異なるようです。
インフラで何か起きた時に、サーバレスでtriggerから実行するってことか。
数年前にも同じことやったが過去と比べて理解度が違ってる。

[Laravel8.46.0] LaravelCollectiveのCheckboxでEditの時

{!! Form::checkbox(‘${column}’, null, false !!} だと、初期値はnullですが、editの場合は、{!! Form::checkbox(‘${column}’, null, null !!} にします。

### create
{!! Form::checkbox(‘${column}’, null, false !!}

                    <div class="custom-control custom-checkbox">
                      {!! Form::checkbox('new_release', null, false, ['class'=>'custom-control-input', 'id'=>'custom-check-1']) !!}
                      <label class="custom-control-label" for="custom-check-1">新商品</label>
                    </div>

### Edit
{!! Form::checkbox(‘${column}’, null, null !!}

                    <div class="custom-control custom-checkbox">
                      {!! Form::checkbox('new_release', null, null, ['class'=>'custom-control-input', 'id'=>'custom-check-1']) !!}
                      <label class="custom-control-label" for="custom-check-1">新商品</label>
                    </div>

チェックボックスってあまり使わないので、ドキュメントも少ない印象です。

[V3 Vue.js] dataとcomputedの書き方

為替計算をサーバーサイド側ではなく、フロント側で実装しようと、Vue.jsを書いていたら、Vue.jsっていつの間にか2系から3系にバージョンアップしてたのね。知らなかった。。orz…
※為替レートはAPIで取得してサーバーサイドから流し込みます。

– new Vueではなく、Vue.createApp({})として、app.mount(‘#app’)とする。

             <div class="card-body" width="" height="">
                  <label for="yen">日本円を入力(単位円)</span></label>
                  <input type="number" v-model.number="yen" class="form-control col-md-2">
                  <br>
                  <label for="dollar">ドル換算</span></label>
                  <input type="string" v-model="dollar" id="dollar" class="form-control col-md-2">
                  <a href="javascript:OnLinkClick();">コピー</a>
              </div>

// 省略

  <script src="https://unpkg.com/vue@next"></script>
  <script>
    const app = Vue.createApp({
      data() {
          return {yen: 10000}
      },
      computed:{
          dollar(){
           return Number(this.yen / 110.05).toLocaleString('en-US', {style:'currency', currency:'USD'});
         }
      },
    });
    app.mount('#app')
  </script>

焦るな、というかtype scriptちゃんと勉強しないとついていけなくなりそう

[python3.x] 空白を含めたコマンドライン引数を送る

英文をコマンドライン引数で送って実行させたいが、英文の場合半角スペースが含まれる為、引数が分かれてしまう。
例えば、「The official site of the Boston Celtics. Includes news, scores, schedules, statistics, photos and video」を引数で渡そうとして実行すると、第一引数は「The」のみになってしまう。

L 半角スペース(” “)の文頭に”\”があると、エスケープされて処理される。

            $input = $request->input;
            $replace_input = str_replace(" ", "\ ", $input);
            $path = app_path() . "/python/en_ja.py";
            $command = "python3 " . $path . " ".$replace_input;
            exec($command, $output);
            $output = $output[0];

上記のようにエスケープすると、英文でも引数として渡すことができる。

なるほど、中々面白いね。

[JavaScript]aタグでテキストエリアの内容をコピー

Output(翻訳結果)をボタン一つでコピーしたい。
L aタグでjsの関数を実行させる
  L getElementsByTagName(“textarea”)[0]でtextareaのtextを取得し、*.select でコピーします。

<div class="card-footer ">
                {!! Form::label('dest', '英語(翻訳結果)') !!}
                {!! Form::textarea('dest', $output, ['class' => 'form-control' ]) !!}
                <a href="javascript:OnLinkClick();">コピー</a>
              </div>

<script>
function OnLinkClick(){
    var text = document.getElementsByTagName("textarea")[1];
    text.select();
}
</script>

おおおおおおおおおおおおお
ええやんか