CCXML 1.0-W3C Development Guide Home  |  Frameset Home

  A: All Things Audio  |  TOC  |  B: Debugging Techniques  

CCXML Call Recording


One of the more sought-after features in CCXML is call recording.  Well, we're pleased to announce that it is now available, and documented.  This tutorial will jump right into recording a fairly straight-forward call, consisting of a pair of dialogs, and eventually a two-party bridged call.  Unfortunately, the ability to record a conference in CCXML is not yet available, however it will be available in a future version of Prophecy.

Please note that call recording in a Production capacity is subject to a per-minute surcharge.  Please contact sales@voxeo.com or your dedicated account manager for additional details.


Recording a pair of dialogs


So, lets get to it.  First we'll set up our CCXML with a text-to-speech dialog, followed by a standard "hello world" VoiceXML dialog.


<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">

<meta name="author" content="Jeff Menkel"/>
<meta name="copyright" content="2008 Voxeo Corporation"/>
<meta name="maintainer" content="YOUR_EMAIL@HERE.COM"/>

  <!-- variable declarations -->
  <var name="state0" expr="'init'"/>
  <var name="connid"/>

  <eventprocessor statevariable="state0">
      <transition event="connection.alerting">
          <accept/>
      </transition>

      <transition event="connection.connected">
        <!-- launching first dialog -->
          <assign name="state0" expr="'tts'"/>
          <assign name="connid" expr="event$.connectionid"/>
          <dialogstart src="'null://?text=Hello and welcome to Voxeo C C X M L one oh re cord call test.&amp;voice=English-Female4'" type="'application/x-texttospeech'"/>
      </transition>

      <transition event="connection.disconnected">
        <log expr="'*** call disconnected, exiting now ***'"/>
        <exit/>
      </transition>

      <transition event="dialog.exit" state="tts">
        <!-- launching second dialog -->
          <assign name="state0" expr="'vxml'"/>
          <dialogstart src="'http://127.0.0.1:9990/helloworld.xml'" connectionid="connid"/>
      </transition>

      <transition event="dialog.exit" state="vxml">
        <!-- dialog exited normally -->
          <log expr="'**** PASS ****'"/>
          <exit/>
      </transition>

      <transition event="dialog.exit">
        <!-- dialog exited abnormally -->
          <log expr="'**** FAIL ****'"/>
      </transition>

      <transition event="error.*">
        <!-- standard error handler -->
          <log expr="'Houston, we have a problem: (' + event$.reason + ')'"/>
          <exit/>
      </transition>
  </eventprocessor>
</ccxml>


Now, let's take a look at what we will be adding into our CCXML application, before we actually do so.  Implementing call recording is as simple as doing a simple assignation.


Inside a connection event:

<assign name="filename" expr="event$.connection._RecordCall(100,'TestRecording')"/>


Outside a connection event:

<assign name="filename" expr="session.connections[connid]._RecordCall(100,'TestRecording')"/>


Here's a basic overview of the arguments involved:

z = _RecordCall(x,y,z)


Implementation

Next, the implementation phase begins, and we add the call recording functionality to our application.


<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">

<meta name="author" content="Jeff Menkel"/>
<meta name="copyright" content="2008 Voxeo Corporation"/>
<meta name="maintainer" content="YOUR_EMAIL@HERE.COM"/>

  <var name="state0" expr="'init'"/>
  <var name="connid"/>
  <var name="filename"/>

  <eventprocessor statevariable="state0">
      <transition event="connection.alerting">
          <accept/>
      </transition>

      <transition event="connection.connected">
        <!-- launching first dialog -->
          <assign name="state0" expr="'tts'"/>
          <assign name="connid" expr="event$.connectionid"/>
          <assign name="filename" expr="event$.connection._RecordCall(100,'TestRecording')"/>
          <log expr="'Recording to filename '+filename"/>

          <dialogstart src="'null://?text=Hello and welcome to Voxeo C C X M L one oh re cord call test.&amp;voice=English-Female4'" type="'application/x-texttospeech'"/>
      </transition>

      <transition event="connection.disconnected">
        <log expr="'*** call disconnected, exiting now ***'"/>
        <exit/>
      </transition>

      <transition event="dialog.exit" state="tts">
        <!-- launching second dialog -->
          <assign name="state0" expr="'vxml'"/>
          <dialogstart src="'http://127.0.0.1:9990/helloworld.xml'" connectionid="connid"/>
      </transition>

      <transition event="dialog.exit" state="vxml">
        <!-- dialog exited normally -->
          <log expr="'**** PASS ****'"/>
          <exit/>
      </transition>

      <transition event="dialog.exit">
        <!-- dialog exited abnormally -->
          <log expr="'**** FAIL ****'"/>
      </transition>

      <transition event="error.*">
          <log expr="'Houston, we have a problem: (' + event$.reason + ')'"/>
          <exit/>
      </transition>
  </eventprocessor>
</ccxml>


In a nutshell, this records a TTS string launched via CCXML <dialogstart>, then transitions to the dialog.exit event, which in turn launches a second dialog, which is also recorded, and is a basic 'hello world' VoiceXML application that looks like this:


<?xml version="1.0" encoding="UTF-8"?>
<vxml version = "2.1">
  <form>
    <block>
    <prompt>
      Hello World. This is my first telephone application.
    </prompt>
    </block>
  </form>
</vxml>


Recording a two-party join

Ok, so now we know how to utilize call recording in our CCXML application.  But, what if we want to record an actual conversation between two parties?  No problemo!


<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">

<meta name="author" content="Jeff Menkel"/>
<meta name="copyright" content="2008 Voxeo Corporation"/>
<meta name="maintainer" content="YOUR_EMAIL@HERE.COM"/>

<var name="initState" expr="'state_1'"/>
<var name="call1"/>
<var name="call2"/>
<var name="filename"/>

<eventprocessor statevariable="initState">

  <transition event="connection.alerting" state="state_1">
    <assign name="call1" expr="event$.connectionid"/>
    <accept connectionid="call1"/>
  </transition>

  <transition event="connection.connected" state="state_1">
    <log expr="'***** CALL WAS ANSWERED *****'"/>
      <assign name="filename" expr="event$.connection._RecordCall(100,'TestRecording')"/>
          <log expr="'Recording to filename '+filename"/>
      <assign name="initState" expr="'calling2'"/>
      <send name="'CallOut'" target="session.id"/>

  </transition>

  <transition event="CallOut">
      <createcall dest="'tel:+14075551212'" connectionid="call2"/>
  </transition>


  <transition event="connection.connected" state="calling2">
        <join id1="call1" id2="call2"/>
  </transition>

  <transition event="connection.disconnect">
    <log expr="'****** DISCONNECTED ******'"/>
      <exit/>
  </transition>

  <transition event="error.*">
    <log expr="'Error: ' + event$.reason"/>
    <exit/>
  </transition>
</eventprocessor>
</ccxml>


There you have it, folks.  You can now utilize recording in CCXML without having to launch a VoiceXML recorder dialog.  You will, of course, still need to do so if you are wanting to record a conference.  As this functionality is not yet readily available, one must still join in a VoiceXML recording call leg into the conference.

Tired of reading and want to start coding yourself?  Download the source code, here!


  ANNOTATIONS: EXISTING POSTS
jbuehring
10/20/2009 9:40 AM (EDT)
One thing this example clearly fails to describe, for those perhaps not 100% familiar with every aspect of CCXML, is the quickest/dirtiest method of posting our newly attained, fully mysterious call recording data to an exterior source for processing/handling/saving.
voxeoJason
10/20/2009 10:19 AM (EDT)
Hi,

Unfortunately what happens is that CCXML makes the recording and then after the application has hung up and the session has ended it pushes the recording to your recording directory.  With this in mind, if you wanted to pass it off to a database, you would need a server side script that waits until it sees that recording in the appropriate directory then pushes it off to a database or another holding system for future use.


Regards,

Jason
Voxeo Support
muks
6/9/2010 3:39 AM (EDT)
In my application I am playing DTMF tones in the ccxml using the following tag:
<dialogstart src="'dtmf://12345?pause=200&amp;duration=100'"
          type="'application/x-senddtmf'"  connectionid="connid" />

My requirement is to record this and save it in a file.
With connection._RecordCall not being available in Prophecy 9, what are the options available.

Note: I have raised the same question in the support forum #1157721

Thanks
Muks
voxeoJeffK
6/9/2010 6:36 AM (EDT)
Hello,

I've posted an answer for you in your other thread, but concerning CCXML call recording I think what you may be referring to here:

  *** NOTE: This functionality will only work on the Prophecy 8 platform ***

is an artifact of when Prophecy 7 was being deprecated. CCXML call recording is available in present versions of Prophecy.

Regards,
Jeff Kustermann
Voxeo Support
moshe
12/9/2010 10:07 AM (EST)
The Javascript version of the code re-uses the z variable; I think what you're trying to say is:

f=session.connections[connid]._RecordCall(100,'TestRecording')

will create a file in your account's webhosting recording directory with a name that starts with 'TestRecording' includes the session ID number, and a suffix of some nature.

moshe
12/9/2010 1:11 PM (EST)
Recording type of "audio/ulaw" produces zero-length files in Prophey 8.
kazokanishi
12/9/2010 4:39 PM (EST)
Hi moshe,

I have tested in our staging:
Prophecy 8.0 - CCXML W3C 1.0
Prophecy 8.0 - CCXML W3C,1.0 Nuance

using the sample from the CCXML call recording tutorial and was not able to reproduce the
issue. The recordings were successful by specifying:

_RecordCall(100,'filename','audio/ulaw')


regards,

Kaz O
Voxeo Support
lbojan
10/13/2011 3:38 PM (EDT)
Hi,

Is there a way to start the recording of a two-party join AFTER the outbound call was connected?

Also, after a successful join, does the "connection.disconnect" event pertain to the first connection, or the second one?

Thanks,
LB
VoxeoDante
10/13/2011 4:30 PM (EDT)
Hello,

I do believe that you will be able to use the filename method outside of a connection event, so you can assign in any transition that you have available.

<assign name="filename" expr="event$.connection._RecordCall(100,'TestRecording')"/>

Regarding the connecion.disconnected event, it can pertain to either.  You will want to check the value of the connectionID for the event to figure out which leg disconnected.

event$.connectionid

I hope this helps.

Regards,
Danté Vitulano
Hosted Solutions Engineer

[url=http://www.voxeo.com/university/home.jsp/]
[img=http://www.voxeo.com/images/logos/VoxeoUnivLogo.png/]
[/url]
[b][color=blue]Interested in Training? Visit the Voxeo University Page to Learn More![/color][/b]

login
  A: All Things Audio  |  TOC  |  B: Debugging Techniques  

© 2012 Voxeo Corporation  |  Voxeo IVR  |  VoiceXML & CCXML IVR Developer Site