UCMA 3.0 - 录制来电

时间:2014-10-31 21:59:47

标签: ucma

我是UCMA的新手,我正在通过实例学习。我正在尝试使用以下方案构建2个Lync客户端A和B,

  1. A致电B
  2. B回答
  3. 播放音频
  4. B使用Recorder记录它。
  5. 我被困在试图记录B的电话。对于B来电。我需要将audiovideoflow附加到录音机,但我不知道如何做到这一点。我将不胜感激任何帮助。 对未格式化的代码抱歉,我不知道如何正确格式化,我试过了。

    感谢。 克里斯

    客户B代码:

    1. 接听来电
    2. 记录来电中收到的媒体。 ***这是我遇到麻烦的部分

      使用System; 使用System.Threading; 使用Microsoft.Rtc.Collaboration; 使用Microsoft.Rtc.Collaboration.AudioVideo; 使用Microsoft.Rtc.Signaling; 使用Microsoft.Rtc.Collaboration.Lync;

      命名空间Microsoft.Rtc.Collaboration.LyncUAS {     公共类LyncUAS     {         #region当地人         private LyncUASConfigurationHelper _helper;         private UserEndpoint _userEndpoint;         private AudioVideoCall _audioVideoCall;         private AudioVideoFlow _audioVideoFlow;         私人谈话_incomingConversation;

          //Wait handles are only present to keep things synchronous and easy to read.
          private AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
          private EventHandler<AudioVideoFlowConfigurationRequestedEventArgs> _audioVideoFlowConfigurationRequestedEventHandler;
          private EventHandler<MediaFlowStateChangedEventArgs> _audioVideoFlowStateChangedEventHandler;
          private AutoResetEvent _waitForAudioVideoCallEstablishCompleted = new AutoResetEvent(false);
          private AutoResetEvent _waitForAudioVideoFlowStateChangedToActiveCompleted = new AutoResetEvent(false);
          private AutoResetEvent _waitForPrepareSourceCompleted = new AutoResetEvent(false);
      
          #endregion
      
          #region Methods
          /// <summary>
          /// Instantiate and run the DeclineIncomingCall quickstart.
          /// </summary>
          /// <param name="args">unused</param>
          public static void Main(string[] args)
          {
              LyncUAS lyncUAS = new LyncUAS();
              lyncUAS.Run();
          }
      
          private void Run()
          {
             string filename = "received.wma";
      
              _helper = new LyncUASConfigurationHelper();
      
              // Create a user endpoint, using the network credential object 
              // defined above.
              _userEndpoint = _helper.CreateEstablishedUserEndpoint("Lync UAS" /*endpointFriendlyName*/);
              _userEndpoint.RegisterForIncomingCall<AudioVideoCall>(On_AudioVideoCall_Received);
              Console.WriteLine("Waiting for incoming call...");
              _autoResetEvent.WaitOne();
              Console.WriteLine("came after call is connected");
              //start recording for audio.
      
              Recorder recorder = new Recorder();            
      
              recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);
              recorder.VoiceActivityChanged += new EventHandler<VoiceActivityChangedEventArgs>(recorder_VoiceActivityChanged);         
      

      // **********这是问题,目前_audioVideoFlow为null,它没有附加到流   //所以这会失败,如何将_audioVideoFlow附加到来电?帮助!!!

             // recorder.AttachFlow(_audioVideoFlow);  ------------> HELP!
      
      
              WmaFileSink sink = new WmaFileSink(filename);
              recorder.SetSink(sink);
              recorder.Start();
              Console.WriteLine("Started Recording ...");
              _autoResetEvent.WaitOne();
              recorder.Stop();
              Console.WriteLine("Stopped Recording ...");
              recorder.DetachFlow();
              Console.WriteLine("Exiting");
              Thread.Sleep(2000); 
          }
      
      
          private void audioVideoFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
          {
              Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State);
      
              //When flow is active, media operations can begin
              if (e.State == MediaFlowState.Active)
              {
                  // Flow-related media operations normally begin here.
                  _waitForAudioVideoFlowStateChangedToActiveCompleted.Set();
              }
      
              // call sample event handler
              if (_audioVideoFlowStateChangedEventHandler != null)
              {
                  _audioVideoFlowStateChangedEventHandler(sender, e);
              }
          }
      
      
          void recorder_VoiceActivityChanged(object sender, VoiceActivityChangedEventArgs e)
          {
              Console.WriteLine("Recorder detected " + (e.IsVoice ? "voice" : "silence") + " at " + e.TimeStamp);
          }
      
          void recorder_StateChanged(object sender, RecorderStateChangedEventArgs e)
          {
              Console.WriteLine("Recorder state changed from " + e.PreviousState + " to " + e.State);
          }
      
          void On_AudioVideoCall_Received(object sender, CallReceivedEventArgs<AudioVideoCall> e)
          {
              //Type checking was done by the platform; no risk of this being any 
              // type other than the type expected.
              _audioVideoCall = e.Call;
      
              // Call: StateChanged: Only hooked up for logging, to show the call 
              // state transitions.
              _audioVideoCall.StateChanged += new
                  EventHandler<CallStateChangedEventArgs>(_audioVideoCall_StateChanged);
              _incomingConversation = new Conversation(_userEndpoint);
      
              Console.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri + " Toast is: " +e.ToastMessage.Message);
              _audioVideoCall.BeginAccept(
                   ar =>
                   {
                       try { 
                           _audioVideoCall.EndAccept(ar);
                           Console.WriteLine("Call must be connected at this point. "+_audioVideoCall.State);
      
                           _autoResetEvent.Set();
                            } catch (RealTimeException ex) { Console.WriteLine(ex); }
                   }, null);
      
          }
      
          //Just to record the state transitions in the console.
          void _audioVideoCall_StateChanged(object sender, CallStateChangedEventArgs e)
          {
              Console.WriteLine("Call has changed state. The previous call state was: " + e.PreviousState +
                  " and the current state is: " + e.State);
              if (e.State == CallState.Terminated)
              {               
                  Console.WriteLine("Shutting down");
                  _autoResetEvent.Set();
                  _helper.ShutdownPlatform();
              }
          }
          #endregion
      }
      

      }

1 个答案:

答案 0 :(得分:0)

我想我已经弄清楚这里不太正确了。

您的代码

    // Create a user endpoint, using the network credential object 
    // defined above.
    _userEndpoint = _helper.CreateEstablishedUserEndpoint("Lync UAS" /*endpointFriendlyName*/);
    _userEndpoint.RegisterForIncomingCall<AudioVideoCall>(On_AudioVideoCall_Received);
    Console.WriteLine("Waiting for incoming call...");
    _autoResetEvent.WaitOne();
    Console.WriteLine("came after call is connected");
    //start recording for audio.

    Recorder recorder = new Recorder();            

    recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);
    recorder.VoiceActivityChanged += new EventHandler<VoiceActivityChangedEventArgs>(recorder_VoiceActivityChanged);         

     //**********This is the issue, currently _audioVideoFlow is null, it is not attached to the flow //So this will fail, how to attach _audioVideoFlow to an incoming call ?? HELP !!!
     // recorder.AttachFlow(_audioVideoFlow);  ------------> HELP!

到目前为止看起来不错。我假设您正在使用CreateEstablishedUserEndpoint方法建立等等,但我没有看到您获取_audioVideoFlow值的位置。

我猜你可能会在其他地方这样做,但实际上你遇到问题的可能性很大,这就是:

获取AVFlow的最简单模式

    public static void RegisterForIncomingCall(LocalEndpoint localEndpoint)
    {
        localEndpoint.RegisterForIncomingCall
                          <AudioVideoCall>(IncomingCallDelegate);
    }

    private static void IncomingCallDelegate(object sender, CallReceivedEventArgs<AudioVideoCall> e)
    {
        e.Call.AudioVideoFlowConfigurationRequested += IncomingCallOnAudioVideoFlowConfigurationRequested;
    }

    private static void IncomingCallOnAudioVideoFlowConfigurationRequested(object sender, AudioVideoFlowConfigurationRequestedEventArgs e)
    {
        AudioVideoFlow audioVideoFlow = e.Flow; // <--- There's your flow, gentleman.
    }

现在,请拨打RegisterForIncomingCall(_userEndpoint);,而不是注册来电。

您的AVFlow将在e.Flow上方挂起,然后您可以将其传递到录音机中:recorder.AttachFlow(e.Flow)或者只是将流程分配到班级中的字段autoResetEvent.WaitOne();并将其设置在哪里你现在正在设置它。

显然这是一个非常天真的实现。在那几行代码中可能会出现很多问题(异常处理/静态事件处理程序内存泄漏会立即出现);不要忘记连接与会话/呼叫和终端上的状态更改相关的事件,以及任何与恢复相关的项目。