Monthly Archives: April 2008

Show videos on your site using PERL and Youtube API

This tutorial uses an old Youtube API, after google acquired Youtube a new API was released

In this brief tutorial i will show you how to show videos from youtube on you web page using PERL and Youtube API, the idea of the script is that it will show by default the favorites videos of some users, and you will be able to navigate to the tags you specify.

For this script we will use some libraries from the CPAN:

  • CGI we will use to get the data send by GET
  • Template toolkit This is an excellent template library
  • XML:DOM this library will help us to parse the XML file that is returned by youtube
  • LWP::UserAgent This is needed by XML:DOM to parse the files in remote locations
  • Unicode::String We will use this to convert data to UTF8

Click here to see this script in action.

Download the code

index.pl this is the perl script.

  1. #!/usr/bin/perl
  2.  
  3. use CGI;
  4. use Template;
  5. use XML::DOM;
  6. use LWP::UserAgent;
  7. use POSIX qw(strftime);
  8. use Unicode::String;
  9.  
  10. # you have to sign up to get a developer id
  11. my $devId = ‘developerid’;
  12. # we will show the favorites videos of this user as front page
  13. my $userFavorites = ‘someuser’;
  14. # this is an array of the tags we will allow to navigate throw
  15. my %tags = (
  16.         ‘tlaxcala’=>‘Tlaxcala’,
  17.         ‘huamantla’=>‘Huamantla’,
  18.         ‘huamantlada’=>‘Huamantlada’,
  19.         ‘feria huamantla’=>‘Feria Huamantla’,
  20.         ‘cacaxtla’=>‘Cacaxtla’,
  21.         ‘apizaco’=>‘Apizaco’,
  22.         ‘tlaxco’=>‘Tlaxco’,
  23.         ‘feria tlaxcala’=>‘Feria Tlaxcala’
  24. );
  25.  
  26. my $query = new CGI;
  27. my $action = $query->param(‘action’);
  28.  
  29. my @videos = ();
  30. my $total = 0;
  31. my $values = {};
  32. my $url;
  33. my $tt = Template->new;
  34.  
  35. print "Content-type: text/html;charset=UTF-8\n\n";
  36.  
  37. SWITCH:{
  38.         if( $action eq ‘view’ ) {
  39.                 $values{‘video’}=$query->param(‘video’);
  40.                 my @comments = ();
  41.                
  42.                 # here we start parsing the XML
  43.                 my $parser = XML::DOM::Parser->new();
  44.                 my $doc = $parser->parsefile(‘http://www.youtube.com/api2_rest?method=youtube.videos.get_details&dev_id=FIq6LWxC3RE&video_id=’ . $values{‘video’} );
  45.                 # we put this on eval to avoid errors
  46.                 eval{
  47.                         # here i add all the commets to an array
  48.                         foreach my $comment ($doc->getElementsByTagName(‘comment’)){
  49.                                 my @date = localtime( $comment->getElementsByTagName(‘time’)->item(0)->getFirstChild->getNodeValue );
  50.                                 push @comments, {
  51.                                         author=>Unicode::String::utf8($comment->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  52.                                         text=>Unicode::String::utf8($comment->getElementsByTagName(‘text’)->item(0)->getFirstChild->getNodeValue),
  53.                                         time=>strftime( ‘%r’, @date ),
  54.                                         date=>strftime( ‘%d-%m-%Y’, @date )
  55.                                 };
  56.                         }
  57.                        
  58.                         # here i format the video time
  59.                         my( $seconds,$hours,$minutes );
  60.                         $seconds = $doc->getElementsByTagName(‘length_seconds’)->item(0)->getFirstChild->getNodeValue;
  61.                         ( $hours, $seconds ) = ( int( $seconds/3600 ), $seconds % 3600 );
  62.                         ( $minutes, $seconds ) = ( int( $seconds/60 ), $seconds % 60 );
  63.                        
  64.                         # here i create an array of the data i will use and show the page using template toolkit
  65.                         my %data = (
  66.                                 video=>$values{‘video’},
  67.                                 title=>Unicode::String::utf8($doc->getElementsByTagName(‘title’)->item(0)->getFirstChild->getNodeValue),
  68.                                 author=>Unicode::String::utf8($doc->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  69.                                 rating_avg=>$doc->getElementsByTagName(‘rating_avg’)->item(0)->getFirstChild->getNodeValue,
  70.                                 tags=>Unicode::String::utf8($doc->getElementsByTagName(‘tags’)->item(0)->getFirstChild->getNodeValue),
  71.                                 description=>Unicode::String::utf8($doc->getElementsByTagName(‘description’)->item(0)->getFirstChild->getNodeValue),
  72.                                 time=>sprintf( ‘%02s:%02s:%02s’, $hours,$minutes, $seconds),
  73.                                 comments=>\@comments
  74.                         );
  75.                                
  76.                         $tt->process( ‘videos_view.tt’, \%data ) || die $tt->error;
  77.                 };
  78.                 last SWITCH;
  79.         }
  80.  
  81.         $values{‘page’}=$query->param(‘page’);
  82.         $values{‘tag’}=$query->param(‘tag’);
  83.  
  84.         if( $values{‘tag’} eq ) {
  85.                 # i show the favorites of the user
  86.                 $url=‘http://www.youtube.com/api2_rest?method=youtube.users.list_favorite_videos&dev_id=FIq6LWxC3RE&user=’ . $userFavorites;
  87.         } else {
  88.                 $values{‘page’}=‘1’ if( $values{‘page’} eq );
  89.                 # here i get videos by tab
  90.                 $url=‘http://www.youtube.com/api2_rest?method=youtube.videos.list_by_tag&dev_id=FIq6LWxC3RE&tag=’ . $values{‘tag’} . ‘&page=’ . $values{‘page’} . ‘&per_page=20’;
  91.                 # since the api dosent support paging, i see if the next xml has data, to show next link
  92.                 $nextXML=‘http://www.youtube.com/api2_rest?method=youtube.videos.list_by_tag&dev_id=FIq6LWxC3RE&tag=’ . $values{‘tag’} . ‘&page=’ . ( $values{‘page’} + 1 ) . ‘&per_page=20’;
  93.         }
  94.         my $parser = XML::DOM::Parser->new();
  95.         # we put this on eval to avoid errors
  96.         eval {
  97.                 my $doc = $parser->parsefile($url);
  98.                
  99.                 # here i create an array with the info for videos
  100.                 foreach $video ($doc->getElementsByTagName(‘video’)){
  101.                         push @videos, {
  102.                                 ‘author’=>Unicode::String::utf8($video->getElementsByTagName(‘author’)->item(0)->getFirstChild->getNodeValue),
  103.                                 ‘id’=>$video->getElementsByTagName(‘id’)->item(0)->getFirstChild->getNodeValue,
  104.                                 ‘title’=>Unicode::String::utf8($video->getElementsByTagName(‘title’)->item(0)->getFirstChild->getNodeValue),
  105.                                 ‘length_seconds’=>$video->getElementsByTagName(‘length_seconds’)->item(0)->getFirstChild->getNodeValue,
  106.                                 ‘rating_avg’=>$video->getElementsByTagName(‘rating_avg’)->item(0)->getFirstChild->getNodeValue,
  107.                                 ‘rating_count’=>$video->getElementsByTagName(‘rating_count’)->item(0)->getFirstChild->getNodeValue,
  108.                                 ‘description’=>Unicode::String::utf8($video->getElementsByTagName(‘description’)->item(0)->getFirstChild->getNodeValue),
  109.                                 ‘view_count’=>$video->getElementsByTagName(‘view_count’)->item(0)->getFirstChild->getNodeValue,
  110.                                 ‘upload_time’=>$video->getElementsByTagName(‘upload_time’)->item(0)->getFirstChild->getNodeValue,
  111.                                 ‘comment_count’=>$video->getElementsByTagName(‘comment_count’)->item(0)->getFirstChild->getNodeValue,
  112.                                 ‘tags’=>Unicode::String::utf8($video->getElementsByTagName(‘tags’)->item(0)->getFirstChild->getNodeValue),
  113.                                 ‘url’=>$video->getElementsByTagName(‘url’)->item(0)->getFirstChild->getNodeValue,
  114.                                 ‘thumbnail_url’=>$video->getElementsByTagName(‘thumbnail_url’)->item(0)->getFirstChild->getNodeValue
  115.                         };
  116.                 }
  117.                 if( defined( $nextXML ) ){
  118.                         my $doc2 = $parser->parsefile($nextXML);
  119.                         $total = @{ $doc2->getElementsByTagName(‘video’) };
  120.                 }
  121.                
  122.         };
  123.         my %data = (
  124.                 total=>$total,
  125.                 tag=>$values{‘tag’},
  126.                 tags=>\%tags,
  127.                 videos=>\@videos,
  128.                 page=>$values{‘page’}
  129.         );
  130.         # i show the page using template toolkit
  131.         $tt->process( ‘videos_list.tt’, \%data ) || die $tt->error;
  132.  
  133. }
  134.  

videos_list.tt The template where we see the list of videos.

  1.  
  2. <ul id="videosList">
  3. [% FOREACH videos %]
  4.   <a href="index.pl?action=view&amp;video=[% id %]"><img src="[% thumbnail_url %]" /></a>
  5.   <h2><a href="index.pl?action=view&amp;video=[% id %]">[% title %]</a></h2>
  6.   <p>[% description %]</p>
  7.  </li>
  8. [% END %]
  9. </ul>
  10.  
  11.  
  12. <div align="center">
  13.  [% IF tag || ( page>1 && total>0 ) %]
  14.  [% IF ( page > 1 ) %]
  15.   <a href="index.pl?tag=[% tag %]&amp;page=[% (page – 1) %]" alt="Previous" title="Previous">Previous</a>
  16.   [% END %]
  17.   [% IF total>0 %]
  18.    <a href="index.pl?tag=[% tag %]&amp;page=[% (page + 1) %]" alt="Next" title=‘Next’>Next</a>
  19.   [% END %]
  20.  
  21.  
  22.  
  23.  [% END %]
  24.  
  25.  [% IF tag == ” %]Favorites[% ELSE %]<a href="index.pl">Favorites</a>[% END %]
  26.  [% FOREACH key = tags.keys %]
  27.   || [% IF tag == key %][% tags.$key %][% ELSE %]<a href="index.pl?tag=[% key %]">[% tags.$key %]</a>[% END %]
  28.  [% END %]
  29. </div>
  30.  

videos_view.tt The template where we see a specific video.

  1.  
  2. <h1>[% title %]</h1>
  3.  
  4. <div align="center">
  5. <object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/[% video %]"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/[% video %]" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></object>
  6. </div>
  7.  
  8. <strong>Author:</strong> <a href="http://www.youtube.com/user/[% author %]" target="_blank">[% author %]</a>
  9.  
  10. <strong>Rating:</strong> [% rating_avg %]
  11.  
  12. <strong>Tags:</strong> [% tags %]
  13.  
  14. <strong>Time:</strong> [% time %]
  15.  
  16. [% description %]
  17. </p>
  18.  
  19. [% IF comments.size > 0 %]
  20.  <h2>Comments</h2>
  21.   [% FOREACH comment=comments %]
  22.    <div class=‘textoComentarios’>[% comment.text %]</div>
  23.  
  24.    <div class=‘pieComentarios’>
  25.    | By <a href=‘http://www.youtube.com/user/[% comentario.author %]’>[% comment.author %]</a> | [% comment.date %] | [% comment.time %] |
  26.  
  27.  
  28.   </div>
  29.  [% END %]
  30. [% END %]
  31.