How to play UStream channels in VLC
Contents
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
$ 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

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 syntaxI’m wondering if you can fix it?
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.
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.
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"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?
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…
Basically this.
http://i48.tinypic.com/2rz2dlj.png
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!Just responding to say I got it working
Thanks for the help, script works a treat.
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)The pattern to use on line 17 of the script is now:
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!)
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.
channelId = re.search("ustream.vars.channelId=(\d+)", html).group(1)
channelTitle = re.search("ustream.vars.channelTitle=\"([^\"]+)\"", html).group(1)
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!
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()
@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
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()
Gah. My indents!
It’ll let you know where you went wrong I guess.
Ustream appears to have changed to a new layout/structure. Any ideas on how to update the Python script to get the dump?
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
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?
Read up in earlier quotes and see the Channel ID issue was already solved
Still getting problem that the connection closes.
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.
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.
Here is my version:
http://pastebin.com/nSTVp2Xg
@kenorb: your script worked for me (I was having problems with the script posted in article above)
@kenorb
Thanks for that!
It seems there are, again, some changes on UStream. Could you update the script?
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 -
It seems that they changed it again. Url is found, but rtmpdump can not find stream with that commandline. Worked yesterday, but not today…
“ERROR: Closing connection: NetStream.Play.StreamNotFound” –
This error keeps coming with all live-channels. What is wrong?
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
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…
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
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
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.
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
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!