Share via


Recorder

A Recorder is an entity that is capable of receiving audio media that comes from an AudioVideoFlow instance and recording it to a file. Depending on the state of the attached AudioVideoFlow instance, a Recorder can automatically start or stop.

Unlike the Player class, which has two modes of operation, the Recorder class can be thought of as having only one mode of operation, which is similar to Automatic mode in the Player class. If an application calls the Start method on a Recorder instance, nothing will be recorded until an active AudioVideoFlow instance is attached to it. In addition, if there is no active AudioVideoFlow instance attached to a Recorder instance, or if the AudioVideoFlow instance is detached or terminated, the Recorder instance stops automatically.

If a Recorder instance has begun recording a file, an application can cause recording to stop by calling the Stop method, and state changes in the attached AudioVideoFlow instance can also cause the Recorder instance to stop. For example, if the State property on the AudioVideoFlow instance changes from Active to Terminated, the Recorder instance stops. Non-state configuration changes in the AudioVideoFlow instance, such as Hold, Retrieve, Mute, and changing the media channel direction, do not stop the Recorder instance. For example, if a call being recorded remains on hold for five minutes, the Recorder instance records five minutes of silence.

A Recorder will not record to a file with the hidden attribute.

Warning

Files recorded by a Recorder device do not support Digital Rights Management (DRM). This means that conversations recorded by a Recorder device can be played by any player that supports the Windows Media Audio (WMA) media format, potentially exposing personal or confidential information.

Support in UCMA 3.0 for More Complex Scenarios

A number of improvements and additions to the Recorder and associated classes have been made in Microsoft Unified Communications Managed API (UCMA) 3.0.

Recorder Class Changes

The following table summarizes the changes in the Recorder class.

New member

Description

Pause() method

Pauses the Recorder instance.

An application can now use the Pause method to pause recording during a recording session. An application can use the Start() method to resume recording from where the file was paused. Note that Start starts recording from the beginning of the file if the Stop method previously was called.

A new enumeration value, Paused, has been added to the RecorderState enumerated type.

VoiceActivityChanged event

Raised to notify an application that the Recorder detected a change in voice state (noise or voice).

An application can use the VoiceActivityChanged event to detect whether the content is voice. An application can use these events to trim any unwanted silence in the recorded files by keeping track of the timeline of the events.

Changes in Associated Classes

The following additions and enhancements have been made in classes used by the Recorder class. These changes are summarized in the following list.

  • A new enumeration value, Paused, has been added to the RecorderState enumerated type.

  • The VoiceActivityChangedEventArgs class has been added. A handler for the VoiceActivityChanged event can use this class to determine the current voice state by evaluating the IsVoice property, and can determine when the voice state changed by evaluating the TimeStamp property.

  • A new encoding file format is supported, that provides more options to the application for Recorder file output. In addition to the already supported format of Windows Media Audio (WMA) at 16Kps, the following formats are also supported.

    • WMA48

      WMA at 48 Kbps

    • PCM8K

      PCM at 8 KHz, 16 bits per sample

    • PCM16K

      PCM at 16 KHz, 16 bits per sample

  • A new enumerated type, WmaEncodingFormat, has been added. The enumeration values represent the encoding formats described in the previous list. The values in this enumeration are Wma16Kbps, Wma48Kbps, Pcm8Khz, and Pcm16Khz.

  • A new EncodingFormat property has been added to the WmaFileSink class. This property returns a value in the WmaEncodingFormat enumeration.

Example – Using a Recorder

The following code example shows the steps involved in using a Recorder.

Warning

This code example is not a complete example. Several methods, properties, and events are used in this example, but are not defined within the example.

The essential points of creating and using a Recorder instance appear in the following steps. Each step is associated with a line of code that is preceded by a comment with a number in it.

  1. Create a Recorder instance, using the constructor for this class.

  2. Attach the flow to the recorder, using the AttachFlow method on the Recorder class.

  3. Create the object that receives the recording, using the WmaFileSink constructor. The parameter to this constructor is a string that contains the name of the WMA file that will be created. As previously mentioned, the file should not be a hidden file.

  4. Register for the StateChanged event.

  5. Call the recorder’s SetSink method, which informs the recorder of where the recorded data should go.

  6. Start the recorder, using the Start method on the Recorder instance.

  7. Pause the recorder, using the Pause method on the Recorder instance.

  8. Stop the recorder, using the Stop method on the Recorder instance.

  9. Detach the flow from the Recorder instance, using the DetachFlow method.

public void Run()
{

  // Initialize and start up the platform.
  ClientPlatformSettings clientPlatformSettings = new ClientPlatformSettings(_applicationName, Microsoft.Rtc.Signaling.SipTransportType.Tls);
  collabPlatform = new CollaborationPlatform(clientPlatformSettings);
  collabPlatform.BeginStartUp(EndPlatformStartup, _collabPlatform);

  // The EndPlatformStartup callback method, not shown in this sample, would call EndStartup to
  // complete the platform startup operation.

  // Initialize and register the endpoint, using the credentials of the user the application will be acting as.
  UserEndpointSettings userEndpointSettings = new UserEndpointSettings(_userURI, _userServer);
  userEndpointSettings.Credential = _credential;
  userEndpoint = new UserEndpoint(_collabPlatform, userEndpointSettings);
  userEndpoint.BeginEstablish(EndEndpointEstablish, _userEndpoint);

  // The EndEndpointEstablish callback method, not shown in this sample, would call EndEstablish to
  // complete endpoint establishment.


  // Set up the conversation and place the call.
  ConversationSettings convSettings = new ConversationSettings();
  convSettings.Priority = _conversationPriority;
  convSettings.Subject = _conversationSubject;
  // Conversation represents a collection of modalities in the context of a dialog with one or multiple callees.
  Conversation conversation = new Conversation(_userEndpoint, _calledParty, convSettings);

  _audioVideoCall = new AudioVideoCall(conversation);

  // Call: StateChanged: Only hooked up for logging.
  _audioVideoCall.StateChanged += new EventHandler<CallStateChangedEventArgs>(audioVideoCall_StateChanged);

  // Subscribe to the AudioVideoFlowConfigurationRequested event; the flow will be used to send the media.
  // Ultimately, as a part of the callback, the media will be sent/received.
  _audioVideoCall.AudioVideoFlowConfigurationRequested += new EventHandler<AudioVideoFlowConfigurationRequestedEventArgs>(audioVideoCall_FlowConfigurationRequested);



  // Place the call to the remote party.
  // Note that the EndCallEstablish callback method is not shown in this sample.
  IAsyncResult asyncResult = _audioVideoCall.BeginEstablish(EndCallEstablish, _audioVideoCall);

  // Sync; wait for the call to complete.
  _audioVideoCall.EndEstablilsh(asyncResult);

  // Sync; wait for the AudioVideoFlow to go Active.
  autoResetAVFlowActiveEvent.WaitOne();

  // Set up a recorder to record the audio from the remote side.
  // 1) Create a recorder.
  Recorder recorder = new Recorder();
  // 2) Attach the flow to the recorder.
  recorder.AttachFlow(_audioVideoFlow);

  // 3) Register for StateChanged event.
  recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);

  // 4) Create a WmaFileSink in which to record. 
  WmaFileSink sink = new WmaFileSink("recording.wma");
  // 5) Inform the recorder about the recording destination.
  recorder.SetSink(sink);

  // 6) Start the recorder.
  recorder.Start();

  Thread.Sleep(9000);

  // 7) Pause the recorder.
  recorder.Pause();

  // 8) Stop the recorder.
  recorder.Stop();

  // 9) Detach the flow from the recorder.
  recorder.DetachFlow();

  collabPlatform.BeginShutdown(EndPlatformShutdown, _collabPlatform);

  // Wait for shutdown to occur.
  autoResetShutdownEvent.WaitOne();
}