Introduction
Here are six examples of SALT and VoiceXML being used
in voice-only applications. The SALT examples are all from
the SALT 1.0 specifications and similar sources. Two SALT
examples have small bits of visual interface in them, which
we identify with grey italic font.
|
Transitioning to a New Page
Stock Ordering
Entering a PIN
Recording a Greeting
Entering a From City and To City ("Unsafely")
Entering a From City and To City ("Safely")
SALT
Forum Companies Back VoiceXML
<html xmlns:salt="http://www.saltforum.org/2002/SALT" >
<body>
<form id="form1" action="nextpage.html">
<input type="button" onclick="transition();" value="go to next page" />
</form>
<salt:prompt id="transitionPrompt">
Let's go to the next page!
</salt:prompt>
<script>
function transition()
{
transitionPrompt.Queue();
PromptQueue.Start();
form1.submit();
}
</script>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
<form>
<block>
Let's go to the next page!
<goto next="nextpage.vxml"/>
</block>
</form>
</vxml>
Figure 2:
transition.vxml
Stock Ordering
The next example
is a four-field stock ordering form. Even though the
SALT is very nicely written, it is nearly four times the
size of the equivalent VoiceXML, because the SALT author
had to write an FIA while the VoiceXML author gets one for
free. Note that the SALT example has some visual elements
that a pure voice dialog would not need (page title, field
titles). On the other hand, it has an artificially
compact help message generation function that doesn't generate
useful help messages. |
<html xmlns:salt="http://www.saltforum.org/2002/SALT">
<title>Context Sensitive Help</title>
<head>
<script>
<![CDATA[
var focus;
function RunSpeech()
{
if (trade.stock.value == "") {
focus="trade.stock";
p_stock.Start();
return;
}
if (trade.op.value == "") {
focus="trade.op";
p_op.Start();
return;
}
if (trade.quantity.value == "") {
focus="trade.quantity";
p_quantity.Start();
return;
}
if (trade.price.value == "") {
focus="trade.price";
p_price.Start();
return;
}
}
function handle()
{
res = event.srcElement.recoresult;
if (res.value == "help") {
text = "Please just say ";
text += document.all[focus].title;
p_help.Start(text);
} else {
// proceed with value assignments
}
}
]]>
</script>
</head>
<body onload="RunSpeech()">
<salt:prompt id="p_help" oncomplete=" RunSpeech()" />
<salt:prompt id="p_stock" oncomplete="g_stock.Start()">
Please say the stock name
</salt:prompt>
<salt:prompt id="p_op" oncomplete="g_op.Start()">
Do you want to buy or sell
</salt:prompt>
<salt:prompt id="p_quantity" oncomplete="g_quantity.Start()">
How many shares?
</salt:prompt>
<salt:prompt id="p_price" oncomplete="g_price.Start()">
What's the price
</salt:prompt>
<salt:listen id="g_stock" onreco="handle(); RunSpeech()">
<salt:grammar src="./g_stock.grxml" />
</salt:listen >
<salt:listen id="g_op" onreco="handle(); RunSpeech()">
<salt:grammar src="./g_op.grxml" />
</salt:listen >
<salt:listen id="g_quantity" onreco="handle(); RunSpeech()">
<salt:grammar src="./g_quant.grxml" />
</salt:listen >
<salt:listen id="g_price" onreco="handle();RunSpeech()">
<salt:grammar src="./g_quant.grxml" />
</salt:listen >
<form id="trade">
<input name="stock" title="stock name" />
<select name="op" title="buy or sell">
<option value="buy" />
<option value="sell" />
</select>
<input name="quantity" title="number of shares" />
<input name="price" title="price" />
</form>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
<form>
<field name="stock">
<grammar src="./g_stock.grxml"/>
<help> Please just say stock name. </help>
Please say the stock name.
</field>
<field name="op">
<grammar src="./g_op.grxml"/>
<help> Please just say buy or sell. </help>
Do you want to buy or sell?
</field>
<field name="quantity">
<grammar src="./g_quant.grxml"/>
<help> Please just say number of shares. </help>
How many shares?
</field>
<field name="price">
<grammar src="./g_price.grxml"/>
<help> Please just say price. </help>
What's the price?
</field>
</form>
</vxml>
Figure 4: stock.vxml
Entering a PIN
The next example
show how to get a PIN number in both approaches. The
size disparity is less, because the hand-crafted SALT FIA
needed for a single field is simple.
|
<html xmlns:salt="http://www.saltforum.org/02/SALT">
<body onload="sayWelcome.Start()">
<form id="PIN" action="checkPIN.html">
<input id="iptPIN" type="text" />
</form>
<salt:prompt id="sayWelcome" oncomplete="askPIN.Start(); recoPIN.Start()">
Welcome to my speech recognition application.
</salt:prompt>
<salt:prompt id="askPIN">
Please say your password.
</salt:prompt>
<salt:listen id="recoPIN" onreco="PIN.submit()">
<salt:grammar src="PINdigits.grxml" />
<salt:bind targetElement="iptPIN" />
</salt:listen>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">
<form>
<block>
Welcome to my speech recognition application.
</block>
<field name="iptPIN">
<grammar src="PINdigits.grxml"/>
Please say your password.
</field>
<block>
<submit next="checkPIN.vxml"/>
</block>
</form>
</vxml>
Recording a Greeting
Here is an example of recording a
greeting.
<html xmlns:salt="http://www.saltforum.org/2002/SALT">
<!-- on page load, run script -->
<body xmlns:salt="http://www.saltforum.org/2002/SALT" onload="RunAsk()">
<form id="f1" action="http://www.example.com/savewaveform.aspx" method="get">
<input name="vmail" type="hidden" />
</form>
<!-- Prompts -->
<salt:prompt id="p_record" oncomplete="l_recordvm.Start()">
Please speak after the tone. You may press any key to end your recording.
</salt:prompt>
<salt:prompt id="p_save">
Do you want to save this voicemail?
</salt:prompt>
<!-- listens -->
<!-- Recording session - max 60 seconds recording -->
<salt:listen id="l_recordvm" initialtimeout="3000"
endsilence="1500" babbletimeout="60000"
onreco="saveAudio()" onnoreco="saveAudio()" onsilence="RunAsk()" >
<salt:record />
</salt:listen>
<!-- listen for capturing whether user wants to save voice mail -->
<salt:listen id="l_save" onreco="processSave()">
<salt:grammar src="./yesno.grxml" />
</salt:listen>
<salt:dtmf id="d_stop_rec" onreco="saveAudio()">
<grammar src="alldigits.grxml" />
</salt:dtmf>
<!-- HTML script controlling dialog flow -->
<script>
function RunAsk() {
if (voicemail.value=="") {
p_record.Start();
}
}
// Ask user if they are satisfied with their recording
function saveAudio () {
p_save.Start();
l_save.Start();
}
// If user is satisfied post file name back to web server
// otherwise start again
function processSave () {
smlResult = event.srcElement.recoresult;
origNode = smlResult.selectSingleNode("//answer/text()");
if (origNode.value == "Yes") {
vmail.value = l_recordvm.recordlocation;
f1.submit();
} else {
RunAsk();
}
}
</script>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml">
<form>
<record name="greeting" beep="true" maxtime="60s"
finalsilence="1500ms" dtmfterm="true" type="audio/wav">
Please speak after the tone. You may press any key to end your recording.
</record>
<field name="save" type="boolean">
Do you want to save this voice mail?
<filled>
<if cond="save">
<submit next="http://www.example.com/savewaveform.aspx" namelist="greeting" method="post"/>
</if>
<clear/>
</filled>
</field>
</form>
</vxml>
Entering a From City and To City ("Unsafely")
The next two pairs
are most instructive. This pair shows how to gather
a from city and a to city. The SALT specification
later claims that this example is "unsafe" (more
on this below). The VoiceXML example is "safe". |
<html xmlns:salt="http://www.saltforum.org/2002/SALT">
<body onload="RunAsk()">
<form id="travelForm">
<input name="txtBoxOriginCity" type="text" />
<input name="txtBoxDestCity" type="text" />
</form>
<!-- Speech Application Language Tags -->
<salt:prompt id="askOriginCity"> Where would you like to leave from? </salt:prompt>
<salt:prompt id="askDestCity"> Where would you like to go to? </salt:prompt>
<salt:prompt id="sayDidntUnderstand" oncomplete="runAsk()">
Sorry, I didn't understand.
</salt:prompt>
<salt:listen id="recoOriginCity"
onreco="procOriginCity()" onnoreco="sayDidntUnderstand.Start()">
<salt:grammar src="city.xml" />
</salt:listen>
<salt:listen id="recoDestCity"
onreco="procDestCity()" onnoreco="sayDidntUnderstand.Start()">
<salt:grammar src="city.xml" />
</salt:listen>
<!-- scripted dialog flow -->
<script>
function RunAsk()
{
if (travelForm.txtBoxOriginCity.value=="") {
askOriginCity.Start();
recoOriginCity.Start();
} else if (travelForm.txtBoxDestCity.value=="") {
askDestCity.Start();
recoDestCity.Start();
}
}
function procOriginCity()
{
travelForm.txtBoxOriginCity.value = recoOriginCity.text;
RunAsk();
}
function procDestCity()
{
travelForm.txtBoxDestCity.value = recoDestCity.text;
travelForm.submit();
}
</script>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
<form>
<field name="txtBoxOriginCity">
<grammar src="city.xml"/>
Where would you like to leave from?
</field>
<field name="txtBoxDestCity">
<grammar src="city.xml"/>
Where would you like to go to?
</field>
</form>
</vxml>
Entering a From City and To City ("Safely")
This is the same
example "made safe".
According to
http://www.saltforum.org/saltforum/downloads/SALT1.0.pdf
section 2.6.5 (A 'safe' voice-only dialog):
This example shows prompt
and listen elements used with script in a simple voice-only
dialog. Its point is to show that all possible user input
and error events are caught and safely handled, so that
the dialog is never left in a 'hanging' state.
So care needs to be taken to
make the earlier SALT example work properly. The VoiceXML
is inherently "safe": VoiceXML interpreters must
never leave a dialog in a "hanging state". |
<html xmlns:salt="http://www.saltforum.org/2002/SALT">
<head>
<title>origin and destination</title>
</head>
<body>
<form id="travelForm" action="http://mysite.com/travel/inquire.php"
method="post">
<input name="txtBoxOriginCity" type="text" />
<input name="txtBoxDestCity" type="text" />
</form>
<!-- SALT -->
<salt:prompt id="askOriginCity" onerror="procError()">
Where from?
</salt:prompt>
<salt:prompt id="askDestCity" onerror="procError()">
Where to?
</salt:prompt>
<salt:prompt id="notUnderstood" onerror="procError()">
Sorry, I could not understand your input.
</salt:prompt>
<salt:prompt id="operator"
oncomplete="transferToOperator()"
onerror="transferToOperator()">
<!-- external function -->
I am transferring you to an operator.
</salt:prompt>
<salt:listen id="recoOriginCity"
onreco="procOriginCity()"
onnoreco="procNothingUnderstood()"
onsilence="procNothingUnderstood()"
onerror="procError()">
<salt:grammar src="./city.grxml" />
</salt:listen>
<salt:listen id="recoDestCity"
onreco="procDestCity()"
onnoreco="procNothingUnderstood()"
onsilence="procNothingUnderstood()"
onerror="procError()">
<salt:grammar src="./city.grxml" />
</salt:listen>
<!-- scripts -->
<script>
function RunAsk()
{
if (txtboxOriginCity.value=="") {
askOriginCity.Start();
recoOriginCity.Start();
} else if (txtboxDestCity.value=="") {
askDestCity.Start();
recoDestCity.Start();
} else {
<!-- all slots filled -->
travelForm.submit();
}
}
function procOriginCity ()
{
txtBoxOriginCity.value = recoOriginCity.value;
RunAsk();
}
function procDestCity ()
{
txtBoxDestCity.value = recoDestCity.value;
RunAsk();
}
function procNothingUnderstood()
{
notUnderstood.Start();
RunAsk();
}
function procError()
{
operator.Start();
}
function terminate()
{
<!-- caller hung up -->
window.close();
}
</script>
<!-- on page load -->
<script>
<!-- detect disconnect at a central place instead of
placing disconnect detect handlers in the listen objects -->
callControl.attachEvent("call.disconnected ",terminate());
<!-- start dialog execution -->
RunAsk();
</script>
</body>
</html>
<?xml version="1.0"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/voice">
<form>
<nomatch> Sorry, I could not understand your input. </nomatch>
<noinput> Sorry, I could not understand your input. </noinput>
<error>
I am tranferring you to an operator.
<goto next="transfer.vxml"/>
</error>
<field name="txtBoxOriginCity">
<grammar src="city.xml"/>
Where from?
</field>
<field name="txtBoxDestCity">
<grammar src="city.xml"/>
Where to?
</field>
<block>
<submit next="http://mysite.com/travel/inquire.php"
method="post" namelist="txtBoxOriginCity txtBoxDestCity"/>
</block>
</form>
</vxml>
|