To do this either as an iframe based app, or FBML driven profile tab isn't to difficult and doesn't require the Facebook API. I did leverage the Google .NET Client API though.
Here's the steps in overview:
- Identify the Channel name you want: ex FlightOfThConchords
- Build the URL for the YouTube call (reference)
- Make the request to YouTube
- Iterate the results into a data object you want to work with
- Iterate relevate sub objects off the return set from YouTube (MediaThumbnails and MediaContents in my case)
- Thrown the results to the page for turning into elements
- If doing an IFRAME app, then use the object tag, if doing FBML do FB:SWF (see previous post)
I'm using ASP.NET MVC so here's my solution:
First I enjoy light weight model objects - so I define my objects I'll pass around:
public class YouTubeVideosCollection : System.Collections.Generic.List<YouTubeVideo>
{
}
public class YouTubeVideo
{
public string Blob;
public string Title;
public string Status;
public string Content;
public System.Collections.Generic.List<YouTubeVideoThumbnail> ThumbNailList = new System.Collections.Generic.List<YouTubeVideoThumbnail>();
public System.Collections.Generic.List<YouTubeVideoMediaType> MediaList = new System.Collections.Generic.List<YouTubeVideoMediaType>();
}
public class YouTubeVideoMediaType
{
public string Url;
public string Format;
public string Duration;
}
public class YouTubeVideoThumbnail
{
public string Url;
public string Width;
public string Height;
}There's no logic or api in those so no special includes needed.
I then build out a provider class that will do the heavy lifting and return my YouTubeVideosCollection object. I head over to Google to register for an application id (app_key, app_name).
public static class YouTubeAppProvider
{
public static YouTubeVideosCollection RetrieveYouTubeChannelVideos() {
//I didn't implement paging yet, but this worker class is ready for it
//this default call requests the first 11 videos starting at index 1
return RetrieveYouTubeChannelVideos("1","11");
}
public static YouTubeVideosCollection RetrieveYouTubeChannelVideos(string indexStartAt, string maxResults)
{
//more info on query string params at: http://code.google.com/apis/youtube/2.0/developers_guide_protocol_api_query_parameters.html#qsp
//get app_id and app_key from google API Parter dashboard
Google.YouTube.YouTubeRequestSettings settings = new Google.YouTube.YouTubeRequestSettings("My App Name", app_id, app_key);
Google.YouTube.YouTubeRequest request = new Google.YouTube.YouTubeRequest(settings);
Uri youtubeChannel = new Uri("http://gdata.youtube.com/feeds/api/users/FlightOfThConchords/uploads?start-index=" + indexStartAt + "&max-results=" + maxResults);
Google.GData.Client.Feed<google.youtube.video> feed = request.Get<google.youtube.video>(youtubeChannel);
YouTubeVideosCollection vids = new YouTubeVideosCollection();
foreach (Google.YouTube.Video entry in feed.Entries)
{
YouTubeVideo vid = new YouTubeVideo();
vid.Title = entry.Title ;
vid.Content = entry.Content;
foreach (Google.GData.Extensions.MediaRss.MediaThumbnail thumb in entry.Thumbnails) {
YouTubeVideoThumbnail thumbnail = new YouTubeVideoThumbnail();
thumbnail.Url = thumb.Url;
thumbnail.Width = thumb.Width;
thumbnail.Height = thumb.Height;
vid.ThumbNailList.Add(thumbnail);
}
foreach (Google.GData.YouTube.MediaContent mediaContent in entry.Contents ) {
//formats: http://code.google.com/apis/youtube/2.0/reference.html#formatsp
//I only want the Format 5 - which is the embedable version
if (mediaContent.Format.Equals("5"))
{
YouTubeVideoMediaType media = new YouTubeVideoMediaType();
media.Duration = mediaContent.Duration;
media.Format = mediaContent.Format;
media.Url = mediaContent.Url;
vid.MediaList.Add(media);
}
}
vids.Add(vid);
}
return vids;
}
}
This class will need the following:
- Google.GData.Client
- Google.GData.Extensions.MediaRss
- Google.YouTube
You get these from the Google .NET Client API
In my controller I define a method to invoke the worker.
public ActionResult Channel()
{
ViewData.Model = SampleBox.Models.YouTubeAppProvider.RetrieveYouTubeChannelVideos();
return View();
}
Lastly I define the view, which is able to be strongly typed off the YouTubeVideosCollection we defined earlier. This first set of code will run in as an independent page (or within an IFRAME as a Facebook App).
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SampleBox.Models.YouTubeVideosCollection>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Channel
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Channel</h2>
<div class="videoCollection">
<ul>
<%
SampleBox.Models.YouTubeVideosCollection videos = ViewData.Model;
bool first = true;
string width = "425";
string height = "350";
foreach (SampleBox.Models.YouTubeVideo vid in videos)
{
if (first)
{%>
<li class="first">
<% } else { %>
<li>
<% } %>
<% foreach (SampleBox.Models.YouTubeVideoMediaType media in vid.MediaList)
{ %>
<%= vid.Title %><br />
<object width="<%=width%>" height="<%=height %>">
<embed src="<%= media.Url %>"
type="application/x-shockwave-flash" wmode="transparent"
width="<%=width %>" height="<%=height %>">
</embed>
</object>
<% } %>
</li>
<%
first = false;
width = "215";
height = "175";
} %>
</ul>
</div>
</asp:Content>This second example will work within the context of a facebook profile tab - note there is no master page to inherit from and no html/body tags, and the style has been defined inline intentionally.
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<SampleBox.Models.YouTubeVideosCollection>" %>
<h2>Channel</h2>
<style type="text/css">
.videoCollection ul
{
border-bottom: 1px #5C87B2 solid;
padding: 0 0 2px;
position: relative;
margin: 0;
width: inherit;
text-align: center;
}
.videoCollection ul li
{
list-style: none;
display:inline-block;
width: 340px;
height: 215px;
border: solid 1px black;
overflow: hidden;
position: static;
}
.videoCollection ul li.first
{
width: 690px;
height: 375px;
display: block;
clear: both;
vertical-align: middle;
}
.videoCollection {
width:690px;
border: solid 1px black;
}
</style>
<div class="videoCollection">
<ul>
<%
SampleBox.Models.YouTubeVideosCollection videos = ViewData.Model;
bool first = true;
string width = "425";
string height = "350";
foreach (SampleBox.Models.YouTubeVideo vid in videos)
{
if (first)
{%>
<li class="first">
<% } else { %>
<li>
<% } %>
<% foreach (SampleBox.Models.YouTubeVideoMediaType media in vid.MediaList)
{ %>
<%= vid.Title %><br />
<fb:swf
imgsrc="<%= vid.ThumbNailList[0].Url %>"
swfsrc="<%= media.Url %>"
height="<%=height%>"
width="<%=width%>"
/>
<% } %>
</li>
<%
first = false;
width = "215";
height = "175";
} %>
</ul>
</div>There's lots of refactoring and error handling yet to do, but this is a solid reference point to share - hope its useful for you.
1 comment:
Post a Comment