顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-通话记录(CDR)接口

通话记录(CDR)

支持把FreeSWITCH的通话记录写入mysql,sqlserver,oracle等数据库,也可以写入redis的list,或者PUBLISH到redis的channel,方便业务程序实时获取通话记录。

使用说明

如果一个通话是A呼叫B,那么就有2个通话记录,一个叫aleg,一个叫bleg。
如果自动外呼或者呼入IVR这样没转接给其他电话或者分机的,就只有一个通话记录。

  • uuid 这个通话的callid,整个系统唯一的。

  • destination_number 一般是拨打的号码(自动外呼的的通话如果接通了,就变成了自动外呼配置的目的地(路由条件)

  • caller_id_number 主叫号码 (来电显示的号码)

  • callee_id_number 被叫号码(DID号),业务系统建议使用dial_number这个cti定义的变量,因为很多sip终端注册的contact地址可能不是实际的分机号,导致这个不是真实的被叫号码。

怎么把一个通话的2个UUID关联起来

主叫的originator为空,被叫的originator 是主叫的UUID。

webrtc(jssip、sip.js、siml5)问题

大部分例子都没设置 正确的contact_uri,会导致 呼叫 webrtc js sip分机 callee_id_number 和 destination_number 变成一个随机字符串,解决这个问题的方法是设置正确的 contact_uri 为 sip:分机号@sip服务器地址,或者使用cti自定义变量,避免使用者2个变量,防止客户端恶意篡改。

计费

可以通过通话时间业务自行计算费用,也可以吧费率设置到通道变量,cti模块就会计算出通话的费用。

费率通道变量

费率格式 单价/计费单位, 比如每分钟计费 1角钱 就是 0.1/60。6秒1分钱 0.01/6。比如ASR一次一分钱 0.01/1

  • tel_cost_rate 电话成本费率
  • tel_sell_rate 电话销售费率
  • asr_bill_type 语音识别计费方式

    • per 按次计费
    • time 按时间计费
  • asr_cost_rate 语音识别成本费率
  • asr_sell_rate 语音识别销售费率
  • traffic_sell_rate sip信令和RTP流量费率 计费单位GB。

    • sip_traffic 每通电话SIP信令需要多少字节的流量
    • RTP流量只统计出口的流量 计算方法为:rtp_audio_out_raw_bytes+rtp_audio_out_packet_count*42
  • da_bill_rate 空号识别费率

    • da_bill_mode
      • 0: 识别到了空关停才计费
      • 1:启动识别了就计费

计费结果变量

可以根据业务情况把需要的通道变量,加入cti.json的cdr.fields 中,同时数据库的CDR表添加对应字段,把计费金额存储到数据库。

  • tel_cost_money 电话成本金额
  • tel_sell_money 电话销售金额
  • asr_cost_money 语音识别成本金额
  • asr_sell_money 语音识别销售金额
  • traffic_sell_money 网络流量计费金额
  • traffic_bill_bytes 网络流量计费字节数
  • da_sell_money 空号识别结果金额

常见计费用法介绍

比如对网关线路(呼出线路) 设置成本费率, 对分机设置销售费率。如果启用了质检,可以对主叫和被叫都设置语音识别费率。

多租户模式 不同租户使用同一个线路设置不同的费率

通道变量 cti_line_name 默认是线路名
通道变量 organization 可以设置为租户信息
假设 cti_line_name 是 trunk, organization是ddt, 那么cdr模块会组合成一个动态线路名 trunk.ddt
然后redis创建一个hash 名字为 cti_line_bill@域名, 添加一个field trunk.ddt value 是json格式的费率信息比如 {"tel_cost_rate":"0.1","tel_sell_rate":"0.2"}
cti_line_bill更新通知格式为{"type":"config_change","table":"cti_line_bill","key":"trunk.ddt"}

来电去电号码归属地区号到CDR

cti.json 配置文件 cdr配置项目里面添加一个配置phoneattribution=true,然后cdr表添加一个areacode字段 varchar(4)。并且确保导入了号码归属地文件到redis。

{
"cdr": {
"phoneattribution": true,
"fields": [
"areacode:cti_areacode"
]
}
}

cdr.phoneattribution配置为true的时候,cti模块会根据cti_dial_number计算区号,并且存储到cti_areacode这个通道变量。呼入的拨号方案要把主叫号码存储到cti_dial_number,呼出的时候要把被叫存储到cti_dial_number。

分机互打

主叫方

  • account 分机号
  • direction inbound (分机呼叫fs,所以是呼入)
  • originator 空
  • bridge_uuid 最后通话的对方的UUID
  • call_source dialplan(拨号方案里面设置的)
  • source_name 主叫分机号(拨号方案里面设置的)
  • dial_number 被叫分机号(拨号方案里面设置的)

    被叫方

  • account 分机号
  • direction outbound (fs呼叫分机,所以是呼出)
  • originator 主叫方uuid
  • bridge_uuid 最后通话的对方的UUID,因为一个通话可能给转移和多个人对话,所以和originator可能不是一个UUID
  • call_source dialplan(拨号方案里面设置的)
  • source_name 主叫分机号(拨号方案里面设置的)
  • dial_number 被叫分机号(拨号方案里面设置的)

    分机呼出

    被叫方

  • account 如果外呼使用的实际线路是网关,就是网关名,如果不是网关对接的是通线路组外呼的,就是线路名。
  • 其他参数和分机互打的被叫方一样。

    自动外呼

    注意:自动外呼的通话记录主叫被叫记录接通和未接通是不一样的。下面描述这些差异。
  • destination_number 未接通的通话是被叫号码,接通的通话是外呼任务配置的路由条件。
  • caller_id_number 未接通的通话是主叫号码,接通的通话是被叫号码(就是自动外呼拨打的号码)
  • callee_id_number 未接通的通话是被叫号码,接通的通话是主叫号码(就是自动外呼设置的主叫号码),如果转接给了分机或者其他手机,这个值就变成了转接的被叫号码。
  • call_source queuedialer
  • source_name 外呼队列名字
  • dial_number 被叫号码
  • cti_line_group_name 外呼使用的线路组

排队呼叫分机

  • call_source acd
  • source_name 排队名字
  • source_number 原始主叫号码
  • dial_number 分机线路名字
  • cti_line_group_name 分机所属线路组

配置说明,在cti.json中添加cdr配置,cdr.json文件路径在cdr.conf.xml中配置,默认时fs的conf目录。

    
"cdr": {
/*details:生产环境的时候设置为flase,details信息很长*/
"details": false,
"enable_msec":false,//时间字段是否带毫秒
/*fields需要记录到cdr表的自定义变量,number:开始的表示使用数字格式。如果变量名和数据库字段名字不一样,可以”字段名:变量名”这样。*/
"fields": [ "rtp_last_audio_codec_string", "number:billsec", "number:duration", "record_filename", "call_source", "source_name", "dial_number:cti_dial_number", "originator", "bridge_uuid" ],
/*如果需要把cdr信息推送到到redis的list或者channels,list配置redis list的名字,channels配置redis cahnnels的名字*/
"redis": {
"channel": "cdr",
"list": ""
},
/*如果需要把cdr记录到数据库,需要配置table, 机器人交互记录,也使用这个配置*/
"database": {
/*dbtype 数据库类型 比如mysql ,sqlserver*/
"dbtype": "mysql",
/*mysql例子:127.0.0.1,3306@dbname sqlserevr例子:tcp:127.0.0.1,1433@dbname*/
"connectionstring": "localhost,3306@cti",
"username": "root",
"password": "123456",
/*cdr表名*/
"table": "cdr",
/*是否启用CDR实时模式,实时模式创建通道的时候插入记录,通话状态变化更新记录,非实时模式通话挂断才记录到CDR*/
"real": false,
"recover":true, //启动时,把最近的异常记录(created_time为最近10分钟,hungup_time为NULL)设置为hungup_time=NOW(), billsec=NOW()-answered_time, duration=NOW()-created_time, hangup_cause='CRASH'
"autocommit": false

},

/*cdr记录写入到数据库推送通知[推送内容为表名和UUID],:disable去了,才使用这个配置*/
"notify:disable": {
"redis": {
"channel": "cdr", //推送到redis的channel
"list": "cdr" //记录到redis的list
},
"http": {
"url": "http://127.0.0.1/notify" //推送到url接口
}
},
/*notify通知是附加的变量*/
"notify_fields": [
"number:billsec",
"tel_sell_money:tel_sell_money"
],
"log":

"log": true //是否输出cdr调试日志
},
  • details 是否记录所有的CDR信息。JSON格式。
  • fields 要记录那些通道变量,number:开始的表示使用数字格式。可以自定义需要记录的通道变量,数据库中也要添加同名字段,如果变量名和数据库字段名字不一样,可以”字段名:变量名”这样,也可以组合2个通道变量记录到一个字段”字段名:${通道变量1}${通道变量2}”。
  • redis 配置CDR记录到redis的信息,如果不需要记录到redis,就不要配置这个。
  • database 数据库配置

    • dbtype 数据库类型 比如mysql ,sqlserver

    • connectionstring 连接串。mysql例子:127..0.0.1,3306@dbname sqlserevr例子:tcp:127.0.0.1,1433@dbname

    • username 用户名

    • password

    • table 表名

    • real 是否启用CDR实时模式,实时模式创建通道的时候插入记录,通话状态变化更新记录,非实时模式通话挂断才记录到CDR

  • notify 写入数据库通知
    • redis 通知到redis的list或者channel
      • {"table":"cdr","uuid":"ac8b888c-c36e-479a-947a-1113fe6de64a","cuase":"storage"}
    • http 通过http get 通知到web服务器
      • http://127.0.0.1/notify?table=cdr&uuid=8c956b55-2b1a-49d8-9971-3e86d5f58397&cause=storage
    • cuase
      • storage:写入数据库成功
      • dump:多次写入数据库失败存储到日志文件。
        • notify_fields 可以在这个配置里面定义更多变量 。

自定义字段记录到CDR

例子记录外呼队列的自定义变量到CDR

  • 外呼队列添加自定义变量

queue_template_demo

queue_myval_demo

  • mysql添加一个 queue_name的字段
  • cdr.json的 “fields”: [ “rtp_last_audio_codec_string”,”number:billsec”, “number:duration”,”record_filename” ,”queue_name”] 添加queue_name这个自定义变量名。
  • 线路也可以同样的方式添加自定义变量到CDR。

sip.js传递参数到CDR

  1. sip.js UA的invite方法的附加参数 extraHeaders参数,接收一个Array(String),我们需要传递到后台的参数需要放到此参数中.
    格式是固定的,必须以X-为前缀,示例:X-MY-ID: id
    sip.js部分代码

    session = ua.invite(number, {
    sessionDescriptionHandlerOptions: {
    constraints: {
    audio: true,
    video: false
    }
    },
    extraHeaders: [ 'X-MY-ID: ID', 'X-MY-VAR: var' ]
    });
  2. 数据库CDR表添加一个varchar的myid字段

  3. cti.json里面cdr的配置”fields”: [ “rtp_last_audio_codec_string”,”number:billsec”, “number:duration”,”record_filename” ,”myid:sip_h_X-MY-ID”]

CTI模块自带的变量,可以根据需求配置到json的 cdr.fields,写入数据库。

  • cti_line_group_name 外呼使用的线路组名
  • cti_line_name 外呼使用的线路名
  • call_source 呼叫来源类型 比如 acd(排队呼叫坐席),queuedialer(队列外呼),scheduledialer(定时呼叫) ,extencallout(分机呼出),exten2exten(分机互打),callin2exten(呼入转分机)
  • source_name 呼叫来源的名字 队列外呼就是队列名字,排队转接的就是排队名字
  • source_number acd呼叫坐席时,被叫坐席端(bleg)记录来源号码
  • cti_dial_number 呼出是被叫号码,呼入是来电号码。(需要拨号方案设置好)
  • record_filename 通话录音地址
  • acd_bridge_line 进入排队后,主叫(aleg)最后接通的坐席线路名
  • acd_bridge_time 进入排队后,主叫(aleg)最后接通的坐席的时间戳
  • cti_asr_call_time 本次通话调用ASR的时间
  • cti_asr_call_count 本次通话调用ASR的次数
  • cti_progress_time 收到sip信令180的时间,如果没180就是183的时间。
  • cti_progress_media_time 收到sip信令183的时间
  • cti_bridged_time 桥接时间
  • cti_transferred_time 转接时间

时间字段记录到毫秒

cdr的配置enable_msec 设置为true,cti_progress_time,cti_progress_media_time,cti_bridged_time,cti_transferred_time,created_time,hungup_time,answered_time 就是带毫秒的(2000-01-01 00:00:00.000)这样的格式。

freeswitch常用变量

  • originator 发起方的UUID
  • bridge_uuid 最后桥接的UUID
  • billsec 接通时间单位秒
  • duration 呼叫总时间单位秒
  • rtp_last_audio_codec_string 声音编码
  • billmsec 接通时间单位毫秒
  • mduration 呼叫总时间单位毫秒

默认字段

  • uuid 通话的UUID
  • channel 通道
  • account 记录规则为如果是分机通话account为分机号,如果是通过网关呼叫account为网关名字,如果是通过线路组呼叫account为线路名字,以上都不是直接获取通道号中的号码。
  • direction 方向 inbound outbound
  • destination_number 拨打的号码(自动外呼接接通后是接通后执行的目的地)
  • caller_id_number 主叫 (自动外呼接通后是自动外呼的被叫号码)
  • callee_id_number 被叫(呼入未转接的呼叫为空,自动外呼接通后为自动外呼的主叫号码)
  • sip_term_status 终止sip代码(主动挂断为空)
  • sip_hangup_disposition 挂断说明 recv_bye:对方发起挂断 send_bye:本地发起挂断 recv_refuse:对方拒接 send_refuse:本地取消呼叫 send_cancel:也是本地取消呼叫,一般是呼叫超时。recv_xxx:收到对方发起的呼叫终止,send_xxx:fs主动终止呼叫。
  • network_addr 对方网络地址
  • created_time 发起呼叫时间
  • answered_time 接通时间(这个时间不为空,就是接通了,判断电话是否接通为这个为准)
  • hungup_time 挂断时间
  • hangup_cause 挂断原因,见下表,含义参考:https://freeswitch.org/confluence/display/FREESWITCH/Hangup+Cause+Code+Table
    常见的几个
    
RECOVERY_ON_TIMER_EXPIRE 呼叫超时,一般网络不通
NO_USER_RESPONSE 一般是SIP480
USER_BUSY 线路忙    
UNALLOCATED_NUMBER  未分配的号码,比如(VOS)路由配置错误    
CALL_REJECTED 呼叫拒绝,路由配置错误或者设备配置错误
USER_NOT_REGISTERED 没有注册    
CRASH FreeSWItCH奔溃,启动时cti模块会恢复话单(需要先配置cti.json的gui.channel.hash),挂机原因会设置为CRASH

全部说明:

NONE
UNALLOCATED_NUMBER
NO_ROUTE_TRANSIT_NET
NO_ROUTE_DESTINATION
CHANNEL_UNACCEPTABLE
CALL_AWARDED_DELIVERED
NORMAL_CLEARING
USER_BUSY
NO_USER_RESPONSE
NO_ANSWER
SUBSCRIBER_ABSENT
CALL_REJECTED
NUMBER_CHANGED
REDIRECTION_TO_NEW_DESTINATION
EXCHANGE_ROUTING_ERROR
DESTINATION_OUT_OF_ORDER
INVALID_NUMBER_FORMAT
FACILITY_REJECTED
RESPONSE_TO_STATUS_ENQUIRY
NORMAL_UNSPECIFIED
NORMAL_CIRCUIT_CONGESTION
NETWORK_OUT_OF_ORDER
NORMAL_TEMPORARY_FAILURE
SWITCH_CONGESTION
ACCESS_INFO_DISCARDED
REQUESTED_CHAN_UNAVAIL
PRE_EMPTED
FACILITY_NOT_SUBSCRIBED
OUTGOING_CALL_BARRED
INCOMING_CALL_BARRED
BEARERCAPABILITY_NOTAUTH
BEARERCAPABILITY_NOTAVAIL
SERVICE_UNAVAILABLE
BEARERCAPABILITY_NOTIMPL
CHAN_NOT_IMPLEMENTED
FACILITY_NOT_IMPLEMENTED
SERVICE_NOT_IMPLEMENTED
INVALID_CALL_REFERENCE
INCOMPATIBLE_DESTINATION
INVALID_MSG_UNSPECIFIED
MANDATORY_IE_MISSING
MESSAGE_TYPE_NONEXIST
WRONG_MESSAGE
IE_NONEXIST
INVALID_IE_CONTENTS
WRONG_CALL_STATE
RECOVERY_ON_TIMER_EXPIRE
MANDATORY_IE_LENGTH_ERROR
PROTOCOL_ERROR
INTERWORKING
SUCCESS
ORIGINATOR_CANCEL
CRASH
SYSTEM_SHUTDOWN
LOSE_RACE
MANAGER_REQUEST
BLIND_TRANSFER
ATTENDED_TRANSFER
ALLOTTED_TIMEOUT
USER_CHALLENGE
MEDIA_TIMEOUT
PICKED_OFF"
USER_NOT_REGISTERED
PROGRESS_TIMEOUT
INVALID_GATEWAY
GATEWAY_DOWN
INVALID_URL
INVALID_PROFILE
NO_PICKUP
SRTP_READ_ERROR
BOWOUT
BUSY_EVERYWHERE
DECLINE
DOES_NOT_EXIST_ANYWHERE
NOT_ACCEPTABLE
UNWANTED

建表SQL例子

CREATE TABLE cdr (
    uuid VARCHAR(50) ,
    channel VARCHAR(100) ,
    account VARCHAR(50) ,
        direction VARCHAR(50) ,
    destination_number VARCHAR(50),
    caller_id_number VARCHAR(50) ,
    callee_id_number VARCHAR(50) ,
    direction VARCHAR(50) ,
    sip_term_status VARCHAR(50) ,
    hangup_cause VARCHAR(100) ,
    sip_hangup_disposition VARCHAR(50) ,
    network_addr VARCHAR(50) ,
    created_time DATETIME ,
    answered_time DATETIME ,
    hungup_time  DATETIME ,
    billsec INT ,
    duration INT ,
    rtp_last_audio_codec_string VARCHAR(50) ,
    record_filename VARCHAR(256) ,
    details TEXT
)

实时通道信息记录到redis

cti.json

"gui": {
/*通道信息推送到redis*/
"channel": {
"hash": "channels",
"channel": "",
"list": ""
}
}

所有通话信息会写入哈希表channels,挂断的通话会自动删除
key:通道UUID
value:通道信息

{
"Event-Name": "CHANNEL_ANSWER",
"Core-UUID": "4ec66b95-7b32-4f64-9c9a-853bde810e5e",
"FreeSWITCH-Hostname": "ai",
"FreeSWITCH-Switchname": "ai",
"FreeSWITCH-IPv4": "192.168.31.57",
"FreeSWITCH-IPv6": "::1",
"Event-Date-Local": "2022-04-07 23:27:14",
"Event-Date-GMT": "Thu, 07 Apr 2022 15:27:14 GMT",
"Event-Date-Timestamp": "1649345234133196",
"Event-Calling-File": "switch_channel.c",
"Event-Calling-Function": "switch_channel_perform_mark_answered",
"Event-Calling-Line-Number": "3884",
"Event-Sequence": "751",
"Channel-State": "CS_EXECUTE",
"Channel-Call-State": "EARLY",
"Channel-State-Number": "4",
"Channel-Name": "sofia/internal/121@192.168.31.57",
"Unique-ID": "276ad4f8-21cc-42cd-b4e1-2718186ea4ba",
"Call-Direction": "inbound",
"Presence-Call-Direction": "inbound",
"Channel-HIT-Dialplan": "true",
"Channel-Call-UUID": "276ad4f8-21cc-42cd-b4e1-2718186ea4ba",
"Answer-State": "answered",
"Channel-Read-Codec-Name": "PCMU",
"Channel-Read-Codec-Rate": "8000",
"Channel-Read-Codec-Bit-Rate": "64000",
"Channel-Write-Codec-Name": "PCMU",
"Channel-Write-Codec-Rate": "8000",
"Channel-Write-Codec-Bit-Rate": "64000",
"Caller-Direction": "inbound",
"Caller-Logical-Direction": "inbound",
"Caller-Username": "121",
"Caller-Dialplan": "XML",
"Caller-Caller-ID-Name": "121",
"Caller-Caller-ID-Number": "121",
"Caller-Orig-Caller-ID-Name": "121",
"Caller-Orig-Caller-ID-Number": "121",
"Caller-Network-Addr": "192.168.31.57",
"Caller-ANI": "121",
"Caller-Destination-Number": "5555",
"Caller-Unique-ID": "276ad4f8-21cc-42cd-b4e1-2718186ea4ba",
"Caller-Source": "mod_sofia",
"Caller-Context": "default",
"Caller-Channel-Name": "sofia/internal/121@192.168.31.57",
"Caller-Profile-Index": "1",
"Caller-Profile-Created-Time": "1649345232522813",
"Caller-Channel-Created-Time": "1649345232522813",
"Caller-Channel-Answered-Time": "1649345234133196",
"Caller-Channel-Progress-Time": "0",
"Caller-Channel-Progress-Media-Time": "1649345232782872",
"Caller-Channel-Hangup-Time": "0",
"Caller-Channel-Transfer-Time": "0",
"Caller-Channel-Resurrect-Time": "0",
"Caller-Channel-Bridged-Time": "0",
"Caller-Channel-Last-Hold": "0",
"Caller-Channel-Hold-Accum": "0",
"Caller-Screen-Bit": "true",
"Caller-Privacy-Hide-Name": "false",
"Caller-Privacy-Hide-Number": "false",
"variable_direction": "inbound",
"variable_uuid": "276ad4f8-21cc-42cd-b4e1-2718186ea4ba",
"variable_session_id": "1",
"variable_sip_from_user": "121",
"variable_sip_from_uri": "121@192.168.31.57",
"variable_sip_from_host": "192.168.31.57",
"variable_video_media_flow": "disabled",
"variable_text_media_flow": "disabled",
"variable_channel_name": "sofia/internal/121@192.168.31.57",
"variable_sip_call_id": "a80ee1bbce7a4ae7a4cac09cc47ad948",
"variable_sip_local_network_addr": "112.49.100.46",
"variable_sip_network_ip": "192.168.31.57",
"variable_sip_network_port": "55458",
"variable_sip_invite_stamp": "1649345232463302",
"variable_acl_token": "121@192.168.31.57",
"variable_sip_received_ip": "192.168.31.57",
"variable_sip_received_port": "55458",
"variable_sip_via_protocol": "udp",
"variable_sip_authorized": "true",
"variable_sip_acl_authed_by": "domains",
"variable_sip_acl_token": "121@192.168.31.57",
"variable_sip-force-contact": "NDLB-connectile-dysfunction-2.0",
"variable_effective_caller_id_name": "121",
"variable_sip-allow-multiple-registrations": "false",
"variable_sip-force-expires": "20",
"variable_force_ping": "false",
"variable_user_name": "121",
"variable_domain_name": "192.168.31.57",
"variable_sip_from_user_stripped": "121",
"variable_sip_from_tag": "5268bb483d5a4d139ed5f7f068510c8b",
"variable_sofia_profile_name": "internal",
"variable_sofia_profile_url": "sip:mod_sofia@192.168.31.57:39468",
"variable_recovery_profile_name": "internal",
"variable_sip_full_via": "SIP/2.0/UDP 192.168.31.57:55458;rport=55458;branch=z9hG4bKPj6e4b4ec52e304b928834efd7174bfe18",
"variable_sip_full_from": "sip:121@192.168.31.57;tag=5268bb483d5a4d139ed5f7f068510c8b",
"variable_sip_full_to": "sip:5555@192.168.31.57",
"variable_sip_allow": "PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS",
"variable_sip_req_user": "5555",
"variable_sip_req_port": "39468",
"variable_sip_req_uri": "5555@192.168.31.57:39468",
"variable_sip_req_host": "192.168.31.57",
"variable_sip_to_user": "5555",
"variable_sip_to_uri": "5555@192.168.31.57",
"variable_sip_to_host": "192.168.31.57",
"variable_sip_contact_params": "ob",
"variable_sip_contact_user": "121",
"variable_sip_contact_port": "55458",
"variable_sip_contact_uri": "121@192.168.31.57:55458",
"variable_sip_contact_host": "192.168.31.57",
"variable_sip_via_host": "192.168.31.57",
"variable_sip_via_port": "55458",
"variable_sip_via_rport": "55458",
"variable_max_forwards": "70",
"variable_switch_r_sdp": "v=0\r\no=- 3858362832 3858362832 IN IP4 192.168.31.57\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4018 RTP/AVP 0 8 120\r\nc=IN IP4 192.168.31.57\r\nb=TIAS:64000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:120 telephone-event/8000\r\na=fmtp:120 0-16\r\na=rtcp:4019 IN IP4 192.168.31.57\r\na=ssrc:1327126755 cname:77bc1a0344685f79\r\n",
"variable_ep_codec_string": "CORE_PCM_MODULE.PCMU@8000h@20i@64000b,CORE_PCM_MODULE.PCMA@8000h@20i@64000b",
"variable_call_uuid": "276ad4f8-21cc-42cd-b4e1-2718186ea4ba",
"variable_rtp_use_codec_string": "PCMU,PCMA",
"variable_remote_video_media_flow": "inactive",
"variable_remote_text_media_flow": "inactive",
"variable_remote_audio_media_flow": "sendrecv",
"variable_audio_media_flow": "sendrecv",
"variable_rtp_remote_audio_rtcp_port": "4019",
"variable_rtp_audio_recv_pt": "0",
"variable_rtp_use_codec_name": "PCMU",
"variable_rtp_use_codec_rate": "8000",
"variable_rtp_use_codec_ptime": "20",
"variable_rtp_use_codec_channels": "1",
"variable_rtp_last_audio_codec_string": "PCMU@8000h@20i@1c",
"variable_read_codec": "PCMU",
"variable_original_read_codec": "PCMU",
"variable_read_rate": "8000",
"variable_original_read_rate": "8000",
"variable_write_codec": "PCMU",
"variable_write_rate": "8000",
"variable_dtmf_type": "rfc2833",
"variable_local_media_ip": "192.168.31.57",
"variable_local_media_port": "25140",
"variable_advertised_media_ip": "192.168.31.57",
"variable_rtp_use_timer_name": "soft",
"variable_rtp_use_pt": "0",
"variable_rtp_use_ssrc": "2465115496",
"variable_rtp_2833_send_payload": "120",
"variable_rtp_2833_recv_payload": "120",
"variable_remote_media_ip": "192.168.31.57",
"variable_remote_media_port": "4018",
"variable_endpoint_disposition": "EARLY MEDIA",
"variable_RECORD_READ_ONLY": "false",
"variable_RECORD_WRITE_ONLY": "false",
"variable_RECORD_BRIDGE_REQ": "false",
"variable_RECORD_STEREO": "false",
"variable_record_filename": "C:/src/utility/freeswitch/x64/Debug/recordings/2022-04-07/121_5555_23-27-13_276ad4f8-21cc-42cd-b4e1-2718186ea4ba.wav",
"variable_export_vars": "record_filename",
"variable_execute_on_answer_record": "record_session C:/src/utility/freeswitch/x64/Debug/recordings/2022-04-07/121_5555_23-27-13_276ad4f8-21cc-42cd-b4e1-2718186ea4ba.wav",
"variable_current_application": "answer",
"variable_rtp_local_sdp_str": "v=0\r\no=ddt 1649320092 1649320094 IN IP4 192.168.31.57\r\ns=ddt\r\nc=IN IP4 192.168.31.57\r\nt=0 0\r\nm=audio 25140 RTP/AVP 0 120\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:120 telephone-event/8000\r\na=fmtp:120 0-15\r\na=ptime:20\r\na=sendrecv\r\na=rtcp:25141 IN IP4 192.168.31.57\r\n",
"variable_sip_nat_detected": "true"
}