I thought I would report the fruits of a weekend of hacking around this.
Some of the things I have learned follow...

Examining streamplayer (the utility that streams from raw TCP and included
in asterisk utils) I found that the way it worked was to keep sucking the
audio stream from the internet... and applying a test to see if asterisk was
ready to read anything from stdout. If not, then it simply threw the data
away and went back to read more from the internet. Thus there is always
network traffic reading the stream

I also learned that asterisk launches the application(s) specified in
musiconhold.conf during startup. They are not started/stoped based on a call
connecting to the music-on-hold. Thus they are always running.

Based on this insight, I tried to apply the same "test to see if anything is
ready to read" to the two programs that my bash script calls... wget and
sox.

Applying the test to wget before writing to stdout improved things somewhat,
but there is still a considerable amount of buffering going on
inside/between sox and asterisk.

Applying the test to sox before writing to stdout improved things a lot...
there is still some buffering going on inside asterisk (about 5 seconds
worth), but there is nothing to do about that. Unfortunately however, sox is
still converting the data from mp3 to ulaw even though it is being thrown
away... so not only am I consuming network bandwith all the time, sox is
also comsuming 15% to 18% of my (ALIX 2C3) cpu.  So I got more adventurous
and applied the test to determine whether sox should read from stdin based
on asterisk being ready to read from stdout. That cured the CPU problem, but
still there is a considerable amount of data in sox's internal buffers that
were not flushed.  So, I tried yet another approach... have sox always
reading from stdin, and apply the test on whether anything is ready to read
from stdout BEFORE sox attempts to do any conversions or apply any effects.
This got CPU consumption down to about 2.5% of CPU in sox, and not
measurable in wget.

So, there we go... some hacking to sox has got the buffering of old
streaming audio down to about 5 seconds, inside of asterisk, at the cost of
2% to 3% of CPU, and a continuous steam over the network.  Ideally I'd like
to find a way to halt the network traffic if nothing is reading from the
stream, but that's for another time.

Footnote...
While I messed around with wget, this is really not the right place for me
to be messing around. The right answer is to "fix" streamplayer to read from
http (and ftp?) sources and not just raw TCP. But that looked like more work
to me (and my current "solution" doesn't require changes to wget).
Additionally, streamplayer should add the function (option) not just to
throw away the data stream if no one is listening to stdout, but to also
stop reading from the network.  Finally, for astlinux, this wouldn't
completely solve the problem because sox is required to convert from mp3 to
ulaw.  It would be nice if astlinux could include the format-mp3 package
from asterisk-addons -- that might improve things further.  In the meantime
I'll live with a hacked sox.

There goes another wasted weekend!

David





On Fri, Sep 26, 2008 at 4:30 PM, David Kerr <[EMAIL PROTECTED]> wrote:

> Humm, good point. Which goes some way to explain why my modification to sox
> only cut the "delay" to a real live stream to about 45 seconds.  There must
> be other buffering going on, possibly between wget and sox, so I have turned
> my attention there for the moment.
>
> David
>
>
> On Fri, Sep 26, 2008 at 1:22 PM, Philip Prindeville <
> [EMAIL PROTECTED]> wrote:
>
>> It's not a .sh extension that decides whether a file needs to be exec'd
>> with an interpreter or not, it's the presence of the "#!" at the top of the
>> file.
>>
>> Also, it's not 8000 bits/sec, it's 8KHz and 8-bit samples, so 64KB is
>> actually an 8-second buffer.
>>
>> -Philip
>>
>>
>> David Kerr wrote:
>>
>>> The stream usually starts pretty much instantly.  I did refine my scripts
>>> a little. I now have a script, stream-mp3 that takes the URL as a parameter.
>>> I also found that I did not need to specify the bit rate of the input, sox
>>> seams to figure that out. So the script now looks like...
>>>
>>> stream-mp3
>>>  #!/bin/bash
>>>  wget -q -O - ${1} | sox -t mp3 - -t ul -r 8000 -c 1 -
>>>
>>> And then in musiconhold.conf:
>>> [streamwnycfm]
>>> mode = custom
>>> format = ulaw
>>> application = /bin/bash /usr/bin/stream-mp3
>>> http://wnycfm.streamguys.com:80/
>>>
>>> For the application line I am not sure whether the /bin/bash is actually
>>> required or not. It is possible that if I gave the script file a .sh tail,
>>> then it would automatically use bash.
>>>
>>> Now, the biggest problem I have is that after a steam starts, if a call
>>> disconnects and then another call comes in later... the stream may no longer
>>> be "live" because sox buffered up a lot of it that asterisk did not read.
>>> See:
>>> http://lists.digium.com/pipermail/asterisk-users/2008-January/204255.html
>>> A hack was suggested that basically kept the stream live all the time,
>>> see
>>> http://lists.digium.com/pipermail/asterisk-users/2008-January/204258.html
>>> and
>>> http://lists.digium.com/pipermail/asterisk-users/2008-January/204263.html
>>>
>>> I didn't like the hack suggested because keeping the stream live all the
>>> time would soak up CPU and network bandwidth. On my ALIX 2C3 the sox MP3 to
>>> ulaw decode consumes about 15% to 18% of the CPU (see the linux "top"
>>> command). But one of these posts made me go look and see how much i/o
>>> buffering is going on in sox....
>>>
>>> I found in ./build_i586/sox-12.17.9/src/stio.c  the following line...
>>> if (setvbuf (ft->fp, NULL, _IOFBF, sizeof(char)*ST_BUFSIZ))
>>> This is setting the outbut buffer for sox to 64 KBytes (ST_BUFSIZ is
>>> defined in  st_i.h as 8192). For a ulaw stream at 8000 bits per second this
>>> works out to approx 65 seconds of buffering, which is petty much what I was
>>> experiencing... connecting to the stream got a minute of non-live stream,
>>> then a second or two of silence, then a live stream started.  So last night
>>> I changed the line in stio.c to...
>>> if (setvbuf (ft->fp, NULL, _IONBF, sizeof(char)*ST_BUFSIZ))
>>> yes, just the change to _IONBF turns off output buffering)
>>> I recompiled (just ran make in the sox-12.19.7 directory) and moved the
>>> resulting sox executable to my astlinux system. This shortened the non-live
>>> portion, but did not eliminate it.  Possibly there is buffering at the
>>> output from wget, but I have not looked into that yet.
>>>
>>> David
>>>
>>>
>>>
>>>
>>> On Thu, Sep 25, 2008 at 9:53 PM, Mark Phillips <[EMAIL PROTECTED] <mailto:
>>> [EMAIL PROTECTED]>> wrote:
>>>
>>>    Hi David,
>>>
>>>    How long does this stream take to arrive when you put a caller on
>>>    hold?
>>>
>>>    In a similar vain I was thinking about Video on Hold. It occurs to me
>>>    that if there was a video file captured into someone's VM account we'd
>>>    be able to migrate it over the the MOH  and thus callers would
>>>    hear the
>>>    audio part and see the video part.
>>>
>>>    This certainly works where a video VM message is left for a non video
>>>    user.
>>>
>>>    Mark
>>>
>>>
>>>    On Mon, 2008-09-22 at 22:29 -0400, David Kerr wrote:
>>>    > I thought report success in my attempt to use live streaming MP3
>>>    as a
>>>    > music on hold source, in case anyone else is interested. Here is
>>>    what
>>>    > I did...
>>>    >
>>>    > First, create a bash script. For example,
>>>    /home/stream-wnyc-fm.sh with
>>>    > the following two lines.
>>>    >
>>>    > #!/bin/bash
>>>    >  wget -q -O - http://wnycfm.streamguys.com:80/ | sox -t mp3 -r
>>>    32000 -
>>>    > -t ul -r 8000 -c 1 -
>>>    >
>>>    > Explanation... use wget to pull the raw MP3 stream from a URL, send
>>>    > result to stdout. Pipe this into sox indicating source is of
>>>    type mp3,
>>>    > sampled at 32kbps from stdin send output of type ulaw sampled at
>>>    8kbps
>>>    > with one channel (mono) to stdout.
>>>    >
>>>    > Now edit your Asterisk musiconhold.conf file and create a new
>>>    context
>>>    > (or change your default) to the following...
>>>    >
>>>    > [streamwnycfm]
>>>    >   mode=custom
>>>    >   format=ulaw
>>>    >   application=/bin/bash /home/stream-wnyc-fm.sh
>>>    >
>>>    > And there you have it.  I have this working on an ALIX 2C3 board
>>>    > running latest 0.6 branch.
>>>    >
>>>    > David
>>>    >
>>>
>>>
>>
>>
>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Astlinux-users mailing list
Astlinux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/astlinux-users

Donations to support AstLinux are graciously accepted via PayPal to [EMAIL 
PROTECTED]

Reply via email to