Appendix C - Understanding the Contoso Microsoft Azure Media Services Video Applications
Microsoft provides SDKs and Player Frameworks that enable you to create client applications that can consume streaming media from Media Services. Player Frameworks are built on top of SDKs and contain user controls for common application scenarios.
This appendix describes the Visual Studio project structure for the different Contoso video applications, and focuses on the implementation of the Contoso video web application.
Understanding the Contoso video web application
The Contoso web video application is implemented in the Contoso.WebClient project in the solution provided with this guide. This project uses Knockout.js to provide MVVM and data binding support.
This Contoso.WebClient project contains the following folders:
- App_Start: Contains the configuration logic for the application.
- Content: Contains the CSS files for the application.
- Controllers: Contains the controller class used by the application.
- fonts: Contains the font data that is loaded when the application is bootstrapped.
- Images: Contains the image that is animated when data is being retrieved from the Contoso web service.
- Scripts: Contains the JavaScript files that implement the view models that contain the application logic.
- Views: Contains the views that display data to the user.
The following sections explain how the Contoso web client application implements the primary business use cases outlined in "The Azure Media Services Video-on-Demand Scenario."
The Contoso video web application does not support capturing videos. It only supports uploading videos to Media Services.
Browsing videos
The following figure shows how the Contoso web video application allows the user to browse thumbnails of available videos that can be viewed.
Thumbnails for each video that can be viewed
The VideoList view allows the user to browse thumbnails of the available videos, and select one for viewing. The following code example shows the HTML that displays the list of videos.
<div class="videolist" id="videolist">
...
<div data-bind="ifnot: Error">
...
<div data-bind="foreach: VideoList">
<div class='videoItem'>
<div>
<img class='videoItemThumbnail' data-bind="attr: {src: ThumbnailUrl, tabindex: TabIndex, videoId: Id}" alt="No Image Available">
</div>
<div class='videoItemInfo'>
<p data-bind="text: Title"> </p>
<span>Length: </span><span data-bind="text: Length"> </span>
</div>
</div>
</div>
...
</div>
...
</div>
This code binds a div element to the VideoList property in the VideoListViewModel class. A thumbnail representing each video is displayed for each item in the VideoList by using an img element, which binds to the ThumbnailUrl of the VideoList item. The class attributes of the DIV elements are set to use styles from the videoList.css file.
The instance of the VideoListViewModel is bound to the videolist DOM element. When the VideoListViewModel instance is created the ajaxGetVideoList function is executed, which retrieves the list of videos for display. The following code example shows the ajaxGetVideoList function.
function ajaxGetVideoList() {
reset();
videoDetailVM.reset();
self.ShowProgress(true);
var request = {
type: "GET",
url: Contoso.apiRoot + "/videos/",
data: { pageIndex: pageIndex, pageSize: pageSize },
timeout: Contoso.ajaxTimeOut,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
...
This function creates a URL that specifies the address that will be requested from the web service, with the paging options being passed as a parameter. When AJAX makes the request the Get method in the VideosController class in the Contoso.Api project is invoked. This method returns a collection of VideoInfoDTO objects in the response message, from which the VideoList collection is populated. For more information about how the VideosController class returns a list of videos to be displayed to the user, see "Browsing videos."
For information about how different methods are invoked in the Contoso web service, see "Appendix A – The Contoso Web Service."
The Contoso web video application consumes the paging functionality offered by the Contoso web service.
Playing videos
The following figure shows how the video player control in the Contoso web video application, along with video information beneath the player. A Show Clip button is displayed directly beneath the video player if a clip of the video also exists.
Video playback
Most web browsers only support progressive download with the HTML5 video element. Additional frameworks are required to enable support for browser-based streaming. For more information about these frameworks see "Developing Azure Media Services Client Applications."
The VideoList view allows the user to control the playback of a selected video, and allows the user to view a clip from the video if one is available. The following code example shows the HTML that displays the video player.
<div class="videodetail" id="videodetail">
...
<div data-bind="with:VideoDetail">
...
<video id="selectedvideo" data-bind="attr: {poster: ThumbnailUrl}, foreach:Videos" preload controls>
<source data-bind="attr: {src: Url, type: EncodingType}" />
</video>
...
</div>
</div>
This code binds a div element to the VideoDetail property of the VideoDetailViewModel class. The video element specifies the video content to be played, and binds to the ThumbnailUrl of the VideoDetail object in order to display the video thumbnail. The source element provides a mechanism to specify an alternative media resource for the video element, and binds to the Url of the VideoDetail object, from which the video stream can be retrieved. The class attributes of the DIV elements are set to use styles from the videoList.css file.
A similar mechanism is used to display video clips, if the Show Clip button is toggled.
The instance of the VideoDetailVideoModel is bound to the videodetail DOM element. When the VideoListViewModel instance is created the ajaxGetVideoDetail function is executed, which retrieves the video details for the video to be played. The following code example shows the ajaxGetVideoDetail function.
function ajaxGetVideoDetail(id) {
reset();
self.ShowProgress(true);
var request = {
type: "GET",
dataType: "json",
timeout: Contoso.ajaxTimeOut,
url: Contoso.apiRoot + "/videos/" + id,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
...
This function creates a URL that specifies the address that will be requested from the web service, which includes the ID of the video whose details will be retrieved. When AJAX makes the request the Get method in the VideosController class in the Contoso.Api project is invoked. This method returns a VideoDetailDTO object in the response message, from which the VideoDetail object is populated. For more information about how the VideosController class returns the video details of the video to be played, see "Playing videos."
For information about how different methods are invoked in the Contoso web service, see "Appendix A – The Contoso Web Service."
Retrieving recommendations
The following figure shows how the Contoso web video application displays the list of recommended videos to the user.
The list of recommended videos to view
The VideoList view allows the user to browse a list of recommended videos, and select one for viewing. The following code example shows the HTML that displays the list of recommendations.
<div class="recommendationlist" id="recommendationlist">
...
<label id="labelRecommendation" hidden>Recommended Videos</label>
<div data-bind="foreach: RecommendationList">
<div class='recommendationItem'>
<div>
<img class='recommendationItemThumbnail' data-bind="attr: {src: ThumbnailUrl, tabindex: TabIndex, videoId: Id}" alt="No Image Available">
</div>
<div class='recommendationItemInfo'>
<p data-bind="text: Title"> </p>
<span>Length: </span><span data-bind="text: Length"> </span>
</div>
</div>
</div>
...
</div>
This code binds a div element to the RecommendationList property of the RecommendationListViewModel class. A thumbnail representing each video is displayed for each item in the RecommendationList by using an img element, which binds to the ThumbnailUrl of the RecommendationList item. A p and a span element are used to display the title and length of the video through appropriate data binding. The class attributes of the DIV elements are set to use styles from the videoList.css file.
The instance of the RecommendationListViewModel is bound to the recommendationlist DOM element. When the RecommendationListViewModel is created the ajaxGetRecommendationList function is executed, which retrieves the recommendations. The following code example shows the ajaxGetRecommendationList function.
function ajaxGetRecommendationList(id) {
self.ShowProgress(true);
$("#labelRecommendation").hide();
var request = {
type: "GET",
dataType: "json",
timeout: Contoso.ajaxTimeOut,
url: Contoso.apiRoot + "/videos/" + id + "/recommendations",
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
...
This function creates a URL that specifies the address that will be requested from the web service, which includes the ID of the video to retrieve recommendations for. When AJAX makes the request the GetRecommendations method in the VideosController class in the Contoso.Api project is invoked. This method returns a collection of VideoInfoDTO objects in the response message, from which the RecommendationList is populated. For more information about how the VideosController class returns a list of recommendations to be displayed to the user, see "Retrieving recommendations."
For information about how different methods are invoked in the Contoso web service, see "Appendix A – The Contoso Web Service."
Uploading a video
The following figure shows how the Contoso web video application allows the user to upload a video to Media Services for processing. When a new video is uploaded a new asset is created by Media Services, and the asset is uploaded to Azure Storage before the assets details are published to the Content Management System (CMS).
The video details that must be provided prior to upload
The Upload view allows the user to upload a video to Media Services, with the following code example showing the relevant HTML.
<div class="video-upload">
<label class="metadata-label" for=" video-inputfile">Select a video file</label>
<div id="file-input-parent">
<input class="file-input" id="file-input" type="file" title="pick a file" accept="video/*" />
</div>
...
<div data-bind="visible:showUploadButton">
<label class="metadata-label" for="submit-button">Upload</label>
<input id="submit-button" data-bind="click: onSubmit" type="button" value="Submit" title="upload selected video file"/>
</div>
...
</div>
This code uses an input element to allow the user to select a file for upload from the file system, with an input element also being used to submit the file for upload. When the Submit button is selected the onSubmit function is executed which performs validation of user input, before creating a SubmitObject that contains the video details entered by the user. Then, the ajaxGenerateAsset function is called, which is shown in the following code example.
function ajaxGenerateAsset(submitObject) {
if (cancelUpload) return cancelCompleted(submitObject);
submitObject.progressStatus = "Calling server to generate asset";
showProgress(submitObject);
var request = {
url: Contoso.apiRoot + "/videos/generateasset",
type: "GET",
dataType: "json",
data: { filename: submitObject.file.name },
timeout: Contoso.ajaxTimeOut,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
...
This function creates a URL that specifies the address that will be requested from the web service. When AJAX makes the request the GenerateAsset method in the VideosController class in the Contoso.Api project is invoked. This method returns a VideoAssetDTO object in the response message, which is handled by the onAjaxSuccess function. This function updates the SubmitObject with an asset ID, and a shared access signature locator URL for the asset, before calling the ajaxUploadFile function. For more information about how the VideosController class generates a new Media Services asset from the uploaded file, see "Upload process in the Contoso applications."
The ajaxUploadFile function uses the FileChunker object to slice the file for upload into a series of 256KB blocks. The onloadend event of the FileReader object is triggered when a block has been created by the readNextBlock function. This event is handled by the readerOnloadend function in order to upload the block to Azure Storage.
function readerOnloadend(evt) {
var requestData;
if (cancelUpload) return cancelCompleted(submitObject);
if (evt.target.readyState == FileReader.DONE) {
var blockId = blockIdPrefix + pad(blockIdArray.length, 6);
blockIdArray.push(btoa(blockId));
requestData = new Uint8Array(evt.target.result);
var request = {
url: submitObject.sasLocator + '&comp=block&blockid=' + blockIdArray[blockIdArray.length - 1],
type: "PUT",
data: requestData,
processData: false,
beforeSend: onAjaxBeforeSend,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
}
This function creates a URL that specifies the address that will be requested from the web service. When AJAX makes the request the block is uploaded to the URL in Azure Storage that is specified by the shared access signature locator URL that was earlier returned by the GenerateAsset method in the VideosController class. When the operation completes the onAjaxSuccess function is executed which in turn either calls readNextBlock to create the next block to be uploaded, or if chunking has completed, calls the ajaxCommitBlockList function which is shown in the following code example.
function ajaxCommitBlockList(submitObject, blockIds) {
...
var requestData = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
for (var i = 0; i < blockIds.length; i++) {
requestData += '<Latest>' + blockIds[i] + '</Latest>';
}
requestData += '</BlockList>';
var request = {
url: submitObject.sasLocator + '&comp=blocklist',
type: "PUT",
data: requestData,
contentType: "text/plain; charset=UTF-8",
crossDomain: true,
cache: false,
beforeSend: onAjaxBeforeSend,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
...
This function commits the block list to Azure, so that the blocks can be reassembled into the uploaded file. When AJAX makes the request the block list for file is uploaded to the URL in Azure Storage that is specified by the shared access signature locator URL that was earlier returned by the GenerateAsset method in the VideosController class. When the operation completes the onAjaxSuccess function is executed which signals that the blocks have been reassembled and hence that the file has been successfully uploaded. In turn the onAjaxSuccess function calls the ajaxPublish function, which is shown in the following code example.
function ajaxPublish(submitObject) {
...
var videoPublishDTO = {};
videoPublishDTO.AssetId = submitObject.assetId;
videoPublishDTO.Title = submitObject.videoTitle;
videoPublishDTO.Description = submitObject.videoDescription;
videoPublishDTO.Resolution = submitObject.videoResolution;
videoPublishDTO.ClipStartTime = submitObject.clipStartTime;
videoPublishDTO.ClipEndTime = submitObject.clipEndTime;
videoPublishDTO.IncludeThumbnails = submitObject.includeThumbnails;
var request = {
url: Contoso.apiRoot + "/videos/publish",
type: "POST",
dataType: "json",
data: JSON.stringify(videoPublishDTO),
contentType: "application/json;charset=utf-8",
crossDomain: true,
timeout: Contoso.ajaxTimeOut,
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
This function creates a new videoPublishDTO object, which contains the details of the video uploaded to Azure Storage. A URL is then created that specifies the address that will be requested from the web service. When AJAX makes the request the Publish method in the VideosController class in the Contoso.Api project is invoked, with the videoPublishDTO object being passed as a parameter to this method. This method saves the uploaded video details to the CMS database and starts the encoding process on the uploaded asset. For more information about how the Publish method in the VideosController class, see "Upload process in the Contoso applications."
For information about how different methods are invoked in the Contoso web service, see "Appendix A – The Contoso Web Service."
Understanding the Contoso video Windows Store application
The Contoso Windows Store video application is primarily implemented in the Contoso.WindowsStore project in the solution provided with this guide. However, some of the business logic is implemented in the Contoso.UILogic project.
The Contoso.WindowsStore project contains the following folders.
Folder |
Description |
---|---|
Assets |
Contains images for the splash screen, tile, and other Windows Store application required images. |
Behaviors |
Contains the NavigateWithEventArgsToPageAction behavior that is exposed to view classes. |
Controls |
Contains the AutoRotatingGridView control. |
Converters |
Contains data converters such as the SecondsToTimeFormatConverter. |
Events |
Contains the SharePersonalInformationChangedEvent class. |
Helpers |
Contains the VisualTreeUtilities class that can be used to walk the XAML visual tree. |
Models |
Contains the IncrementalLoadingVideoCollection class that is used to provide incremental loading support to the application. |
Services |
Contains interfaces and classes that implement services that are provided to the application, such as the FilePickerService and CaptureService classes. |
Strings |
Contains resource strings used by the project, with subfolders for each supported locale. |
ViewModels |
Contains the Windows Runtime specific application logic that is exposed to XAML controls. |
Views |
Contains the pages and Flyout for the application. |
The Contoso.UILogic project contains classes and other resources that are shared with the Windows Store and Windows Phone projects. Placing these classes into a separate assembly enables reuse by the two applications, and provides a simple mechanism for ensuring that view models are independent from their corresponding views. The project contains the following folders.
Folder |
Description |
---|---|
Common |
Contains the CaptureSource enumeration and constants that are used by the Windows Store and Windows Phone projects, such as the address of the web service. |
Models |
Contains the entities that are used by view model classes. |
Services |
Contains interfaces and classes that implement services that are provided to the application, such as the VideoService class. |
ViewModels |
Contains the shared application logic that is exposed to XAML controls in the Windows Store and Windows Phone projects. |
The main chapters in this guide explain how the Contoso video Windows Store application works, and how it interacts with the Contoso web service to upload, encode, and consume videos.
For information about the frameworks with which you can delivery adaptive streaming content to Windows applications, see "Developing Azure Media Services Client Applications."
Understanding the Contoso video Windows Phone application
The Contoso Windows Phone video application is primarily implemented in the Contoso.WindowsPhone project in the solution provided with this guide. However, some of the business logic is implemented in the Contoso.UILogic project.
The Contoso.WindowsPhone project contains the following folders.
Folder |
Description |
---|---|
Assets |
Contains images for the tiles, and other Windows Phone application required images. |
Behaviors |
Contains behaviors that are exposed to view classes in order to respond to events from view model classes. |
Controls |
Contains the CaptureSourceViewport control. |
Converters |
Contains data converters such as the BooleanToVisibilityConverter. |
DesignViewModels |
Contains design-time view model classes that are used to display sample data in the visual designer. |
Resources |
Contains resource strings used by the project. |
Services |
Contains interfaces and classes that implement services that are provided to the application, such as the FilePickerService and CaptureService classes. |
Styles |
Contains a resource dictionary that defines the application styles used by the app. |
ViewModels |
Contains the Windows Phone specific application logic that is exposed to XAML controls. |
Views |
Contains the pages for the application. |
The Contoso video Windows Phone application shares much of its application logic with the Contoso video Windows Store application. Therefore, an understanding of how the Windows Phone application works can be gained by reading the main chapters in this guide, which explain how the Contoso video Windows Store application works, and how it interacts with the Contoso web service to upload, encode, and consume videos.
For information about the structure of the Contoso.UILogic project see the second table in "Understanding the Contoso video Windows Store application."
For information about the frameworks with which you can deliver adaptive streaming content to Windows Phone applications, see "Developing Azure Media Services Client Applications."
Understanding the other Contoso video applications
The Contoso video applications for iOS and Android can be downloaded from the CodePlex site for this guide (https://wamsg.codeplex.com/).
For information about the frameworks with which you can deliver adaptive streaming content to iOS and Android devices, see "Developing Azure Media Services Client Applications."
More information
- For information about the iOS and Android Contoso video applications, see the Azure Media Services Guidance Community site on CodePlex.
- For information about the Microsoft SDKs and Player Frameworks that allow you to create client applications that can consume streaming media from Media Services, see "Developing Azure Media Services Client Applications" on MSDN.