Programming
20 May 2012 38 Comments

How to play UStream channels in VLC

Introduction

Ustream.tv doesn’t support opening streams in VLC by default, but it is possible with some effort. Most video streaming sites use the Real Time Messaging Protocol (RTMP) for transmitting video data to your flash player. Using rtmpdump we can connect to RTMP streams, and record them or play them in VLC.

1: Install rtmpdump

On Ubuntu:

$ sudo apt-get install rtmpdump

Binaries for all platforms: here.

2: Find the RTMPDump Parameters

It’s not trivial to find out the correct parameters for rtmpdump, so use this Python script:

#!/usr/bin/env python
# This script finds the rtmpdump command syntax for opening a UStream stream.
 
import sys
import urllib2
import re
 
 
def getVideoData(url):
    # Get the HTML contents
    req = urllib2.Request(url)
    response = urllib2.urlopen(req)
    html = response.read()
 
    # Extract the channel ID from the HTML
    channelId = None
    m = re.search("Channel\sID\:\s+(\d+)", html)
    if (m):
        channelId = m.group(1)
 
    # Extract the channel title from the HTML
    channelTitle = None
    m = re.search("property\=\"og\:url\"\s+content\=\"http\:\/\/www." +
            "ustream\.tv\/(?:channel\/)?([^\"]+)\"", html)
    if (m):
        channelTitle = m.group(1)
 
    amfContent = None
    if (channelId):
        amfUrl = ("http://cdngw.ustream.tv/Viewer/getStream/1/"
        + channelId + ".amf")
        response = urllib2.urlopen(amfUrl)
        amfContent = response.read()
 
        rtmpUrl = re.search("(rtmp\:\/\/[^\x00]+)", amfContent).group(1)
        f = open('tmp.txt', 'w')
        f.write(amfContent)
        streamName = re.search("streamName(?:\W+)([^\x00]+)",
                amfContent).group(1)
 
    return (channelId, channelTitle, rtmpUrl, streamName)
 
 
def getRtmpCommand(rtmpUrl, streamName):
    result = ("rtmpdump -v -r \"" + rtmpUrl + "/" + streamName + "\""
              " -W \"http://www.ustream.tv/flash/viewer.swf\" --live")
    return result
 
 
def main(argv=None):
    # Process arguments
    if argv is None:
        argv = sys.argv[1:]
 
    usage = ("Usage: ustreamRTMPDump.py <ustream channel url> [filename]\n"
            "e.g. \"ustreamRTMPDump.py 'http://www.ustream.tv/ffrc'\"")
 
    if (len(argv) < 1):
        print usage
        return
 
    # Get RTMP information and print it
    url = argv[0]
    print "Opening url: " + url + "\n"
 
    (channelId, channelTitle, rtmpUrl, streamName) = getVideoData(url)
    print "Channel ID: " + channelId
    print "Channel Title: " + channelTitle
    print "RTMP URL: " + rtmpUrl
    print "RTMP Streamname: " + streamName + "\n"
 
    rtmpCmd = getRtmpCommand(rtmpUrl, streamName)
    print "RTMP Command:\n" + rtmpCmd
 
if __name__ == "__main__":
    main()

To use this script to get the rtmpdump command for a UStream channel, simply call it with the channel URL:

python ustreamRTMPDump.py <url>

For example:

$ python ustreamRTMPDump.py "http://www.ustream.tv/decoraheagles"
Opening url: http://www.ustream.tv/decoraheagles
 
Channel ID: 3064708
Channel Title: decoraheagles
RTMP URL: rtmp://ustreamlivefs.fplive.net/ustream3live-live/
RTMP Streamname: stream_live_1_1_3064708
 
RTMP Command:
rtmpdump -v -r "rtmp://ustreamlivefs.fplive.net/ustream3live-live//stream_live_1_1_3064708" -W "http://www.ustream.tv/flash/viewer.swf" --live

Running this command will connect to the stream and write the binary data to the terminal as characters. Not exactly what we want. But we can easily write the stream data to a file, or play it in VLC!

3: Record or Play the Stream

To play the stream in VLC, simply pipe the command into VLC by adding | vlc -.

$ rtmpdump -v -r "rtmp://ustreamlivefs.fplive.net/ustream3live-live//stream_live_1_1_3064708" 
-W "http://www.ustream.tv/flash/viewer.swf" --live | vlc -

To record the stream to a file video.flv simply add -o video.flv to the command.

$ rtmpdump -v -r "rtmp://ustreamlivefs.fplive.net/ustream3live-live//stream_live_1_1_3064708" 
-W "http://www.ustream.tv/flash/viewer.swf" --live -o video.flv

You can then play this file in VLC, even while it is being recorded:

$ vlc video.flv

Example Output

$ rtmpdump -v -r "rtmp://ustreamlivefs.fplive.net/ustream3live-live//stream_live_1_1_3064708" -W "http://www.ustream.tv/flash/viewer.swf" --live | vlc -
RTMPDump v2.4
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
VLC media player 2.0.1 Twoflower (revision 2.0.1-0-gf432547)
WARNING: You haven't specified an output file (-o filename), using stdout
[0x8d07908] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
ERROR: RTMP_HashSWF: couldn't contact swfurl http://www.ustream.tv/flash/viewer.swf (HTTP error 302)
Connecting ...
INFO: Connected...
Starting Live Stream
INFO: Metadata:
INFO:   author                
INFO:   copyright             
INFO:   description           
INFO:   keywords              
INFO:   rating                
INFO:   title                 
INFO:   presetname            Custom
INFO:   creationdate          Sat May 19 23:01:07 2012
INFO:   videodevice           ATI AVStream Analog Capture
INFO:   framerate             30.00
INFO:   width                 720.00
INFO:   height                480.00
INFO:   videocodecid          avc1
INFO:   videodatarate         500.00
INFO:   avclevel              50.00
INFO:   avcprofile            77.00
INFO:   videokeyframe_frequency1.00
INFO:   audiodevice           Microphone (Realtek High Defini
INFO:   audiosamplerate       22050.00
INFO:   audiochannels         1.00
INFO:   audioinputvolume      100.00
INFO:   audiocodecid          .mp3
INFO:   audiodatarate         48.00
0.634 kB / 0.00 sec"sni-qt/24365" WARN  20:30:09.944 void StatusNotifierItemFactory::connectToSnw() Invalid interface to SNW_SERVICE 
36.430 kB / 0.00 sec[flv @ 0xb5211aa0] Estimating duration from bitrate, this may be inaccurate
214.671 kB / 1.13 sec

38 Responses to “How to play UStream channels in VLC”

  1. Alex 25 May 2012 at 2:55 pm #

    Good idea to publish that script. Unfortunately, I can’t get it working (Win X86-64), there is an error:

    File "ustreamRTMPDump.py", line 59
      print usage
                ^
     
    SyntaxError: invalid syntax

    I’m wondering if you can fix it?

    • tboerman 25 May 2012 at 3:16 pm #

      Hi,

      The code works fine here, I just tested it on an old Ubuntu installation with Python 2.6.5. What is your Python version? I haven’t tested it, but if you are using Python 3 then it is entirely possible this script doesn’t work. So be sure to use Python 2.6 or 2.7.

  2. Garrett.S 7 June 2012 at 2:14 pm #

    Hi, I have no knowledge of python whatsoever however I have gotten far enough to be able to run .py files. Could somebody walk me through what I have to put where in here preferably in baby steps please, you don’t have to explain the inner workings of python to me, literally just what URLs and such I have to put where for this to work? It’s just I have a great idea but I need to get this to work for it to work, thanks in advance. Also sorry if that’s asking too much.

    • tboerman 7 June 2012 at 2:17 pm #

      You say you can run .py files, so all you have to do is call the script with the URL of the UStream video as a parameter:

      python ustreamRTMPDump.py "http://www.ustream.tv/decoraheagles"

  3. Garrett.S 7 June 2012 at 4:24 pm #

    Sorry about this, I think I got slightly ahead of myself. I have the means to run the script I just don’t know how. Where do I have to put the script.py for the command line to recognise it as I keep getting invalid syntax?

    • tboerman 7 June 2012 at 5:02 pm #

      You can put the script anywhere. Just put it in a directory, navigate to that directory, and enter the command. If you can’t figure it out you can post the error here…

  4. Garrett.S 7 June 2012 at 5:17 pm #

    Basically this.

    http://i48.tinypic.com/2rz2dlj.png

    • tboerman 7 June 2012 at 5:39 pm #

      The first command will work if you put the script in C:\Python27\ustreamRTMPDump.py. You may want to check out a Python tutorial first if you run into more problems. Good luck!

  5. Garrett.S 7 June 2012 at 8:41 pm #

    Just responding to say I got it working :) Thanks for the help, script works a treat.

  6. HL 29 July 2012 at 8:18 pm #

    Hi,

    Thanks for the code. I got it to work after a change which may help others.

    I found that the ustream.tv html response did not have the channel Id in the expected format.
    It worked with the following regular expression:

        
        # Extract the channel ID from the HTML
        m = re.search("data-content-id\D+(\d+)", html)
            if (m):
            channelId = m.group(1)
    
  7. Sandra Bell 5 August 2012 at 5:33 am #

    The pattern to use on line 17 of the script is now:

        m = re.search("channelId=(\d+)", html)

    If they change it again, look in the giant “ustream.vars” block just before the HTML </head> tag.

    With that, I got live streams working (2012-08-05, just in time for Mars landing!)

  8. Vhati 6 August 2012 at 12:29 pm #

    f = open('tmp.txt', 'w')
    should be
    f = open('tmp.txt', 'wb')

    Otherwise universal newlines will mangle the file.
    But most users would comment out those lines anyway.

    Here’s a safer regex.

    rtmpUrl, streamName = re.search("\x00\x06cdnUrl\x02\x00.(rtmp:[^\x00]+)\x00\x0astreamName\x02\x00.([^\x00]+)", amfContent).groups([1,2])


    And it looks like there’s a section in the amf for alternate servers too.

    altInfoPtn = re.compile("\x00\x0dcdnStreamName\x02\x00.([^\x00]+)\x00\x0ccdnStreamUrl\x02\x00.(rtmp:[^\x00]+)")
    for m in re.finditer(altInfoPtn, amfContent):
    altName, altUrl = m.groups([1,2])
    if (altUrl == rtmpUrl and altName == streamName): continue
    # Print or append name/url pairs to a list.


    I didn’t see this in the amf, but Wireshark found several stream names with varying bitrates:
    HQ: stream_live_1_1_6540154
    480p: stream_live_8_1_6540154
    360p: stream_live_4_1_6540154
    240p: stream_live_6_1_6540154
    So that first number determines quality somehow.

  9. Vhati 6 August 2012 at 12:40 pm #

    If they change it again, look in the giant “ustream.vars”


    channelId = re.search("ustream.vars.channelId=(\d+)", html).group(1)
    channelTitle = re.search("ustream.vars.channelTitle=\"([^\"]+)\"", html).group(1)

  10. Mike 8 August 2012 at 6:06 am #

    Hey folks… this has been immensely helpful, but I’m running into a problem where sometimes for some channels, ustream will go into a mode where it’s basically playing previously recorded content. It seems like when this happens, the AMF that comes back does not have the rtmp:// in it, so the regex fails, e.g:


    python rtmp_discover.py "http://www.ustream.tv/channel/nasa-media-channel"
    Opening url: http://www.ustream.tv/channel/nasa-media-channel

    Traceback (most recent call last):
    File "rtmp_discover.py", line 76, in
    main()
    File "rtmp_discover.py", line 66, in main
    (channelId, channelTitle, rtmpUrl, streamName) = getVideoData(url)
    File "rtmp_discover.py", line 35, in getVideoData
    rtmpUrl = re.search("(rtmp\:\/\/[^\x00]+)", amfContent).group(1)
    AttributeError: 'NoneType' object has no attribute 'group'

    Has anyone found a workaround for this? Thanks!

  11. Vhati 18 August 2012 at 10:13 pm #

    Oops. I misread the api docs.
    Where I wrote “.groups([1,2])” I should have had

    rtmpUrl, streamName = re.search("\x00\x06cdnUrl\x02\x00.(rtmp:[^\x00]+)\x00\x0astreamName\x02\x00.([^\x00]+)", amfContent).groups()
    ...
    altName, altUrl = m.groups()

    • ArdVark 24 August 2012 at 3:08 pm #

      @Vhati

      Could you please re post the whole script complete with all of your updates

      as I’m getting errors when I try to add your changes as posted, such as,


      Traceback (most recent call last):
      File "rtmpScript.py", line 47, in
      rtmpUrl, streamName = re.search("\x00\x06cdnUrl\x02\x00.(rtmp:[^\x00]+)\x00\x0astreamName\x02\x00.([^\x00]+)", amfContent).groups()
      NameError: name 'amfContent' is not defined

      Thanks

      • Vhati 11 September 2012 at 6:23 pm #

        Here’s what I ended up with.

        #!/usr/bin/env python
        # This script finds the rtmpdump command syntax for opening a UStream stream.
        # http://www.tech-juice.org/2012/05/20/how-to-play-ustream-channels-in-vlc/

        import sys
        import urllib2
        import re

        def getVideoData(url):
        # Get the HTML contents
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        html = response.read()

        # Extract the channel ID from the HTML
        channelId = re.search("ustream.vars.channelId=(\d+)", html).group(1)

        # Extract the channel title from the HTML
        channelTitle = re.search("ustream.vars.channelTitle=\"([^\"]+)\"", html).group(1)

        amfContent = None
        if (channelId):
        amfUrl = "http://cdngw.ustream.tv/Viewer/getStream/1/%s.amf" % channelId
        response = urllib2.urlopen(amfUrl)
        amfContent = response.read()

        streams = []
        rtmpUrl, streamName = re.search("\x00\x06cdnUrl\x02\x00.(rtmp:[^\x00]+)\x00\x0astreamName\x02\x00.([^\x00]+)", amfContent).groups()
        streams.append({"url":rtmpUrl, "name":streamName})

        altPtn = re.compile("\x00\x0dcdnStreamName\x02\x00.([^\x00]+)\x00\x0ccdnStreamUrl\x02\x00.(rtmp:[^\x00]+)")
        for m in re.finditer(altPtn, amfContent):
        altName, altUrl = m.groups()
        if (altUrl == rtmpUrl and altName == streamName): continue
        streams.append({"url":altUrl, "name":altName})

        #f = open('tmp.txt', 'wb')
        #f.write(amfContent)

        return (channelId, channelTitle, streams)

        def getRtmpCommand(rtmpUrl, streamName):
        result = "rtmpdump -v -r \"%s/%s\" -W \"http://www.ustream.tv/flash/viewer.swf\" --live" % (rtmpUrl, streamName)
        return result

        def main(argv=None):
        # Process arguments
        if argv is None:
        argv = sys.argv[1:]

        usage = "Usage: ustreamRTMPDump.py "
        usage += "\ne.g. ustreamRTMPDump.py \"http://www.ustream.tv/ffrc\""

        if (len(argv) < 1):
        print usage
        return

        # Get RTMP information and print it
        url = argv[0]
        print "Opening url: %s\n" % url

        (channelId, channelTitle, streams) = getVideoData(url)
        print "Channel ID: %s" % channelId
        print "Channel Title: %s" % channelTitle
        for stream in streams:
        print "RTMP URL: %s\nRTMP Streamname: %s" % (stream["url"], stream["name"])
        print ""
        rtmpCmd = getRtmpCommand(streams[0]["url"], streams[0]["name"])
        print "RTMP Command: %s\n" % rtmpCmd

        # Example streams...
        # HQ: stream_live_1_1_6540154
        # 480p: stream_live_8_1_6540154
        # 360p: stream_live_4_1_6540154
        # 240p: stream_live_6_1_6540154
        # HQ: ustream-sj2_63@53274
        # 480p: ustream-sj2_677@19148
        # 360p: ustream-sj2_195@20448
        # 240p: ustream-sj2_44@7605

        if __name__ == "__main__":
        main()

        • Vhati 11 September 2012 at 6:30 pm #

          Gah. My indents!
          It’ll let you know where you went wrong I guess.

  12. aliquid 28 September 2012 at 6:59 pm #

    Ustream appears to have changed to a new layout/structure. Any ideas on how to update the Python script to get the dump?

  13. dr 7 October 2012 at 11:32 pm #

    trying to watch the SpaceX launch… anyone have an updated script?
    here’s the current output of my command

    python uRTMP.py “http://www.ustream.tv/nasahdtv”

    Traceback (most recent call last):
    File “uRTMP.py”, line 76, in
    main()
    File “uRTMP.py”, line 66, in main
    (channelId, channelTitle, rtmpUrl, streamName) = getVideoData(url)
    File “uRTMP.py”, line 41, in getVideoData
    return (channelId, channelTitle, rtmpUrl, streamName)
    UnboundLocalError: local variable ‘rtmpUrl’ referenced before assignment

  14. aliquid 11 October 2012 at 2:21 pm #

    Found one problem with the change at ustream and fixed it.

    The channel ID can be found using the following:

    if channelId is None:
    m = re.search(‘data-content-id=”(.*?)”‘, html)
    channelId = m.group(1)

    I am now getting “ERROR: Closing connection: NetStream.Play.Failed” when the rtmpdump is run.

    I don’t understand why as I have chcked the rtmp url and stream name in the amf file and python script is picking this up correctly.

    Any ideas?

    • aliquid 11 October 2012 at 2:26 pm #

      Read up in earlier quotes and see the Channel ID issue was already solved :-)

      Still getting problem that the connection closes.

      • aliquid 11 October 2012 at 2:37 pm #

        The ustream.vars now has it as “contentid”. Using “m = re.search(‘data-content-id=”(.*?)”‘, html)” works for me.

        Also, problem with “ERROR: Closing connection: NetStream.Play.Failed” is ustream showing a recording and not live streaming. Works now with LIVE streaming.

        Still trying to work out how to dump the recording.

        • DCode 13 October 2012 at 12:06 am #

          Would you be able to upload to paste bin, I’m easing my way into python (out of functional demand *smile*). It appears to be indentation sensitive

          Thank you aLiquid.

  15. kenorb 14 November 2012 at 7:06 pm #

    Here is my version:
    http://pastebin.com/nSTVp2Xg

    • Garrett 4 March 2013 at 1:58 pm #

      @kenorb: your script worked for me (I was having problems with the script posted in article above)

  16. ArdVark 20 November 2012 at 7:47 pm #

    @kenorb

    Thanks for that!

  17. stranger 12 December 2012 at 2:04 pm #

    It seems there are, again, some changes on UStream. Could you update the script?

  18. stranger 22 December 2012 at 6:50 pm #

    srry, works ok with:

    @C:\PROGRA~1\RTMPDump\rtmpdump -v -r “rtmp://ustreamlivefs.fplive.net/ustream1live-live//stream_live_1_1_6540154″ -W “http://www.ustream.tv/flash/viewer.swf” –live | C:\PROGRA~1\VideoLAN\VLC\vlc.exe -

  19. Slippery 31 January 2013 at 8:49 am #

    It seems that they changed it again. Url is found, but rtmpdump can not find stream with that commandline. Worked yesterday, but not today…

  20. Slippery 31 January 2013 at 11:26 am #

    “ERROR: Closing connection: NetStream.Play.StreamNotFound” –
    This error keeps coming with all live-channels. What is wrong?

  21. K 28 February 2013 at 8:48 pm #

    I recieve this error with the above example, and another channel. What is this about?
    $ python /usr/bin/ustreamRTMPDump.py “http://www.ustream.tv/decoraheagles”
    Traceback (most recent call last):
    File “/usr/bin/ustreamRTMPDump.py”, line 76, in
    main()
    File “/usr/bin/ustreamRTMPDump.py”, line 66, in main
    (channelId, channelTitle, rtmpUrl, streamName) = getVideoData(url)
    File “/usr/bin/ustreamRTMPDump.py”, line 41, in getVideoData
    return (channelId, channelTitle, rtmpUrl, streamName)
    UnboundLocalError: local variable ‘rtmpUrl’ referenced before assignment

  22. watson 20 April 2013 at 10:34 pm #

    kenorb’s file still works fine with python 2.7, I guess, since it gives an output. But the rtmpdump command is freezing after less than 2MB of downloaded data for me…

  23. archive.cruvoir.com 25 April 2013 at 6:59 pm #

    Hi! This post could not be written any better! Reading through
    this post reminds me of my good old room mate! He always kept chatting about this.
    I will forward this page to him. Fairly certain he will have
    a good read. Many thanks for sharing!

    Check out my site; archive.cruvoir.com

  24. can install cccam dreambox 27 April 2013 at 8:47 am #

    Hurrah, that’s what I was seeking for, what a information! present here at this website, thanks admin of this site.

    Feel free to visit my web-site – can install cccam dreambox

  25. http://www.merawindows.com/ 28 April 2013 at 10:26 am #

    Your style is unique in comparison to other folks I’ve read stuff from. Thanks for posting when you’ve got the opportunity, Guess I will just bookmark this
    blog.

  26. natox reviews 2 May 2013 at 12:03 pm #

    This is very interesting, You’re a very skilled blogger. I have joined your feed and look forward to seeking more of your fantastic post. Also, I’ve shared your website
    in my social networks!

    Thank you for taking a moment to visit my profile.
    Please feel free to consider a glance at my personal internet
    site as well for extra information and facts and practical strategies; natox reviews

  27. social media marketing 11 May 2013 at 8:12 am #

    I was suggested this blog by means of my cousin.
    I am no longer certain whether this submit is written by means of him as nobody else realize such certain approximately my difficulty.

    You’re wonderful! Thank you!


Leave a Reply

You can use: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Examples:
<code>This is some inline code<
<pre lang"text">Block of code or text (not syntax highlighted)</pre>
<pre lang"python">Block of Python code (syntax highlighted)</pre>