0

目標:ユーザーが S3 にアップロードすると、Lambda がトリガーされてファイルが取得され、分析のために Google Vision API に送信され、結果が返されます。

thisによると、google-cloudネイティブ ライブラリが必要であり、ラムダが実行されている OS に対してコンパイルする必要があります。使用lambda-packagerするとエラーがスローされましたが、代わりにノードと NPM を備えた EC2 を使用してインストールを実行するインターネット検索が表示されました。これをハッキングする精神で、それが私がそれをほとんど機能させるためにしたことです*。少なくともラムダは ELF ヘッダー エラーを出さなくなりました。

私の現在の問題は、Vision API を呼び出す方法が 2 つあり、どちらも機能せず、両方とも (ほとんどの場合) 別のエラーを返すことです。


共通コード:このコードは常に同じで、関数の先頭にあり、後のコード ブロックが問題に集中できるように分離しています。

'use strict';

const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'my-awesome-bucket'; 

const gCloudConfig = {
    projectId: 'myCoolApp',
    credentials: {
        client_email: 'your.serviceapi@project.email.com',
        private_key: 'yourServiceApiPrivateKey'
    }
}
const gCloud = require('google-cloud')(gCloudConfig);
const gVision = gCloud.vision();

使用法detect(): このコードは常にエラーを返しますError: error:0906D06C:PEM routines:PEM_read_bio:no start line。URL が公開されているため、理論的には機能するはずです。エラーを検索したところ、HTTPS の可能性があると考えられたので、HTTPS を HTTP に置き換えたバリエーションを試してみましたが、同じエラーが発生しました。

exports.handler = (event, context, callback) => {
    const params = {
        Bucket,
        Key: event.Records[0].s3.object.key
    }
    const img = S3.getSignedUrl('getObject', params);
    gVision.detect(img, ['labels','text'], function(err, image){
        if(err){
            console.log('vision error', err);
        }
        console.log('vision result:', JSON.stringify(image, true, 2));
    });
}

使用法detectLabels():このコードは常に を返しますError: ENAMETOOLONG: name too long, open ....[the image in base64]...。提案では、メソッドに base64 イメージを渡すのではなく、パブリック パスを渡す必要があると考えられていました。これは、名前が長すぎると言う理由を説明します (base64 画像はかなりの URL です)。残念ながら、上記の PEM エラーが発生します。また、base64エンコーディングを行わず、オブジェクトバッファをawsから直接渡そうとしましたが、PEMエラーも発生しました。

exports.handler = (event, context, callback) => {
    const params = {
        Bucket,
        Key: event.Records[0].s3.object.key
    }
    S3.getObject(params, function(err, data){
        const img = data.Body.toString('base64');
        gVision.detectLabels(img, function(err, labels){
            if(err){
                console.log('vision error', err);
            }
            console.log('vision result:', labels);
        });
    });
}

Best Practicesによると、画像は base64 でエンコードする必要があります。

API ドキュメントや例などから、これらを正しく使用しているようです。これらすべてのドキュメントを百万回読んだような気がします。

base64 を想定している場合、NAMETOOLONG エラーをどうすればよいかわかりません。これらの画像は 1 MB 以下です。

*PEMエラーは資格情報に関連しているようです。これらすべての資格情報がどのように機能し、モジュールがEC2(PEMファイルの種類がない)でどのようにコンパイルされているかを理解しているため、それが私の問題かもしれません. npm installLinuxボックスにインストールする必要があるのと同じように、実行する前にいくつかの資格情報を設定する必要があるのでしょうか? これは私の理解の範囲を超え始めているので、ここの誰かが知っていることを願っています。

理想的には、detect検出したいものを指定できるため、 を使用する方が良いでしょうが、Google から有効な応答を取得するだけでも素晴らしいでしょう。皆さんが提供できる手がかりは大歓迎です。

4

1 に答える 1

2

そのため、別の同僚との会話で、API のロード全体を放棄してgoogle-cloudモジュールを使用することを検討するように指示されました。代わりに、Cloud REST API を試してcurlみて、そのように機能するかどうかを確認することを検討する必要があります。

簡単に言うと、HTTP リクエストを作成し、Google Cloud 用の REST API を使用することで、この問題を解決しました。

これが私が今持っているラムダ関数です。おそらくまだ微調整が必​​要ですが、これは機能しています。

'use strict';

const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'yourBucket';
const fs = require('fs');
const https = require('https');

const APIKey = 'AIza...your.api.key...kIVc';

const options = {
    method: 'POST',
    host: `vision.googleapis.com`,
    path: `/v1/images:annotate?key=${APIKey}`,
    headers: {
        'Content-Type': 'application/json'
    }
}

exports.handler = (event, context, callback) => {
    const req = https.request(options, res => {
        const body = [];
        res.setEncoding('utf8');
        res.on('data', chunk => {
            body.push(chunk);
        });
        res.on('end', () => {
            console.log('results', body.join(''));
            callback(null, body.join(''));
        });
    });

    req.on('error', err => {
        console.log('problem with request:', err.message);
    });

    const params = {
        Bucket,
        Key: event.Records[0].s3.object.key
    }
    S3.getObject(params, function(err, data){
        const payload = {
            "requests": [{
                "image": {
                    "content": data.Body.toString('base64')
                },
                "features": [{
                    "type": "LABEL_DETECTION",
                    "maxResults": 10
                },{
                    "type": "TEXT_DETECTION",
                    "maxResults": 10
                }]
            }]
        };

        req.write(JSON.stringify(payload));
        req.end();
    });
}
于 2016-10-17T21:03:02.193 に答える