Use voice instructions from server#614
Conversation
🚮 |
|
@1ec5 should we just do an index? |
There was a problem hiding this comment.
The plain text instruction is still needed for the AVSpeechSynthesizer fallback. I think it would be reasonable to pass the whole VoiceInstruction object into this method.
There was a problem hiding this comment.
Is userDistance still needed?
There was a problem hiding this comment.
I'd like to keep spokenInstructionFormatter.string around for testing and comparison, so yes still needed.
I guess it depends what our customization story will be. In the future, how will custom milestones interact with the preset ones provided by the API? Would the API be able to add more or fewer than three announcements for a particular step if necessary? As I see it, the main use case for exposing alert levels publicly was to allow developers to time UI changes around the announcements. We can meet that need by calling a delegate method whenever an announcement will be spoken or has been spoken; we’d need to pass in some way of indicating which announcement was spoken, and that information should be pretty closely tied to the API’s way of referring to the announcements. The API doesn’t currently expose any reliable way to determine the urgency of an announcement, other than its position in the array. Other current uses of alerts should transition over to the much more flexible RouteProgress class. |
There was a problem hiding this comment.
It’s pretty weird that RouteController is observing for notifications posted by itself. Can we call these methods directly wherever we’re posting the notifications?
Observing oneself is a little risky since failing to remove the observer for whatever reason would be guaranteed to leak memory. (We’re correctly calling removeObserver(_:) in suspendNotifications(), but it’s still risky.)
There was a problem hiding this comment.
Let's fix this in it's own PR.
There was a problem hiding this comment.
A notification should never have “should” in its name: rename this constant to RouteControllerDidPassVoiceInstructionPoint or something along those lines.
A delegate method can have “should” – that would indicate that the method returns a Boolean that controls whether something happens or not. But a notification observer is never able to control the program flow.
There was a problem hiding this comment.
This is a trap. We don’t currently document that NavigationRouteOptions or includesVoiceInstructions must be used with this library. In fact, the readme currently omits any mention of NavigationRouteOptions. We should either devise a graceful fallback strategy or fail upfront whenever NavigationViewController is created without the necessary route options. Either way, we need to update the documentation to use NavigationRouteOptions.
There was a problem hiding this comment.
Shouldn’t we continue to track this distance? Seems like it would continue to be useful for developers at least.
There was a problem hiding this comment.
Let's cut it if it's not used.
There was a problem hiding this comment.
Why does this code live on RouteLegProgress if it’s specific to the current step?
There was a problem hiding this comment.
This will render the volume and speaking rate options nonfunctional. What should we do about those options until API support for them lands?
|
cc @ksummerill to keep 👀 on this for a customer |
10fb598 to
f2c31c1
Compare
There was a problem hiding this comment.
With my security hat on, this seems like it would enable someone to break the navigation SDK simply by renaming a road to something like <speak> or </speak>. Using a proper XML parser would be best, although if we’re absolutely certain that the Directions API will be giving us a document with <speak> as the root element, then we could address the security concern by restricting finding-and-replacing only at the beginning and end of the string.
There was a problem hiding this comment.
Since alert levels are no more, describe this notification in terms of the user passing an ideal point at which to announce an upcoming maneuver.
There was a problem hiding this comment.
Rename to currentSpokenInstruction for consistency with currentStep, currentLeg, etc.
There was a problem hiding this comment.
Rename to RouteControllerDidPassSpokenInstructionPoint for consistency. Can you look through the PR for other places that should say “spoken” instead of “voice”?
There was a problem hiding this comment.
Is it possible to nest <prosody> tags in SSML? I could imagine a future in which the Directions API decides to pronounce some portion of an instruction slightly louder than another portion.
f2c31c1 to
08bfe22
Compare
bda2dcd to
109bb42
Compare
There was a problem hiding this comment.
Pull this logic out into an extension on Locale, then get the current locale’s measurement system:
mapbox-navigation-ios/MapboxCoreNavigation/DistanceFormatter.swift
Lines 31 to 37 in e1b588b
46ab7e9 to
7472ed8
Compare
|
In order how this PR is blocked:
Let's start powering through this list. @1ec5 @mcwhittemore can I get your eyes on Project-OSRM/osrm-text-instructions#168 today? |
7472ed8 to
79f20ec
Compare
|
Began working on prefetching audio instructions here. Blocked by a few PRs. voice-instructions...prefetch-audio |
79f20ec to
4394192
Compare
|
This branch is pretty far from compiling. Are you working within a CocoaPods workspace? If so, please try developing directly against the project in this repository. |
dcf1328 to
ebc163f
Compare
|
Scratch that, still some work to do. |
2c84966 to
2de56a9
Compare
|
@1ec5 @frederoni @JThramer okay, this is now ready for review. |
1ec5
left a comment
There was a problem hiding this comment.
Everything looks good to go, although I’m not sure if we’re planning to hold this PR until the Directions API catches up to the latest dependencies. Please test against the production API before merging.
| input.text = "<speak><amazon:effect name=\"drc\"><prosody volume='\(instructionVoiceVolume)' rate='\(instructionVoiceSpeedRate)'>\(text)</prosody></amazon:effect></speak>" | ||
| let wrappedSSML = text | ||
| .replacingOccurrences(of: "^<speak\\s*(?:\\s+[^>]*)?>", with: "$0<amazon:effect name=\"drc\"><prosody volume='\(instructionVoiceVolume)' rate='\(instructionVoiceSpeedRate)'>", options: .regularExpression) | ||
| .replacingOccurrences(of: "</speak>$", with: "</prosody></amazon:effect></speak>",options: .regularExpression) |
There was a problem hiding this comment.
Noting for posterity that we need to remove this code once the Directions API begins to add these tags itself.
There was a problem hiding this comment.
@1ec5 what do you think about making this future proof-able and adding an xml parsing dependency? It might make sense to check and make sure we have all necessary keys.
There was a problem hiding this comment.
No, I think we should introduce an XML parsing library only when we need it for a particular purpose, so that we can evaluate each candidate library based on how well it’d handle our use case. As it stands, we’re planning to have the Directions API add these tags, so the SDK won’t have any XML parsing needs for now.
| */ | ||
| case arrive | ||
| } | ||
| import AVFoundation |
There was a problem hiding this comment.
Do we use AVFoundation in RouteProgress?
|
Removed our custom tag addition code in 7254395. We'll need the new tags deployed to the Directions API before merging this. |
696cf6c to
9521078
Compare
Need mapbox/mapbox-directions-swift#175 merged first
Todo:
Alerts/cc @mapbox/guidance @1ec5 @frederoni @ericrwolfe