Programmatically Uploading Videos to YouTube
March 21st, 2008 Posted in Software Development
YouTube recently updated their API with some new features. YouTube is now using the GoogleData API instead of a proprietary API. One of the new features is the ability to upload videos via the API. This means that web sites and client applications now have the ability to upload videos directly to YouTube.
I’ve been playing around with the YouTube API upload feature and have a quick and dirty little C# class library that can upload videos straight to YouTube via the API.
Before you can upload a video you have to get an authorization code using your YouTube username and password. The code is then used in the call that actually uploads the video.
The Authorize method of the YouTube library performs the authentication.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public bool Authorize(string username, string password) { bool result = false; this.username = username; this.password = password; using (WebClient client = new WebClient()) { // Send the requeset with username and password client.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); string response = client.UploadString( "https://www.google.com/youtube/accounts/ClientLogin", string.Format("Email={0}&Passwd={1}&service=youtube&source=TrailsintheSand.YouTube.Library", username, password)); // The response is plain text containing: // Auth=<authorization code> string[] split = response.Split('\n'); foreach (string s in split) { string[] nvsplit = s.Split('='); if (nvsplit.Length == 2) { if (nvsplit[0] == "Auth") { authCode = nvsplit[1]; result = true; } } } } return result; } |
This simple method uses the WebClient class. WebClient is the simplest way to perform an HTTP request in .NET. The UploadString method of the WebClient class is used because we need to POST the username and password to the server. The response that comes back contains the string “Auth=
The Upload method is passed several parameters including the title of the video, a description of the video, the video’s category, a list of keywords and the path to the video on the local hard drive.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public bool Upload(string title, string description, Catagory catagory, string keywords, string videoFileName, out string error) { bool result = false; error = null; // Build byte arrays for the header file and footer byte[] header = Encoding.UTF8.GetBytes(GetHeader(title, description, catagory, keywords, videoFileName)); byte[] file = File.ReadAllBytes(videoFileName); byte[] footer = Encoding.UTF8.GetBytes(lineTerm + boundary + "--"); // Combine the byte arrays into one big byte array byte[] data = new byte[header.Length + file.Length + footer.Length]; Array.Copy(header, 0, data, 0, header.Length); Array.Copy(file, 0, data, header.Length, file.Length); Array.Copy(footer, 0, data, header.Length + file.Length, footer.Length); // Using a HttpWebRequest here because it allows us to control the timeout HttpWebRequest req = (HttpWebRequest)WebRequest .Create(string.Format("http://uploads.gdata.youtube.com/feeds/api/users/{0}/uploads", username)); req.Method = "POST"; req.ContentType = string.Format("multipart/related; boundary={0};", boundaryheader); req.ContentLength = data.Length; req.Timeout = timeout; req.Headers.Add("Authorization", "GoogleLogin auth=" + authCode); req.Headers.Add("X-GData-Client", clientCode); // supposed to be optional req.Headers.Add("X-GData-Key", devCode); req.Headers.Add("Slug", Path.GetFileName(videoFileName)); using (Stream postStream = req.GetRequestStream()) { // Send the data to the server postStream.WriteTimeout = timeout; postStream.Write(data, 0, data.Length); postStream.Close(); try { // Get the response back from the server WebResponse webResponse = req.GetResponse(); using (Stream responseStream = webResponse.GetResponseStream()) { using (StreamReader reader = new StreamReader(responseStream)) { // Should check the response here reader.Close(); result = true; } responseStream.Close(); } webResponse.Close(); } catch (WebException ex) { // Got a bad response using (StreamReader sr = new StreamReader(ex.Response.GetResponseStream())) { error = sr.ReadToEnd(); } } } return result; } |
Upload builds the content of the HTTP POST. The content is of type multipart/related meaning there will be more than one part and the parts are related. In the case of a YouTube video upload there are two parts. The first part contains an XML document describing the video. It contains the title, description, category, keywords and file name. The Upload method calls the GetHeader method to get a string that contains both the HTTP headers for the parts of the content and the XML data for the video.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private string GetHeader(string title, string description, Catagory catagory, string keywords, string videoFileName) { StringBuilder xml = new StringBuilder(); xml.Append(boundary + lineTerm + "Content-Type: application/atom+xml; charset=UTF-8" + lineTerm + lineTerm); xml.Append("<?xml version=\"1.0\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" "); xml.Append("xmlns:media=\"http://search.yahoo.com/mrss/\" xmlns:yt=\"http://gdata.youtube.com/schemas/2007\">"); xml.AppendFormat("<media:group><media:title type=\"plain\">{0}</media:title>", title); xml.AppendFormat("<media:description type=\"plain\">{0}</media:description>", description); xml.AppendFormat("<media:category scheme=\"http://gdata.youtube.com/schemas/2007/categories.cat\">{0}</media:category>", catagory); xml.AppendFormat("<media:keywords>{0}</media:keywords>", keywords); xml.Append("</media:group></entry>" + lineTerm); xml.Append(boundary + lineTerm + "Content-Type: video/*" + lineTerm + "Content-Transfer-Encoding: binary" + lineTerm + lineTerm); return xml.ToString(); } |
GetHeader simply uses a StringBuilder to build the header data containing the XML. It would probably be better to use an XmlWriter or XmlDocument to build the XML part of this data.
The Upload method then builds a byte array containing the entire content of the POST which includes the raw data for the video to be uploaded. The File.ReadAllBytes method is used to load the video into a byte array.
The HttpWebRequest class is used to POST the video to YouTube. This class is used instead of the simple WebClient because we need to be able to set the timeout for the POST. Since video files can be very large it may take longer than the default timeout for a WebClient request and the WebClient timeout cannot be changed.
Here is an example of using the class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Trails.YouTube youTube = new Trails.YouTube(); Console.WriteLine("Authorizing..."); if(youTube.Authorize("youtube username", "youtube password")) { Console.WriteLine("Authorized"); Console.WriteLine("Uploading..."); string error; if (youTube.Upload("Test Video", "This is a test", YouTube.Catagory.Howto, "test", @"c:\test.mp4", out error)) { Console.WriteLine("Upload complete"); } else { Console.WriteLine("Upload failed: {0}", error); } } else { Console.WriteLine("Authorization failed"); } |
Using the GoogleData API requires you to have a developer key. Go to the Google YouTube API web page to request a developer key. The library contains two constants named clientCode and devCode. Set devCode to the developer key you got from Google. You will also get a Client ID with your developer key. Set the clientCode constant to the client ID you received.
As you can see it is very easy to upload a video to YouTube from your application. The class has some room for improvement but serves as an example of how to upload videos directly to YouTube. For instance, the Upload method is not checking the response after an upload. A successful upload will return a list of uploaded videos for the YouTube account being used.
Here is the Visual Studio 2005 project with all of the source code.
Trails in the Sand YouTube Library
Enjoy!

Related Articles:

[…] speaks the GData XML format and querying YouTube with C# is fairly simple from there. You can even upload videos programmatically to YouTube like this […]
[…] speaks the GData XML format and querying YouTube with C# is fairly simple from there. You can even upload videos programmatically to YouTube like this […]
I plan on playing around with this code this weekend.
There’s one thing I wanted to let you know though. Catagory is misspelled. It should be Category (with an ‘e’).
Cheers.
i use your helping code but where i can get YouTube.Catagory
hi i used your code but it threw exceptiom
403
help me ASAP i m not sure video is upload or not
Video uploads succesfully, but there is any way to know the url of the uploaded video, or the code generated? i.e:
http://www.youtube.com/watch?v=aOfeI3gmNGw
aOfeI3gmNGw <—– that thing
Thank you very much
well, finally i can know, in the webresponse header is the generated code
thanks anyway