<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14641] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14641">14641</a></dd>
<dt>Author</dt> <dd>hunmonk</dd>
<dt>Date</dt> <dd>2009-08-26 10:49:57 -0500 (Wed, 26 Aug 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>lua script for trimming files.  leverages sox and can be used via the dialplan or called from another lua script.  see documentation at the top of the file for usage details.</pre>

<h3>Added Paths</h3>
<ul>
<li>freeswitch/trunk/contrib/hunmonk/lua/</li>
<li><a href="#freeswitchtrunkcontribhunmonkluarecord_trimlua">freeswitch/trunk/contrib/hunmonk/lua/record_trim.lua</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribhunmonkluarecord_trimlua"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/hunmonk/lua/record_trim.lua (0 => 14641)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/hunmonk/lua/record_trim.lua                                (rev 0)
+++ freeswitch/trunk/contrib/hunmonk/lua/record_trim.lua        2009-08-26 15:49:57 UTC (rev 14641)
</span><span class="lines">@@ -0,0 +1,101 @@
</span><ins>+--[[
+  This script provides a simple mechanism to trim recordings made in
+  FreeSWITCH.
+  
+  To use in the dialplan:
+  Set the following channel variables:
+  record_trim_file: Full path to the file you want trimmed.
+  record_trim_pre:  Amount (in seconds) you want trimmed from the beginning
+                    of the file.
+  record_trim_post: Amount (in seconds) you want trimmed from the end of
+                    the file.
+  Then call this script.
+  
+  To use in another lua script:
+  Make sure that the channel variable record_trim_file is not set.
+  Include this script in your script.
+  Call trim_file(file_to_trim, pre_trim_seconds, post_trim_seconds).
+  
+  Things to note:
+  1. The trim values do not have to be integers.  You can do .5 seconds, for
+     example.
+  2. Currently the script only works with .wav files.
+
+]]
+
+function print_error(file_to_trim, error_message)
+  freeswitch.consoleLog(&quot;error&quot;, string.format([[Error trimming file %s: %s]] .. &quot;\n&quot;, file_to_trim, error_message))
+end
+
+function trim_file(file_to_trim, pre_trim_seconds, post_trim_seconds)
+  -- Make sure the file is valid.
+  local f = io.open(file_to_trim)
+  if f then
+    io.close(f)
+    -- Test for the existence of sox.  Since sox seems to output it's help to
+    -- stderr, and return 1 or 256 as the return code when it's installed,
+    -- that's what we'll check for.  Weird, but functional.
+    local result = os.execute(&quot;sox -h 2&gt; /dev/null&quot;)
+    if result == 1 or result == 256 then
+      -- Get the length of the file in seconds from sox.  sox outputs the
+      -- stat data to stderr, so bind stderr to stdout.
+      local sox_info = assert(io.popen(&quot;sox &quot; .. file_to_trim .. &quot; -e stat 2&gt;&amp;1 | grep Length | awk '{print $3;}'&quot;, 'r'))
+      local file_length = sox_info:read(&quot;*n&quot;)
+      
+      local trim_length
+      if file_length then
+        -- sox's trim command wants beginning position and length.
+        -- Length is total length of the file minus both trim lengths.
+        trim_length = file_length - pre_trim_seconds - post_trim_seconds
+        if trim_length &gt; 0 then
+          -- Make a trimmed version of the file, then move it in
+          -- place over the old version.
+          result = os.execute(string.format([[sox %s %s.new.wav trim %f %f]], file_to_trim, file_to_trim, pre_trim_seconds, trim_length))
+          if result == 0 then
+            result = os.execute(string.format([[mv -f %s.new.wav %s]], file_to_trim, file_to_trim))
+            if result == 0 then
+              freeswitch.consoleLog(&quot;info&quot;, string.format([[Trimmed file %s at %f seconds, length %f seconds]] .. &quot;\n&quot;, file_to_trim, pre_trim_seconds, trim_length))
+            else
+              print_error(file_to_trim, &quot;unable to write trimmed file.&quot;)
+            end
+          else
+            print_error(file_to_trim, &quot;unable to run sox trim command.&quot;)
+          end
+        else
+          print_error(file_to_trim, &quot;negative trim length.&quot;)
+        end
+      else
+        print_error(file_to_trim, &quot;unable to find file length.&quot;)
+      end
+    else
+      print_error(file_to_trim, &quot;sox not installed.&quot;)
+    end
+  else
+    print_error(file_to_trim, &quot;unable to open file.&quot;)
+  end
+end
+
+function check_for_file_to_trim()
+  local file_to_trim = session:getVariable(&quot;record_trim_file&quot;)
+
+  if file_to_trim then
+    local pre_trim_seconds = session:getVariable(&quot;record_trim_pre&quot;)
+    local post_trim_seconds = session:getVariable(&quot;record_trim_post&quot;)
+    if not pre_trim_seconds then
+      pre_trim_seconds = 0
+    else
+      pre_trim_seconds = tonumber(pre_trim_seconds)
+    end
+    if not post_trim_seconds then
+      post_trim_seconds = 0
+    else
+      post_trim_seconds = tonumber(post_trim_seconds)
+    end
+    freeswitch.consoleLog(&quot;info&quot;, string.format([[Found file to trim: %s, %f seconds from beginning, %f seconds from end]] .. &quot;\n&quot;, file_to_trim, pre_trim_seconds, post_trim_seconds))
+    trim_file(file_to_trim, pre_trim_seconds, post_trim_seconds)
+  end
+end
+
+if session and session:ready() then
+  check_for_file_to_trim()
+end
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>