Fiddler Web Debugger

One of the tools I can't do without when I need to inspect http request/response messages in RAW/JSON/XML format is Fiddler 2.

 

http://www.fiddler2.com/fiddler2/

 

Not sure if others use it as well...

 

It inserts itself as a proxy between your pc and the web server allowing you to watch the traffic.

 

IC68965.gif

 

Another great feature is using it as a proxy for mobile devices so that you can examine their traffic to the target server as well. e.g. Enter the proxy setting on your wireless connection on your ipad and enable remote connections within fiddler and all http traffic from the ipad is now visible in the fiddler app on your pc (assuming they are both in the same subnet).

 

Hope it helps others as it has helped me.

 

That looks pretty handy.  I personally use Charles Proxy (and I know a couple of the other channel devs do as well) -- but it's not freeware.

Some more on Fiddler...which I find very useful and here’s why…

[Note 1: the following information is from my own investigation and may not be entirely correct but works in part for me – take from it what you need]

[Note 2: The example from TVNZ is geo-locked for NZ so try with a site from your region]

[Note 3: Before doing any of the following steps Start Fiddler]

1.       Take a content delivery network (CDN) such as Brightcove that is used by an on-demand provider such as http://www.tvnz.co.nz/ondemand to host an rtmpe stream.

Via Google Chrome we can browse to a show which resolves to the friendly URL e.g.  http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240

2.       Inspection of the HTTP Response to the page request above in Fiddler shows the following flash player object

http://images.tvnz.co.nz/brightcove/message/message.xml" name="localizedErrorXML"/>

http://tvnz.co.nz/the-carrie-diaries/ s1-ep11-video-5389240" name="linkBaseURL"/>

The key information here is:

swfURL = http://admin.brightcove.com/viewer/us20130328.1037/BrightcoveBootloader.swf

PlayerID = playerID=1029272630001

VideoPlayer = ref: 5389240

3.       Immediately following this we see the outbound AMF request (which we need to mirror in our own code):

http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001

And this request is very important to dissect so that we can extract the rtmpe information.

From Fiddler we can see the browser request content (Fiddler: RAW http request view) which contains the BrightCove class references requiring instantiation in our own code:

  • com.brightcove.experience.ViewerExperience
  • com.brightcove.experience.ContentOverride

Our URL Service needs to extract the rtmpe FLVFullLengthURL which will look something like this:

Video_URL: [u'rtmpe://cp133145.edgefcs.net/ondemand/', u'mp4:videos/963482467001/963482467001_2250946345001_5380974.mp4']

To do this we need to look closer at the http request http://c.brightcove.com/services/messagebroker/amf?playerId=1029272630001

Fiddler Hex http request view shows us the class properties above and most importantly the value population for each property. In our URL service code we can map this as follows:

class ContentOverride(object):

    def __init__ (self, videoPlayer=None):

        self.contentType = int(0)

        self.contentIds = None

        self.target = None

        self.contentId = None

        self.featuredRefId = None

        self.contentRefIds = None

        self.featuredId = float('nan')

        self.contentRefId = videoPlayer ## ‘5389240’’

class ViewerExperienceRequest(object):

    def __init__ (self, url=None, playerID=None, playerKey=None, video_obj=None):

        self.experienceId = int(playerID) ## 1029272630001

        self.playerKey = ''

        self.contentOverrides = []

        self.contentOverrides.append(video_obj) ## the ContentOverride object

        self.TTLToken = ''

        self.URL = url  ## http://tvnz.co.nz/the-carrie-diaries/s1-ep11-video-5389240

        self.deliveryType = ''

4.       Construct the URL Service code to extract the rtmpe including the above class definitions

#########################################################################################

def DoAmfRequest(url):

    Log('Get Data From:::: '+url)

    data = HTML.ElementFromURL(url).xpath('//object[@class="BrightcoveExperience "]')

    if len(data) == 0:

        Log('No data')

        return None

    else:

        data = data[0]

    playerID = data.xpath('./param[@name="playerID"]')[0].get('value')

    Log('PlayerID: '+playerID)

   

    videoPlayer = data.xpath('./param[@name="@videoPlayer"]')[0].get('value').strip('ref:')

    result = AmfRequest(url=url, playerID=playerID, playerKey=playerID, videoPlayer=videoPlayer)

   

    return result

#########################################################################################

def AmfRequest(url=None, playerID=None, playerKey=None, videoPlayer=None):

    endpoint = AMF_URL ## http://c.brightcove.com/services/messagebroker/amf

    if playerKey:

        endpoint += '?playerId=%s' % playerKey

    client = AMF.RemotingService(url=endpoint, user_agent='', amf_version=3)

    service = client.getService('com.brightcove.experience.ExperienceRuntimeFacade')

   

    AMF.RegisterClass(ContentOverride, 'com.brightcove.experience.ContentOverride')

    AMF.RegisterClass(ViewerExperienceRequest, 'com.brightcove.experience.ViewerExperienceRequest')

    video_obj = ContentOverride(videoPlayer)

    experience = ViewerExperienceRequest(url, playerID, playerKey, video_obj)

   

    try:

   

        result = service.getDataForExperience('', experience)

        Log(result.items())

        return result['programmedContent']['videoPlayer']['mediaDTO']

    except:

        Log('Exception in AMF Request')

        raise Ex.MediaGeoblocked

The request to the service returns the full metadata associated with the media in the result var

result = service.getDataForExperience('', experience)

From the result we can now grab the FLVFullLengthURL along with a number of other useful properties:

[u'rtmpe://cp133145.edgefcs.net/ondemand/', u'mp4:videos/963482467001/963482467001_2250946345001_5380974.mp4']

Now using the downloadable app rtmpDump.exe (http://rtmpdump.mplayerhq.hu/) we can confirm the stream by downloading the file and saving out as a flash player video (flv) which can be played using a video player such as VLC (http://www.videolan.org/vlc/download-windows.html)

Rtmpdump.exe -r "rtmpe://cp133145.edgefcs.net/ondemand/" -a "ondemand" -y "mp4:videos/963482467001/963482467001_2250946345001_5380974.mp4" -o myVideo.flv

5.  The final stage is to have Plex play the stream

This is actually the point in my current project which is not working yet but the theory is that the rtmpe is passed back in the callback from your plex playVideo method via RTMPVideoURL

IndirectResponse(VideoClipObject, key=RTMPVideoURL(url=player, clip=playpath, app='ondemand', swf_url=SWF_URL, args=[False, playpath]))

Enabling rtmp in the info.plist and serviceinfo.plist is essential with the following addition to both files:

       PlexFrameworkFlags

      

              UseRealRTMP

      

6.  Monitoring the logs

For the URL service I watch the log file:

%LocalAppData%\Plex Media Server\Logs\PMS Plugin Logs\ com.plexapp.system.log

2013-04-02 21:32:58,650 (1b60) :  DEBUG (context:198) - Checking for Real RTMP support...  Enabled:True  Platform:Chrome  Product:Web Client  Client:0.9.9.13  Server:0.9.7.19-3baac57

2013-04-02 21:32:58,651 (1b60) :  DEBUG (objectkit:754) - Using Real RTMP

2013-04-02 21:32:58,654 (1b60) :  DEBUG (runtime:106) - Sending packed state data (99 bytes)

2013-04-02 21:32:58,654 (1b60) :  DEBUG (runtime:896) - Response: [200] MediaContainer, 1270 bytes

… and this is where it all stops for me… the video doesn't play from the browser or the windows client for some reason :(

Ok...fixed...playing in clients now...I missed specifying the rtmp protocol

def MediaObjectsForURL(url):
    return [
      MediaObject(
        video_codec = VideoCodec.H264,
        audio_codec = AudioCodec.AAC,
        container = Container.MP4,
        protocol='rtmp',
        parts = [PartObject(key=Callback(PlayVideo, url = url))],
        audio_channels = 2,
        optimized_for_streaming = True
      )
    ]

HI, did you use this information as the basis of a tvnz plugin?  Wondering if things have changed now they've gone brightcove and/or released an ios app.

Yes, it was for tvnz.co.nz/ondemand where they are serving content from the Brightcove service.

I have one issue where the rtmp feed stops playing after 2 mins and I have to press play again. Not sure why this is happening.

I was wondering if you had solved the feed stopping issue please?  I'm using the TVNZ Bundle that Ian developed and the playback stops after about 90-120 seconds

Is there a full bundle for this that can be downloaded?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.