I’ve been following Adobe’s RTMP protocol for awhile, and kudos go out to all the brave souls that have tried to build alternative clients for it. There are various projects in Java, Python, and a notable closed-source app, the Orbitz Downloader, also seems to work if you don’t mind a standalone browser plugin.
For C/C++, the XBMC team wrote the only client I’ve seen in their libRTMP namespace, and this was used as the basis for the excellent rtmpdump project on sourceforge, which was ported over to linux (and for Windows, cygwin). I should note that there’s also Gnash, the open-source Flash player, but it has a lot of dependencies to build (and the latest Win32 binary release is from 2007; no one builds it regularly on Windows apparently) so I haven’t really looked at it.
As an experiment I wanted to see if I could get rtmpdump 1.3d running on pure-Windows, no cygwin needed (you still need the Boost C++ libraries, but of course these are platform-independent). In the end, I was able to compile it on Visual Studio 2008 on Vista, and it “mostly” runs.
The porting steps were:
- Install the Windows SDK v6.1. You need at least XP or later for this SDK I believe.
- Install the Boost libraries with the Windows installer
- In rtmpdump, get rid of the linux headers and replace them with the Win32 equivalents. The tips at http://www.fearthecow.net/guest/rosetta was the key here.
- Since the time-related stuff is far different in Win32, I changed rtmpdump::GetTime(). Not positive I did this correctly though – it’s possible that a logic error here may cause downloads to get rejected (see below).
- getopts() had to be replaced with XGetOpt, an alternate (public-domain) implementation I found. No longopts support but it works with the “short” options.
- The longopts[] initializer doesn’t compile with VS, so I took it out – it’s not needed anyway because of #5.
Everything I changed is marked with “TODO” if you want to see the diffs. After configuring the include and library paths for #1 and #2, you should be able to build the VS2008 solution. So it runs (and indeed behaves the same as the Cygwin version I built to compare it to) but I should note that neither one actually downloads an FLV file from a real-life RTMP server for me. But at least both codebases now behave the same. Specifically if I try a real Flash Media Server url, I get something like:
C:\rtmpdump-v1.3d\Debug>rtmpdump -r rtmp://flashstream.adobe.com/ondemand/flash/devcenter/max_2007/effective_ui.flv -o out.flv RTMPDump v1.3d (c) 2009 Andrej Stepanchuk, license: GPL DEBUG: Setting buffer time to: 36000000ms Connecting to rtmp://flashstream.adobe.com/ondemand/flash/devcenter/max_2007/effective_ui.flv ... DEBUG: Hostname: flashstream.adobe.com DEBUG: Port: 1935 DEBUG: connected, hand shake: DEBUG: handshaked Connected... Starting download at 0.000 KB DEBUG: RTMP_LIB::CRTMP::GetNextMediaPacket, received: invoke DEBUG: Property: DEBUG: Property: DEBUG: Property: NULL DEBUG: Property: DEBUG: Property: DEBUG: Property: DEBUG: Property: DEBUG: RTMP_LIB::CRTMP::HandleInvoke, server invoking <_error> ERROR: rtmp server sent error DEBUG: RTMP_LIB::CRTMP::GetNextMediaPacket, received: invoke DEBUG: Property: DEBUG: Property: DEBUG: RTMP_LIB::CRTMP::HandleInvoke, server invoking ERROR: rtmp server requested close DEBUG: zero read! Closing connection... done!
Now I hope that I am just missing a “real-life” parameter like swfURL or app, but as I said, at least it works like the Cygwin version for this limited test case. Anyone got any real-life parameters I can try?
Anyway, thanks again to the rtmpdump and XBMC guys. They did all the hard work!
Download the Visual Studio 2008 project here: rtmpdump-v13d-win32-no-cygwin.zip
Hi
I just trying download it but i can’t, appears the next:
Any Ideas??
C:>rtmpdump -r \rtmpe://xxxx.xxxx.net/ondemand/?auth=xxxxx
_d_d_d_d_d_d_d_cvbhbkdIaHaTbGckdDcDbbbBacbQcba6-bkmrEd-vga-4qoGDqRxmEt&aifp=
v006&slist=c1/s/1314116/video.mp4\ -o \video.mp4\
RTMPDump v1.6
(c) 2009 Andrej Stepanchuk, license: GPL
DEBUG: Parsing…
DEBUG: Parsed protocol: 3
DEBUG: Parsed host : xxxx.xxxx.net
DEBUG: Parsed app : ondemand/?auth=eaEd_d_d_d_d_d_d_d_d_d_d_d_d_d_d_d_cvbhbk
dIaHaTbGckdDcDbbbBacbQcba6-bkmrEd-vga-4qoGDqRxmEt&aifp=v006&slist=c1/s/1
314116/video.mp4
DEBUG: Parsed playpath: c1/s/1314116/video.mp4
DEBUG: Setting buffer time to: 36000000ms
Connecting …
DEBUG: Protocol : RTMPE
DEBUG: Hostname : xxxx.xxxx.net
DEBUG: Port : 1935
DEBUG: Playpath : c1/s/1314116/video.mp4
DEBUG: tcUrl : rtmpe://cp71915.edgefcs.net:1935/ondemand/?auth=xxxxx
_d_d_d_d_d_d_d_d_d_d_cvbhbkdIaHaTbGckdDcDbbbBacbQcba6-bkmrEd-vga-4qoGDqRxmEt&
;aifp=v006&slist=c1/s/1314116/video.mp4
DEBUG: app : ondemand/?auth=xxxxx_cvbhbkdIaHaT
bGckdDcDbbbBacbQcba6-bkmrEd-vga-4qoGDqRxmEt&aifp=v006&slist=c1/s/1314116
/video.mp4
DEBUG: flashVer : LNX 9,0,124,0
DEBUG: live : no
DEBUG: timeout : 300 sec
DEBUG: Connect, … connected, handshaking
DEBUG: HandShake: Client type: 06
DEBUG: HandShake: DH pubkey position: 1215
DEBUG: HandShake: Client digest offset: 410
DEBUG: HandShake: Initial client digest:
2C 0A 37 80 66 E0 83 1C 2C FC 2B 99 45 9B 40 0C 94 0C 6F 67 FC 9E 9E 63 DC F7 37
DA EA D4 46 DC
DEBUG: HandShake: Type Answer : 06
DEBUG: HandShake: Server Uptime : 921729606
DEBUG: HandShake: FMS Version : 3.0.3.1
DEBUG: HandShake: Server DH public key offset: 330
DEBUG: HandShake: Secret key:
0A 3F 91 0E 75 FC 7E 47 2D C4 5E 3E F3 58 36 0E 3B C8 BD 31 56 25 03 A7 BC 22 D9
33 32 BC D3 EC C4 BC 5B FE 86 52 3D 27 8B BE 05 15 AF 47 CA D3 74 C2 61 E4 53 0
C 09 77 A7 E7 EA D9 2B 41 46 6C 09 ED 2B DA F3 92 D3 6D 87 1D 4C 3E AB AA 5D 0B
15 0F 5E 07 92 A5 6A 25 B5 DD 40 69 2C F1 60 1B 67 C4 D2 DB A3 A0 FF 37 F7 18 5F
FD 60 91 93 7C E7 2A 8E 04 A2 C6 51 4A 4E 59 A3 50 22 60 2C 34
DEBUG: RC4 Out Key:
30 BC 2D B1 83 67 7E 16 63 36 7A 82 DC 3F 26 AE
DEBUG: RC4 In Key:
A3 A1 5B 70 2E 5E 0B CD 0E 98 57 0F 22 F8 F0 C1
DEBUG: HandShake: Client signature digest position: 410
DEBUG: HandShake: Digest key:
FC 65 F3 DC 53 51 30 45 9C 39 5B F2 10 6E E3 1A 2A D5 10 A2 87 A5 FA ED B5 DE C3
5C 9F 7B 15 3D
DEBUG: HandShake: Signature calculated:
C1 F8 53 EE 81 1E E0 B7 4E D9 0C 0C 97 25 5D AC 9C 7B CA 02 E3 E1 3A CA 19 92 28
BD AB BB 64 07
DEBUG: HandShake: Server sent signature:
C1 F8 53 EE 81 1E E0 B7 4E D9 0C 0C 97 25 5D AC 9C 7B CA 02 E3 E1 3A CA 19 92 28
BD AB BB 64 07
DEBUG: HandShake: Genuine Adobe Flash Media Server
DEBUG: HandShake: Calculated digest key from secure key and server digest:
3F 5C 9F A6 70 35 32 12 06 72 21 AF 2A FF 97 E4 43 13 A5 A7 12 6B F3 31 AA E8 59
79 9A 26 43 16
DEBUG: HandShake: Client signature calculated:
E4 3B 9A 61 DF B1 35 DC EF 7C 80 C4 9C F2 AF 17 12 5C 34 D3 06 6E B0 E5 5D ED B9
22 08 E9 C2 CA
DEBUG: HandShake: Handshaking finished….
DEBUG: Connect, handshaked
Connected…
Starting download at 0.000 KB
DEBUG: GetNextMediaPacket, received: invoke 134 bytes
DEBUG: Property:
DEBUG: Property:
DEBUG: Property: NULL
DEBUG: Property:
DEBUG: Property:
DEBUG: Property:
DEBUG: Property:
DEBUG: HandleInvoke, server invoking
ERROR: rtmp server sent error
DEBUG: GetNextMediaPacket, received: invoke 18 bytes
DEBUG: Property:
DEBUG: Property:
DEBUG: HandleInvoke, server invoking
ERROR: rtmp server requested close
Closing connection… done!
Sorry- wish I could help… Since the server sent an error are you sure that’s a valid RTMP URL?