DOKK Library

Streaming

Authors Jason Self

License GPL-3.0-or-later

Plaintext
jxself.org


Streaming                                                                                             Home

Tue, 13 Sep 2016                                                                                      Linux-libre
I recently found myself wanting to stream some video to a friend of mine in another country. This
was a new experience for me so I wanted to document what I did in case it's helpful for other         GitWeb
people.
                                                                                                      How To
I knew I wanted to use Icecast, the streaming media server. I was doing this on Trisquel 7, which
had version 2.3.3. I later learned that this version didn't support WebM so a new version was         Articles
needed:

sudo apt-get install checkinstall                                                                     RSS Feed
wget http://downloads.xiph.org/releases/icecast/icecast-2.4.3.tar.gz
tar xf icecast-2.4.3.tar.gz                                                                           About Me
cd icecast-2.4.3
./configure
make                                                                                                  Contact Me
sudo checkinstall make install

(Accept all of the default answers.)                                                                  GPL enforced

A newer version of Icecast may have come out since this was written, or if you're using Trisquel
8 or later then you probably already have a new-enough version of Icecast.                             If you appreciate any of the
                                                                                                       things I am doing you can
Edit the file /usr/local/etc/icecast.xml mostly to set passwords to stream. No, this doesn't           make a donation.
mean that people will need passwords to view the steams. Rather, these are used by the
programs that send the audio & video to Icecast to be streamed out to the internet.

Then start Icecast:

/usr/local/bin/icecast -c /usr/local/etc/icecast.xml

Icecast listens on port 8000 by default, unless you've changed this in the icecast.xml file.
Whatever port icecast listens on will need to be opened in your firewall.

Now that Icecast is running it's time to send it audio and video to stream. I used FFmpeg for this.
I made my own statically compiled version of FFmpeg in order to get the latest version of libvpx
without having to mess with what was on the host system. Feel free to do that if you want or use
the version provided by the distro. Alternatively, the FFmpeg website also has links to download
static builds if you'd rather not make your own.
Anyway, once FFmpeg is available through whatever means you've decided it's time to use it to
encode the source video and send it to Icecast:

~/ffmpeg -i xxx -y -f webm -codec:v libvpx -codec:a libvorbis -aq -1 -ac 1
-af "volume=2.5, aresample=async=44800:min_hard_comp=0.000000, asetpts=PTS-
(1.15/TB)" -ar 24000 -vf "yadif=0:-1:1, fps=fps=24000/1001, scale=569:320"
-deadline realtime -cpu-used 0 -threads 3 -profile:v 0 -crf 10 -vb 256K
-content_type video/webm icecast://source:password@127.0.0.1:8000/file.webm

This may look long and scary but it's not, I promise. Let's walk through this:

~/ffmpeg

This runs FFmpeg. I had placed the binary in my home directory but invoke FFmpeg as
appropriate for wherever the program is at.

Next, replace xxx with whatever the input of your audio & video are. This may be a webcam so
maybe /dev/something or whatever else you're using.

-f webm -codec:v libvpx -codec:a libvorbis

This sets the format and audio and video codecs.

-aq -1

This sets Vorbis is use quality-based encoding, using "quality level -1." Vorbis accepts a range
anywhere from -1 all the way to 10 to represent a quality level, and lower numbers generally
represent lower bitrates. Keeping the bitrate low was important to me. The audio still sounded
great.

-ac 1

This changes the audio to a single channel (mono) instead of the multi-channel audio input that
the source had. This was also done to reduce the overall bandwidth needed.

-af "volume=2.5, aresample=async=44800:min_hard_comp=0.000000, asetpts=PTS-(1.15/TB)"

This needs some explaining. "af" is for "audio filter." The first increases the volume by 2.5x since
I've found that the encoded audio was somewhat quiet. The others (aresample and asetpts)
were used because I found myself with out of sync audio. This can be worked around in the
program playing the stream (VLC in this case) by pressing J and K to adjust the audio until it
looked like it was in sync with the speaker's mouth but I really wanted to find a way to fix it from
the streaming server. Sadly, I never did.

The aresample with async lets you stretch/squeeze the audio to match with the video (with
44800 representing the maximum number of times per second that the audio would be adjusted)
but this didn't help. asetpts did help by letting me adjust the delay of the video. First I'd watch the
stream in VLC and see how far off I'd need to adjust the audio (using the J and K I mentioned
earlier.) Then I'd kill the stream and adjust the audio by that number of seconds.

As a special note, VLC shows the audio adjustments in milliseconds while FFmpeg accepts the
number in seconds so you need to convert.

I never did figure out why the audio and video of my stream were not in sync but these filters
along with using the J and K buttons on the keyboard were helpful to compensate.

-ar 24000

This is used to change the sampling frequency (which was originally 48000Hz) and so I am
cutting it in half here, once again to try to reduce bandwidth.

-vf "yadif=0:-1:1, fps=fps=24000/1001, scale=569:320"

This is another one that needs explaining. While af stood for audio filter, vf stands for video filter.
In this case I am using yadif to deinterlace the video (since it was interlaced - if yours is not the
yadif filter is not needed.) fps is being used to reduced the number of video frames per second. If
you do that math 24000/1001 is about 23.976. Finally, scale was being used to reduce the size
of the video frame. FFmpeg can also crop the video frame too if that's needed. I didn't but look
on ffmpeg.org for information on the cropping video filter if you need to crop as well.

-deadline realtime

This is used to tell libvpx to use its real-time encoding mode for live streaming. If you try other
options like good or best or whatever you will probably find the encoding speed too slow for real-
time use.

-cpu-used 0

This sets the target CPU utilization. I went for using as much as I could. It accepts a range from
0-15.

-threads 3

I used this for multi-threaded encoding. The recommended number to use here is the number of
real CPU cores - 1)

-profile:v 0

libvpx lets you set the encoder complexity so that lower-powered devices can play the video
more easily. It accepts a range of 0-3, with 0 being a good default, unless you are having
problems with playing stuff on very low power devices.

-crf 10 -vb 256K
This is a critical area for controlling the bandwidth used by the video. crf sets a constant quality
mode (from 4-63). 10 is a good starting point. Lower values mean better quality. The -vb sets a
maximum amount of bandwidth to use. If you want only constant bitrate leave out the -crf. If you
want only constant quality and don't care of what the maximum bitrate might be, leave -vb there
but set it to -vb 0M. It must be present.

-content_type video/webm

This sets the MIME type that is sent to Icecast and it shown to people accessing the stream.

icecast://source:password@127.0.0.1:8000/file.webm

This last part tells FFmpeg to send the results to Icecast. Be sure to replace "password" with
whatever password you made up in the icecast.xml file. Change the IP and port to match
whatever Icecast is listening on (for me, Icecast and FFmpeg were running on the same
machine.) Finally, file.webm is the file name that people will see in Icecast. It also forms part of
the URL that people would use to access the stream. In this case: http://127.0.0.1:8000
/file.webm

And that's it. You can give people the direct URL of the stream or direct them to the IP & port in
their browser to interact with Icecast directly.

You can also invoke FFmpeg multiple times if you want multiple streams to be available in
Icecast.


Copyright © 2016 Jason Self. See license.shtml for license conditions. Please copy and share.