2018-10-20に更新

Nuxt.js+FirebaseでAIメーカーのAPIを使ったサンプルを作った

先日AIメーカーにてAPIが公開されたので、試しにAPIを使ったWebアプリケーションを作ってみました。今回は画像をアップしなくても、ボタンを押すだけで自分のTwitterアイコンで判定できるようにしてみました。

ちなみに、現在はAIメーカー本家にもTwitterアイコンで判定できる機能が実装されています。個人開発のサービスでAPIまで公開されているものは珍しいので遊んでみたくなりました。

もくじ

ai maker api tester.png

構築環境

  • Nuxt.js
  • Firebase Authentication
  • Google Cloud Functions
  • Now

という感じのサーバーレス構成です。GitHubから取得してNowにデプロイするまでをざっと説明していきます。

開発環境の準備

ソースはGitHubにあげてあります。基本的な流れはそちらのREADMEにも書いてあります。

dala00/ai-maker-api-sample

依存関係のインストール

yarn

AIメーカーのapikeyを取得

AIメーカーにログインし、他の方が作成されているAIの詳細画面にあるAPIのパラメータを見ると自分のapikeyが表示されていますので、そちらをメモっておきます。

Firebaseの環境設定

予めFirebaseに登録し、Firebase Consoleにてプロジェクトを作成しておきます。

Firebaseのウェブアプリ設定

プロジェクトの設定画面を開くとこのボタンがありますので、クリックして設定情報を取得します。

env.sample.jsというファイルがありますので、それをenv.development.jsenv.production.jsとしてコピーし、各ファイルの中身を上記で取得した設定で埋めておきます(CLOUD_FUNCTIONS_BASE_URL以外)。

Authenticationの設定

Twitterログインを使用していますので、Firebase ConsoleのAuthenticationのログイン方法設定でTwitterを有効にしておきます。(Twitter側でのアプリケーションの設定も必要です)

Cloud Functionsの設定

firebase-toolsをPCにインストールし、シェルでfunctions関連の操作を行えるようにします。それを使ってfirebaseにログインし、functionsを初期化します。

npm install -g firebase-tools
firebase login
firebase init functions
アプリケーションの設定

functions内で使う値を設定しておきます。許可するURLとAIメーカーのapikeyの設定です。

firebase functions:config:set cors.origin=http://localhost:3000
firebase functions:config:set ai_maker.apikey=apikeygotfromaimaker
functionsをデプロイ
firebase deploy --only functions

これでfunctionsの管理画面を見るとURLが表示されているので、前述のCLOUD_FUNCTIONS_BASE_URLに値を入れておきます。imageClassificationの前のスラッシュまで入れます。

ローカルで起動

問題なければこれでローカル環境で動くようになっていると思います。開発モードで起動し、http://localhost:3000にアクセスします。

yarn run dev

Nowにデプロイ

now

これでデプロイできます。デプロイ時にURLが表示されますので、あとはFirebase Authenticationの許可ホスト名にそのホスト名を設定しておきます。また、cors.originも本番のURLを指定します。

デプロイするたびにホスト名が変わってしまいますが、その度に毎回設定するのは非常に面倒なので、何度もデプロイする場合はnow aliasを利用するとよいでしょう。一つ固定のホスト名を指定しておき、デプロイ時に発行されるURLにそれを関連付ける事ができます。

下記は実際にデプロイしたデモです。(しばらく誰もアクセスしていないと一度止まるようですので、その場合にアクセスすると表示されるまでに少々時間がかかります)

https://ai-maker-api-tester.now.sh

あと細かい調整をしていないのですが、Twitterログインから戻ってきた直後は少しだけログイン前の画面の表示になっています。待っていればログイン状態になり判定が行われます。(その他も変な挙動があるかもしれません。SPAだとgetRedirectResultのコールバックとか何度も呼ばれてるかも)

細かい処理の流れ

細かい処理の流れを簡単に説明しておきます。

データ

データは data/ai.js の中に配列で定義されています。現在AIの一覧取得APIは無いようですので、必要な分だけここで定義しておきます。

Twitterアイコンをfunctionsに送信

apikeyは隠したいため、functionsのconfigに設定し、function内でAIメーカーのAPIを実行します。そのため、Nuxt側からはAIのidとTwitterアイコンURLだけをfunctionに送信します。

      const params = {
        id: this.ai.id,
        image: this.$store.state.user.photoURL
      };
      axios
        .post(
          process.env.CLOUD_FUNCTIONS_BASE_URL + "imageClassification",
          params
        )
        .then(response => {
          this.labels = response.data.labels;
        })
        .catch(error => {
        });

function内でAPIを実行

Firebaseで取得できる画像URLは小さい画像のもので、これだといい感じに判定されないため大きい画像のURLに変換します。まずそのURLの画像を取得しておき、それをAPIに送信します。画像ファイル名も送信する必要があります。

    const form = new FormData();
    const image = await getImage(req.body.image.replace("normal.", "400x400."));
    form.append("id", req.body.id);
    form.append("apikey", functions.config().ai_maker.apikey);
    form.append("file", image, getFileName(req.body.image));
    form.submit(
      "https://aimaker.io/image/classification/api",
      (err, apiResponse) => {
        if (err) {
          console.error(err);
          res.status(500).json({ error: true });
          return;
        }

        chunks = [];
        apiResponse
          .on("data", chunk => {
            chunks.push(chunk);
          })
          .on("end", () => {
            const body = Buffer.concat(chunks).toString();
            const labels = JSON.parse(body);
            console.info(labels);
            res.json(labels);
          });
      }
    );

ここで返却した値はNuxt側でそのまま表示され、完了です。(実際にはスコア順に並び替えています)

まとめ

以上のように、Nuxt.js + Firebase + Cloud Functionsを利用したサーバーレス構成でのアプリケーション作成で遊んでみました。Nuxt.jsなのでSPA、SSR、PWAも可能ですし、FirebaseとCloud Functionsでサーバーを持つ必要もないので非常に気が楽ですね。

今回はデプロイにNowを使いましたが、GAE、Herokuでも同様のことが無料枠で可能です。

完成後再度環境構築までは試していないので、もし環境構築でつまづく場合があれば連絡いただければ確認します。


dala00

Crieitの開発者です。 主にLAMPで開発しているWebエンジニアです(在宅)。大体10年程。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel5, CakePHP3, JavaScript, RoR 趣味:Elixir, Phoenix, Node, Nuxt, Express, Vue等色々

Crieitはαバージョンで開発中です。進捗は公式Twitterアカウントをフォローして確認してください。 興味がある方は是非記事の投稿もお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか
関連記事

コメント