YouTube API Feed Reader: Source Code

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    YouTube API Feed Reader: Source Code

    One of the users of our RSS Feed Reader code was trying to adapt the code there to work with YouTube XML data returned through the api2_rest method youtube.videos.list_by_tag. He was having some trouble so I've adapted the code to create a new PHP class that produces a decent rendering of a list of video feeds including thumbnails and other details. Enjoy.

    1. Embedding a YouTube API Feed as HTML
    the calling method has been kept extremely simple:
    Code:
      include "class.myyoutubeparser.php";
    
      # where is the feed located?
      $url = "http://gdata.youtube.com/feeds/api/videos?q=skateboarding+dog&start-index=21&max-results=10&v=2";
    
      # create object to hold data and display output
      $parser = new myYouTubeParser($url);
    
      $output = $parser->getOutput(); # returns string containing HTML
      echo $output;
    ?>
    If you want to do more than just simple searches you will need to apply for a Developer ID key before you can access the YouTube API. To do that, register as a YouTube user and then complete a second application form under Account Settings > Developer Profile.

    Please Note: before embedding any third-party video content content on your website you should check that you're not violating the YouTube Terms of Service or infringing on anyone's copyright.

    2. Source code of class.myyoutubeparser.php

    This class is by no means the be-all and end-all of YouTube XML parsing. It's designed to be simple, functional and easily customisable. Please let me know using the Feedback link below if you have any problems or suggestions.

    File: class.myyoutubeparser.php
    Code:
    <?PHP
      # Original PHP code by Chirp Internet: www.chirp.com.au
      # Please acknowledge use of this code by including this header.
    
      class myYouTubeParser
      {
        # keeps track of current and preceding elements
        var $tags = array();
    
        # array containing all feed data
        var $output = array();
    
        # return value for display functions
        var $retval = "";
    
        # constructor for new object
        function myYouTubeParser($file)
        {
          # instantiate xml-parser and assign event handlers
          $xml_parser = xml_parser_create("");
          xml_set_object($xml_parser, $this);
          xml_set_element_handler($xml_parser, "startElement", "endElement");
          xml_set_character_data_handler($xml_parser, "parseData");
    
          # open file for reading and send data to xml-parser
          $fp = @fopen($file, "r") or die("myYouTubeParser: Could not open $file for input");
          while($data = fread($fp, 4096)) {
            xml_parse($xml_parser, $data, feof($fp)) or die(
              sprintf("myYouTubeParser: Error <b>%s</b> at line <b>%d</b><br>",
              xml_error_string(xml_get_error_code($xml_parser)),
              xml_get_current_line_number($xml_parser))
            );
          }
          fclose($fp);
    
          # dismiss xml parser
          xml_parser_free($xml_parser);
        }
    
        function startElement($parser, $tagname, $attrs=array())
        {
          # capture LINK href where rel='alternate'
          if(($tagname == "LINK") && $attrs['HREF'] && $attrs['REL'] && $attrs['REL'] == 'alternate') {
            $this->startElement($parser, 'LINK', array()); 
            $this->parseData($parser, $attrs['HREF']);
            $this->endElement($parser, 'LINK');
          }
    
          # capture HQ image URL
          if($attrs['URL'] && $attrs['HEIGHT'] && $attrs['WIDTH'] && !$attrs['TIME']) {
            $this->startElement($parser, 'MEDIA:THUMBNAIL', array()); 
            $this->parseData($parser, $attrs['URL']);
            $this->endElement($parser, 'MEDIA:THUMBNAIL');
          }
    
          # capture duration
          if($tagname == 'YT:DURATION') {
            $this->startElement($parser, 'DURATION', array());
            $this->parseData($parser, $attrs['SECONDS']);
            $this->endElement($parser, 'DURATION');
          }
    
          # capture rating details
          if($tagname == 'GD:RATING') {
            $this->startElement($parser, 'RATING', array());
            $this->parseData($parser, $attrs['AVERAGE']);
            $this->endElement($parser, 'RATING');
    
            $this->startElement($parser, 'NUMRATERS', array());
            $this->parseData($parser, $attrs['NUMRATERS']);
            $this->endElement($parser, 'NUMRATERS');
          }
    
          # capture statistics
          if($tagname == 'YT:STATISTICS') {
            $this->startElement($parser, 'FAVORITECOUNT', array());
            $this->parseData($parser, $attrs['FAVORITECOUNT']);
            $this->endElement($parser, 'FAVORITECOUNT');
    
            $this->startElement($parser, 'VIEWCOUNT', array());
            $this->parseData($parser, $attrs['VIEWCOUNT']);
            $this->endElement($parser, 'VIEWCOUNT');
          }
    
          # check if this element can contain others - list may be edited
          if(preg_match("/^(FEED|ENTRY)$/", $tagname)) {
            if($this->tags) {
              $depth = count($this->tags);
              if(is_array($tmp = end($this->tags))) {
                list($parent, $num) = each($tmp);
                if($parent) $this->tags[$depth-1][$parent][$tagname]++;
              }
            }
            array_push($this->tags, array($tagname => array()));
          } else {
            # add tag to tags array
            array_push($this->tags, $tagname);
          }
        }
    
        function endElement($parser, $tagname)
        {
          # remove tag from tags array
          array_pop($this->tags);
        }
    
        function parseData($parser, $data)
        {
          # return if data contains no text
          if(!trim($data)) return;
          $evalcode = "\$this->output";
          foreach($this->tags as $tag) {
            if(is_array($tag)) {
              list($tagname, $indexes) = each($tag);
              $evalcode .= "[\"$tagname\"]";
              if(${$tagname}) $evalcode .= "[" . (${$tagname} - 1) . "]";
              if($indexes) extract($indexes);
            } else {
              if(preg_match("/^([A-Z]+):([A-Z]+)$/", $tag, $matches)) {
                $evalcode .= "[\"$matches[1]\"][\"$matches[2]\"]";
              } else {
                $evalcode .= "[\"$tag\"]";
              }
            }
          }
          eval("$evalcode = $evalcode . '" . addslashes($data) . "';");
        }
    
        # display channel as HTML
        function display_channel($data)
        {
          extract($data);
          $this->retval .= "<h2>" . htmlspecialchars($TITLE) . "</h2>\n";
          if($SUBTITLE) $this->retval .= "<p>" . htmlspecialchars($SUBTITLE) . "</p>\n";
          if($ENTRY) {
            $this->retval .= "<table border=\"0\" cellpadding=\"5\" cellspacing=\"0\">\n";
            foreach($ENTRY as $item) $this->display_item($item, "VIDEO_LIST");
            $this->retval .= "</table>\n\n";
          }
        }
    
        # display a single video as HTML
        function display_item($data, $parent)
        {
          extract($data);
          if(!$TITLE) return;
          $this->retval .= "<tr style=\"vertical-align: top;\">\n";
          $this->retval .= "<td style=\"text-align: center;\">";
          if($THUMBNAIL_URL = $MEDIA['GROUP']['MEDIA']['THUMBNAIL']) {
            $this->retval .= "<p>";
            if($LINK) $this->retval .=  "<a href=\"$LINK\" target=\"_blank\">";
            $this->retval .= "<img src=\"$THUMBNAIL_URL\" border=\"0\" width=\"120\" alt=\"\">";
            if($LINK) $this->retval .= "</a>";
            if($DURATION = $MEDIA['GROUP']['DURATION']) {
              $this->retval .= "<p><small><b>Duration:</b> " . sprintf("%02.2d:%02.2d", floor($DURATION/60), $DURATION%60) . "</small></p>";
            }
            $this->retval .= "</p>";
          }
          $this->retval .= "</td>\n";
          $this->retval .= "<td>";
          $this->retval .=  "<h3>";
          if($LINK) $this->retval .=  "<a href=\"$LINK\" target=\"_blank\">";
          $this->retval .= stripslashes($TITLE);
          if($LINK) $this->retval .= "</a>";
          if($AUTHOR) $this->retval .= " <small style=\"white-space: nowrap;\">by <a href=\"http://www.youtube.com/user/{$AUTHOR['NAME']}\">{$AUTHOR['NAME']}</a></small>";
          $this->retval .=  "</h3>";
          if($SUMMARY) {
            $this->retval .= "<p>" . nl2br(htmlspecialchars(stripslashes($SUMMARY))) . "</p>\n";
          } elseif($DESCRIPTION = $MEDIA['GROUP']['MEDIA']['DESCRIPTION']) {
            $this->retval .= "<p>" . nl2br(htmlspecialchars(stripslashes($DESCRIPTION))) . "</p>\n";
          }
          $tmp = array();
          if($PUBLISHED) {
            $tmp[] = "<b>Added:</b> " . date('j F Y', strtotime($PUBLISHED));
          } elseif($UPLOAD_TIME = $MEDIA['GROUP']['YT']['UPLOADED']) {
            $tmp[] = "<b>Added:</b> " . date('j F Y', strtotime($UPLOAD_TIME));
          }
          if($RATING && $NUMRATERS) $tmp[] = "<b>Rating:</b> " . number_format($RATING, 2) . " (" . number_format($NUMRATERS) . " ratings)";
          if($VIEWCOUNT) $tmp[] = "<b>Views:</b> " . number_format($VIEWCOUNT);
          if($FAVORITECOUNT) $tmp[] = "<b>Favorite:</b> " . number_format($FAVORITECOUNT);
          $this->retval .= "<p><small>";
          $this->retval .= implode("; ", $tmp);
          if(($TAGS = $MEDIA['GROUP']['MEDIA']['KEYWORDS']) && $TAGS = explode(' ', $TAGS)) {
            $this->retval .= "<br>\n<b>Tags:</b>";
            foreach($TAGS as $tmp) {
              $this->retval .= " <a href=\"http://www.youtube.com/results?search_query=$tmp&amp;search=tag\" target=\"_blank\">$tmp</a>";
            }
            $this->retval .= "</small></p>\n";
          }
          $this->retval .= "</td>\n</tr>\n";
        }
    
        function fixEncoding($input, $output_encoding)
        {
          if(!function_exists('mb_detect_encoding')) return $input;
    
          $encoding = mb_detect_encoding($input);
          switch($encoding)
          {
            case 'ASCII':
            case $output_encoding:
              return $input;
            case '':
              return mb_convert_encoding($input, $output_encoding);
            default:
              return mb_convert_encoding($input, $output_encoding, $encoding);
          }
        }
    
        # display entire feed as HTML
        function getOutput($output_encoding='UTF-8')
        {
          $this->retval = "";
          $start_tag = key($this->output);
    
          switch($start_tag)
          {
            case "FEED":
              # youtube xml format
              $this->display_channel($this->output[$start_tag]);
              break;
    
            default:
              die("Error: unrecognized start tag '$start_tag' in getOutput()");
          }
    
          return $this->fixEncoding($this->retval, $output_encoding);
        }
    
        # return raw data as array
        function getRawOutput($output_encoding='UTF-8')
        {
          return $this->fixEncoding($this->output, $output_encoding);
        }
      }
    ?>
    The parsing of the XML data into a PHP array is done by the myYouTubeParser class using the startElement, endElement and parseData functions. The remaining functions are used only for displaying the data or accessing it as an array.

    The output of this script is HTML code for a TABLE with video thumbnails in the left column and other information in the right, including: Title, Author, Description, Date Added, Rating and Tags.
    ________________
    Jacques
    jacques@gw-designs.co.za
    http://coding.biz.tm
    Come join and lets make it a place to learn all the noobies how to code
    __________________

    NEVER FORGET TO CLICK THE TANX BUTTON IF U LIKE WHAT IM SHARING OR HELPING WITH
Working...
X