ガイド変更履歴HERE SDK API references
ガイド

音声ガイダンスを追加する

ナビゲーションはNavigateライセンスでのみ利用できます。

運転中は、ユーザーの注意がルートに集中するようにしなければなりません。提供された運転操作データからビジュアル表現を構築できるだけでなく (上のセクションを参照)、経路誘導のガイダンス中に対話できるようにするためのローカライズされたテキスト表現を取得することもできます。これらの運転操作通知はStringとして提供され、任意のTTSソリューションと組み合わせて使用できます。

運転操作通知はドライバーを対象としています。歩行者のガイダンスに使用することは推奨しません。

HERE SDK には、事前に録音された音声スキンは含まれていません。そのため、再生用に TTS エンジンを統合する必要があります。オーディオ再生の詳細と例を以下に紹介します。

通知の例 (文字列として提供):

Voice message: After 1 kilometer turn left onto North Blaney Avenue.
Voice message: Now turn left.
Voice message: After 1 kilometer turn right onto Forest Avenue.
Voice message: Now turn right.
Voice message: After 400 meters turn right onto Park Avenue.
Voice message: Now turn right.

これらの通知を受信するには、EventTextListener を設定します。

// Notifies on messages that can be fed into TTS engines to guide the user with audible instructions.
// The texts can be maneuver instructions or warn on certain obstacles, such as speed cameras.
visualNavigator.setEventTextListener(new EventTextListener() {
    @Override
    public void onEventTextUpdated(@NonNull EventText eventText) {
        // We use the built-in TTS engine to synthesize the localized text as audio.
        voiceAssistant.speak(eventText.text);
        // We can optionally retrieve the associated maneuver. The details will be null if the text contains
        // non-maneuver related information, such as for speed camera warnings.
        if (eventText.type == TextNotificationType.MANEUVER && eventText.maneuverNotificationDetails != null) {
            Maneuver maneuver = eventText.maneuverNotificationDetails.maneuver;
        }
    }
});
// Notifies on messages that can be fed into TTS engines to guide the user with audible instructions.
// The texts can be maneuver instructions or warn on certain obstacles, such as speed cameras.
visualNavigator.eventTextListener =
    EventTextListener { eventText: EventText ->
    // We use the built-in TTS engine to synthesize the localized text as audio.
    voiceAssistant.speak(eventText.text)
    // We can optionally retrieve the associated maneuver. The details will be null if the text contains
    // non-maneuver related information, such as for speed camera warnings.
    if (eventText.type == TextNotificationType.MANEUVER && eventText.maneuverNotificationDetails != null) {
        val maneuver = eventText.maneuverNotificationDetails!!.maneuver
    }
}

ここでは VoiceAssistant というヘルパー クラスを使用し、音声合成エンジンをラップして操作通知を読み上げます。エンジンはAndroidのTextToSpeechクラスを使用します。

関心がある場合は、このクラスは「Navigation」サンプルアプリの一部として、Java版およびKotlin版がGitHubで公開されています。

スピード取締カメラの警告は特定の国でのみ利用可能であり、SafetyCameraWarningListenerが設定されている場合にのみEventTextとして含まれます。

Natural Guidance は、運転操作通知を改善するために重要なオブジェクトを使用します。

必要に応じて、Natural Guidance を有効にすることもできます。EventText テキストを強化して、ルートに沿って重要なオブジェクト (信号機や停止標識など) を含めることで、運転操作をよりわかりやすくできます。例:「次の信号機で左折してウォール ストリートに入ります」この機能はデフォルトで無効になっています。有効にするには includedNaturalGuidanceTypes のリストを使用して、TRAFFIC_LIGHT などの NaturalGuidanceTypeManeuverNotificationOptions に少なくとも 1 つ追加します。

LanguageCode を設定すると、通知テキストと UnitSystem をローカライズしてメートル法またはインペリアル法の長さ単位を決定できます。ルートが設定される前にこれを呼び出すようにしてください。そうしないと、デフォルト設定 (EN_USMETRIC) になります。ManeuverNotificationOptionsの詳細については、「APIリファレンス」を参照してください。

private void setupVoiceGuidance() {
    if(this.voiceAssistant == null) {
        this.voiceAssistant = new VoiceAssistant(MainActivity.this);

        ManeuverNotificationOptions maneuverNotificationOptions = new ManeuverNotificationOptions();
        LanguageCode ttsLanguageCode = getLanguageCodeForDevice(VisualNavigator.getAvailableLanguagesForManeuverNotifications());
        // Set the language in which the notifications will be generated.
        maneuverNotificationOptions.language = ttsLanguageCode;
        // Set the measurement system used for distances.
        maneuverNotificationOptions.unitSystem = UnitSystem.METRIC;
        visualNavigator.setManeuverNotificationOptions(maneuverNotificationOptions);
        Log.d(TAG, "LanguageCode for maneuver notifications: " + ttsLanguageCode);

        // Set language to our TextToSpeech engine.
        Locale locale = LanguageCodeConverter.getLocale(ttsLanguageCode);
        if (voiceAssistant.setLanguage(locale)) {
            Log.d(TAG, "TextToSpeech engine uses this language: " + locale);
        } else {
            Log.e(TAG, "TextToSpeech engine does not support this language: " + locale);
        }
    }
}
private fun setupVoiceGuidance(visualNavigator: VisualNavigator) {
    val ttsLanguageCode =
        getLanguageCodeForDevice(VisualNavigator.getAvailableLanguagesForManeuverNotifications())
    val maneuverNotificationOptions = ManeuverNotificationOptions()
    // Set the language in which the notifications will be generated.
    maneuverNotificationOptions.language = ttsLanguageCode
    // Set the measurement system used for distances.
    maneuverNotificationOptions.unitSystem = UnitSystem.METRIC
    visualNavigator.maneuverNotificationOptions = maneuverNotificationOptions
    Log.d(
        TAG,
        "LanguageCode for maneuver notifications: $ttsLanguageCode"
    )

    // Set language to our TextToSpeech engine.
    val locale = LanguageCodeConverter.getLocale(ttsLanguageCode)
    if (voiceAssistant.setLanguage(locale)) {
        Log.d(
            TAG,
            "TextToSpeech engine uses this language: $locale"
        )
    } else {
        Log.e(
            TAG,
            "TextToSpeech engine does not support this language: $locale"
        )
    }
}

この例では、以下に示すようにデバイスの優先言語設定を使用しています。

private LanguageCode getLanguageCodeForDevice(List<LanguageCode> supportedVoiceSkins) {

    // 1. Determine if preferred device language is supported by our TextToSpeech engine.
    Locale localeForCurrenDevice = Locale.getDefault();
    if (!voiceAssistant.isLanguageAvailable(localeForCurrenDevice)) {
        Log.e(TAG, "TextToSpeech engine does not support: " + localeForCurrenDevice + ", falling back to EN_US.");
        localeForCurrenDevice = new Locale("en", "US");
    }

    // 2. Determine supported voice skins from HERE SDK.
    LanguageCode languageCodeForCurrenDevice = LanguageCodeConverter.getLanguageCode(localeForCurrenDevice);
    if (!supportedVoiceSkins.contains(languageCodeForCurrenDevice)) {
        Log.e(TAG, "No voice skins available for " + languageCodeForCurrenDevice + ", falling back to EN_US.");
        languageCodeForCurrenDevice = LanguageCode.EN_US;
    }

    return languageCodeForCurrenDevice;
}
// Get the language preferably used on this device.
private fun getLanguageCodeForDevice(supportedVoiceSkins: List<LanguageCode>): LanguageCode {
    // 1. Determine if preferred device language is supported by our TextToSpeech engine.

    var localeForCurrenDevice = Locale.getDefault()
    if (!voiceAssistant.isLanguageAvailable(localeForCurrenDevice)) {
        Log.e(
            TAG,
            "TextToSpeech engine does not support: $localeForCurrenDevice, falling back to EN_US."
        )
        localeForCurrenDevice = Locale("en", "US")
    }

    // 2. Determine supported voice skins from HERE SDK.
    var languageCodeForCurrenDevice =
        LanguageCodeConverter.getLanguageCode(localeForCurrenDevice)
    if (!supportedVoiceSkins.contains(languageCodeForCurrenDevice)) {
        Log.e(
            TAG,
            "No voice skins available for $languageCodeForCurrenDevice, falling back to EN_US."
        )
        languageCodeForCurrenDevice = LanguageCode.EN_US
    }

    return languageCodeForCurrenDevice
}

内部的には、運転操作通知のテキストは RouteProgress イベントからアクセスできる Maneuver データから生成されます。RouteProgress イベントは、渡された位置情報の更新に基づいて頻繁に生成されます。運転操作通知では、テキスト メッセージを生成する頻度とタイミングを指定できます。これは、ManeuverNotificationTimingOptions で指定できます。

ManeuverNotificationType のそれぞれに、移動モードと道路タイプごとの ManeuverNotificationTimingOptions を設定できます。また、メートル単位の距離または秒単位でタイミングを指定できます。

  1. ManeuverNotificationType.RANGE:最初の通知。rangeNotificationDistanceInMeters または rangeNotificationTimeInSeconds で指定。
  2. ManeuverNotificationType.REMINDER:2 つ目の通知。reminderNotificationDistanceInMeters または reminderNotificationTimeInSeconds で指定。
  3. ManeuverNotificationType.DISTANCE:3 つ目の通知。distanceNotificationDistanceInMeters または distanceNotificationTimeInSeconds で指定。
  4. ManeuverNotificationType.ACTION:4 つ目の通知。actionNotificationDistanceInMeters または actionNotificationTimeInSeconds で指定。

タイプは距離の順に並べられます。運転操作の数メートル手前のみの TTS メッセージをカスタマイズする場合は、distanceNotificationDistanceInMeters のみを設定します。maneuverNotificationOptions.includedNotificationTypes でタイプを除外することもできます。たとえば、DISTANCE タイプのみを設定すると、運転操作が行われても (= ACTION)、他の通知は受信しません。

以下では、高速道路 (道路タイプ) の車 (= 移動モード) の DISTANCE タイプ値のみを調整し、その他の値はすべてそのままにしています。

// Get currently set values - or default values, if no values have been set before.
// By default, notifications for cars on highways are sent 1300 meters before the maneuver
// takes place.
ManeuverNotificationTimingOptions carHighwayTimings = navigator.getManeuverNotificationTimingOptions(TransportMode.CAR, TimingProfile.FAST_SPEED);

// Set ManeuverNotificationType.DISTANCE (3rd notification):
// Set a new value for cars on highways and keep all other values unchanged.
carHighwayTimings.distanceNotificationDistanceInMeters = 1500;

// Apply the changes.
navigator.setManeuverNotificationTimingOptions(TransportMode.CAR, TimingProfile.FAST_SPEED, carHighwayTimings);

// By default, we keep all types. If you set an empty list you will disallow generating the texts.
// The names of the type indicate the use case: For example, RANGE is the farthest notification.
// ACTION is the notification when the maneuver takes place.
// And REMINDER and DISTANCE are two optional notifications when approaching the maneuver.
maneuverNotificationOptions.includedNotificationTypes = Arrays.asList(
        ManeuverNotificationType.RANGE, // first notification.
        ManeuverNotificationType.REMINDER, // second notification.
        ManeuverNotificationType.DISTANCE, // third notification.
        ManeuverNotificationType.ACTION); // fourth notification.

デフォルトでは、運転操作通知のテキストはプレーン テキストの正字法 ("Wall Street") です。一部の TTS エンジンはボイス データをサポートしており、SSML 表記の "wɔːl"striːt" の他プレーン テキストの "Wall Street" も追加されています。これにより、より正確な発音になります。以下のコードを呼び出してボイス データを有効にします。

// Add phoneme support with SSML.
// Note that phoneme support may not be supported by all TTS engines.
maneuverNotificationOptions.enablePhoneme = true;
maneuverNotificationOptions.notificationFormatOption = NotificationFormatOption.SSML;

ボイス データを使用した音声メッセージの例:

After 300 meters turn right onto <lang xml:lang="ENG"><phoneme alphabet="nts"  ph="&quot;wɔːl&quot;striːt" orthmode="ignorepunct">Wall Street</phoneme></lang>.

「API リファレンス」を参照して、ManeuverNotificationOptions で設定できるその他のオプションを確認してください。

HERE SDK では 37 の言語がサポートされています。VisualNavigator.getAvailableLanguagesForManeuverNotifications() を使用して VisualNavigator から言語をクエリできます。HERE SDK 内のすべての言語は LanguageCode 列挙型 (enum) として指定されます。これをLocaleインスタンスに変換するには、LanguageCodeConverterを使用できます。これはオープン ソースのユーティリティ クラスで、GitHubVisualNavigator.getAvailableLanguagesForManeuverNotifications()NavigationVisualNavigator のサンプル アプリの一部として含まれています。

運転操作通知の生成でサポートされている各言語は、HERE SDK フレームワーク内に音声スキンとして格納されています。フレームワークを展開し、voice_assets フォルダーを探してください。使用予定のないアセットを削除して、HERE SDK パッケージのサイズを小さくすることができます。ファイルを削除する方法の詳細については、地図のセクションを参照してください。

ただし、運転操作通知を TTS エンジンにフィードするには、選択した TTS エンジンで指定の言語がサポートされていることを確認する必要もあります。通常、各デバイスにはいくつかの言語がプレインストールされていますが、最初はすべての言語が表示されていない場合があります。

SpatialAudioNavigation のサンプル アプリでは、VisualNavigator と Android のネイティブ コードを併用して、オーディオ パンを使用して TTS オーディオ メッセージを再生し、ステレオ パノラマを使用して方向を示す方法を確認できます。この例は GitHub で確認できます。

音声ガイダンスの対応言語

以下で、サポートされているすべての音声言語のリストと、HERE SDK フレームワーク内に保存されている関連する音声スキンの名前を確認できます。

  • アラビア語 (サウジアラビア):voice_package_ar-SA
  • ベンガル語:voice_package_bn-IN
  • ブルガリア語:voice_package_bg-BG
  • カタルーニャ語:voice_package_ca-ES
  • 中国語 (簡体字中国):voice_package_zh-CN
  • 中国語 (繁体字香港):voice_package_zh-HK
  • 中国語 (繁体字台湾):voice_package_zh-TW
  • クロアチア語:voice_package_hr-HR
  • チェコ語:voice_package_cs-CZ
  • デンマーク語:voice_package_da-DK
  • オランダ語:voice_package_nl-NL
  • 英語 (英国):voice_package_en-GB
  • 英語 (米国):voice_package_en-US
  • ペルシア語 (イラン):voice_package_fa-IR
  • フィンランド語:voice_package_fi-FI
  • フラマン語 (ベルギー):voice_package_nl-BE
  • フランス語 (カナダ):voice_package_fr-CA
  • フランス語:voice_package_fr-FR
  • ドイツ語:voice_package_de-DE
  • ギリシャ語:voice_package_el-GR
  • グジャラート語:voice_package_gu-IN
  • ヘブライ語:voice_package_he-IL
  • ヒンディー語:voice_package_hi-IN
  • ハンガリー語:voice_package_hu-HU
  • インドネシア語 (バハサ):voice_package_id-ID
  • イタリア語:voice_package_it-IT
  • 日本語:voice_package_ja-JP
  • カンナダ語:voice_package_kn-IN
  • 韓国語:voice_package_ko-KR
  • マラヤーラム語:voice_package_ml-IN
  • ノルウェー語 (ブークモール):voice_package_nb-NO
  • ポーランド語:voice_package_pl-PL
  • ポルトガル語 (ブラジル):voice_package_pt-BR
  • ポルトガル語 (ポルトガル) voice_package_pt-PT
  • ルーマニア語:voice_package_ro-RO
  • ロシア語:voice_package_ru-RU
  • セルビア語:voice_package_sr-CS
  • スロバキア語:voice_package_sk-SK
  • スペイン語 (アルゼンチン):voice_package_es-AR
  • スペイン語 (メキシコ):voice_package_es-MX
  • スペイン語 (スペイン):voice_package_es-ES
  • スウェーデン語:voice_package_sv-SE
  • タミル語:voice_package_ta-IN
  • テルグ語:voice_package_te-IN
  • タイ語:voice_package_th-TH
  • トルコ語:voice_package_tr-TR
  • ウクライナ語:voice_package_uk-UA
  • ベトナム語:voice_package_vi-VN

HERE SDKフレームワークを展開し、voice_assetsフォルダーを見つけます。フレームワークのサイズを縮小する場合は、不要な音声パッケージを削除できます。

空間的な運転操作の音声通知

EventTextListener から提供される同じ voiceText (上記を参照) を、空間オーディオ情報を使用して強化することもできます。

空間オーディオの通知を使用すると、音声合成文字列のステレオパノラマをリアルタイムで調整できます。これは、車に座っているドライバーと関連する次のキュー (運転操作および警告) の位置に基づいて行われます。

EventTextListener を使用すると、次のキューの運転操作テキストだけでなく、EventTextListener.SpatialNotificationDetails で HERE SDK によって定義された空間オーディオ軌跡の 1 つを構成する方位角要素も取得できます。結果の SpatialTrajectoryData には次に使用される方位角が含まれており、空間オーディオの軌跡が終了したかどうかを示します。

この情報を取得するには、EventTextOptions.enableSpatialAudio を有効にする必要があります。

SpatialNotificationDetails.AudioCuePanning を使用してパンを開始し、CustomPanningData を渡して estimatedAudioCueDuration を更新し、その initialAzimuthInDegreessweepAzimuthInDegrees のプロパティをカスタマイズします。例:

spatialAudioCuePanning.startAngularPanning(customPanningData, spatialTrajectoryData -> {
    Log.d(SpatialAudioCuePanning.class.getSimpleName(), "Next azimuth:" + spatialTrajectoryData.azimuthInDegrees);
    updatePanning(spatialTrajectoryData);
});

サンプルアプリを試す

  • GitHubJavaおよびKotlinの両方で提供されている「Navigation」サンプルアプリでは、TTSエンジンを統合して音声コマンドを再生する方法の例を示しています。
  • 空間オーディオの詳細については、GitHubの「SpatialAudioNavigation」サンプルアプリをご覧ください。

EN 日本語

HERE documentation

Find answers to your product and technical questions

Documentation

What's new

Videos

EN 日本語

HERE ドキュメント

製品や技術に関する質問の答えを見つけましょう。より多くの内容と最新の情報については、英語版をご覧ください。

ドキュメント

ダイナミックマップ

動的コンテンツ関連のAPIをアプリやサービスに活用して、ドライバーが安全・快適かつ予定どおりに目的地へ到着できるよう支援します。

地図とデータ

世界中を走行する多数のマッピング車両から得られる最新の位置情報データを活用し、精度の高い地図やカスタムレイヤーを構築できます。

最新情報

動画

(function () { const input = document.querySelector('input[data-typeahead]'); if (!input) return; // Prevent the form from submitting/navigating input.closest('form')?.addEventListener('submit', e => e.preventDefault()); input.addEventListener('input', function () { const q = this.value.trim().toLowerCase(); document.querySelectorAll('.nav-group-name').forEach(group => { let anyVisible = false; group.querySelectorAll('.nav-group-task').forEach(task => { const text = task.textContent.trim().toLowerCase(); const show = !q || text.includes(q); task.style.display = show ? '' : 'none'; if (show) anyVisible = true; }); // Hide the whole group header if nothing matches group.style.display = anyVisible || !q ? '' : 'none'; }); }); })(); (function () { function onTokenClick(event) { var link = event.target.closest('.sdk-for-ios .item .token'); if (!link) return; event.preventDefault(); console.log('token clicked', link.textContent.trim()); var item = link.closest('.item'); if (!item) return; var content = item.querySelector('.height-container'); if (!content) { console.log('no .height-container found for item', item); return; } var isHidden = window.getComputedStyle(content).display === 'none'; content.style.display = isHidden ? 'block' : 'none'; link.classList.toggle('token-open', isHidden); var href = link.getAttribute('href'); if (href) { if (history.pushState) history.pushState({}, '', href); else location.hash = href; } } function openHashTarget() { var hash = window.location.hash.slice(1); if (!hash) return; var anchor = document.querySelector('.sdk-for-ios a[name="' + hash + '"]'); if (!anchor) return; var item = anchor.closest('.item'); if (!item) return; var link = item.querySelector('.token'); var content = item.querySelector('.height-container'); if (!link || !content) return; content.style.display = 'block'; link.classList.add('token-open'); } function init() { console.log('HERE SDK accordion init'); openHashTarget(); } document.removeEventListener('click', onTokenClick); document.addEventListener('click', onTokenClick); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hashchange', openHashTarget); window.addEventListener('pageLoad', init); })();