A Youtube Connector for Sitecore Media Framework Part 5 – Import Data From Youtube

Finally, I made some time to get back to blogging. In the previous blog of this series, I talked about authenticating to my Google Account using OAuth2, so that, I can access my Youtube videos. In this blog post, I will discuss how to get the data of my Youtube videos and synchronize them with Sitecore. For purpose of the blog, I will only talk about the one way synchronization, that is, importing data from Youtube. In real life the synchronization should be two ways, where connector should be able to export the data from Sitecore to Youtube and upload videos too.

The Import process starts with code that implements IImportExecuter interface. There is only one method in this interface as below

IEnumerable<object> GetData(Item accountItem)

This method takes the accountItem (in my case, it is the MyYoutubeVideos Account) and returns the IEnumerable of type object. This method is supposed to return the data gathered from Youtube. But, how does Sitecore Framework knows what is in the data returned by this method? That’s where the configuration is used. In the Media Framework Config for my Youtube connector (Sitecore.MediaFramework.Services.Youtube.config), I need to declare the entity type for the video data inside the synchronizers element as shown below (highlighted) and I need to map my Youtube data to this entity and return that from the GetData method.

<synchronizers>
 <add name="youtube_video"
 entity="Sitecore.MediaFramework.Youtube.Entities.Video, Sitecore.MediaFramework.Youtube"
 templateId="{D5DCE266-13E8-4583-A318-F3C19212754C}"
 type="Sitecore.MediaFramework.Youtube.Synchronize.VideoSynchronizer, Sitecore.MediaFramework.Youtube">
 <databaseFallback type="Sitecore.MediaFramework.Youtube.Synchronize.Fallback.VideoFallback, Sitecore.MediaFramework.Youtube"/>
 </add>
 </synchronizers>

Once the Media Framework gets the list of video entities, it needs to convert them to Sitecore items based on the ‘MyYoutubeVideos Video’ template and it finds the template from the templateId mentioned the above configuration. For creating the Sitecore items Media Framework use the VideoSynchronizer class from the configuration. The VideoSynchronizer is derived from the Media Framework’s SynchronizerBase class. For each item returned by the GetData method, the Media Framework calls the synchronizer to sync that item with Sitecore. First thing Media Frameworks does is, to see if the item already exists. It does that by calling the GetSearchResult method from the VideoSynchronizer class. The GetSearchResult uses templateId and the Id from the Video entity to find the item in the search index that I created just for the Video Items save in the ‘Media Content’ folder under ‘/sitecore/media library/Media Framework/Accounts/MyYoutubeVideos Account’. If GetSearchResult doesn’t return any result Media Framework falls back to VideoFallBack class, which looks for item using fast query. If the item exists Media Framework calls the UpdateItem and updates item with new data collected from Youtube. If item doesn’t exists Media Frameworks calls the GetMediaData to create the initial item in the folder returned by the GetRootItem method with VideoId and name as the Title of the video and then call UpdateItem to save the rest of the information. Here is code for VideoSynchronizer and then the VideoFallBack class.

 public class VideoSynchronizer : SynchronizerBase
 {
   public override MediaFramework.Entities.MediaServiceEntityData GetMediaData(object entity)
   {
     BaseEntity baseEntity = (BaseEntity)entity;
     return new MediaServiceEntityData()
     {
        EntityId = baseEntity.Id,
        EntityName = baseEntity.Title,
        TemplateId=TemplateIDs.Video
     };
   }

   public override Data.Items.Item GetRootItem(object entity, Data.Items.Item accountItem)
   {
     return accountItem.Children["Media Content"];
   }

   public override MediaFramework.Entities.MediaServiceSearchResult GetSearchResult(object entity, Data.Items.Item accountItem)
   {
     Sitecore.MediaFramework.Youtube.Entities.Video video = (Sitecore.MediaFramework.Youtube.Entities.Video)entity;
     return (MediaServiceSearchResult)base.GetSearchResult<VideoSearchResult>(Constants.IndexName, accountItem, (Expression<Func<VideoSearchResult, bool>>)(i => i.TemplateId == TemplateIDs.Video && i.Id == video.Id));
   }

 public override Data.Items.Item UpdateItem(object entity, Data.Items.Item accountItem, Data.Items.Item item)
 {
   Sitecore.MediaFramework.Youtube.Entities.Video video = (Sitecore.MediaFramework.Youtube.Entities.Video)entity;
   using (new EditContext(item))
   {
     item.Name = ItemUtil.ProposeValidItemName(video.Title);
     item[FieldNames.MediaElement.Id] = video.Id;
     item[FieldNames.MediaElement.Title] = video.Title;
     item[FieldNames.MediaElement.Description] = video.Description;
     item[FieldNames.MediaElement.ChannelName] = video.ChannelName;
     item[FieldNames.Video.VideoUrl] = video.VideoUrl;
     item[FieldNames.Video.StillImageUrl] = video.StillImageUrl;
     item[FieldNames.Video.ThumbnailUrl] = video.ThumbnailUrl;
     item[FieldNames.Video.UploadDate] = video.UploadDate.ToString();
     item[FieldNames.Video.VideoFileName] = video.VideoFileName;
     item[FieldNames.Video.Views] = video.NumberOfViews.ToString();
     item[FieldNames.Video.Likes] = video.NumberOfLikes.ToString();
     item[FieldNames.Video.Dislikes] = video.NumberOfDislikes.ToString();
     item[FieldNames.Video.NumberOfComments] = video.NumberOfComments.ToString();
     item[FieldNames.Video.NumberFavorited] = video.NumberFavorited.ToString();
     item[FieldNames.Video.NumberShared] = video.NumberShared.ToString();
    }
    return item;
  }
 }
 public class VideoFallBack : BaseFallBack<VideoSearchResult>
 {
   protected override Data.Items.Item GetItem(object entity, Data.Items.Item accountItem)
   {
     Sitecore.MediaFramework.Youtube.Entities.Video video = (Sitecore.MediaFramework.Youtube.Entities.Video)entity;
     return accountItem.Axes.SelectSingleItem(string.Format("./Media Content//*[@@templateid='{0}' and @id='{1}']", (object)TemplateIDs.Video, (object)video.Id));
   }

   protected override MediaFramework.Entities.MediaServiceSearchResult GetSearchResult(Data.Items.Item item)
   {
     VideoSearchResult videoSearchResult = (VideoSearchResult)base.GetSearchResult(item);
     videoSearchResult.VideoUrl=item[FieldNames.Video.VideoUrl];
     videoSearchResult.StillImageUrl=item[FieldNames.Video.StillImageUrl];
     videoSearchResult.ThumbnailUrl=item[FieldNames.Video.ThumbnailUrl];
     videoSearchResult.UploadDate=item[FieldNames.Video.UploadDate];
     videoSearchResult.VideoFileName=item[FieldNames.Video.VideoFileName];
     videoSearchResult.NumberOfViews = item[FieldNames.Video.Views];
     videoSearchResult.NumberOfLikes=item[FieldNames.Video.Likes];
     videoSearchResult.NumberOfDislikes=item[FieldNames.Video.Dislikes];
     videoSearchResult.NumberOfComments=item[FieldNames.Video.NumberOfComments];
     videoSearchResult.NumberFavorited=item[FieldNames.Video.NumberFavorited];
     videoSearchResult.NumberShared=item[FieldNames.Video.NumberShared];
     return videoSearchResult;
   }
 }

 That’s it,  my youtube connector is ready to sync my youtube Videos with Sitecore. Once I deploy the code and click on the ‘Import All’ button in the Sitecore Content Editor, I can see the items created in Sitecore. Below is the search result in the Content Editor.

Sitecore Media Framework

And here is one Video item

Sitecore Media Framework

Now since my Youtube Videos are Sitecore items, the possibilities of using them are endless. First of all, I can embed my videos in the Content Managed website, I can use DMS to personalize the videos for the user. There are so many ways I can use them.

That’s all for today. In the next part I will discuss how to preview the videos in the Content Editor. Exciting!!

Advertisements

About Himadri Chakrabarti

I am a software developer architect and a Sitecore MVP. My professional interest is everything and anything related to Software Architecture, .NET, Sitecore, Node.js, NoSQL etc. Outside of my profession, I am a hobbyist photographer. Link to my photography site http://himadriphotography.com/
This entry was posted in Connnector, Media Framework, Sitecore and tagged , , , . Bookmark the permalink.

2 Responses to A Youtube Connector for Sitecore Media Framework Part 5 – Import Data From Youtube

  1. Tingting says:

    Hi Himadri,

    Really like this work!

    Can I also ask: (1) How do you embed these youtube video items into components?
    (2) Have you tried embedding these youtube video items by using Rich text editor? If so, how did you do that?

    Thanks
    Tingting

    • Hi, please look at this class YoutubePlayerMarkupGenerator. This generates the player markup. I used this to show videos in the content editor. I never had time to try it in an application outside of the content editor. You use that class to display the video in a user control or in the MVC view.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s