Compartir vía


Appendix C - Understanding the Contoso Microsoft Azure Media Services Video Applications

patterns & practices Developer CenterDownload Reference ImplementationDownload book

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

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

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 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 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

Previous Topic | Home | Community