[Freeswitch-users] FreeSWITCH call recording missing header information
Chad Phillips
chad at apartmentlines.com
Sun Dec 13 23:52:55 UTC 2020
I have a dialplan setup that records a bridged call in FreeSWITCH,
which sets the 'api_hangup_hook' variable to call a lua script when the
call hangs up, and the called lua script moves the recorded .wav file from
it's temporary location to a final destination.
This works, but recently I noticed that some of my .wav recordings have no
header information, which results in many players choking when trying to
play it.
I eventually figured out that the header information for the .wav file
appears to be written *after* the call is hung up, and file move operation
in the api_hangup_hook moves the file before the header information has
been written. This occurs sporadically.
I've found that introducing a 1 second sleep in my lua script fixes this
race condition, but that seems a bit of an ugly hack.
Curious if anybody else has run into this, and/or can offer me a cleaner
solution than my sleep hack.
I'm attaching a brief summary of the dialplan and lua script for anyone
that wants to see the code.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freeswitch.org/pipermail/freeswitch-users/attachments/20201213/dba06bae/attachment-0001.html>
-------------- next part --------------
<!-- Sets up channel variables related to doing a session recording. -->
<extension name="apartmentlines_operator_recording_setup">
<condition field="destination_number" expression="^apartmentlines_operator_recording_setup$">
<action application="set" data="RECORD_TITLE=Recording ${caller_id_number} to customer ${MASTER_ID}"/>
<action application="set" data="RECORD_COPYRIGHT=(c) ${strftime(%Y)} Cardinal One Ventures, LLC"/>
<action application="set" data="RECORD_SOFTWARE=FreeSwitch"/>
<action application="set" data="RECORD_COMMENT=Call center: ${CALL_CENTER} Number: ${DIAL_CALL_CENTER_NUMBER}"/>
<action application="set" data="RECORD_DATE=${strftime(%Y-%m-%d %H:%M)}"/>
<action application="set" data="RECORD_STEREO=false"/>
<action application="set" data="RECORD_ANSWER_REQ=true"/>
<action application="execute_extension" data="apartmentlines_set_operator_recording_filename"/>
<action application="set" data="bridge_pre_execute_bleg_app=record_session"/>
<action application="set" data="bridge_pre_execute_bleg_data=$${AL_RECORDING_TEMP_DIR}/operator_recordings_in_progress/${OPERATOR_RECORDING_FILENAME}"/>
</condition>
</extension>
<!-- Sets a filename for an operator recording. -->
<extension name="apartmentlines_set_operator_recording_filename">
<condition field="destination_number" expression="^apartmentlines_set_operator_recording_filename$">
<action application="set" data="OPERATOR_RECORDING_FILENAME=${MASTER_ID}--${strftime(%Y-%m-%dT%H:%M:%S)}_${caller_id_number}.wav"/>
</condition>
</extension>
<!-- Briges the caller to a call center. -->
<extension name="apartmentlines_call_center_outdial">
<condition field="destination_number" expression="^apartmentlines_call_center_outdial$">
<!-- ...other call setup ... ->
<!-- Set up the recording. -->
<action application="execute_extension" data="apartmentlines_operator_recording_setup"/>
<!-- Set up the hangup hook. -->
<action application="set" data="session_in_hangup_hook=true"/>
<action application="set" data="api_hangup_hook=lua apartmentlines_operator_call.lua hangup ${a_leg_uuid}"/>
<action application="lua" data="apartmentlines_operator_call.lua insert ${a_leg_uuid}"/>
<!-- Bridge the call. -->
<action application="bridge" data="{origination_uuid=${b_leg_uuid}}${DIAL_CALL_CENTER_STRING}"/>
</condition>
</extension>
--[[
Moves a completed operator recording from operator_recordings_in_progress to
operator_recordings. This prevents the cron-based script that processes
these recordings to customer directories from processing recordings in
progress.
]]
function process_finished_operator_recording()
local AL_RECORDING_TEMP_DIR = get_value("AL_RECORDING_TEMP_DIR")
local OPERATOR_RECORDINGS = get_value("OPERATOR_RECORDINGS")
local operator_recording_filename = get_value("OPERATOR_RECORDING_FILENAME")
local in_progress_recording = AL_RECORDING_TEMP_DIR .. "/operator_recordings_in_progress/" .. operator_recording_filename
local recording = OPERATOR_RECORDINGS .. "/" .. operator_recording_filename
if file_exists(in_progress_recording) then
local sleep_secs = 1
debug_print(string.format([[Sleeping %d seconds to allow recording to finish]], sleep_secs))
os.execute(string.format([[sleep %d]], sleep_secs))
local ok = os.execute(string.format([[mv '%s' '%s']], in_progress_recording, recording))
if ok then
debug_print(in_progress_recording .. " -> " .. recording)
--[[
This can be used to dump recordings to a temp directory for inspection.
local tmpdir = '/tmp/'
local ok = os.execute(string.format("cp -a '%s' '%s'", recording, tmpdir))
if ok then
debug_print(recording .. " copied to " .. tmpdir)
end
]]
end
end
end
More information about the FreeSWITCH-users
mailing list