YouTube Google Data API

I am very active in the vlogging community at YouTube and Stickam. Vlogging is clearly the future of online communication and social networking sites. I have been particularly impressed by how effective vlogging is for forming genuine friendships and online community. I've always been an anti-social IT geek and I never appreciated the value of social networking sites until I found YouTube where you can see and hear the people you are communicating with. Many of the YouTube vloggers are addicted to video conferencing on the Stickam web site. I have witnessed many instances of vloggers collaborating with each other on video projects. It would be interesting if there were a social networking site for developers that used video to forge an effective online community for collaboration. I do have an account on ITtoolbox which is a professional networking site for IT geeks but it lacks any video sharing capabilities and therefore does not create a real sense of community.

I've invested a lot of time in learning video editing and motion graphics software. I plan to do some really innovative work to combine my programming experience with video production. With the Internet becoming a multimedia platform, there will be a need to combine data dynamically with video elements just as ASP.NET is used to dynamically combine data with HTML code as text.

After YouTube was bought by Google, they switched their developer's API to the Google Data API. The Google Data API has a client library for .NET but it does not include the YouTube GData service yet. This is not too much of a problem because you are just consuming a XML data feed. As usual, I had a great deal of difficulty finding the correct XPath for a particular XML node but I've found an excellent free tool to help with this problem. The Liquid XML Studio 2008 from Liquid Technologies is a free download that has a handy XPath Query Builder. It even generates the C# code you need to properly reference the target XML node. You can even generate the XSL which is really awesome!

YouTube is frequently deleting user accounts for vloggers because they upload videos containing copyrighted material or violate the terms of service. So I wanted to use the Google Data API to save my account information to my own database as a back up in case I lose my account. I've written a C# Windows application to save my video favorites into a SQL Server database table. I saw no reason to do this in ASP.NET but there is a lot of HTML in the video description that you may want to include in a web page. You can only retrieve 50 results at a time so it was necessary to determine how many requests to make, varying the start-index parameter.

private void btnBackUp_Click(object sender, EventArgs e)
        {
            
try
            {
                
Uri HttpSite = new Uri("http://gdata.youtube.com/feeds/users/robrobbins/favorites");
                
HttpWebRequest wreq = ((HttpWebRequest)WebRequest.Create(HttpSite));
                wreq.KeepAlive =
false;
                wreq.Timeout = 30000;
                
// Get the data as an HttpWebResponse object
                WebResponse resp = wreq.GetResponse();
                
StreamReader strReader = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8);
                
XmlTextReader tr = new XmlTextReader(strReader);
                
XmlDocument doc = new XmlDocument();
                doc.Load(tr);
                
XmlNodeList xnl = doc.GetElementsByTagName("openSearch:totalResults");
                rtbMessage.Text +=
"Count:" + xnl.Count.ToString() + "\r\n";
                
if (xnl.Count > 0)
                {
                    intLoopCount =
Convert.ToInt32(xnl[0].InnerText);
                    intLoopCount =
Convert.ToInt32(Math.Round(intLoopCount / 50.0));
                    rtbMessage.Text +=
"[" + xnl[0].InnerText + "]" + "\r\n";
                    rtbMessage.Text +=
"Loop Count: " + intLoopCount.ToString() + "\r\n";
                }
                resp.Close();
                wreq.Abort();

                
// request 50 results at a time
                int intStartIndex = 1;
                
for (int i = 0; i < intLoopCount; i++)
                {
                    RequestFavorites(intStartIndex, 50);
                    intStartIndex = intStartIndex + 50;
                }

            }
            
catch (Exception ex)
            {
                rtbMessage.Text += ex.Source +
" " + ex.Message + " " + ex.StackTrace;
            }
        }

        
private void RequestFavorites(int intStartIndex, int intMaxResults)
        {
            
Uri HttpSite = new Uri("http://gdata.youtube.com/feeds/users/robrobbins/favorites?start-index=" + intStartIndex.ToString() + "&max-results=" + intMaxResults.ToString());
            rtbMessage.Text += HttpSite.ToString() +
"\r\n";
            
HttpWebRequest wreq = ((HttpWebRequest)WebRequest.Create(HttpSite));
            wreq.KeepAlive =
false;
            wreq.Timeout = 30000;
            
// Get the data as an HttpWebResponse object
            WebResponse resp = wreq.GetResponse();
            
StreamReader strReader = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8);
            
XmlTextReader tr = new XmlTextReader(strReader);
            
XmlDocument doc = new XmlDocument();
            doc.Load(tr);
            
// Select XML nodes by namespace
            XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
            nsMgr.AddNamespace(
"tns", "http://www.w3.org/2005/Atom");
            
XmlNodeList xnlID = doc.SelectNodes("//tns:entry//tns:id", nsMgr);
            
XmlNodeList xnlAuthor = doc.SelectNodes("//tns:entry//tns:author//tns:name", nsMgr);
            
XmlNodeList xnlURI = doc.SelectNodes("//tns:entry//tns:author//tns:uri", nsMgr);
            
// Get XML nodes by tag name
            XmlNodeList xnlTitle = doc.GetElementsByTagName("media:title");
            
XmlNodeList xnlDescription = doc.GetElementsByTagName("media:description");
            
XmlNodeList xnlKeywords = doc.GetElementsByTagName("media:keywords");
            
XmlNodeList xnlDuration = doc.GetElementsByTagName("yt:duration");
            
XmlNodeList xnlCategory = doc.GetElementsByTagName("media:category");
            
XmlNodeList xnlViewCount = doc.GetElementsByTagName("yt:statistics");
            
XmlNodeList xnlRating = doc.GetElementsByTagName("gd:rating");
            
// declare database objects
            string strSQL = "";
            
string strCN = "Initial Catalog=YouTube; Data Source=ORPHEUS;uid=*****;pwd=****;Connect Timeout=120;Pooling=True";
            
SqlConnection objConnection = new SqlConnection(strCN);
            
SqlCommand objCommand = new SqlCommand();
            objConnection.Open();
            rtbMessage.Text +=
"xnlID Count: " + xnlID.Count.ToString() + "\r\n";
            
if (xnlID.Count > 0)
            {
                
for (int i = 0; i < xnlID.Count - 1; i++)
                {
                    strSQL =
"INSERT INTO Favorites (ID,Author,Uri,Title,Description,Keywords,Duration,Category,ViewCount,Rating) VALUES (" +
                        
"'" + xnlID[i].InnerText.Replace("'", "''") + "'," +
                        
"'" + xnlAuthor[i].InnerText.Replace("'", "''") + "'," +
                        
"'" + xnlURI[i].InnerText.Replace("'", "''") + "'," +
                        
"'" + xnlTitle[i].InnerText.Replace("'", "''") + "'," +
                        
"'" + xnlDescription[i].InnerText.Replace("'","''") + "'," +
                        
"'" + xnlKeywords[i].InnerText.Replace("'", "''") + "'," +
                        
"'" + xnlDuration[i].Attributes["seconds"].Value + "'," +
                        
"'" + xnlCategory[i].InnerText + "'," +
                        
"'" + xnlViewCount[i].Attributes["viewCount"].Value + "'," +
                        
"'" + xnlRating[i].Attributes["average"].Value + "');";
                    rtbMessage.Text += strSQL +
"\r\n";
                    objCommand.CommandText = strSQL;
                    objCommand.Connection = objConnection;
                    objCommand.ExecuteNonQuery();
                }
            }
            objConnection.Close();
            resp.Close();
            wreq.Abort();
        }
    }

No Comments