先日AIメーカーにてAPIが公開されたので、試しにAPIを使ったWebアプリケーションを作ってみました。今回は画像をアップしなくても、ボタンを押すだけで自分のTwitterアイコンで判定できるようにしてみました。
ちなみに、現在はAIメーカー本家にもTwitterアイコンで判定できる機能が実装されています。個人開発のサービスでAPIまで公開されているものは珍しいので遊んでみたくなりました。
もくじ
構築環境
- Nuxt.js
- Firebase Authentication
- Google Cloud Functions
- Now
という感じのサーバーレス構成です。GitHubから取得してNowにデプロイするまでをざっと説明していきます。
開発環境の準備
ソースはGitHubにあげてあります。基本的な流れはそちらのREADMEにも書いてあります。
依存関係のインストール
yarn
AIメーカーのapikeyを取得
AIメーカーにログインし、他の方が作成されているAIの詳細画面にあるAPIのパラメータを見ると自分のapikeyが表示されていますので、そちらをメモっておきます。
Firebaseの環境設定
予めFirebaseに登録し、Firebase Consoleにてプロジェクトを作成しておきます。
プロジェクトの設定画面を開くとこのボタンがありますので、クリックして設定情報を取得します。
env.sample.js
というファイルがありますので、それをenv.development.js
、env.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でも同様のことが無料枠で可能です。
完成後再度環境構築までは試していないので、もし環境構築でつまづく場合があれば連絡いただければ確認します。
Top comments (3)
aah ok i will translate it , no worries :)
Oh, thank you guys.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.