Youtube Metadata Backup (C# .NET 2012)

Ever needed to backup your Youtube channel’s videos’ titles, descriptions and tags? Here is a C# console application that uses the Youtube Data API to backup your Youtube videos’ metadata and thumbnails.

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;

using System.Text.RegularExpressions;
using System.Drawing;
using System.Drawing.Imaging;

using System.Linq;

namespace youtube_metadata_backup
{
    internal class MyUploads
    {
        static string account_name;

        private static string clean_file_name(string fileName)
        {
            // License: cc by-sa 3.0 
            // Michael Minton
            // Stackoverflow - http://stackoverflow.com/questions/146134/how-to-remove-illegal-characters-from-path-and-filenames
            
            // Removes invalid characters from file / folder name
            return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
        }

        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("YouTube Channel Metadata Backup");
            Console.WriteLine("===============================");

            try
            {
                Console.Write("Youtube account username: ");
                account_name = Console.ReadLine();
                new MyUploads().Run().Wait();
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    Console.WriteLine("Error: " + e.Message);
                }
            }

            Console.WriteLine("Done!");
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        private async Task Run()
        {
            // builds upon the Youtube Data API official C# code sample 

            String client_secret_path = ""; // here you put the path to your .json client secret file, generated in your Google Developer Account

            UserCredential credential;
            using (var stream = new FileStream(client_secret_path, FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    // This OAuth 2.0 access scope allows for read-only access to the authenticated 
                    // user's account, but not other types of account access.
                    new[] { YouTubeService.Scope.Youtubepartner },
                    account_name,
                    CancellationToken.None,
                    new FileDataStore(this.GetType().ToString())
                );
            }

            var youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = this.GetType().ToString()
            });

            var channelsListRequest = youtubeService.Channels.List("contentDetails, snippet");
            channelsListRequest.Mine = true;

            // Retrieve the contentDetails, snippet part of the channel resource for the authenticated user's channel.
            var channelsListResponse = await channelsListRequest.ExecuteAsync();


            foreach (var channel in channelsListResponse.Items)
            {
                // From the API response, extract the playlist ID that identifies the list
                // of videos uploaded to the authenticated user's channel.

                var uploadsListId = channel.ContentDetails.RelatedPlaylists.Uploads;

                Console.WriteLine("Channel: " + channel.Snippet.Title);
               
                var nextPageToken = "";
                int video_total_no = 0;
                
                List<PlaylistItem> video_list = new List<PlaylistItem>();

                Console.WriteLine("Scanning channel videos... ");
                while (nextPageToken != null)
                {
                    try
                    {
                        var playlistItemsListRequest = youtubeService.PlaylistItems.List("snippet, status, contentDetails");
                        playlistItemsListRequest.PlaylistId = uploadsListId;
                        playlistItemsListRequest.MaxResults = 50;
                        playlistItemsListRequest.PageToken = nextPageToken;

                        // Retrieve the list of videos uploaded to the authenticated user's channel.
                        var playlistItemsListResponse = await playlistItemsListRequest.ExecuteAsync();

                        video_list.AddRange(playlistItemsListResponse.Items);

                        video_total_no += playlistItemsListResponse.Items.Count;
                        Console.WriteLine("Videos found so far: " + video_total_no.ToString());

                        nextPageToken = playlistItemsListResponse.NextPageToken;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                }

                Console.WriteLine("Found " + video_total_no.ToString() + " videos");
                Console.WriteLine();
                Console.WriteLine("Getting video metadata...");
                for (int i = 0; i <video_total_no; i++) // iterate through the videos found on the channel
                {
                        var playlistItem = video_list[i];
                        string video_id = playlistItem.ContentDetails.VideoId;
                        Console.WriteLine((i + 1).ToString() + "/" + video_total_no.ToString() + ": " + playlistItem.Snippet.Title);

                        // Create directories necessary for the video data
                        if (System.IO.Directory.Exists(account_name + "\\" + playlistItem.Status.PrivacyStatus) == false) System.IO.Directory.CreateDirectory(account_name + "\\" + playlistItem.Status.PrivacyStatus);
                        string folder_name = clean_file_name(playlistItem.Snippet.Title);
                        if (folder_name.Length > 75) folder_name = folder_name.Substring(0,75);
                        string directory_path = account_name + "\\" + playlistItem.Status.PrivacyStatus + "\\" + i.ToString() + " - " + folder_name;
                        @System.IO.Directory.CreateDirectory(directory_path);

                        int views = 0;
                        System.DateTime published_at = DateTime.MinValue;

                        // try to get views and date published
                        try
                        {
                            var my_video_request = youtubeService.Videos.List("statistics, status");
                            my_video_request.Id = playlistItem.Snippet.ResourceId.VideoId;
                            my_video_request.MaxResults = 1;

                            var my_video_response = await my_video_request.ExecuteAsync();
                            if (my_video_response.Items.Count > 0)
                            {
                                if (my_video_response.Items[0].Statistics.ViewCount != null)
                                {
                                    views = Convert.ToInt32(my_video_response.Items[0].Statistics.ViewCount.ToString());
                                }
                                if (my_video_response.Items[0].Status.PublishAt.HasValue) published_at = my_video_response.Items[0].Status.PublishAt.Value;
                            }
                        }
                        catch (Exception err)
                        {
                            Console.WriteLine("Could not get views and/or date published.");
                            Console.WriteLine(err.ToString());
                        }

                        if (published_at == DateTime.MinValue)
                        {
                            published_at = DateTime.Now;
                        }
                        
                        String published_at_str = published_at.Year.ToString() + "-" + published_at.Month.ToString() + "-" + published_at.Day.ToString() + " ";
                        published_at_str = published_at_str + published_at.Hour.ToString() + ":" + published_at.Minute.ToString() + ":" + published_at.Second.ToString();

                        string metadata = "";
                        metadata = playlistItem.Snippet.Title + Environment.NewLine + Environment.NewLine;
                        metadata += playlistItem.Snippet.Description.Replace("\n",System.Environment.NewLine) + Environment.NewLine + Environment.NewLine;

                        // try to get video tags
                        try
                        {
                            var my_video_request = youtubeService.Videos.List("snippet");
                            my_video_request.Id = playlistItem.Snippet.ResourceId.VideoId;
                            my_video_request.MaxResults = 1;

                            var my_video_response = await my_video_request.ExecuteAsync();

                            if (my_video_response.Items[0].Snippet.Tags != null)
                            {
                                for (int t = 0; t < my_video_response.Items[0].Snippet.Tags.Count; t++)
                                {
                                    if (t > 0) metadata += ",";
                                    metadata += my_video_response.Items[0].Snippet.Tags[t];
                                }
                            }
                        }
                        catch
                        {
                            Console.WriteLine("Could not get tags.");
                        }

                        File.WriteAllText(directory_path + "\\metadata.txt", metadata); // write core metadata to file
                        
                        string other_info = "";
                        other_info = "Views: " + views.ToString() + Environment.NewLine;
                        other_info += "Date published: " + published_at_str + Environment.NewLine;
                        other_info += "Video id: " + video_id;
                        File.WriteAllText(directory_path + "\\other_info.txt", other_info); // write the other metadata 
                        

                        // try getting the video thumbnails
                        try
                        {
                            using (System.Net.WebClient Client = new System.Net.WebClient())
                            {
                                Client.DownloadFile(playlistItem.Snippet.Thumbnails.Maxres.Url, directory_path + "\\thumbnail_maxres.jpg");
                                Client.DownloadFile(playlistItem.Snippet.Thumbnails.High.Url, directory_path + "\\thumbnail_high.jpg");
                                Client.DownloadFile(playlistItem.Snippet.Thumbnails.Medium.Url, directory_path + "\\thumbnail_medium.jpg");
                                Client.DownloadFile(playlistItem.Snippet.Thumbnails.Standard.Url, directory_path + "\\thumbnail_standard.jpg");

                            }
                        }
                        catch
                        {
                            Console.WriteLine("Could not get video thumbnails.");
                        }


                } // end for

            }
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close