BBC iPlayer

From MythTV

Jump to: navigation, search

Outdated: The information on this page may no longer be relevant to the current version of MythTV.

This is out of date!! Go MythStreams



The BBC iPlayer was launched in early 2007, offering repeats of BBC programmes to download to UK net users who were running Windows XP.

On 13th December 2007 they launched a service offering flash video streaming versions of the shows.

Later that day... the first version of the BBC iPlayer integration scripts were made.

On 7th March 2008 the beeb went on to launch a version of the iPlayer site for iPhone users, which provides mp4 (h264) vids delivered over http.

On the 8th March 2008 a plugin was made to use these streams. Vid of it in action is here:

http://www.youtube.com/watch?v=Z7eVgPMTa0g


Contents

BBC iPlayer Details

The flash based iPlayer offers video in flv over RTMP (and possible RTMPT). This is a pain as there is no way in linux that I'm aware of to rip the video streams or play in any sensible application, so we are restricted to using a flash player to watch the vids. The flash player can be embedded into any doc with the following code:

<div id="vvq47659d10bc9f3" class="vvqbox vvqiPlayer" style="width: 512px; height: 323px;">
  <embed type="application/x-shockwave-flash"
         src="http://www.bbc.co.uk/iplayer/emp/flash/iplayer-external.swf"
         style="" id="emp" name="emp" bgcolor="#000000" quality="high" 
         allowfullscreen="true" wmode="transparent"
flashvars="config=http://www.bbc.co.uk/iplayer/emp/xml/config.xml&metafile=http://www.bbc.co.uk/iplayer/metafiles/episode/b0079t3d.xml&debug=false" 
         height="323" width="512">
</div>

The clip is defined by its metafile, b0079t3d.xml (in this case Dr. Who). There is now way to resize the standard flash browser, so for now well leave it in the standard BBC pages. That will meant that any integration is unlikely to break T&Cs or get blocked.

All videos have a unique id (PID), an XML file with some info, a thumbnail and description. Resolution is 522x288.

MythTV Integration

After a bit of playing I decided the best way to play the videos was to stream them from the browser. With Flash 9.0.115 the videos can be streamed in full screen. However, video quality is very stuttery when viewing content full screen on my Nvidia 9150 running at 720p.

The solution thus far is to start another X session with a lower resolution. Next firefox has to be launched to the correct page, and then the video played by clicking on the video and the fullscreen icon is pressed. To automate this I use xautomation.

At the moment the only way to exit to Myth is to kill the X session.

I am by no means saying this is the best way to do things, or that my scripts are any good, or that this won't make your PC melt and destroy your life. Its just a start, a few hours coding, nothing more.

Requirements

  • xautomation (available for most dists, provides xte which can send mouse and key presses to X)
  • firefox (Or any browser which supports the flash plugin)
  • flash player >= 9.0.115.0
  • php (i wrote the scripts in PHP, they started as a website and I couldn't be arsed starting again.)
  • fluxbox (not a requirement, but I use it. The BBC iPlayer full screen mode doesn't seem to work without a window manager.

All programs wil be available through apt in Debian and Ubuntu and emerge in Gentoo.

If you use fluxbox as your wm and firefox as your browser, and run X at 800x600 the scripts provided should work without any alterations. If you run a different resolution, web browser or WM then the mouse positions in my scripts will need to be changed for your own setup.

Methods

First setup an X display config to make a screen 800x600. Call it xorg.conf.bbciplayer

If you dont know how to do this, just cd /etc/X11 and copy your current xorg.conf to xorg.conf.bbciplayer, edit it and change the resolution, and save it. The lower resolution makes video playback much smoother for flash.

Next grab the script to start the display and launch the web browser:


echo playing > /tmp/bbciplayerstatus
curl $1 > /dev/null
X :1 -ac -config xorg.conf.small &
sleep 1
export DISPLAY=:1.0
/usr/bin/fbsetroot -solid black
fluxbox &
sleep 1
/usr/bin/firefox $1 &
sleep 1

export BBCNET="loading"

while [ "$BBCNET" != "" ]; do
  sleep 1
  export BBCNET=`netstat -t| grep bbc| grep -v CLOSE | grep -v TIME`
done

cat /usr/local/share/mythtv/firefoxfull | xte

I save mine to /usr/local/bin/bbciplayer.sh

The script starts X with the right config file, starts up a wondow manager (fluxbox), sets the background to be black then starts firefox with the URL. It uses netstat to tell when the webpage has fully loaded, before sending the commands to launch the player in full screen.

I also use curl to get the initial page, it means less hanging around in firefox with the page loading, as the OS will do and cache the DNS and other gubbins with the mythmenu on screen instead of a blank firefox page which looks naff.

Next grab the xte commands. If you don't use 800x600 and fluxbox you will need to customise these to move the mouse where it has to be and click.


mousemove 100 20
mouseclick 1
key f
sleep 1
mousemove 245 295
mouseclick 1
mousemove 300 330
mouseclick 1
mousemove 700 490
mouseclick 1
sleep 1
mouseclick 1
mousemove 9999 9999

Save that to /usr/local/share/mythtv/firefoxfull

Then add in the main menu option for the iPlayer:


   <button>
     <type>MOVIETIMES</type>
     <text>BBC iPlayer</text>
     <action>MENU iplayer.xml</action>
   </button>

Save that into /usr/local/share/mythtv/library.xml

Finally get this script:

<?php

$month = date("m");
$day = date("d");

$txslots = array();
$txslots[] = "evening";
$txslots[] = "afternoon";
$txslots[] = "morning";

$fhmenu = fopen("/usr/local/share/mythtv/iplayer.xml", 'w');
fwrite($fhmenu, "<mythmenu name=\"IPLAYER\">\r\n");

for($i = 0 ; $i < 8 ; $i ++)
{
  $date = strtotime("-$i days");
  
  $day = date("d", $date);
  $month = date("m", $date);
 
  $fh = fopen("/usr/local/share/mythtv/iplayer-day$i.xml", 'w');
  fwrite($fh, "<mythmenu name=\"IPLAYER$i\">\r\n");

  $title = date("l jS M", $date);
  $action = "MENU iplayer-day$i.xml";
  $menubutton = mythButton($title, $action);

  fwrite($fhmenu, $menubutton);
 
  foreach($txslots as $txslot)
  {
    $url = "http://www.bbc.co.uk/iplayer/last7days/?filter=txdate:$day-$month&filter=txslot:$txslot&scope=iplayerlast7days" ;
    
    $buttons = makeButtons($url);
    fwrite($fh,$buttons);
  }

  fwrite($fh, "</mythmenu>");
}

fwrite($fhmenu, "</mythmenu>");

fclose($fh);
fclose($fhmenu);

function makeButtons($url)
{
    $var = fread_url($url);
            
    preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+".
                    "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/", 
                    $var, &$matches);
        
    $matches = $matches[1];
    $list = array();

    $buttons = "" ;

    foreach($matches as $var)
    {    
        if(strpos($var, "pid") > 1)
        {
        #echo $var . "<br />";
        $start = strpos($var, "item/") + 5;
        $pid = substr($var, $start, 8);
        $pid = getIplayerMeta($pid);

        $action = "EXEC /usr/local/bin/bbciplayer.sh " . $pid['url'] ;

        if($pid) $buttons .= mythButton($pid['title'], $action);
        }
    }

    return $buttons ;
}



function mythButton($title, $action)
{
  $button = "<button>\r\n";
  $button .= "  <type>MOVIETIMES</type>\r\n";
  $button .= "  <text>$title</text>\r\n";
  $button .= "  <action>$action</action>\r\n";
  $button .= "</button>\r\n\r\n";
  return $button;
}



function getIplayerMeta($pid)
{
$doc = new DOMDocument();
#echo "http://www.bbc.co.uk/iplayer/metafiles/episode/$pid.xml" ;
$doc->load("http://www.bbc.co.uk/iplayer/metafiles/episode/$pid.xml");
  
$concepts = $doc->getElementsByTagName( "concept" );
$concept = $concepts->item(0) ;

if($concept == NULL) return false;

$pids = $concept->getElementsByTagName( "pid" );
$pid = $pids->item(0)->nodeValue;

$titles = $concept->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;

$subtitles = $concept->getElementsByTagName( "subtitle" );
$subtitle = $subtitles->item(0)->nodeValue;

$urls = $concept->getElementsByTagName( "url" );
$url = $urls->item(0)->nodeValue;

$thumbs = $concept->getElementsByTagName( "thumbnail" );
$thumburl = $thumbs->item(0)->getElementsByTagName( "url" )->item(0)->nodeValue;

$iplayer['title'] = $title;
$iplayer['pid'] = $pid ;
$iplayer['url'] = $url ;

return $iplayer ;
}



    function fread_url($url,$ref="")
    {
        if(function_exists("curl_init")){
            $ch = curl_init();
            $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; ".
                          "Windows NT 5.0)";
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
            curl_setopt( $ch, CURLOPT_HTTPGET, 1 );
            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
            curl_setopt( $ch, CURLOPT_URL, $url );
            curl_setopt( $ch, CURLOPT_REFERER, $ref );
            curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
            $html = curl_exec($ch);
            curl_close($ch);
        }
        else{
            $hfile = fopen($url,"r");
            if($hfile){
                while(!feof($hfile)){
                    $html.=fgets($hfile,1024);
                }
            }
        }
        return $html;
    }

?>

Edit the output path for the menu and save that to /usr/local/bin/bbciplayerexport.php

Try running it manually (php script.php) to make sure that it works. It won't output anything to screen, just to the menu file.

If it works, add it to cron to run daily. Or maybe a few times per day. For the love of profitable teddy bears don't set it to hammer the BBC's servers, they won't like it, and then they'll cut us off.

And that's it!

To kill off the iPlayer once it's working use this script:


#!/bin/bash

STATUS=`cat /tmp/bbciplayerstatus`;

if [ $STATUS = "playing" ]; then
  XID=`ps -ef | grep X\ \:1`
  kill ${XID:6:13}
  echo off > /tmp/bbciplayerstatus ;
fi

Save it to /usr/local/bin/killx1

To run that script execute from the remote control use irexec (comes with lirc, executes a command on remote keypress). My ~/.lircrc file looks like:


begin
        prog = irexec
        button = Back
        repeat = 3
        config = /usr/local/bin/killx1
end

Controlling iPlayer

Once the iPlayer has been launched we want to be able to control it, skip around, pause video.

Thus far I've just done the script for pausing/playing video:


STATUS=`cat /tmp/bbciplayerstatus`;
export DISPLAY=:1

if [ $STATUS = "playing" ]; then
  echo mousemove 20 570 | xte
  echo mouseclick 1 | xte
fi

Thanks

Thanks to the dude who did the Apple Trailers plugin, I stole your method of creating menus instead of a full blown plugin. Great way of adding extra features to myth without requiring C++ skills.

Also thanks to the BBC. The iPlayer service rocks, just now give us the video in a higher quality format and provide an API :D

To Do

  • Use all the info provided to add thumbnails, descriptions etc. This will probably require a full plugin to be written.
  • Create scripts for xte to jump 10%, 20% etc. through video when pressing 1,2 etc. on the remote. Do the same for pausing the video.


MP4 Streaming

On March 7th, a version of BBC iPlayer was launched for the iPhone and iPod Touch. This uses the built-in webbrowser of the software, but notably, also introduced MP4 streaming versions of shows. This streaming option has not been made available to non-iPhone users, but there files are there so there is potential for this plugin to be updated for the higher quality H.264 videos.

A plugin has been created using these streams, and will be released to the public shortly.

Personal tools