2012년 5월 3일 목요일

Resolving Audio Problems


Reference : http://www.freepbx.org/support/documentation/howtos/howto-resolving-audio-problems

One of the most common issues to plague new users is the lack of audio. Calls appear to complete, and show up in the call detail, etc. but nothing is heard by one or both of the parties on the conversation. This section of the wiki will be devoted to such problems and their solutions, and I encourage others to add to it as you encounter problems and then discover the solution, particularly if it's not posted here already.

NAT issues

Perhaps the most common problem encountered is one-way audio and 99% of the time this is caused by a NAT firewall. So here are the steps you must take to configure FreePBX to work behind a NAT firewall.

Make sure you have a resolvable address on the Internet.

If you don't want to pay a few bucks to get a static IP address, and are served by an ISP that periodically changes your IP address, then get a free account with DynDNS or some similar service. Your router may already have built-in support for one or more of these services, if so, use one that your router supports and then configure your router to automatically update your dynamic address when your ISP changes your IP address. Failing that, you can set up an updater program such as inadyn, there are instructions for doing that at this blog page.

Make use that your system knows its own name.

Once you get a DynDNS or other address that identifies your system on the Internet, put it in your etc/hosts file. For example, if you are assigned foo.dyndns.net, then open etc/hosts in your favorite text editor (nano, or Midnight Commander's editor will do - use mc -a from the command prompt to access Midnight Commander) and look for this line:
127.0.0.1 localhost
DO NOT REMOVE OR CHANGE THAT LINE. On a NEW line directly underneath it, place this line:
127.0.0.1 foo.dyndns.net
But substitute YOUR address, of course.

Add some information to your /etc/asterisk/sip_nat.conf file

If this file doesn't exist you'll have to create it, but make sure that the ownership and permissions match those of sip.conf and other files in that directory. You can use the command
touch /etc/asterisk/sip_nat.conf
To create the file. I personally use Midnight Commander's "Advanced CHOWN" feature to check and change permissions; if you are a true Linux geek you probably already have a preferred method.
Now edit the file and insert AT LEAST these two lines:
externip=your.external.dotted.IPaddess
localnet=192.168.0.0/255.255.255.0
The above localnet line assumes that your local network uses 192.168.0.x addresses, but if it uses something else, make the appropriate substitution.
Personally I use four lines, as follows:
nat=yes
externip=your.external.dotted.IPaddess
fromdomain=foo.dyndns.com
localnet=192.168.0.0/255.255.255.0
The "fromdomain" line would contain your public address, while "externip" contains the numeric IP address your ISP has assigned you (which hopefully doesn't change often).
If your ISP does change IP addresses on you frequently, and for some reason you can't/won't change ISP's or get a static IP address, and you are running at least Asterisk 1.2.x then there is an alternative way to specify your address to the system (however, note that some users find that this simply does not work as expected):
externhost=foo.dyndns.net
externrefresh=10
These are used IN PLACE OF the "externip" (and "fromdomain", if you have included that) lines. DO NOT use both "externhost" and "externip." Supposedly, "externhost" will cause Asterisk to perform DNS queries periodically, but they say it is "Not recommended for production environments!" and suggest using "externip" instead. "externrefresh" tells the system how often to refresh "externhost". If this method does not work for you, see the Addendum at the bottom of this document for another approach.

Reload SIP

After you have added whichever lines you need in sip_nat.conf, go to the Command Line Interface and type
sip reload
And hit enter. Alternately you could restart Asterisk, but that will interrupt any calls that are in progress.

Open the SIP and RTP ports to your Asterisk server

You must make sure that you open the correct UDP ports in your router's firewall and pointed at your Asterisk server. For SIP protocol, open UDP (NOT TCP) port 5060 (SIP) AND ports 10001-20000 (RTP, which must also be defined in /etc/asterisk/rtp.conf, see below). All these ports are UDP, opening the TCP ports will NOT help anything and may expose your system needlessly. While you are in your firewall configuration, you may as well also open UDP port 4569 (IAX), since sooner or later you'll probably want to accept IAX connections.

Check your /etc/asterisk/rtp.conf file

It should contain these two lines:
rtpstart=10001
rtpend=20000
If the port values are any different, change them. N.B. These MUST match what you opened in your firewall, and DO NOT start with port 10000, because it conflicts with usage in Webmin (and despite what anyone may tell you, Webmin does use UDP port 10000 in addition to TCP port 10000 - it uses the UDP port in an attempt to discover and communicate with other Webmin servers running on your network. So don't believe anyone who tells you that Webmin only uses TCP port 10000 and therefore there is no conflict).
Some people feel the need to open fewer than 10,000 ports. I don't recommend this because six months from now when you start having audio problems you may not remember that you opened fewer than the recommended number of ports, and may spend hours troubleshooting the issue. But if you are simply obsessive about open ports, remember that each open SIP connection may require as many as FOUR concurrent ports, so don't cut it down to some ridiculously small number. For the non-paranoid, I suggest sticking with the recommendations above (and remember, if a hacker is looking at ports on your system, he's going to scan ALL of them, so having fewer UDP ports open really doesn't make you any more secure).

CODEC issues

Whenever a call is placed, both ends of the call must agree on the codecs they want to use. If one end speaks only ulaw and the other end refuses to communicate using anything other than gsm, no communication is going to take place. This is why I would recommend that beginners always allow ulaw (also known as g.711u) and alaw (also known as g.711a) unless specifically instructed not to but whomever you are connecting to. There are actually five different places that codecs can be specified:
  • At an endpoint/device (phone or ATA), typically in the device's configuration.
  • In a FreePBX EXTENSION configuration, however it's best to leave those settings blank in most cases.
  • In a FreePBX TRUNK configuration, using allow= statements coupled with disallow=all. If these are omitted, then the defaults in sip.conf and iax.conf are used.
  • In sip.conf, using allow= statements coupled with disallow=all. These are the system defaults for SIP calls but can be overridden by trunk or extension settings.
  • In iax.conf, using allow= statements coupled with disallow=all. These are the system defaults for IAX calls but can be overridden by trunk or extension settings.
Note that as of Asterisk 1.4, the order of allow and disallow statements is important. If you use a disallow=all statement, it must be placed before any allow statements, because if it is placed after any allow statements it will negate them. This was not the case in Asterisk 1.2 and earlier versions.
Asterisk will attempt to translate formats if the codecs are available on the system and allowed for that leg of the call. So if you have a trunk that only allows gsm but your extensions will only communicate in ulaw, that's not a problem as long as you have allowed gsm in the trunk configuration. To see the available codecs and translations, type core show translation (or just show translation in Asterisk 1.2 and earlier) from the Command Line Interface - if there is a number showing between two codecs in the grid then translations are possible, if a single line (and it's not to the same codec) then translations are not possible, usually because one of the codecs isn't installed on the system.

Missing files/incorrect paths

If calling into an IVR or voicemail box, and the expected recording isn't played, it's possible that it's missing or not in the expected location. Did you use the System Recordings module to import the recording? If not, are you sure it's in the correct location?

Permissions/ownership issues

This most commonly occurs when people copy audio files directly onto the system and forget that it's a Linux box and that Linux is finicky about file permissions and ownership. If permissions or ownership aren't correct, Asterisk will be unable to access the file, and therefore can't play it. One thing you can try to resolve this is to run the following from the Linux command prompt:
amportal chown
This is supposed to set appropriate permissions on files used by Asterisk

Incorrect audio format

Sometimes people create system audio files using an external sound file editor, such as Audacity, in order to get better sound quality. What they don't realize is that Asterisk is very picky about the format of audio files it will play back. For example, if the file is .wav file format, Asterisk wants a file recorded at 8000 Hz, 16 bit, monaural (a.k.a. single channel) format and if you directly upload a file in any other format, the CLI may show that the file is being played, but callers hear nothing. If normal system files play correctly but the files you've created do not, check the format, especially if you've directly copied it to a particular location on the system instead of importing it with the System Recordings module.

Hardware issues

Yes, even a hardware problem can cause audio failures. In one case, a T1 card had been installed in the system but not configured, and that stopped all recorded audio from being played. So if all else fails, look for any unconfigured or misconfigured hardware device, particularly if it's a zaptel card (it appears that having ANY non-configured zaptel card in a system may cause problems with audio output).

Addendum: A Perl script to rewrite sip_nat.conf when your IP address changes

The following is a Perl script that checks your IP address using whatismyip.com, and rewrites /etc/asterisk/sip_nat.conf if the external IP address has changed. Note that you may have to install additional Perl modules, and you WILL need to modify one line in the script:
#!/usr/bin/perl

#
# This program gets the current IP address (as assigned by the ISP) from
# whatismyip.org and modifies /etc/asterisk/sip_nat.conf if the external IP
# address has changed. You can Use Webmin to install any missing Perl
# modules, and to invoke the script as cron job that runs every 5 minutes
#
use strict;
use warnings;
use WWW::Mechanize;
use Tie::IxHash;
use Data::Validate::IP qw(is_public_ipv4);
my $s_filepath = "/etc/asterisk/sip_nat.conf";
my $mech = WWW::Mechanize->new( autocheck => 1 );
$mech->get('http://whatismyip.com/automation/n09230945.asp');
$mech->success or die 'Cannot connect to http://whatismyip.com/automation/n09230945.asp';
my ($ip) = ($mech->content() =~ /(\d+\.\d+\.\d+\.\d+)/);
if (is_public_ipv4($ip)) {
 tie my %configvars, 'Tie::IxHash';
# The 'fromdomain' (& possibly 'localnet') values in the next line MUST be changed
 %configvars = ('nat' => 'yes', 'externip' => '0.0.0.0','fromdomain' => 'foo.dyndns.com','localnet' => '192.168.0.0/255.255.255.0') ;
 open IN,"<$s_filepath";
 while (my $i = <IN>) {
  chop $i;
  if ($i =~ /=/) {
   $i =~ s/\s//g;
   my ($key,$value) = split /=/,$i;
   $configvars{$key} = $value;
  }
 }
 close IN;
 if ($configvars{'externip'} ne $ip) {
  $configvars{'externip'} = $ip;
  open OUT,">$s_filepath";
  while (my ($key, $value) = each %configvars) {
   select OUT;
   print "$key=$value\n";
  };
  select STDOUT;
  close OUT;
  `/usr/sbin/asterisk -rx reload`;
 };
};
Please be sure to change foo.dyndns.com to YOUR dynamic IP address, and 192.168.0.0/255.255.255.0 to a value consistent with your local network address range (if you are not using addresses in the 192.168.0.x range).
It is suggested that you place the above script in your /var/lib/asterisk/agi-bin/ directory, make sure the permissions and ownership are set correctly (make the script executable!), backup your existing /etc/asterisk/sip_nat.conf file, and then as a test invoke the script from a command prompt, e.g. (assuming you name the script checkip.pl):
cd /var/lib/asterisk/agi-bin
perl checkip.pl
If the script exits without printing any error messages, check /etc/asterisk/sip_nat.conf to make sure that the all of the lines in it contain correct values. If all looks as it should, you can can then set up a cron job to run the script every five minutes. I did this using Webmin's System|Scheduled Cron Jobs page, but you may prefer to do it from the command line. If you get any errors about missing Perl modules when you run the script, these will have to be installed (there are Webmin modules that can do this also - look for one called "Perl Modules" or "CPAN").
One other note - if this script is running and sip_nat.conf gets deleted for any reason, the script will probably recreate it but with the wrong ownership and permissions - so if you ever accidentally delete that file, and after that Asterisk acts like it isn't there, check the permissions and ownership to make sure it is the same as for the other sip_*.conf files in /etc/asterisk.

댓글 없음:

댓글 쓰기