Okay, so I've been playing an
iSKY video with
Chrome, then using
Process Explorer to find the Process ID (e.g. 1234) of the Chrome process that's playing the stream (it's usually the process gobbling up CPU!). Next I use
PMDump to dump the memory contents of the Chrome process into a file:
Code:
pmdump 1234 iSKY.txt
Next I open this file in
HxD and search (Control-F) for "rtmp" and look for my stream URL. Sometimes it can be spread around a bit, so it's worth looking before and after the part of memory that has the rtmp URL. There will be lots of copies of the same URL, and some of them may have more interesting info around them than others.
So for iSKY I find:
Code:
rtmpte://cdn.isky.co.nz/c1181/?vxttoken=00004D82521500000000283F238AFC39FD998309B96A6053D0AF5352EB87FCA71C91,00004D82521500000000283F238AF55168F1D438F2F67AE2FDD2E4770748BAB88BA4,00004D82521500000000283F238A718A0C91F962C22369ACBA79CF6A2BFA5030045B
This seems to suggest that iSKY is using an authentication token (vxttoken) for their streams, which makes sense as the service is only available to paying Sky TV customers. However, I'm sure this isn't the whole URL, as an example URL for C4 for comparison would look like:
Code:
rtmpe://nzcontent.mediaworks.co.nz/c4/_definst_/mp4:video/08032011/W0028245_330K
Therefore we can search our memory dump for the rest of the stream (I searched for .mp4), and we find:
Code:
Sky_TV_Prod_CP/730/425/OM005215_300.mp4
This is looking more like it! Now we have the two hard parts of our job left to do. The first is to construct a full RTMP URL and test it, which we can do with
RTMPDump. To create our RTMPDump command, we need to know the SWF player that is being used, as the RTMP streaming server expects a file size and hash of this player to ensure we're not using a third party player (and RTMPDump is clever enough to download this SWF file and then pretend to be the official player by reporting its file size and hash). So, we can now save our page from Chrome and open the base HTML file and all other interesting associated files (JS, HTML, AXD) and search for a reference to our flash player. When we do this we find in player2.js:
Code:
var so = new SWFObject(publishing_path+"_pdk/swf/flvPlayer.swf", "playerwidget", "730", "424", "9.0.115.0", "#000000", "high", false, false, false, true);
I was lazy and looked back in the memory for this, rather than trying to find out what "publishing_path" was, and I found:
http://www.isky.co.nz/_pdk/swf/flvPlayer.swf
As an aside, I also found a link to an auth SWF file in the same JS file, but I'm not sure if we'll need to pay any attention to this when we come to scrape the site:
Code:
so.addVariable("plugin0", "type=plugin|URL="+publishing_path+"_pdk/swf/UserAuthPlugin.swf|token=" + user_token);
So now we should have enough info to try and construct a workable command for RTMPDump. I put this all together and tried to run:
Code:
rtmpdump -r "rtmpte://cdn.isky.co.nz/c1181/?vxttoken=00004D82521500000000283F238AFC39FD998309B96A6053D0AF5352EB87FCA71C91mp4:Sky_TV_Prod_CP/549/893/PKS00732_1200.mp4" -W "http://www.isky.co.nz/_pdk/swf/flvPlayer.swf" -o iSKY.mp4 -V
What we're doing here is basically telling RTMPDump the stream we want it to grab, the location of the player it should pretend to be, the output file we want to write the stream to and to please be verbose.
This didn't work, and I tried several variations which didn't work either. A typical output from RTMPDump is:
Code:
RTMPDump v2.3
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
ERROR: RTMP_HashSWF: couldn't contact swfurl http://www.isky.co.nz/_pdk/swf/flvPlayer.swf (HTTP error 302)
DEBUG: Protocol : RTMPTE
DEBUG: Hostname : cdn.isky.co.nz
DEBUG: Port : 80
DEBUG: Playpath : mp4:Sky_TV_Prod_CP/549/893/PKS00732_1200.mp4
DEBUG: tcUrl : rtmpte://cdn.isky.co.nz:80/c1181/?vxttoken=00004D82521500000000283F238AFC39FD998309B96A6053D0AF5352EB87FCA71C91,00004D82521500000000283F238AF55168F1D438F2F67AE2FDD2E4770748BAB88BA4,00004D82521500000000283F238A718A0C91F962C22369ACBA79CF6A2BFA5030045B
DEBUG: swfUrl : http://www.isky.co.nz/_pdk/swf/flvPlayer.swf
DEBUG: app : c1181/?vxttoken=00004D82521500000000283F238AFC39FD998309B96A6053D0AF5352EB87FCA71C91,00004D82521500000000283F238AF55168F1D438F2F67AE2FDD2E4770748BAB88BA4,00004D82521500000000283F238A718A0C91F962C22369ACBA79CF6A2BFA5030045B
DEBUG: live : no
DEBUG: timeout : 30 sec
DEBUG: Setting buffer time to: 36000000ms
Connecting ...
DEBUG: RTMP_Connect1, ... connected, handshaking
DEBUG: HandShake: Client type: 06
DEBUG: HandShake: DH pubkey position: 166
DEBUG: HandShake: Client digest offset: 879
DEBUG: HandShake: Initial client digest:
DEBUG: 1f 4a 70 7a a4 6c 96 35 a6 18 e1 52 ad bf e7 c5
DEBUG: be e8 e1 be 29 56 af 37 8f 4d f7 3c 42 ef 70 79
DEBUG: HandShake: Type Answer : 06
DEBUG: HandShake: Server Uptime : 1640707746
DEBUG: HandShake: FMS Version : 3.5.4.1
DEBUG: HandShake: Server DH public key offset: 108
DEBUG: HandShake: Secret key:
DEBUG: f5 90 1a 89 af c4 07 b5 fc c6 5e 88 f9 7d fd 00
DEBUG: ed 76 f9 9d 19 fe c2 61 12 6e 70 9e 86 63 dd 22
DEBUG: c9 4a b5 45 e2 13 89 18 2a a8 27 7a 4f 97 59 b5
DEBUG: f5 99 36 06 f3 a9 75 b2 e7 c5 3f c1 0f 7b 51 dd
DEBUG: b4 03 7b c0 01 58 81 ae 88 cf 0b c6 fc 97 ec ef
DEBUG: 4e 13 23 6f f0 55 d5 36 fa 9b 9e 2f 01 80 88 08
DEBUG: 6b 51 18 54 d9 1f 93 05 33 26 0e 1a d7 29 65 b3
DEBUG: 4a a8 61 b4 25 59 51 ce 89 79 a6 ac 24 62 b6 19
DEBUG: RC4 Out Key:
DEBUG: 0d 64 d7 b4 0c 97 90 d6 38 f8 1d 5a 10 98 ef 90
DEBUG: RC4 In Key:
DEBUG: b3 f3 b0 54 07 cc fa f5 86 dc 5d 44 bc 94 db 4e
DEBUG: HandShake: Calculated digest key from secure key and server digest:
DEBUG: 80 ce 46 fa b3 c4 d8 e3 10 7c f4 09 93 71 73 06
DEBUG: 1a 37 a8 7e 9f 04 97 34 b1 fb d3 1e bb 62 16 98
DEBUG: HandShake: Client signature calculated:
DEBUG: d2 39 57 b4 a1 08 52 ce da 41 da 4a 33 1c f2 8f
DEBUG: f5 13 46 b1 66 75 e0 8c 4f 29 31 4d a4 d6 25 0d
DEBUG: HandShake: Server sent signature:
DEBUG: 6b f6 94 b9 f3 15 d3 2c 4f 31 24 c5 15 36 51 ee
DEBUG: 33 82 a4 bf 22 5f 62 b6 9f 5f 50 30 26 e9 35 89
DEBUG: HandShake: Digest key:
DEBUG: 08 26 98 85 33 84 79 82 84 03 50 21 e7 29 ab 59
DEBUG: d8 88 f1 de 50 db 7e 90 5f e6 ea 9c 27 34 10 5c
DEBUG: HandShake: Signature calculated:
DEBUG: 6b f6 94 b9 f3 15 d3 2c 4f 31 24 c5 15 36 51 ee
DEBUG: 33 82 a4 bf 22 5f 62 b6 9f 5f 50 30 26 e9 35 89
DEBUG: HandShake: Genuine Adobe Flash Media Server
DEBUG: HandShake: Handshaking finished....
DEBUG: RTMP_Connect1, handshaked
DEBUG: Invoking connect
INFO: Connected...
DEBUG: HandleServerBW: server BW = 2500000
DEBUG: HandleClientBW: client BW = 2500000 2
DEBUG: HandleCtrl, received ctrl. type: 26, len: 3
DEBUG: HandleCtrl, SWFVerification ping received:
ERROR: HandleCtrl: Ignoring SWFVerification request, use --swfVfy!
DEBUG: RTMP_ClientPacket, received: invoke 242 bytes
DEBUG: (object begin)
DEBUG: (object begin)
DEBUG: Property: <Name: fmsVer, STRING: FMS/3,5,4,1011>
DEBUG: Property: <Name: capabilities, NUMBER: 127.00>
DEBUG: Property: <Name: mode, NUMBER: 1.00>
DEBUG: (object end)
DEBUG: (object begin)
DEBUG: Property: <Name: level, STRING: status>
DEBUG: Property: <Name: code, STRING: NetConnection.Connect.Success>
DEBUG: Property: <Name: description, STRING: Connection succeeded.>
DEBUG: Property: <Name: objectEncoding, NUMBER: 0.00>
DEBUG: Property: <Name: data, OBJECT>
DEBUG: (object begin)
DEBUG: Property: <Name: version, STRING: 3,5,4,1011>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <connect>
DEBUG: sending ctrl. type: 0x0003
DEBUG: Invoking createStream
DEBUG: RTMP_ClientPacket, received: invoke 29 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <createStream>
DEBUG: SendPlay, seekTime=0, stopTime=0, sending play: mp4:Sky_TV_Prod_CP/549/893/PKS00732_1200.mp4
DEBUG: Invoking play
DEBUG: sending ctrl. type: 0x0003
DEBUG: RTMP_ClientPacket, received: invoke 133 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object begin)
DEBUG: Property: <Name: level, STRING: error>
DEBUG: Property: <Name: code, STRING: NetStream.Failed>
DEBUG: Property: <Name: description, STRING: Failed to play (streamID: 1).>
DEBUG: Property: <Name: clientid, STRING: pa8Q2tmX>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onStatus>
DEBUG: HandleInvoke, onStatus: NetStream.Failed
ERROR: Closing connection: NetStream.Failed
DEBUG: Closing connection.
This is where I get stuck. If anyone can help get me past this hurdle, I'd be a very happy man! Once this is done, the only remaining step is to try and construct a valid URL from information in the HTML/JS files received when logging into the site and playing a video. This may not be easy either, but there's no point in me attempting it until I actually know what the URL needs to look like.