Re: Запись разговора при трансфере

От: Dmitry Akindinov <CGatePro_at_mx_ru>
Дата: Tue 19 Jun 2007 - 09:36:25 MSD

Здравствуйте,

Чтобы две стороны могли разговаривать, а третья - подслушивать, необходима трехсторонняя конференция. То есть, будет как минимум три задачи: принявшая звонок, осуществляющая звонок на указанный номер, осуществляющая звонок на номер записывающего устройства.

Еще коментарии ниже.

Никитин Андрей wrote:
> День добрый!

> 
> Подскажите, как реализовать запись разговора при трансфере.
> 
> Код.
> 

[]

> 
> В таком виде, CGP начинает запись до соединения, если вставить строчку 
> tmp=recordTalk(60, "?????????????");
> после peerLeg = callerLeg(parameters,false); , то соединение разрывается.

У задачи только один медиа канал. Либо его используют для передачи медиа удаленному клиенту, либо используют для записи. Разбить медиа поток на два нельзя. Но можно построить миксер - с тремя задачами.

В аттачменте - пример програмки, которую можно использовать для экспериментов. Первый параметр - куда звоним, второй - кого подключаем дополнительно. Если вторыми параметрами указаны слова file или mail, а первый параметр роутится в локальный аккаунт, то програмка просто записывает медиа и, в зависимости от второго параметра, либо пишет в файл персонального сайта аккаунта, либо отправляет по почте этому аккаунту.

Пример: при звонке на 101 нас соединят с 102 и 103 одновременно (на 103 может быть айБим в режиме атоматического приема звонков и автоматической же записи):

S: <101> = ed{102,103}#pbx

Пример: при звонке на 101 нас соединят 102, а запись разговора сохранится в персональном сайте аккаунта 103 (то есть, будут запущены две копии програмки ed):

S: <recorder> = ed{103,file}#pbx
S: <101> = ed{102,recorder}#pbx

Не судите строго - програмка используется исключительно для тестирования CGPro, но может быть использована для иллюстрации применения миксера.

> С уважением Никитин Андрей

-- 
Best regards,
Dmitry Akindinov -- Stalker Labs.

ed.sppr:
========================================================================

function caller(uri) forward;
function submitVoiceMail(recordedMessage,fromAddress,toAddress) forward;

entry Main is
   phoneNumber = Vars().startParameter;
   if IsArray(phoneNumber) then
     recorderNum = phoneNumber[1];
     if recorderNum != "mail" and then recorderNum != "file" then
       recorderNum = "sip:" + recorderNum + "@" + MyDomain() + 
";services=no";
       phoneNumber = "sip:" + phoneNumber[0] + "@" + MyDomain() + 
";services=no";
     else
       phoneNumber = phoneNumber[0];
     end if;
   else
     RejectCall("555-Bad params");
   end if;

   syslog("Recording to " + recorderNum);
   if recorderNum == "mail" or else recorderNum == "file" then
     if AcceptCall() == null then
       data = Record(300);
       if recorderNum == "mail" then
 
void(submitVoiceMail(data,"mailer-daemon@"+MyDomain(),phoneNumber));
       else
         if FindSubstring(phoneNumber, "@") < 0 then phoneNumber = 
phoneNumber + "@" + MyDomain(); end if;
         phoneNumber = RouteLocalURI(EmailToSIPURI(phoneNumber));
         if phoneNumber == null then phoneNumber = MyEmail(); end if;
         sysLog("Filing to " + objectToString(phoneNumber));
         if phoneNumber != null then
           void(WriteSiteFile("~" + phoneNumber + "/recording.wav", data));
         end if;
       end if;
     end if;
     stop;
   end if;

   callee = caller(phoneNumber);
   if not IsTask(callee) then
     syslog("Callee failed: " + callee);
     RejectCall("486-"+callee);
     stop;
   end if;

   errCode = null;
   while errCode == null and then not IsConnected() loop
     syslog("--- half connected");
     input = ReadInput(180);
     if input.sender == callee and then input.what == "provision" then
       errCode = ProvisionCall(null, null);
     elif input.sender == callee and then input.what == "connected" then
       errCode = AcceptCall();
     elif input.sender == callee and then (input.what == "error" or else 
input.what == "stop") then
       RejectCall("487-" + ObjectToString(input.parameter));
       stop;
     end if;
   exitif not IsDictionary(input) or else errCode != null or else 
isDisconnectEvent(input);
   end loop;

   if errCode == null and then IsConnected() then
     errCode = SendEvent(callee, "connected", null);
     if errCode == null then
       input = ReadInput(10);
       if IsStartBridgeEvent(input) then
         errCode = AttachMixer(input);
       else
         errCode = "unexpected event: " + ObjectToString(input);
       end if;
     end if;
   else
     errCode = "not connected";
   end if;

   if errCode != null then
     void(SendEvent(callee, "stop", ObjectToString(errCode)));
     syslog("--- Something failed: " + ObjectToString(errCode));
     stop;
   end if;

   recorder = caller(recorderNum);
   if not IsTask(recorder) then
     syslog("Recorder failed: " + callee);
     PlayFile("Failure");
   end if;


   while IsConnected() loop
     input = ReadInput(180);
     syslog("--- Event: " + ObjectToString(input));
     if IsStartBridgeEvent(input) and then input.sender == recorder then
       errCode = AttachMixer(input);
       if errCode != null then
         syslog("--- Failed to attach the recorder");
         PlayFile("Failure");
       end if;
     elif IsDictionary(input) then
       if input.what == "stop" and then input.sender == callee then
         Disconnect();
       elif input.what == "connected" and then input.sender == recorder then
         void(SendEvent(recorder,"connected", null));
       end if;
     end if;
   end loop;


end entry;

entry callerTask forward;

function caller(uri) is
   theTask = spawn callerTask;
   if theTask == null then return "failed to spawn"; end if;
   params = NewDictionary();
   params.("") = uri;
   params.From = RemoteURI();
   params.impersonate= "*";
   params.referMode  = "peer";
   params.("Call-ID")= PendingRequestData("Call-ID")+".ed";
   errCode = SendEvent(theTask, "start", ObjectToString(params));
   if errCode != null then return errCode; end if;
   return theTask;
end function;

entry callerTask is
   startEvent = ReadInput(10);
   if not IsDictionary(startEvent) or else startEvent.what != "start" then
     syslog("=== Caller got unexpected event: " + 
ObjectToString(startEvent));
     stop;
   end if;

   params = TextToObject(startEvent.parameter);
   if not IsDictionary(params) then
     syslog("=== Caller got unexpected param: " + ObjectToString(params));
     stop;
   end if;

   if params.impersonate != null then 
void(Impersonate(params.impersonate)); end if;
   if params.referMode   != null then SetReferMode(params.referMode); 
end if;
   SetForeignCredentials(params.authUsername,params.authPassword);
   SetBridgeBreakMode("disconnect");

   errCode  = StartCall(params);
   if errCode != null then
     syslog("=== StartCall failed with: " + ObjectToString(errCode));
     void(SendEvent(startEvent.sender,"error",ObjectToString(errCode)));
     stop;
   end if;

   loop
     syslog("=== half connected");
     input = ReadInput(10);
     if IsCallProvisionEvent(input) then
       void(SendEvent(startEvent.sender,"provision",null));
     elif IsDictionary(input) and then input.what == "stop" then
       syslog("=== stopping on the parent's request");
       stop;
     elif IsCallCompletedEvent(input) then
       errCode = input.parameter;
       syslog("=== call completed: " + ObjectToString(errCode));
       if errCode != null then
         errCode = ObjectToString(errCode);
         syslog("=== Call failed with: " + errCode);
         void(SendEvent(startEvent.sender,"error", errCode));
         stop;
       end if;
     end if;
   exitif IsCallCompletedEvent(input);
   end loop;

   if IsConnected() then
     syslog("=== connected");
     void(SendEvent(startEvent.sender,"connected",ObjectToString(errCode)));
     while IsConnected() loop
       input = ReadInput(1800);
       if IsDictionary(input) and then input.what == "connected" then
         errCode = StartBridge(startEvent.sender);
       end if;
     end loop;
   end if;

   void(SendEvent(startEvent.sender, "stop", "terminating"));

   syslog("=== quitting");
end entry;

function submitVoiceMail(recordedMessage,fromAddress,toAddress) is

   when = LocalTime();
   voiceContent = NewDictionary();
   voiceContent.("Content-Type")        = "audio";
   voiceContent.("Content-Subtype")     = "32KADPCM";
   voiceContent.("Content-Disposition") = "inline";
   voiceContent.("filename")            = "recording-" +
          String(Year(when)) + "-" + Month(when)           + "-" + 
SubString("0"+String(MonthDay(when)       ),-1,2) + "_" +
          SubString("0"+String(TimeOfDay(when)/3600),-1,2) + "-" + 
SubString("0"+String(TimeOfDay(when)/60%60),-1,2) + ".wav";
   voiceContent.body                    = recordedMessage;

   multiparts    = newArray();
   multiparts[0] = voiceContent;

   content = NewDictionary();
   content.("Content-Subtype")          = "voice-message";
   content.body                         = multiparts;

   headers = newDictionary();
   headers.("Content-Class")            = "audio";
   headers.("Message-Context")          = "voice-message";
   headers.protocol                     = "SIP";
   headers.sourceType                   = "PBX";
   headers.emptyReturnPath              = "YES";
   headers.("X-Priority")               = "1";

   return SendEmail(fromAddress,"Recorded Call",toAddress,headers,content);
end function;
Получено Tue Jun 19 05:35:52 2007

Этот архив был сгенерирован hypermail 2.1.8 : Tue 19 Jun 2007 - 10:13:40 MSD