| VoiceXML 2.1 Development Guide | Home | Frameset Home |
|
<?xml version='1.0'?>
<vxml version="2.0">
<form id="main">
<record name="CallersMessage" beep="true" maxtime="60s" finalsilence="2500ms" type="audio/wav">
<prompt>
Please record your message after the beep. You may record a message up to sixty seconds long. To end recording,
press any key or simply quit speaking.
</prompt>
</record>
<field name="confirmMessage" type="boolean">
<prompt>
I heard you say <value expr="CallersMessage"/>. To save this message say yes. To discard it say no.
</prompt>
<filled>
<if cond="confirmMessage">
<goto nextitem="askName"/>
<else/>
<goto next="#main"/>
</if>
</filled>
</field>
<field name="askName">
<prompt>
are you Jim, Jackson, or Aaron?
</prompt>
<grammar type="text/gsl"> [ aaron jackson jim ] </grammar>
<filled>
<if cond="askName == 'jim' || askName == 'jackson' || askName == 'aaron'">
<submit expr="'RecordMessage.asp?askName='+askName"
method="post" namelist="CallersMessage" enctype="multipart/form-data"/>
<else/>
<prompt>
sorry charlie, we will not submit your file.
</prompt>
</if>
</filled>
</field>
</form>
</vxml>
<!--#include file="upload.inc"-->
<%
byteCount = Request.TotalBytes
RequestBin = Request.BinaryRead(byteCount)
Dim UploadRequest
Set UploadRequest = CreateObject("Scripting.Dictionary")
BuildUploadRequest RequestBin
picture = UploadRequest.Item("CallersMessage").Item("Value")
Filename = DatePart ( "h" , Now ) & DatePart ( "m" , Now ) & DatePart ( "s" , Now ) & DatePart ( "m" , Now ) & DatePart ( "d" , Now ) & DatePart ( "yyyy" , Now ) & ".wav"
Set FileSystem = CreateObject ("Scripting.FileSystemObject" )
Set WaveFile = FileSystem.CreateTextFile ( Server.MapPath ( filename ) )
WaveFile.Write getString(picture)
WaveFile.Close
Set WaveFile = Nothing
Set FileSystem = Nothing
%><?xml version='1.0'?>
<vxml version="2.0">
<form>
<block>
<prompt>
Thanks, <% =Request.Querystring("askName")%> Your message has been saved.
</prompt>
</block>
</form>
</vxml>
<%
Dim Filename
Dim FileSystem
Dim WaveFile
Dim binRead
Dim byteCount
'Byte string to string conversion
Function getString(StringBin)
getString =""
For intCount = 1 to LenB(StringBin)
getString = getString & chr(AscB(MidB(StringBin,intCount,1)))
Next
End Function
'String to byte string conversion
Function getByteString(StringStr)
For i = 1 to Len(StringStr)
char = Mid(StringStr,i,1)
getByteString = getByteString & chrB(AscB(char))
Next
End Function
Sub BuildUploadRequest(RequestBin)
'Get the boundary
PosBeg = 1
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
boundary = MidB(RequestBin,PosBeg,PosEnd-PosBeg)
boundaryPos = InstrB(1,RequestBin,boundary)
'Get all data inside the boundaries
Do until (boundaryPos=InstrB(RequestBin,boundary & getByteString("--")))
'Members variable of objects are put in a dictionary object
Dim UploadControl
Set UploadControl = CreateObject("Scripting.Dictionary")
'Get an object name
Pos = InstrB(BoundaryPos,RequestBin,_
getByteString("Content-Disposition"))
Pos = InstrB(Pos,RequestBin,getByteString("name="))
PosBeg = Pos+6
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))
Name = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
PosFile=InstrB(BoundaryPos,RequestBin,getByteString("filename="))
PosBound = InstrB(PosEnd,RequestBin,boundary)
'Test if object is of file type
If PosFile<>0 AND (PosFile<PosBound) Then
'Get Filename, content-type and content of file
PosBeg = PosFile + 10
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))
FileName = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
'Add filename to dictionary object
UploadControl.Add "FileName", FileName
Pos = InstrB(PosEnd,RequestBin,getByteString("Content-Type:"))
PosBeg = Pos+14
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
'Add content-type to dictionary object
ContentType = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
UploadControl.Add "ContentType",ContentType
'Get content of object
PosBeg = PosEnd+4
PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
Value = MidB(RequestBin,PosBeg,PosEnd-PosBeg)
Else
'Get content of object
Pos = InstrB(Pos,RequestBin,getByteString(chr(13)))
PosBeg = Pos+4
PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
Value = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
End If
'Add content to dictionary object
UploadControl.Add "Value" , Value
'Add dictionary object to main dictionary
UploadRequest.Add name, UploadControl
'Loop to next object
BoundaryPos=InstrB(BoundaryPos+LenB(boundary),RequestBin,boundary)
Loop
End Sub
%>
<?xml version='1.0'?>
<vxml version="2.0">
<cfheader name="Cache-Control" value= "no-cache">
<cfheader name="Expires" value="#Now()#">
<CFIF IsDefined("form.greeting")>
<CFFILE Action="upload"
filefield="form.greeting"
destination="#getdirectoryfrompath(getcurrenttemplatepath())#"
mode="777"
nameconflict="makeunique">
<form>
<block>
<prompt>
We have saved this audio file to the server.
<audio src="<CFOUTPUT>#serverfile#</CFOUTPUT>" />
Please call back to record again.
</prompt>
</block>
</form>
<CFELSE>
<form>
<record name="greeting" beep="true" maxtime="30s" finalsilence="4000ms" type="audio/wav">
<prompt>
At the tone, please say your greeting.
</prompt>
<noinput>
I didn't hear anything, please try again.
</noinput>
<nomatch>
Your greeting is <value expr="greeting"/>.
</nomatch>
</record>
<field name="confirm" type="boolean">
<prompt>
Your greeting is <value expr="greeting"/>.
To keep it, say yes. To discard it, say no.
</prompt>
<filled>
<if cond="confirm">
<submit next="RecUpload.cfm" method="post" namelist="greeting" enctype="multipart/form-data"/>
</if>
<clear/>
</filled>
</field>
</form>
</CFIF>
</vxml>
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0">
<CFIF IsDefined("form.greeting")>
<CFFILE Action="upload"
filefield="form.greeting"
destination="#getdirectoryfrompath(getcurrenttemplatepath())#"
mode="777"
nameconflict="makeunique">
<CFMAIL TO="me@here.com"
FROM="you@there.com"
SUBJECT="WAV EMAIL TEST">
Attached is your saved wav file.
<CFMAILPARAM
FILE="#file.serverdirectory#\#file.serverfile#">
</CFMAIL>
<form>
<block>
<prompt>
Data recieved.Thanks for recording.
</prompt>
</block>
</form>
<CFELSE>
<form>
<record name="greeting" beep="true" maxtime="10s" finalsilence="4000ms" type="audio/wav">
<prompt>
At the tone, please say your greeting.
</prompt>
<noinput>
I didn't hear anything, please try again.
</noinput>
</record>
<field name="confirm" type="boolean">
<prompt>
Your greeting is <value expr="greeting"/>.
Our shadow var for duration is <value expr="greeting$.duration"/>,
for size is <value expr="greeting$.size"/>
and for term character is <value expr="greeting$.termchar"/>
</prompt>
<prompt>
To keep this message, say yes. To discard it, say no.
</prompt>
<filled>
<if cond="confirm">
<submit next="cfrecord.cfm" method="post" namelist="greeting" enctype="multipart/form-data"/>
</if>
<clear/>
</filled>
</field>
</form>
</CFIF>
</vxml>
<?PHP
header('Cache-Control: no-cache');
error_reporting (0);
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
echo "<vxml version=\"2.0\">";
echo "<form id=\"main\">";
echo "<block>";
if ($HTTP_POST_FILES) {
foreach ($HTTP_POST_FILES as $key => $value) {
foreach ($value as $Filename) {
if (strpos($Filename, "WINNT")) { $ServerSide = $Filename; }
if (strpos($Filename, ".wav")) { $ClientSide = $Filename; }
} // for each statement
$ServerSide = str_replace("\\\\", "/", $ServerSide);
if (!copy($ServerSide, "c:/audio-storage/temp.wav")) {
echo "Could not save filename: " . $ServerSide;
} // if statement
else {
echo "Successfully saved filename: " . $ServerSide;
} // else statement
} // for each statement
} // if statement
echo "</block>";
echo "</form>";
echo "</vxml>";
?>
| ANNOTATIONS: EXISTING POSTS |
riyer
|
|
| To record & store audio data, do I need to upgrade to professional evolution on voxeo? | |
MattHenry
|
|
|
Hello Riyer, I'm going to take a guess on where it is that you are coming from on this inquiry. Can I assume that you are asking about the ability to use a JSP/PHP/etc script hosted on the voxeo servers that will store audio data for you? Note that if you have a host that is JSP/ASP/etc-capable, then you should be able to run the code sample of your choice and store recorded audio without any cost at all. ~Matt |
|
riyer
|
|
| Thanks Matt. My host sits behind a firewall. I will dig around a little more to see how I can set this up -- | |
symphonyx
|
|
| Thanks Matt.
Greetings from Chile. Bye, |
|
symphonyx
|
|
| Here the problem solved using vxml+php.
When submit a record the post to php is : file://localhost/yourtempwavfolder/yourtempfile.wav Is necessary "cut" the "file://localhost/" to get the correct file path. record.vxml <?xml version="1.0"?> <vxml version="2.0"> <form> <record beep="true" name="file" type="audio/x-wav" maxtime="5s" dtmfterm="true"> <prompt> Say something. Press any key to stop recording. </prompt> <noinput> I can't heard you. </noinput> <filled> <prompt> Your message <value expr="file" /> </prompt> <submit next="php/upload.php" method="post" namelist="file" enctype="multipart/form-data" /> </filled> </record> </form> </vxml> upload.php <? header('Cache-Control: no-cache'); include 'util.php'; $MAX_FILE_SIZE = 15000000; $folder = "/tmp/"; $logfile = "log.txt"; // Post variables $fname = $HTTP_POST_FILES['file']['name']; $ftype = $HTTP_POST_FILES['file']['type']; $fsize = $HTTP_POST_FILES['file']['size']; $ftmp = $HTTP_POST_FILES['file']['tmp_name']; //save log $handler=fopen($folder.$logfile,"w"); fwrite($handler,the_file_name($fname)); fclose($handler); if($fize > $MAX_FILE_SIZE){$error = 2;} if(file_exists($folder."m_".$fname)){$error = 3;} if(copy(the_file_name($fname),$ftmp."wav")) {$error = 0;} switch($error){ case'0': $mensaje="File saved Ok."; break; case'1': $mensaje="Incorrect Format."; break; case'2': $mensaje="File so Big."; break; case'3': $mensaje="File already exists."; break; } echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"; echo "<vxml version=\"2.0\">"; echo "<form id=\"main\">"; echo "<block>"; echo $mensaje; echo "</block>"; echo "</form>"; echo "</vxml>"; ?> util.php <?php function the_file_name($file){ $j=0; $l=strlen($file); for ($k=0;$k<=$l;$k++){ if (substr($file,$k,1)=='/'){ $j++; if ($j==3){ return substr($file,$k); } } } return ""; } ?> Greetings from Chile. Luis |
|
fayyazkl
|
|
| Hi,
Can i record audio along with simultaneously playing a song to caller. If this is possible, please provide some directions to do so. Thanks, Fayyaz |
|
mikethompson
|
|
| Hi Fayyaz,
Unfortunately, this is not natively supported within VoiceXML. However, if you *really* want to achieve this functionality, you will want to use CallXML or CCXML. This way, you can create a conference and join in another CallXML leg which simply records. Then dial another seperate CallXML application (and join it into the conference) to do the audio streaming. I know it is a lot of work for something which sounds simple, but this is currently the best way to approach recording audio while streaming audio. If you want to get started with this, here are some helpful links: http://docs.voxeo.com/callxml/2.0/t_14cxml.htm?search=conference#anchor http://docs.voxeo.com/callxml/2.0/joinconference.htm?search=conference#anchor Best, Mike Thompson Voxeo Corporation |
|
danielvinson
|
|
| Hiya
The ASP example seems to work when hosted on the Voxeo server. However I assume the Cold Fusion, JSP and PHP examples require specific servers. Is this correct? Can you tell me the advantage of using CF, JSP or PHP over ASP? The CF 2 example allows the caller to send the recorded message. Is it possible to do this in XML or ASP? Thanks Daniel |
|
VoxeoTony
|
|
| Hi Daniel,
Your questions are covered in the posting at http://docs.voxeo.com/voicexml/2.0/intro_serverside.htm?search=server#anchor However, since ASP is native to the Windows server environment the ASP example would be able to work on the hosted platform. We hope this helps you along. Tony~ |
|
danielvinson
|
|
| Hi Tony
Thanks for the link. Understand a bit better now. But using the ASP code when hosted on the Voxeo server...is this dynamic? Sorry for repeating myself but is it possible to write the ASP code such that it will email the recorded message or is this only available in CF, JSP etc Thanks Daniel |
|
VoxeoTony
|
|
| Hello Daniel,
I'm glad you were able to get some insight to your questions. For your questions on ASP we do know that ASP as a language is very powerful. The example on the site is dynamic in the sense that it is not a static file being sent off to the application. I do know that ASP will be able to email when properly coded. While we do not have examples for this in the tutorial, doing a search for ASP email examples should prove useful. Please let us know if this information helps. Regards, Tony |
|
fayyazkl
|
|
|
Hi Mike and others! Thank you very much for such a prompt response and favor. I just needed some further info. If i use a conference call for achieving simultaneous playback and recording, is it possible that i be charged a single call? Actually, i am working on an application which once go into production will obviously be charged per call through your network. However, we don't want to double that cost by making two calls per customer. Could you suggest a way out or something?? Thanking in anticipation. Fayyaz Khan Lodhi |
|
MattHenry
|
|
|
Fayyaz, This is really dependent on the nature of the application you are running, the amount of traffic that you are willing to commit to, and several other factors. As this is really a question of pricing, I think it might be best to direct such inquiries to sales@voxeo.com. As each customer has their own specific needs, each customer contract is going to be a little bit different in terms of what is billed. Hope this helps, ~Matthew henry |
|
fayyazkl
|
|
| Hi Mike and others,
Further to my question above i.e. i want to play a song to the caller while recording his voice simultaneously, I have learned conferencing with CCXML. But problem i am facing is, Conference is created when we call separate numbers, they are picked up by different people and we join these legs. But here i have a single caller who calls my application, the application picks up, and records his voice. If i want to play him a song while doing this, how would i call him in the middle of his running call? May be i have missed a point or have not explained my needs to you clearly. Please advise. Fayyaz Khan Lodhi |
|
MattHenry
|
|
|
To be clear: You have an app outdial app that, upon pickup by only a single party, will play a .wav file, and record the caller input, is this correct? If this is the case, then I would think that using a code structure with block/audio would serve to address the first part of the equation, and the <voxeo:recordcall> element would allow you to record both sides of the call. Is this what you are looking for? The finer details aren't very clear to me, so please forgive me if this is off-topic. ~Matt |
|
fayyazkl
|
|
|
Dear Matt, You almost understood correctly but missed one part i guess so i will elborate once to be clear. A user calls my in bound application i.e. he has the number attached to my application and he makes a call through normal phone. Upon picking the call, the application starts playing a song to him. During this play back he starts singing as well. And i want to record ONLY HIS SINGING and not the song played by application. Moreover, these two things i need to take place at the same time. From what you suggested, if i play with block/audio and then use voxeo :recordcall, recording will start AFTER the song being played is completed i.e. the playing and recording wont occur in parallel. Whereas my needs are to get both the functionalities done in parallel. Hope i have clarified my query. Hoping for a solution.Thanks Fayyaz |
|
MattHenry
|
|
|
Hello Fayyaz, This might be a bit tricky. There aren't any provisions within the VXML specification for simultaneous recording and input, where we can block out one of the audio streams, (a half-duplex connection). You *might* be able to figure a way to do this via a CCXML wrapper that <joins> two seperate legs, (one full duplex, the other half-duplex), but then we have the problem of how to disambiguate the prerecorded audio, and the callers voice input into the recorded file that you wish to generate. Much as I hate to say it, I'm not seeing a really easy way around this, as this is somewhat outside the boundaries of what VoiceXML is really designed to do. Regards, ~Matthew henry |
|
kubeworks
|
|
| when i try the CF2 example i get an error. I tried changing the cfrecord.cfm to the same name as my file and it gives me server as internal error.
Is there really a seperate CF script to be able to successfully do this test on CF? |
|
jbassett
|
|
| Hello,
The tutorial is for the recording and email of a file and should work by itself. If you feel there is something wrong, feel free to log in to your account and open a support forum ticket and wwe will be glad to assist you. You can also use the "Support" tab in the Debugger window to email us the logs from a failed session. This will give us a much better base of information to troubleshoot with, ultimately shortening the time to resolution. Thanks Jesse Bassett Voxeo Support |
|
georgelai
|
|
| I have tried and tried the php post script, and your php example fails every time, with the message: Could not save filename: file-1188123569661.wav
I even tried to change the { $ClientSide = $Filename; } to { $ServerSide = $Filename; } because the code was recognizing only ".wav" but it still failed to save. What is going on? From putting in the php code: echo "<log expr=\"'".$Filename."'\" />"; I see the following: LOG: file-1188123569661.wav LOG: audio/x-wav LOG: /tmp/phplVRimF LOG: 0 LOG: 27134 Help, please! This is driving me crazy! |
|
MattHenry
|
|
|
George, To be clear, *which* PHP code are you using? Is it the PHP in our tutorial, or the code posted by username "symphonyx" on 5/10/2006 2:41 PM (EDT)? Note that we aren't habit of providing dynamic coding support, but if you can provide us with some indication as to what is failing, and how, perhaps I can lend a hand. ~Matt |
|
rastgoo
|
|
| Hi
I was looking at w3 And here is what I have saw in definition of record tag "Platform support for recognition of speech grammars during recording is optional." Essentially this is exactly what we need to do. according to specification if input phrase match local grammer we should be able to get the interpretation thourgh application.lastapplication.lastresult$ Her is the link to specification http://www.w3.org/TR/voicexml20/#dml2.3.6 Also some platform supports the same functionality through <field> tag and using shadow vaiables. Also consider that <record> tag can have a child tag of <grammar> so look like there has to be some recognition functionality available via record rag. Sincerely |
|
rastgoo
|
|
| I forgot to mentioned that all of my test have failed till now.
here is the sample code which I tried to use <?xml version="1.0"?> <vxml version="2.0" xmlns="http://www.w3.org/2001/vxml"> <form> <script> <![CDATA[ function dumpResults(){ var result = "something"; for ( var i = 0; i < application.lastresult$.length; i++ ){ result += "Utterance is "+application.lastresult$.utterance + "."; result += "Utterance is "+application.lastresult$.interpretation+ "."; } return result; } function dumpResults2(){ var result = application.lastresult$.length; return result; } ]]> </script> <record name = "digit"> <!--record name="digit"--> <grammar src="builtin:grammar/digits"/> <prompt bargein="true"> <audio src="/vxml/audio/FD4945.VOX" fetchhint="prefetch"/> </prompt> <noinput> <audio src="/vxml/audio/FD4943.VOX" fetchhint="prefetch"/> </noinput> <nomatch> <audio src="/vxml/audio/FD4945.VOX" fetchhint="prefetch"/> </nomatch> <filled> <log >++++++++++++++++++++++<value expr = "dumpResults()" /></log> <audio src="/vxml/audio/FD4941.VOX" fetchhint="prefetch"/> </filled> </record> <!--/record--> </form> </vxml> I appriciate any help on this regard. |
|
VoxeoDustin
|
|
| Hey Rastgoo,
You are correct. I have reproduced this behavior and it does not agree with the spec. I have opened an internal Engineering ticket to address this issue and it will be resolved in a future build of Prophecy. Cheers, Dustin |
|
fahdbaig
|
|
| Hi,
I was wondering if its possible to record the speech in say 2 seconds chunks as the caller speaks? In other words, as the speaker is speaking every 2 seconds his/her speech is recorded as a WAV file. I'll have another application that will be taking in these WAV files, as they are recorded, and process them. Can you guide me on how to do this. Thank you very much. Fahd |
|
VoxeoDustin
|
|
| Hey Fahd,
Unfortunately, the VoiceXML spec does not provision for the ability to split the audio files into 2 second pieces. This is something that would need to be handled with post processing on the server side. Let me know if we can be of further assistance. Thanks, Dustin |
| login |
|