Sunday, April 25, 2010

Webcam Stream over the Internet on Linux, with VLC and VLC-QT

I am playing with streaming Linux webcam output over the internet. Apparently one package for streaming is VLC (it is it seems the most featured video handling package overall).

Eventually I got webcam VLC streaming working on Linux (Opensuse 11.3)  in multiple ways. This was not straighforward (what with video is on Linux :) ) - so I took take some notes below, sort of a step by step process. Now, I am succesfully streaming webcam over the internet, using bandwith-saving multicast and dynamic IP for my domain milanzimmermann.com. (Next: to connect the webcam inside a bluebird' nesthouse.)


Step A: Stream an AVI file from one instance of VLC-QT, capturing and playing on other instance of VLC, without transcoding as H.264.

This is a first step to create a localhost client server setup. The bricks that need to be connected for a working simple configuration are as follows:


1. Source of the stream: an AVI file, downloaded from a multimedia test site:  Electric_Guitar_Scrape_And_Pound_DivX.avi

2. VLC setup as a streaming server. VLC reads the AVI file, and outputs it "straight" (without transcoding) as UDP, without transcoding as H.264. To achieve this, do the following:

on command line, run VLC:
Server prompt $: vlc # the VLC gui starts
click media->streaming, dialog opens. following describes clicking through the VLC wizard (each line represents a click on a UI item):

file
add - browser to the Electric_Guitar_Scrape_And_Pound_DivX.avi
stream
next
new destination: udp
check "display locally" - this will allow viewing on this streaming VLC server
add
address = localhost
port=1234
check "activate transcoding" OFF !!
next

having done the above, the screen now shows the parameters VLC generated from our steps:
"
:sout=#duplicate{dst=std{access=udp,mux=ts,dst=localhost:1234},dst=display}
"


From now on, we can simply start the server as follows: 

server prompt $: vlc -vvv /home/mzimmermann/Documents/Electric_Guitar_Scrape_And_Pound_DivX.avi --sout '#duplicate{dst=std{access=udp,mux=ts,dst=localhost:1234},dst=display}'

This streams to 2 destinations: the display, so we can see what the file contains, and to a UDP output on localhost, port 1234.

3. Server Output Stream: The above set of steps will start streaming the AVI file into UDP on localhost, port 1234, and also the VLC "streaming server" display., and at the same time, as the client input stream, processed in the "client VLC" - see step 4.

4. VLC client, setup as UDP client

on the client system (which in out case is same system as the server), run the client VLC as follows:

Client prompt $: vlc udp://@:1234   # Note no localhost is specified on the client uvc (This is because any-source multicast does figure out the source of the stream on the network!!)

If you run the above, you will see the webcam displayed on the client VLC.

5. Summary - run it all:

Now, find the streaming server VLC GUI, and click the play sign. This will start playing the AVI file in the "streaming server GUI" started in Step A, item 2, and also streaming it to UDP localhost port 1234. The UDP stream is  automatically showing the video in  the "streaming client GUI" started in Step A, item 4


Step B: Stream from AVI file (same as in Step A) from one instance of VLC-QT, capturing and playing on other instance of VLC as RTP, without transcoding as H.264. (difference from step A, we use RTP instead of UDP)


Server prompt $: vlc -vvv /home/mzimmermann/Documents/Electric_Guitar_Scrape_And_Pound_DivX.avi --sout '#duplicate{dst=rtp{dst=localhost,port=5004,mux=ts},dst=display}'

Client prompt $: vlc rtp://@:5004

Note that the WEIRD difference between the UDP and RTP specification for --sout !!!!!! - but it makes a difference for playing . I have no idea why this is so messed up... (the port number does not matter as long as client/server is same)

Step C: Stream from Webcam as source (instead of an AVI file in Step B) over Real Time Transport (RTP)  from one
instance of VLC-QT, capturing and
playing on other instance of VLC, without transcoding as H.264.


Server prompt $: vlc -vvv v4l2:// --sout
'#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:rtp{mux=ts,dst=localhost,sdp=sap,name="TestStream"}'
vlc rtp://@:5004

Client Prompt $: vlc rtp://@:5004

This shows webcam in client (really?? - not sure this worked for me)

Note: vlc comes with it's own HTTP server, start it like:
vlc -I http --http-host localhost:8083

Step D: Multicast UDP Streaming (probably works same for RTP). This works, BUT client can only access localhost as "vlc udp://@:1234" I have NO IDEA why I can specify Multicast on server (something in range 239.255), but on client , no IP can be specified, otherwise the stream does not show in the client...  

See also  http://www.videolan.org/doc/videolan-howto/en/ch08.html

Server prompt $:  vlc -vvv v4l2:// --sout '#transcode{vcodec=mp4v,acodec=mpga,vb=3000,ab=256,vt=800000,keyint=80,deinterlace}:std{access=udp,mux=ts,url=239.255.12.13}' --ttl 12

Notes:
  1. The URL can be almost anything, e.g. 239.255.12.13@milanzimmermann.com and client still works
  2. The ttl 12 specifies time to live - how many routes UDP can pass. It is 1 by default. For clients outside of the local host, override the default (we use 12 here)


Client prompt $: vlc udp://@:1234 # But the client CANNOT USE ANY IP, like vlc udp://@239.255.12.13:1234 - thiis does not work why?

Step E: VLC server controlled via telnet: Serves stream as UDP-Multicast on mulitcast IP=239.255.12.13 and also HTTP-Singlecast. Cients can view the stream via HTTP or UDP.  This can be setup in 2 command prompts (client/server telnet). We also need a command prompt for testing http access- see also http://www.ringoy.org/?p=40.

Prerequisits:

1.In router, enabled multicast (Linksys Advanced->Advanced network settings), enable multicast streams
2.In router, enabled port 1234 (for both UDP and TCP, although UDP likely not needed) (Linksys Advanced, add open port)
3. V4L2 is installed, and Webcam works .

Start Shell Prompt 1 (Server) and type in:

vlc -I telnet # Start VLC server and open port 4212 for telnet.


Start Shell Prompt 2 (Client) and type in:

telnet localhost 4212  # Starts VLC client - here we use localhost, as we run from the same system as telnet. But it can be run from anywhere with telnet access to the system that started server in shell prompt 1. Would have to reaspecify some-ip instead of localhost. some-in is IP of the system wistarting server in step 1.

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Password: admin
Welcome, Master

> new cam broadcast enabled

> setup cam input "v4l2://"

> setup cam output "#transcode{vcodec=mp4v,acodec=mpga,vb=3000,ab=256,vt=800000,keyint=80}:duplicate{dst=standard{mux=ts,dst=239.255.12.13,access=udp,sap,name="CAM_UDP"},dst=standard{mux=ts,dst=:1234,access=http}}"

> setup cam enabled

> control cam play


Start Shell Prompt 3 (Accesses the system where Client telnet from prompt 2 is running):

vlc http://milanzimmermann.com:1234

(This will display the webcam stream)


Enable support for viewing webcam stream via HTTP

a) in the HTTP server, create a file similar to the contents this:( credit http://videolan)

http://milanzimmermann.com/test-vlc.html

b) From anywhere on the internet, browse to:

http://milanzimmermann.com/test-vlc.html

and see the video


Step F: FINAL "SOLUTION": Serves stream as UDP-Multicast on any-source mulitcast IP=239.255.12.13 and also HTTP-Singlecast. Clients can view the stream via HTTP or UDP.

Prerequisits for the steps below to work:

  1. Your kernel has multicast enabled (if you want to use multicast, which is a must for multiple simultaneous clients).
  2. V4L2 is installed, and Webcam works .
  3. In your router, enable multicast (Linksys Advanced->Advanced network settings), enable multicast streams
  4. In your router firewall, allow port 1234  (TCP if you use http, UDP for udp - we use both here) (Linksys Advanced, add open port)
  5. If you are using Masquerading (at home most likely you are), you also need to forward port 1234 to the server - in our example, to 192.168.0.199

Server Prompt (running on system with Intranet IP=192.168.0.199, Internet IP milanzimmermann.com) $: vlc $HOME/Documents/Electric_Guitar_Scrape_And_Pound_DivX.avi --loop --sout "#transcode{vcodec=mp4v,acodec=mpga,vb=3000,ab=256,vt=800000,keyint=80}:duplicate{dst=standard{mux=ts,dst=239.255.12.13:1234,access=udp,sap,name="CAM_UDP"},dst=standard{mux=ts,dst=:1234,access=http},dst=display}" --ttl 12

Notes:
  1. 239.255.12.13 is the IP of the UDP multicast group. Clients must specify this group to access the multicast. More precisely, clients must use source_system_ip@239.255.12.13 - see below for sample client use.
  2. To stream from a webcam rather then the AVI file above, replace the path to the AVI file "$HOME/Documents/Electric_Guitar_Scrape_And_Pound_DivX.avi" with "v4l2://", and remove the "--loop" option.
  3. To prevent the stream from showing in the VLC window on the server (does it save anything?), remove the ",dst=display" above.
  4. Note that we use port 1234 both for http:// (uses TCP) and udp:// (uses UDP)
  5. To remove streaming across http, remove the ",dst=standard{mux=ts,dst=:1234,access=http}" above.
  6. The ttl 12 specifies time to live - how many routers UDP can pass. It is 1 by default. Non-default value (default 1) is needed for UDP clients to work outside the local host (we use 12 here).
  7. The "--loop" option will play the file over and over - good for testing the client.
  8. Trying to use "dst=milanzimmermann.com:1234,access=http" instead of "dst=:1234,access=http" does not work. No idea why.

    vlc as udp client from prompt any host on localnet $:
    vlc udp://@239.255.12.13:1234 # This works. Alos 1234 is default for udp

    Notes:
    1. The @239.255.12.13 is ANY-SOURCE-MULTICAST
      vlc as udp client from prompt any host on localnet $:
      vlc udp://192.168.0.199@239.255.12.13:1234 # This works.

      Notes:
      1. I think this only works because of coincidence. I think host only provides ANY-SOURCE MULTICAST, NOT SINGLE_SOURCE_MULTICAST_ IP@239.255.12.13
      2. IP for SINGLE_SOURCE_MULTICAST_ IP must start with 232 (not 239) but I do NOT think VLC works for SINGLE-SOURCE
      3. 192.168.0.199 is the source IP = IP of the system where multicast sender creates the multicast source. @239.255.12.13 is multicast IP served by the VLC server.(see the server vlc command)
      4. 192.168.0.199 can NOT be replaced with 127.0.0.1 even when running from same system as server. 
      5. If the client n the same system as server, you can omit 192.168.0.199 use vlc udp://@239.255.12.13

      vlc as udp client prompt from any host on internet $: 
      vlc udp://milanzimmermann.com@239.255.12.13:1234
      1. This does NOT work - because UDP port not open in firewall??  
      2. No, I think this is because milanzimmermann.com@239.255.12.13 indicates SOURCE-SPECIFIC-MULTICAST, but the server only provides ANY-SOURCE-MULTICAST

      vlc as http client prompt from any host on localnet $:  
      vlc http://192.168.0.199:1234 # This works if port 1234 is open on server

      vlc as http client prompt from any host on internet or localnet:  
      vlc http://milanzimmermann.com:1234 # This works, if port 1234 is open on the server.


      http browser client from any host on internet or localnet:  
      type address http://milanzimmermann.com:1234 into the browser # This does NOT work as browser is not VLC client (but it can be if stream served via embed tag on html, see below)

      vlc plugin in http browser with VLC PluginFrom anywhere on the internet:

      to try this, browse to:

      http://milanzimmermann.com/test-vlc.html  # This works, as long as the page is written correctly with the embed tag, and VLC plugin installed in the browser. See the source of the above page


      This concludes it alll.... (but test step F on source=V4l2 instead of AVI file.... and attach to the multicast via internet ... what ports does it go through?)




      No comments: