Streaming Desktop with Audio to the Internet

· klm's blog


Original post is here: eklausmeier.goip.de

Task at hand: You want to show your desktop including audio to a person in another country.

This task is similar to watching YouTube with multiple people using w2g.tv.

1. Terms used.

  1. FFmpeg, initially developed by Fabrice Bellard. Name comes from "Fast Forward MPEG".
  2. HLS or "HTTP Live Streaming"
  3. Native HLS Playback by Gaetan Hervouet
  4. m3u8, a simple file format providing the list of media files available for download
  5. AAC, successor of MP3 audio codec

Using information from

  1. ArchWiki on FFmpeg
  2. Martin Riedl on HLS streaming server
  3. FFmpeg Trac entry regarding pulseaudio
  4. FFmpeg Trac entry regarding capturing your desktop

2. Solution. The command on the server side, machine trying to offer its desktop, is:

1ffmpeg -f x11grab -s 1280x720 -framerate 15 -i $DISPLAY \
2	-f pulse -i default -c:v libx264 \
3	-crf 21 -preset veryfast -g 25 -sc_threshold 0 \
4	-c:a aac -b:a 128k -ac 2 \
5	-f hls -hls_time 4 -hls_list_size 3 -hls_flags delete_segments \
6	stream.m3u8

This way ffmpeg will continuously produce streamXXXX.ts files, thereby continuously updating stream.m3u8, for example:

1$ ls stream*
2stream1579.ts  stream1580.ts  stream1581.ts  stream1582.ts  stream.m3u8

By using delete_segments they are deleted all the time. In above example 3+1 files are kept. See ffmpeg(1) and ffmpeg-all(1). Without delete_segments you would stay with 1582 files, taking the above list as an example.

The directory, where all these stream-files are produced, must now be "published" via any web-server. There is no need for any extra plugin or module on the web-server side.

Assume all streamXXXX.ts files are in /tmp. From your web-server root you symlink to /tmp via

1cd /srv/http
2ln -s /tmp ffmpeg

Then the URL in the web-browser is

1http://<YourAddress>/ffmpeg/stream.m3u8

x11grab allows to specify a specific window (window_id), or part of the screen, see x11grab. Use the xwininfo program to find the window-id. Use xdpyinfo to find resolution of your display. Streaming a particular window is thus:

1ffmpeg -f x11grab -window_id 0xa00002 -framerate 15 -i $DISPLAY ...

3. Client side. According the HLS wiki Apple devices support HLS out of the box. Google Chrome does not. For Google Chrome you have to use the HLS extension. On Android I had no luck with Google Chrome, but with VLC for Android you can then watch HLS.

4. Unsuccessful attempts. I was not able to get RTP working using different machines.

1ffmpeg -f x11grab -s 1280x720 -framerate 15 -i $DISPLAY -f rtp rtp://0.0.0.0:1234

Client side:

1ffplay -i sdp -protocol_whitelist file,udp,rtp

Content of the sdp file is the output of above ffmpeg command.