How-To: Create an image recognition app with Vuforia and HoloLens

Image recognition and interpretation is a very requested task into modern application. Either you want to identify a specific image or object or either you want to interpret what the users get in front their smartphone camera.

A technology that is becoming more and more popular among developers with this task is Vuforia. This framework can recognize a specific image and track it while the image is in the scene. The same goes to Custom 3D object, Cylinders, boxes, etc.

Moreover, Vuforia is widely accepted because we can use it with almost any device, from older and cheap Android smartphone to the most recent VR/AR/MX devices. In this post, we will use the Vuforia capabilities from Unity3D because it is also multi-platform.

Read More

//BUILD 2017: Day 1 Recap

If you’ve been watching Microsoft’s live stream for //Build 2017 that is taking place at Seattle, WA, you know that it is impossible to make a recap of all the news of Day 1 without leaving out a few things. If you haven’t been watching, well, you missed a lot! But don’t panic, while we’re here we wanted to share the latest and most important announcements.

New: Azure mobile app for iOS and Android

Microsoft announced an app that will allow us to manage our Azure account: check statuses and metrics and launching and stopping resources. You can go ahead and download it right now!

New: Azure Cloud Shell integrated into Azure Portal

There’s now (in Preview) a command line integrated into the Azure Portal. This allows you to manage your resources in a programmatic way (websites, virtual machines…). Note that in order to be able to persist your files across sessions, you need to create a storage account and file share. Also, support for PowerShell will be coming soon. Read more about the Shell here.

cloud shell

New: Visual Studio Snapshot Debugger

You don’t have to leave your IDE to find out what’s crashing your production app. Azure can now collect snapshots and you can launch them in Visual Studio 2017 Enterprise. These snapshots show you the state of the variables at the moment the error occurred. Read more about this Preview feature here and download the extension here.

Snapshot Debugger

New: Visual Studio for Mac

One of the biggest announcements made today is not even for Microsoft’s main platform. We were all very excited when cross-platform Visual Studio Code was launched, but now the Visual Studio we all know is available as a native app for MacOS, and you can develop Windows, Mac and mobile applications through Xamarin. Download it here.

Visual Studio for Mac

Updated data support in Azure: MySQL, PostgreSQL and NoSQL

Until now, Microsoft only offered SQL Azure databases for the relational database developers. Today it was announced that support for MySQL and PostgreSQL servers will be added too. Microsoft also announced support for Azure Cosmos DB – a globally distributed, multi-model database which supports key-value, document and graph data types.

Updated Visual Studio 2017

Visual Studio has seen many interesting updates in the last couple of weeks, and today we got to learn about some more. Docker is now fully integrated with Visual Studio, and cross-container debugging is supported.

Cross-container debugging in VS

Visual Studio 2017 Version 15.3 Launched

VS 2017 15.3

This Preview version of Visual Studio can be installed in parallel to Visual Studio 2017 and it includes many useful features:

  • Added support for Azure Functions (Microsoft’s serverless experience), enabling developers build and debug functions. Download the Tools here and see the full release notes here.

Azure Functions

  • Automatic file detection: when you drop a file into a folder, Visual Studio will automatically detect it and include it in the project.

Automatic File Detection

  • Live unit testing support for .NET Core projects: run your tests as you code.

Live Unit Testing

  • Enhanced debugging experience; for example, by showing which variable is null on exceptions.Null Var Unknown? Not anymore!

Azure IoT Edge & Azure Stack

With IoT Edge you can run all sorts of services in devices like the Raspberry Pi, including Azure Functions, Machine Learning and the IoT Hub, even when their connection to the Internet is limited and enabling real-time analytics. Along these lines, Azure Stack, an on-premises version of Azure, was announced.

Azure Stack

Updated Cognitive Services with Custom Cognitive Services

Microsoft wants to push the boundaries on what be done with AI. It already offers a very large set of APIs to perform complex processing tasks like speech recognition, image analysis and language understanding, and it announced today a new set of services that will allow developers to build their own custom models and train them.

Cognitive Services

There’s obviously a lot more to come on Day 2, but we didn’t want to end this post without giving a special mention unrelated to the previous updates: Emma’s Project, a piece of wearable technology made to improve the handwriting ability of people with Parkinson’s disease.

Parkinson's Gadget

Latest Azure Media Services updates in portal.azure.com

The Azure Media Services team has been regularly updating, improving and adding new features to the portal.azure.com (codename Ibiza) since its initial announcement last year.

In this post, I will be covering the latest updates that were added this week.

Support for new Media Encoder Standard presets

The Azure Media Services team recently released an update for the Media Encoder Standard processor that supports new presets, and now they are all also available to use in the portal:

  • “Adaptive Streaming”. This is the new default preset for video assets that auto-generates a bitrate ladder based on the input resolution and bitrate.
  • “AAC Stereo for Streaming”. This is an audio-only preset. If the primary asset file happens to be an audio file (“.mp3“, “.wav“, “.wma“, “.m4a“, “.pcm“, “.f4a“, “.mka“, “.ogg“) then this preset will be selected by default.
  • “AAC 5.1 Channel for Streaming”. This is an audio-only preset.
  • “AAC Good Quality Audio for Download”. This is an audio-only preset.

New Media Encoder Standard presets

 

Job Details blade updates

The Job Details blade now has the following new commands to manage a job instance:

  • “Change priority”: Allows the user to change the priority of the job instance; it’s only enabled while the job is in Queued state.
  • “Cancel”: Allows the user to cancel the job instance; it’s only enabled while the job is transitioning through not final states.
  • “Delete”: Allows the user to delete the job instance; it’s only enabled when the job has reached a final state (Finished, Cancelled or Error).

Additionally, a new “Output Assets” grid was added at the bottom that contains the list of output assets generated by the job. Each item in the grid has deep linking support to open the corresponding Asset Details blade.

Job Details blade updates

New “Archive for download” command for Live Events (Programs)

The portal now supports a straightforward way to archive the top bitrate audio/video track from a live event (program) as an MP4 and then download the file. You can do this by following these steps from the Live Event blade.

  1. Once the Live Event (Program) is stopped, click the “Archive for download” command and confirm the operation.
  2. Click the “Archive for download job added” content state message to open the Job Details blade.
  3. In the Job Details blade, wait until the job finishes (the blade has auto-refresh logic).
  4. Click the row in the “Output Assets” grid to open the Assets Details blade for the job output asset containing the live archive.
  5. In the Asset Details blade, click the “Publish” command and create a “Progressive” locator. This is required to download the MP4 archive file in the next steps.
  6. Click the MP4 file row in the “Files” table to open the Asset File Details blade.
  7. Copy the Download URL field and use it to download the file to your local machine.

Archive for download live event (program)

Enjoy!

New Azure Media Services quickstart template for Orchard CMS Video Portal integration

The Azure Media Services team has just published a new ARM template in the azure-quickstart-templates repository to let users easily configure and deploy Orchard CMS integrated with the Azure Media Services module ready to use as a Video Portal hosted in Azure App Service Web Apps. You can find it @ https://github.com/Azure/azure-quickstart-templates/tree/master/orchard-cms-video-portal

Additionally, this template deploys a new Orchard CMS image that contains the following updates for the Azure Media Services module:

The following are the high-level steps to configure and deploy the new Orchard CMS Video Portal template:

  1. Open a browser, navigate to https://github.com/Azure/azure-quickstart-templates/tree/master/orchard-cms-video-portal and click “Deploy to Azure”.
    Orchard CMS Video Portal Template
  2. This will redirect you to the Azure Portal. Sign in with an account that has write access to an active Azure subscription and you will see the Azure quickstart template blade.
  3. Select the parameters in the Basics section to choose where to deploy the template (Subscription, Resource group and Location).
  4. In the Settings section, complete the following parameters, make sure to check the terms and conditions agreement and then click Purchase.
    • App Name: This must be the unique name for your Azure App Service Web App (.azurewebsites.net).
    • Db Administrator Login: This is the login name for the SQL Azure server administrator (it’s a SQL Identifier).
    • Db Administrator Login Password: The password for the SQL Azure server administrator.
    • Non Admin Database User Name: This is the login name for that user that will be used to connect to the Orchard CMS database (it’s a SQL Identifier).
    • Non Admin Database Password: The password for the Orchard CMS database user.

    Orchard CMS Video Portal Template in Azure Portal
    Note: The template only exposes the end-user facing parameters. In order to customize additional resource settings, you can modify the following variables in the template:

    "variables": {
        "appServicePlanName":"[concat('serviceplan', uniqueString(resourceGroup().id))]",      
        "appServiceTier": "Basic",
        "appServiceWorkerSize": "0",
        "dbServerName": "[concat('sqlserver', uniqueString(resourceGroup().id))]",
        "dbName": "[concat('sqldatabase', uniqueString(resourceGroup().id))]",
        "dbEdition": "Standard",
        "mediaServicesAccountName": "[concat('media', uniqueString(resourceGroup().id))]",
        "storageAccountName": "[concat('storage', uniqueString(resourceGroup().id))]",
        "storageAccountType": "Standard_LRS"
    },

     

  5. Wait until the deployment completes. You should see a new Resource Group with the following resources.
    Orchard CMS Video Portal Resource Group
  6. Navigate to the Azure App Service Web App hosting your Orchard CMS instance. It should be https://%yourappnameparameter%.azurewebsites.net.
  7. In the Welcome to Orchard setup screen, complete all the form fields, make sure that the “Video Portal” recipe is selected and then click Finish Setup.
    Orchard CM Video Portal Setup
  8. Once the setup is done, you can navigate to the Admin Dashboard page at https://%yourappnameparameter%.azurewebsites.net/Admin. Open the Settings menu and click Microsoft Azure Media module. You should see that all the account credentials are already configured.
    5-orchard-cms-video-portal-admin-settings
  9. Finally, in order to upload, encode and publish videos with the Microsoft Azure Media module, you just need to go to the Media Library, create a new folder, click Import and then select Microsoft Azure Media.
    Orchard CMS Video Portal Media Library

 

Enjoy!

New Azure Media Services .NET SDK Extensions Release

Azure Media ServicesYesterday, the Azure Media Services team released a new version of the Azure Media Services .NET SDK Extensions nuget package (v3.7.0.1) that contains some fixes, updates and new features. The previous nuget package version (v3.5.2) is a broken build, so it’s now deprecated/unlisted; please make sure to update your projects to use the new and fixed package version: v3.7.0.1.

In this post, I will share the change log by describing all the changes that were included in this release.

Change Log

Upgraded to latest Azure Media Services .NET SDK (v3.7.0.1).

Marked as obsolete these processors in MediaProcessorNames class: Windows Azure Media Encoder, Azure Media Encoder, Windows Azure Media Packager, Windows Azure Media Encryptor.

[Obsolete]
public const string WindowsAzureMediaEncoder = "Windows Azure Media Encoder";

[Obsolete]
public const string AzureMediaEncoder = "Azure Media Encoder";

[Obsolete]
public const string WindowsAzureMediaPackager = "Windows Azure Media Packager";

[Obsolete]
public const string WindowsAzureMediaEncryptor = "Windows Azure Media Encryptor";

Marked as obsolete the task preset strings for Azure Media Encoder processor in MediaEncoderTaskPresetStrings class.

[Obsolete]
public static class MediaEncoderTaskPresetStrings

Added names for new Media Analytics’ processors in MediaProcessorNames class.

public const string AzureMediaFaceDetector = "Azure Media Face Detector";

public const string AzureMediaHyperlapse = "Azure Media Hyperlapse";

public const string AzureMediaIndexer = "Azure Media Indexer";

public const string AzureMediaIndexer2Preview = "Azure Media Indexer 2 Preview";

public const string AzureMediaMotionDetector = "Azure Media Motion Detector";

public const string AzureMediaOCR = "Azure Media OCR";

public const string AzureMediaStabilizer = "Azure Media Stabilizer";

public const string AzureMediaVideoThumbnails = "Azure Media Video Thumbnails";

Added task preset strings for Media Encoder Standard processor in MediaEncoderStandardTaskPresetStrings class.

public static class MediaEncoderStandardTaskPresetStrings
{
// H264 Multiple Bitrate Presets
public const string H264MultipleBitrate1080pAudio51 = "H264 Multiple Bitrate 1080p Audio 5.1";
public const string H264MultipleBitrate1080p = "H264 Multiple Bitrate 1080p";
public const string H264MultipleBitrate16x9foriOS = "H264 Multiple Bitrate 16x9 for iOS";
public const string H264MultipleBitrate16x9SDAudio51 = "H264 Multiple Bitrate 16x9 SD Audio 5.1";
public const string H264MultipleBitrate16x9SD = "H264 Multiple Bitrate 16x9 SD";
public const string H264MultipleBitrate4KAudio51 = "H264 Multiple Bitrate 4K Audio 5.1";
public const string H264MultipleBitrate4K = "H264 Multiple Bitrate 4K";
public const string H264MultipleBitrate4x3foriOS = "H264 Multiple Bitrate 4x3 for iOS";
public const string H264MultipleBitrate4x3SDAudio51 = "H264 Multiple Bitrate 4x3 SD Audio 5.1";
public const string H264MultipleBitrate4x3SD = "H264 Multiple Bitrate 4x3 SD";
public const string H264MultipleBitrate720pAudio51 = "H264 Multiple Bitrate 720p Audio 5.1";
public const string H264MultipleBitrate720p = "H264 Multiple Bitrate 720p";

// H264 Single Bitrate Presets
public const string H264SingleBitrate1080pAudio51 = "H264 Single Bitrate 1080p Audio 5.1";
public const string H264SingleBitrate1080p = "H264 Single Bitrate 1080p";
public const string H264SingleBitrate4KAudio51 = "H264 Single Bitrate 4K Audio 5.1";
public const string H264SingleBitrate4K = "H264 Single Bitrate 4K";
public const string H264SingleBitrate4x3SDAudio51 = "H264 Single Bitrate 4x3 SD Audio 5.1";
public const string H264SingleBitrate4x3SD = "H264 Single Bitrate 4x3 SD";
public const string H264SingleBitrate16x9SDAudio51 = "H264 Single Bitrate 16x9 SD Audio 5.1";
public const string H264SingleBitrate16x9SD = "H264 Single Bitrate 16x9 SD";
public const string H264SingleBitrate720pAudio51 = "H264 Single Bitrate 720p Audio 5.1";
public const string H264SingleBitrate720pforAndroid = "H264 Single Bitrate 720p for Android";
public const string H264SingleBitrate720p = "H264 Single Bitrate 720p";
public const string H264SingleBitrateHighQualitySDforAndroid = "H264 Single Bitrate High Quality SD for Android";
public const string H264SingleBitrateLowQualitySDforAndroid = "H264 Single Bitrate Low Quality SD for Android";
}

Added new CreateFromBlobAsync / CreateFromBlob extension methods for AssetBaseCollection class to create a new asset by copying a source blob. This extension works with a source blob belonging to any Storage account (not necessary bound to the Media Services account and even across different datacenters).

CloudMediaContext context = new CloudMediaContext("%accountName%", "%accountKey%");
StorageCredentials storageCredentials = new StorageCredentials("%storageAccountName%", "%storageAccountKey%");

// Get a reference to the source blob that will be copied in the new asset.
CloudBlockBlob sourceBlob = null;

// Create a new asset and copies the sourceBlob parameter using a single extension method.
IAsset asset = context.Assets.CreateFromBlob(sourceBlob, storageCredentials, AssetCreationOptions.None);

Added new CopyAsync / Copy extension methods for IAsset interface to copy all files in the source asset into the destination asset. This extension works with regular assets, live archive assets (FragBlob format) and source/destination assets belonging to different Media Services accounts (even across different datacenters).

CloudMediaContext context = new CloudMediaContext("%accountName%", "%accountKey%");

// Get a reference to the source asset.
string sourceAssetId = "%sourceAssetId%";
IAsset sourceAsset = context.Assets.Where(a => a.Id == sourceAssetId).First();

// Create an empty destination asset where the source asset files are going to be copied.
IAsset destinationAsset = context.Assets.Create("Asset Copy", AssetCreationOptions.None);
StorageCredentials destinationStorageCredentials = new StorageCredentials("%storageAccountName%", "%storageAccountKey%");

// Copy the files in the 'sourceAsset' instance into the 'destinationAsset' instance.
sourceAsset.Copy(destinationAsset, destinationStorageCredentials);

Added new CopyBlobHelpers static class with some helper methods for copying blob.

/// <summary>
/// Returns a <see cref="System.Threading.Tasks.Task"/> instance for the copy blobs operation from <paramref name="sourceContainer"/> to <paramref name="destinationContainer"/>.
/// </summary>
/// <param name="sourceContainer">The <see cref="Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer"/> instance that contains the blobs to be copied into <paramref name="destinationContainer"/>.</param>
/// <param name="destinationContainer">The <see cref="Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer"/> instance where the blobs from <paramref name="sourceContainer"/> will be copied.</param>
/// <param name="options">The <see cref="Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions"/>.</param>
/// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken"/> instance used for cancellation.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task"/> instance for the copy blobs operation from <paramref name="sourceContainer"/> to <paramref name="destinationContainer"/>.</returns>
public static async Task CopyBlobsAsync(CloudBlobContainer sourceContainer, CloudBlobContainer destinationContainer, BlobRequestOptions options, CancellationToken cancellationToken);

/// <summary>
/// Returns a <see cref="System.Threading.Tasks.Task"/> instance for the copy blob operation from <paramref name="sourceBlob"/> to <paramref name="destinationBlob"/>.
/// </summary>
/// <param name="sourceBlob">The <see cref="Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob"/> instance to be copied to <paramref name="destinationBlob"/>.</param>
/// <param name="destinationBlob">The <see cref="Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob"/> instance where <paramref name="sourceBlob"/> will be copied.</param>
/// <param name="options">The <see cref="Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions"/>.</param>
/// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken"/> instance used for cancellation.</param>
/// <returns>A <see cref="System.Threading.Tasks.Task"/> instance for the copy blob operation from <paramref name="sourceBlob"/> to <paramref name="destinationBlob"/>.</returns>
public static async Task CopyBlobAsync(CloudBlockBlob sourceBlob, CloudBlockBlob destinationBlob, BlobRequestOptions options, CancellationToken cancellationToken);

 

As usual, feedback and contributions in the GitHub project are always welcome.

 

Enjoy!

Using Facebook’s QuickReplies with PromptDialogs

In my last post I showed how easy it is to send Facebook’s quick replies using Microsoft Bot Framework. Using what we’ve learned; I’m now going to show you how you can use quick replies when using a PromptDialog.

 

Some of the PromptDialogs coming out of the box with the BotBuilder library (like the PromptChoice or PromptConfirm) expects a set of options (like the options to choose from) to be presented to the user. By default, these dialogs use a PromptStyler that based on the PromptStyle selected when creating the dialog; it will render the options in different ways: cards with buttons, all the options inline or one option per line to mention some of them.

The good news is that you can create your own PromptStyler and so, change the way the options are being rendered.

 

At this point, you might already have spotted what I will be doing as part of this post Smile. The whole idea is to create a custom PromptStyler that will take the provided options and render them as quick replies.

 

The code
The full sample is in GitHub. To run the sample, publish your bot, for example to Azure or use Ngrok to interact with your local bot in the cloud.

The code is extremely simple and is taking advantage of the models I put together in the previous post.

[Serializable]
public class FacebookQuickRepliesPromptStyler : PromptStyler
{
public override void Apply<T>(ref IMessageActivity message, string prompt, IList<T> options)
{
if (message.ChannelId.Equals("facebook", StringComparison.InvariantCultureIgnoreCase) && this.PromptStyle == PromptStyle.Auto && options != null && options.Any())
{
var channelData = new FacebookChannelData();

var quickReplies = new List<FacebookQuickReply>();

foreach (var option in options)
{
var quickReply = option as FacebookQuickReply;

if (quickReply == null)
{
quickReply = new FacebookTextQuickReply(option.ToString(), option.ToString());
}

quickReplies.Add(quickReply);
}

channelData.QuickReplies = quickReplies.ToArray();

message.Text = prompt;
message.ChannelData = channelData;
}
else
{
base.Apply<T>(ref message, prompt, options);
}
}
}

 

Using it in your dialogs is a no-brainer. Just provide an instance of the new PromptStyler when defining the prompt options and that’s it.

var promptOptions = new PromptOptions<string>(
"Please select your age range:",
options: new[] { "20-35", "36-46", "47-57", "58-65", "65+" },
promptStyler: new FacebookQuickRepliesPromptStyler());

PromptDialog.Choice(context, this.ResumeAfterSelection, promptOptions);

 

One caveat that I’m not addressing in this post is how to access the payload of the quick replies from the PromptDialog. In order to access to the payload, you will likely have to extend the PromptDialog (PromptConfirm is sealed but you can inherit from PromptChoice), override the MessageReceivedAsync and/or the TryParse and include the logic related to extracting the payload. Please refer to my previous post for the logic on how to extract the payload.

 

The outcome

image

image

Enjoy!

Sending Facebook’s Quick replies using Microsoft Bot Framework

Facebook’s quick replies are a great way to present buttons to the users. Per Facebook’s Quick Replies documentation:

Quick Replies provide a new way to present buttons to the user. Quick Replies appear prominently above the composer, with the keyboard less prominent. When a quick reply is tapped, the message is sent in the conversation with developer-defined metadata in the callback. Also, the buttons are dismissed preventing the issue where users could tap on buttons attached to old messages in a conversation.

Taking advantage of this feature when using Microsoft Bot Framework is really simple, even knowing this functionality is very specific to Facebook.

If you want to use special features or concepts for a channel, the Bot Framework provides a way to send native metadata to that channel giving you much deeper control over how your bot interacts on a channel. The way Bot Framework enables this is through the ChannelData property in the C# SDK and the sourceEvent property in Node.js.

Not every capability provided by a channel must go through the ChannelData property; that will basically depend on whether the functionality can be consistent across channels. When that’s the case, it’s very likely the functionality will be addressed in the core API, like with Rich card attachments.

 

The code

The full sample is in GitHub. To run the sample, publish your bot, for example to Azure or use Ngrok to interact with your local bot in the cloud.

The quick replies schema is pretty straightforward. Below is the portion of the code that creates some text only quick replies and assigns them to the activity’s ChannelData.

if (reply.ChannelId.Equals("facebook", StringComparison.InvariantCultureIgnoreCase))
{
var channelData = JObject.FromObject(new
{
quick_replies = new dynamic[]
{
new
{
content_type = "text",
title = "Blue",
payload = "DEFINED_PAYLOAD_FOR_PICKING_BLUE",
image_url = "https://cdn3.iconfinder.com/data/icons/developperss/PNG/Blue%20Ball.png"
},
new
{
content_type = "text",
title = "Green",
payload = "DEFINED_PAYLOAD_FOR_PICKING_GREEN",
image_url = "https://cdn3.iconfinder.com/data/icons/developperss/PNG/Green%20Ball.png"
},
new
{
content_type = "text",
title = "Red",
payload = "DEFINED_PAYLOAD_FOR_PICKING_RED",
}
}
});

reply.ChannelData = channelData;
}

Note that in the code I’m checking for the channel so quick replies are only sent in outgoing messages to a Facebook channel.


ProTip
: If you are planning to use quick replies in many places or in many bots and you don’t want to remember the required schema; I would recommend creating some helper classes to ease the work. I included those as part of the sample, and now the code looks like:

var channelData = new FacebookChannelData
{
QuickReplies = new[]
{
new FacebookTextQuickReply("Blue", "DEFINED_PAYLOAD_FOR_PICKING_BLUE", "https://cdn3.iconfinder.com/data/icons/developperss/PNG/Blue%20Ball.png"),
new FacebookTextQuickReply("Green", "DEFINED_PAYLOAD_FOR_PICKING_GREEN", "https://cdn3.iconfinder.com/data/icons/developperss/PNG/Green%20Ball.png"),
new FacebookTextQuickReply("Red", "DEFINED_PAYLOAD_FOR_PICKING_RED")
}
};

When a Quick Reply is tapped, a text message will be sent to your webhook Message Received Callback. The text of the message will correspond to the title of the Quick Reply. The message object will also contain the payload custom data defined on the Quick Reply.

Accessing the payload information only requires using the ChannelData of the message received after the user tapped the Quick Reply button. Optionally, you can create a typed model of the response and deserialize the channel data.

private async Task OnColorPicked(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var colorMessage = await result;

var message = $"Color picked: {colorMessage.Text}.";

if (colorMessage.ChannelId.Equals("facebook", StringComparison.InvariantCultureIgnoreCase))
{
var quickReplyResponse = colorMessage.ChannelData.message.quick_reply;

if (quickReplyResponse != null)
{
message += $" The payload for the quick reply clicked is: {quickReplyResponse.payload}";
}
else
{
message += " It seems you didn't click on a quick reply and you just typed the color.";
}
}

await context.PostAsync(message);

context.Wait(this.MessageReceivedAsync);
}

 

The outcome

As soon as you send a message to the Bot, it will respond with a question and the three quick replies. Intentionally, I’m showing quick replies with and without images.

image_thumb17

Once you tap on the quick reply button, the Bot will respond with the selected color and also it will show the defined payload for the quick reply button.

image_thumb18

Quick replies are just hints, you can still type something different, in which case the sample will detect that you didn’t tap on a quick reply button and it won’t look for the defined payload.

image_thumb19

 

As you can see, quick replies are powerful and really easy to use right from your Bot Framework based bot. If one of the channels you are supporting within your bot is Facebook, I would strongly recommend using them. To learn more about Facebook features with Bot Framework, please read here.

New Microsoft Azure Media Services SDK’s for Java and PHP release with FairPlay Streaming support

Over the last few days, the Azure SDK team published new releases of the Azure SDK for Java and Azure SDK for PHP packages that contain updates and new features for Microsoft Azure Media Services about Content Protection. In particular, both SDK’s now support Apple FairPlay Streaming (FPS) DRM dynamic encryption configuration and include improvements for Widevine DRM dynamic encryption configuration.

To take advantage of these features in your Java Maven projects, you need to use the latest Azure Media Service Java SDK (v0.9.4) by adding the following azure-media dependency in your pom.xml file.

<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-media</artifactId>
<version>0.9.4</version>
</dependency>

 

For PHP Composer projects, you need to use the latest Azure Media Service PHP SDK (v0.4.4) by adding the following microsoft/windowsazure dependency in the composer.json file – make sure to call require_once(‘vendor/autoload.php’); in your PHP files.

{
  "name": "my/sample",
    "license": "Apache-2.0",
    "require": {
        "microsoft/windowsazure": "^0.4"
    }
}

 

FairPlay Streaming DRM support

With this new release, you can now use the Azure Media Services REST API operations and entities to configure DRM dynamic encryption with Apple FairPlay Streaming (FPS) in both Java and PHP. Below you can find a sample VOD workflow that shows how to enable FairPlay Streaming:

For more details about Apple FairPlay Streaming (FPS) support in Azure Media Services, you can read the official general availability announcement by @mingfeiy: https://azure.microsoft.com/blog/apple-fairplay-streaming-for-azure-media-services-generally-available/.

 

Widevine DRM updates

When you create a Widevine Asset Delivery Policy, you have to specify the license acquisition URL for the common encryption Content Key assigned to the Asset. This value can be obtained by calling the GetKeyDeliveryUrl REST API operation on the Content Key instance. The URL returned by this call, however, contains the Content Key ID as a query string parameter: ?KID=<Guid>. This means that if you use this value “as is” in the configuration, the resulting Widevine Asset Delivery Policy will only be valid for that single Content Key instance.

With the new release, you can now reuse the same Widevine Asset Delivery Policy among multiple Assets. To do this, you just need to remove the query string from the Content Key license acquisition URL and then set it in the Asset Delivery Policy configuration using the new “Widevine Base License Acquisition Url” option. Below you can find some sample code snippets showing how to do this in both Java and PHP.

PHP sample code snippet

// $restProxy: Azure Media Services client context
// $contentKey: a common encrytion content key

$widevineUrl = $restProxy->getKeyDeliveryUrl($contentKey, ContentKeyDeliveryType::WIDEVINE);

// Remove query string
if (strpos($widevineUrl, '?') !== false) {
$widevineUrl = substr($widevineUrl, 0, strrpos($widevineUrl, "?"));
}

// Generate the AssetDeliveryPolicy configuration
$config = [AssetDeliveryPolicyConfigurationKey::WIDEVINE_BASE_LICENSE_ACQUISITION_URL => $widevineUrl];
$configuration = AssetDeliveryPolicyConfigurationKey::stringifyAssetDeliveryPolicyConfiguartionKey($config);

// Create a reusable AssetDeliveryPolicy for Widevine
$adpolicy = new AssetDeliveryPolicy();
$adpolicy->setName('Reusable Widevine Delivery Policy');
$adpolicy->setAssetDeliveryConfiguration($configuration);
$adpolicy->setAssetDeliveryProtocol(AssetDeliveryProtocol::DASH);
$adpolicy->setAssetDeliveryPolicyType(AssetDeliveryPolicyType::DYNAMIC_COMMON_ENCRYPTION);
$adpolicy = $restProxy->createAssetDeliveryPolicy($adpolicy);

Java sample code snippet

// mediaService: Azure Media Services client context
// contentKey: a common encrytion content key

String widevineUrl = mediaService.create(ContentKey.getKeyDeliveryUrl(contentKey.getId(), ContentKeyDeliveryType.Widevine));

// Remove query string
if (widevineUrl.contains("?")) {
widevineUrl = widevineUrl.substring(0, widevineUrl.indexOf("?"));
}


// Generate the AssetDeliveryPolicy configuration
Map<AssetDeliveryPolicyConfigurationKey, String> configuration = new HashMap<AssetDeliveryPolicyConfigurationKey, String>();
configuration.put(AssetDeliveryPolicyConfigurationKey.WidevineBaseLicenseAcquisitionUrl, widevineUrl);

AssetDeliveryPolicyInfo assetDeliveryPolicy = mediaService.create(AssetDeliveryPolicy.create()
.setName("Reusable Widevine Delivery Policy")
.setAssetDeliveryConfiguration(configuration)
.setAssetDeliveryPolicyType(AssetDeliveryPolicyType.DynamicCommonEncryption)
.setAssetDeliveryProtocol(EnumSet.of(AssetDeliveryProtocol.Dash)));

 

Enjoy!

Azure Media Services updates in new Azure portal

Azure Portal

Last month, the Azure Media Services team announced the availability of Azure Media Services functionalities through portal.azure.com (codename Ibiza) in public preview; you can check all the details in this blog post by @mingfeiy. After this announcement, there were some updates to the new portal with more features, enhancements and several bug fixes.

In this post you will find a quick summary of what is new and what has changed in the new portal for Azure Media Services.

 

Add FairPlay DRM protection onto both VOD and live stream

You can now configure the default content key authorization policy for FairPlay DRM from the Content Protection blade by providing the App Certificate (.pfx file containing the private key along with its password) and the Application Secret Key (ASK) received when you generate the certification using Apple Developer portal.

Content Protection blades for FairPlay DRM

After configuring the default content key authorization policy for FairPlay DRM, two new encryption options are going to be available for both VOD and live stream assets.

  • PlayReady and Widevine with MPEG-DASH + FairPlay with HLS
  • FairPlay only with HLS

Adding FairPlay delivery policy in a VOD asset

Adding FairPlay delivery policy in a live stream asset

For more details about FairPlay Streaming (FPS) support, you can check this blog post: Stream premium content to Apple TV with Azure Media Services.

 

Enable/Disable CDN in Streaming Endpoint

After creating a streaming endpoint, you can now enable/disable CDN feature from the Streaming Endpoint Details blade. Remember that, in order to enable CDN feature, the streaming endpoint must be in Stopped state and have at least one streaming unit.

Streaming Endpoint Details blade

 

Improve delete Channel experience

In order to delete a channel, the Azure Media Services REST API validates that:

  • The channel is in Stopped state 
  • The channel does not contain any programs

The original implementation of the Delete command was only enabled in channels satisfying both conditions. To make it easier for Azure portal users, it is now always enabled and takes care of performing these operations (if necessary):

  • Stop all the programs in the channel
  • Delete all the programs in the channel
  • Stop the channel
  • Delete the channel

Channel blade

 

Show ‘Account ID’ property in the Summary and Properties blades

The Media Services ‘Account ID’ is now available in both the Summary and Properties blades. This value is useful, for example, when you want to submit a support request through the Azure portal and univocally identify your account.

Summary and Properties blades

 

Bug Fixes

  • Create Media Services Account blade: Account Name availability validation fails when the user has a disabled subscriptions
  • Create Media Services Account blade: Location dropdown is empty for some subscriptions
  • Asset blade: Encrypt command does not get automatically enabled when the asset type changes after an encoding job finishes
  • Publish the Asset blade: Notification error message when scaling streaming endpoint while creating a streaming locator
  • Asset Media Analytics blade: Remove frame limit for Azure Media Hyperlapse Media Processor
  • Create a new Channel wizard (Custom Create): Channel creation fails when ingest streaming protocol is set to RTP/MPEG-2
  • Create a new Channel wizard (Custom Create): Wrong ingest streaming protocol set when creating multiple channels
  • Create a Live Event blade: Binding issue in Archive Window field
  • Streaming Endpoint Details blade: Streaming units max limit is 5 but it should be 10
  • Streaming Endpoint Settings blade: Setting an entry in the Streaming Allowed IP Addresses table breaks media streaming
  • Media Services blades fail to load in Safari for Mac
  • Delete operations do not work after performing an update on the same entity

 

Enjoy!

Microsoft Azure Media Services SDK for Java v0.9.1 released with support for Widevine dynamic encryption

microsoft-azure-java-sdk-for-media-services

Last Friday, the Azure SDK team published a new release of the Azure SDK for Java Maven packages; you can find the full list at http://search.maven.org/#search|ga|1|com.microsoft.azure. In particular, there were was a minor new release (v0.9.1) of the Azure Media Services SDK for Java that adds support for Widevine (DRM) Dynamic Common Encryption and License Delivery Service; below I’m listing the change log.

If you want to use the Java SDK in your Maven project, you just need to add the “azure-media” dependency in your pom.xml file as follows:

<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-media</artifactId>
<version>0.9.1</version>
</dependency>

 

To demonstrate the new Java SDK features, I created the azure-media-dynamic-encryption-playready-widevine sample console Java application that contains a VOD end-to-end workflow that uses PlayReady and Widevine (DRM) Dynamic Common Encryption and the License Delivery Service for playback. It is based on the .NET sample explained in this documentation article: https://azure.microsoft.com/documentation/articles/media-services-protect-with-drm/.

You can access the full source code of this sample at: https://github.com/southworkscom/azure-sdk-for-media-services-java-samples/tree/master/azure-media-dynamic-encryption-playready-widevine.

Media Services SDK for Java sample projects in Eclipse

 

v0.9.1 Change Log

 

Enjoy!