Diving Deep into the Video Caption Editor's Integration with Azure Functions

Introduction

In our previous post, we introduced the Video Caption Editor for the Sitecore Content Hub and shed light on its importance in terms of efficiency and cost-saving. Today, we'll journey deeper into the technical aspects of this groundbreaking tool, especially its integration with Azure Functions.

Video Processing and Properties

Before sending video data to the Content Hub, it's crucial to obtain specific properties of the video that can aid in its correct representation and playback. This involves understanding the compression formats, such as the Apple ProRes 422 HQ.

Converting HTML to Images

One of the fascinating features of the Video Caption Editor is its capability to transform HTML content into images. This is particularly useful for generating overlays from HTML-based video captions. Leveraging powerful libraries such as SkiaSharp and HtmlAgilityPack, this feature provides high-fidelity conversions.

using HtmlAgilityPack;
using SkiaSharp;
using System.Collections.Generic;
using Topten.RichTextKit;

namespace Sitecore.CH.Implementation.AzFunctions.Model.Video
{
public class VideoHtmlToImage
{
public byte[] ConvertHtmlToImage(string html, int originalTextBoxWidth, int originalTextBoxHeight, int targetTextBoxWidth, int targetTextBoxHeight, SKColor backgroundColor, SKColor textColor, int videoWidth)
{
// Calculate aspect ratios
float originalAspectRatio = (float)originalTextBoxWidth / originalTextBoxHeight;
float targetAspectRatio = (float)targetTextBoxWidth / targetTextBoxHeight;

// Calculate scaled dimensions based on the aspect ratio
int scaledWidth, scaledHeight;
if (originalAspectRatio > targetAspectRatio)
{
scaledWidth = targetTextBoxWidth;
scaledHeight = (int)(targetTextBoxWidth / originalAspectRatio);
}
else
{
scaledWidth = (int)(targetTextBoxHeight * originalAspectRatio);
scaledHeight = targetTextBoxHeight;
}

// Create a new image surface
using (SKBitmap bitmap = new SKBitmap(targetTextBoxWidth, targetTextBoxHeight))
using (SKCanvas canvas = new SKCanvas(bitmap))
{
canvas.Clear(backgroundColor);
// Convert the HTML to a RichString
var richString = HtmlToRichString(html, textColor, videoWidth);
richString.MaxWidth = scaledWidth;
richString.MaxHeight = scaledHeight;
richString.Paint(canvas, new SKPoint(15, 20));

// Encode the bitmap as PNG
using (SKData data = SKImage.FromBitmap(bitmap). Encode(SKEncodedImageFormat.Png, 100))
{
return data.ToArray();
}
}
}

Dictionary<string, string> fontMap = new Dictionary<string, string>
{
{ "ql-font-timesnewroman", "Times New Roman" },
{ "ql-font-arial", "Arial" },
{ "ql-font-verdana", "Verdana" },
{ "ql-font-couriernew", "Courier New" },
{ "ql-font-georgia", "Georgia" },
{ "ql-font-comicsansms", "Comic Sans MS" },
{ "ql-font-consolas", "Consolas" },
{ "ql-font-impact", "Impact" },
{ "ql-font-lucidaconsole", "Lucida Console" },
{ "ql-font-lucidasansunicode", "Lucida Sans Unicode" },
{ "ql-font-microsoftsansserif", "Microsoft Sans Serif" },
{ "ql-font-palatinolinotype", "Palatino Linotype" },
{ "ql-font-segoe-ui", "Segoe UI" },
{ "ql-font-tahoma", "Tahoma" },
{ "ql-font-trebuchetms", "Trebuchet MS" },
{ "ql-font-symbol", "Symbol" },
{ "ql-font-webdings", "Webdings" },
{ "ql-font-wingdings", "Wingdings" }
};

// Additional methods and functionalities...
}
}

Asset Management in Content Hub

The core functionality revolves around managing video assets within the Content Hub. This encompasses creating, updating, and fetching assets. The Sitecore Content Hub SDK is at the heart of these operations, ensuring seamless integration.

Creating Asset Files

When introducing new video assets to the Content Hub, we utilize Azure Blob Storage for efficient storage and retrieval.

public async Task<(long ResponseId, long FileSize)> UploadVideoToContentHub(string videoBlobUrl, string videoExtension)
{
long responseId = 0;
long fileSize = 0;

try
{
_logger.LogInformation("Starting the video upload process...");
var uri = new Uri(videoBlobUrl, UriKind.Absolute);
var mClient = _mClientFactory.Client;
var cancellationTokenSource = new CancellationTokenSource();

using (var memoryStream = await MemoryStreamHelper. GetMemoryStreamFromUrlAsync(uri, cancellationTokenSource.Token))
{
string shortUniqueId = Guid.NewGuid().ToString().Substring(0, 7);
var contentType = VideoHelper.GetVideoContentType(videoExtension);
var name = $"video_caption_editor_{shortUniqueId}.{videoExtension}";
var uploadSource = new StreamUploadSource(memoryStream, contentType, name);
fileSize = memoryStream.Length;
var request = new UploadRequest(uploadSource, "AssetUploadConfiguration", "NewAsset")
{
ActionParameters = new Dictionary<string, object>
{
{ "FileSize", fileSize },
}
};

// Initiate upload and wait for its completion.
var response = await mClient.Uploads.UploadAsync(request, cancellationTokenSource.Token).ConfigureAwait(false);
responseId = (long)await mClient.LinkHelper.IdFromEntityAsync(response.Headers.Location).ConfigureAwait(false);
}
_logger.LogInformation("Video upload process completed successfully.");
return (responseId, fileSize);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.Forbidden)
{
_logger.LogError(ex, "Authentication failed. Check your credentials or authorization token.");
throw new AuthenticationException("Authentication failed. Check your c redentials or authorization token.");
}
catch (Exception ex)
{
_logger.LogError(ex, $"File upload failed: {ex.Message}");
throw new VideoUploadException($"File upload failed: {ex.Message}");
}
}
}
}


// Additional methods and functionalities...

Updating Asset Files

The Video Caption Editor allows for updating existing assets. This is vital for making real-time edits to video captions and ensuring the Content Hub contains the most recent version.


public async Task<(long ResponseId, long FileSize)> UploadVideoToContentHub(IEntity asset, string fileName, string videoBlobUrl, string videoExtension)
{
long responseId = 0;
long fileSize = 0;
long assetId = asset.Id.Value;

try
{
_logger.LogInformation("Starting the video upload process...");
var uri = new Uri(videoBlobUrl, UriKind.Absolute);
var mClient = _mClientFactory.Client;
var cancellationTokenSource = new CancellationTokenSource();

using (var memoryStream = await MemoryStreamHelper.GetMemoryStreamFromUrlAsync(uri, cancellationTokenSource.Token))
{
var contentType = VideoHelper.GetVideoContentType(videoExtension);
var uploadSource = new StreamUploadSource(memoryStream, contentType, fileName);
fileSize = memoryStream.Length;
var request = new UploadRequest(uploadSource, "AssetUploadConfiguration", "NewMainFile")
{
ActionParameters = new Dictionary<string, object>
{
{ "AssetId", assetId},
{ "FileName", $"{assetId}_{fileName}" },
{ "FileSize", fileSize },
}
};

var response = await mClient.Uploads.UploadAsync(request, cancellationTokenSource.Token).ConfigureAwait(false);
responseId = (long)await mClient.LinkHelper.IdFromEntityAsync(response.Headers.Location).ConfigureAwait(false);
}
_logger.LogInformation("Video upload process completed successfully.");
return (responseId, fileSize);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.Forbidden)
{
_logger.LogError(ex, "Authentication failed. Check your credentials or authorization token.");
throw new AuthenticationException("Authentication failed. Check your credentials or authorization token.");
}
catch (Exception ex)
{
_logger.LogError(ex, $"File upload failed: {ex.Message}");
throw new VideoUploadException($"File upload failed: {ex.Message}");
}
}


// Additional methods and functionalities...

Azure Batch Video Processing

For efficient video processing, especially when dealing with bulk operations, the Video Caption Editor integrates with Azure Batch. This provides scalability and ensures videos are processed in a timely manner without overloading resources.

BatchSharedKeyCredentials credentials = new BatchSharedKeyCredentials(batchAccountUrl, batchAccountName, batchAccountKey);
using (BatchClient batchClient = BatchClient.Open(credentials))
{
// Additional methods and functionalities...
            }

Conclusion

The Video Caption Editor, with its integration into the Sitecore Content Hub and Azure Functions, represents a significant advancement in DAM systems. Whether you're converting HTML captions to images, managing assets, or processing videos in batches, this tool ensures a streamlined and efficient workflow.

Stay tuned as we continue to explore more features and dive deeper into the world of DAM through the lens of our Video Caption Editor for Sitecore Content Hub.

Comments