見出し画像

Webブラウザ上でアプリと同等の音声案内を行うための解決策

こんにちは。ナビタイムジャパンの「カップMEN」と「コタツ」です。カップMENはソリューション事業にて、プロダクトの開発、コタツは研究開発部門でナビゲーションの案内開発を担当しています。

今回は、当社のプロダクトの一つである『NAVITIME WebNAVI』のご紹介と、Webブラウザ上でアプリと同等の音声案内を実現するにあたっての課題と、その解決策のお話します。

『NAVITIME WebNAVI』とは

『NAVITIME WebNAVI』は法人向けクラウドベースの音声ナビゲーションサービスです。
徒歩・自転車・バイク・車の音声案内付きナビゲーション機能をお客様のサービス内に導入でき、アプリのように専用の開発技術がなくても、簡単にWebブラウザ上でナビゲーション機能を提供できます。

HTML5で動作するクラウドベースのサービスのため、お客様側での作り込みが不要で、手軽にお客様のサービス内に組み込むことが可能です。

今回は、この『NAVITIME WebNAVI』の音声発話機能を改善するために行った施策についてお話しします。

当社におけるナビゲーション機能について

本題に入る前に、当社におけるナビゲーション機能の開発について簡単にご説明します。
当社のナビゲーション機能は、たくさんのアプリケーションや徒歩、車など移動体に共通のコンポーネントを利用し、地図、航法、ルート検索、音声案内機能等を提供しています。さらにマルチプラットフォーム対応すべく、各OS独自の処理とは別にOSに依存しない共通処理をC++で実装して開発、運用コストを極力下げる工夫をしています。

当社コンポーネントの構成

Webブラウザ上でアプリと同等の音声案内を実現するために直面した課題

Webブラウザ上で「アプリと同等の音声案内」を目指す上で大きく2つの問題がありました。

1つ目は処理速度の問題です。
 アプリ向けに提供しているコンポーネントでは各アプリケーションで実現したい案内に対応すべく音声案内の種類が多いこと、また、交差点名称などを含む動的な発話をタイミングよく行わなければなりません。
そのためには現在位置の情報をもとに案内する内容を判断し必要な音声データの作成を高速に行う必要があります。

2つ目はアプリとWebブラウザ上で実現している機能の差分です。
 対応以前のWebNAVIでは「右に曲がります」などの静的な音声案内のみを行なう独自のWebブラウザ向けのコンポーネントを開発してサービスを提供しており、アプリ向けの共通コンポーネントと異なる運用をしていました。また、アプリ向けの共通コンポーネントは、提供しているサービスも多いことからWebブラウザ向けのコンポーネントより機能追加の頻度が高く、追従するのが難しい状況でした。

処理の高速化かつ機能の差分を埋めるために「WebAssembly」を活用

上述した2つの問題を解決するために着目したのが「WebAssembly」です。

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

出典:https://webassembly.org/

「Webassembly」とは上述の通りWebブラウザ上で動作するバイナリのことです。事前にコンパイルされたバイナリを高速に実行できるよう設計されているため、JavaScript に比べて高速に実行が可能と言われています。
また、C/C++、Rust等を含めたさまざまな言語で書かれたソースコードを活用してコンパイルでき、多くのブラウザで実行できるものになります。

今回「WebAssembly」を活用した経緯は以下の2つです。

  • Webブラウザ上で高速実行できる

  • 当社のナビゲーションコンポーネントを最大活用するべくC/C++をコンパイルしWebブラウザで利用できる

機能差分のキャッチアップだけでなく今後の新規機能への追従および運用コストの削減が可能になると考えて、研究開発の一環として採用しました。

「WebAssembly」の導入にあたって苦労した点

ここからは一番苦労したJavaScriptとのインターフェース部分について触れていきます。

今回、既存のC++ 層を活用するにあたり、新規でWebブラウザ向けのラッパー層を作成いたしました。
ラッパー層は主に2つのことを行なうために作成しています。

  1. extern "C"でexportする関数を定義する

  2. iOS、AndroidのOS層でやっている処理の一部を内包してシンプルなset/getの関数にする

1について、C++の関数はname manglingされるため定義する必要があるかつ、既存のC++ 層への修正はiOS、Andoroidへの影響を与える可能性もあったためラッパー層を作成して実施しています。

2について、C++ 層のクラスをWebから透過的に利用することは可能だが、多種多様な案内発話に対応するために複数の型のフィールドを持つ既存のクラスの設定を定義して利用可能にすることは実装コストが高かったことと、また同時にWeb側の実装も増えコンポーネントの利用者観点からも複雑になると考えて実施しています。

一般的に技術紹介の記事や文献などを見るとシンプルな例が多く、容易に出来そうに見えたのですが、それらの例よりも大規模なプロダクトコードに実際に適用するとなると、うまくいかないことも多々あり苦労しました。

WebNAVIの最新構成

他にもバイナリサイズが大きくなる問題などまだまだ工夫が必要な部分がありますが、iOS、Androidで利用している共通部分をWebブラウザ向けにも提供できC++ 層で行なっているロジックについて、ほぼ全ての機能のキャッチアップができました。

おわりに

『NAVITIME WebNAVI』の音声発話機能の改善のため、既存のコンポーネントをWeb上で利用可能にしたことについて、直面した課題や解決策を紹介しました。

今後も『NAVITIME WebNAVI』への機能の追加やブラッシュアップを行っていく予定ですので、ご興味を持っていただいた方はぜひお試しください。