This document contains the instructions for generating streaming content (both VOD and Live) in Azure Media Services so it can be used for testing the different 3rd party players. The different playback endpoints (HLS, DASH, DRM, etc.), ingest URLs, and license server URLs will be the output of this process. The output then is used to generate an index page with links to test all the content in each player. The scripts also deploy the samples (that will contain the output and the index page) to a static website hosted on an Azure storage blob container.
-
Clone the repository.
git clone https://github.com/Azure-Samples/media-services-3rdparty-player-samples.git
-
Launch a PowerShell terminal.
-
Login into your Azure account.
az login
-
Select a subscription.
az account set --subscription "subscription name"
-
Navigate to the
setupfolder in the cloned directory.cd .\media-services-3rdparty-player-samples\setup
-
Copy the example configuration.
Configuration without FairPlay:
Copy-Item .\config.json.example .\config.jsonConfiguration with FairPlay (This configuration requires a FairPlay Private key and public certificate):
Copy-Item .\config.json.fairplay.example .\config.jsonNote: If the
config.jsonfile doesn't exist, the script will automatically copy it fromconfig.json.example. We suggest you to create your ownconfig.jsonbefore running the script if you want to customize the configuration. -
Update the configuration
Open the
config.jsonto select the names of the Azure resources that you'll use. If these resources doesn't exist, the script will create them for you:"ResourceGroup": "amsplayerresource", "StorageAccount": "amsplayerstorage", "MediaServiceAccount": "amsplayeraccount"
Configure the token by setting the
keyproperty in thetokensection:key: Either a string (40 characters) for symmetric key, or a file path to a certificate (X509) or public key (RSA).
See here for additional configurations options.
If you are configuring FairPlay complete the
config.jsonwith the following values:typeValue: with the path of your private key.ask: with the key that must be used as FairPlay Application Secret Key, which is a 32-character hex string.fairPlayPfxPasswordwith the password encrypting FairPlay certificate in PKCS 12 (pfx) format.FairPlayPublicCertPath: with the path of your public certificate.
This should be loaded both in
DRMOpenandDRMTokensections of the Content Key Policies. -
Set up the content
After completing the required fields in the
config.json, you can configure the basic Azure resources with:.\setup.ps1 .\setup-vod.ps1 .\setup-live.ps1
Note: Find detailed information of what each script doesbelow.
While running the
setup-vod.ps1script, you'll be asked if you want to start the default streaming endpoint and, if you do, your content will be ready to be played.Note: Keep in mind that once the streaming endpoint is started you will begin to be charged (more information in the Avoiding extra costs section). You can always start the default streaming endpoint later by executing the following command:
.\start-endpoint.ps1After running the
setup-vod.ps1script, anoutput.jsonfile in thesrcfolder will be generated, containing the VOD manifests URLs, a token (for testing), the license URLs, and the content keys IDs (one for the DRM open and one for the DRM with token protected content). More information about theoutput.jsonfile can be found in the Documentation section.Also, a
transcript.vttfile, generated using Video Indexer, will be downloaded into thesrcfolder.Execute the following script to start a live stream:
.\start-live.ps1While running the
start-live.ps1, you'll be asked to connect your live encoder to one of the ingest URLs provided. You can skip this but the script will try to get the manifests URLs anyway and they won't be completely generated until the encoder is correctly connected, so you will see just the host name of the manifests (obtained from the streaming endpoint) in theoutput.json. If you decided to skip it, you can re-run thestart-live.ps1script once you have your encoder connected and this will complete theoutput.jsonwith the live stream content (manifests and license URLs and content keys IDs).Keep in mind that once you run the
start-live.ps1script, the default streaming endpoint and the live event will be running whether you connect the encoder or not, and this will generate costs. Please see the Avoiding extra costs section for more information.The live streaming content is different from the VOD content since the manifest URLS (and, therefore, the content key IDs) will change every time you start and stop it. So the section for live stream in the
output.jsonwill change constantly.If you need to change the mode of the live stream to enable low latency or live transcription, you need to run the
setup-live.ps1script. This will stop and delete any running resource and create a new live event so when you run thestart-live.ps1it will use that mode. In this case, the ingest URLs will change. -
Deploy a static web site.
In the
srcfolder there is anindexpage configured which generates links with the URLs and parameters needed in the player to reproduce the content. This data is loaded from theoutput.json.You can create a static website with the
indexand the players samples with:.\upload-samples.ps1This script enables a static web site in the storage account selected in the
config.jsonand uploads into its blob container, called$web, the entiresrcfolder. It also configures theindexand returns the URL to access it.If you run this without previously executing the other scripts, the
indexwill contain only a link to each player sample where you can test any manifest.If you change the live stream mode, run this script again so the
output.jsonis updated and the links use the new URLs.Once you have completed all the tests, and if you won't use any of the content anymore, you can delete your resource group with the script
delete.ps1.More technical details on what each file and script does and contains is here.
There are three main cost-generators when you set up the content:
- The
streaming endpointin running state. - The
live eventin running state. - The
blob storage.
More information about Azure Media Services pricing is here. You can also find the encoding price for the VOD, but as the scripts use a short video to encode and as it's run just once, the cost should be negligible.
More information about blob storage pricing here.
The live stream content requires both live event and streaming endpoint to be running to work and the VOD just requires the streaming endpoint.
We recommend that once the live stream is not used anymore run:
.\stop-live.ps1This will stop the live event and will delete all the generated content, so the overall blob storage costs will be reduced. Take into account that this script won't stop the streaming endpoint, so the VOD content will continue to work. Once you start it again, all the live stream content from the output.json will be removed as it will change.
To stop the streaming endpoint run:
.\stop-endpoint.ps1The resource creation process can be configured through a config.json file. An example is uploaded here.
If you run a script and there is no config.json, it will create it from the example.
config.json
"ResourceGroup": "amsplayerresource", // Name of the resource group
"StorageAccount": "amsplayerstorage", // Name of the storage account. Supports only lowercase letters between 4-40 characters
"MediaServiceAccount": "amsplayeraccount", // Name of the media service account. Supports only lowercase letters between 4-40 characters
"Location": "westus2", // Location where the script will verify and create the resources
"CKP": {
"DRMOpen": {
"name": "drmopen", // Name of the Content Key Policy
"options": [] // Options of the Content Key Policy
},
"DRMToken": {
"name": "drmtokenized", // Name of the Content Key Policy
"options": [] // Options of the Content Key Policy
},
"encryptionOpen": {
"name": "clearkeyopen", // Name of the Content Key Policy
"options": [] // Options of the Content Key Policy
},
"encryptionToken": {
"name": "clearkeytoken", // Name of the Content Key Policy
"options": [] // Options of the Content Key Policy
}
},
"token": {
"type": "Jwt", // The type of token. Allowed values: Jwt, Swt
"keyType": "Symmetric", // The type of the token key to be used for the primary verification key. Allowed values: Symmetric, RSA, X509
"key": "{secure key}", // Either a string (40 characters) for symmetric key or a file path to a certificate (x509) or public key (rsa)
"issuer": "randomissuer", // The token issuer for the token
"audience": "randomaudience", // The audience for the token
"duration": "604800" // The time in seconds that the token will work. A week is set by default
},
"VOD": {
"video": "sample-vod.mp4", // Path to the file relative to the script location to be uploaded and encoded
"preset": "adaptiveStreaming" // Encode option for the transform (https://docs.microsoft.com/en-us/azure/media-services/latest/encoding-concept#builtinstandardencoderpreset)
},
"liveStream": {
"liveEventName": "liveeventname", // The name for the Live Event to be created.
"assetName": "liveassetname", // The asset where the Live Encoding will save the output to be streamed
"encodingType": "Standard", // The encoding type for live event. This value is specified at creation time and cannot be updated. Allowed values: Basic, None, Standard.
"presetName": "Default720p", // The encoding preset name. This value is specified at creation time and cannot be updated.
"liveOutputName": "liveoutput", // The name of the live event.
"mode": "default" // Allowed values: default, transcription, lowLatency
},
"FairPlayPublicCertPath": "" // Path to Public FairPlay CertificateThe Content Key Policies can have more than one option. Each option can have the fields:
name: Name of the option which is required for all Content Key Policiestype: Parameter to configure the DRM or encryption option (--widevine-template /--play-ready-template / -fair-play-pfx / --clear-key-configuration) which is required for all Content Key PoliciestypeValue: Value of the type, a path to the json license file, json string (Widevine works with an empty json), empty for encryption or the file path to a FairPlay certificate file in PKCS 12 (pfx) format (including private key). This field is required for all Content Key Policies.ask: The key that must be used as FairPlay Application Secret Key which is a 32 character hex string and is required for FairPlay Content Key PolicyfairPlayPfxPassword: The password encrypting FairPlay certificate in PKCS 12 (pfx) format which is required for FairPlay Content Key PolicyrentalAndLeaseKeyType: The rental and lease key type using the available values: Undefined, DualExpiry, PersistentUnlimited, PersistentLimitedrentalDuration: The rental duration which must be greater than or equal to 0
In this sample, the Content key Policy with DRM and token protection will be created with Widevine and PlayReady options:
"DRMToken": {
"name": "drmtokenized",
"options": [
{
"name": "widevineopen",
"type": "--widevine-template",
"typeValue": "\"{}\""
},
{
"name": "playreadyopen",
"type": "--play-ready-template",
"typeValue": "@payload/playreadylicense.json"
},
{
"name": "fairplayopen",
"type": "--fair-play-pfx",
"typeValue": "@fairplay.pfx",
"ask": "ask-32-chars-hex-string",
"fairPlayPfxPassword": "pfxPassword",
"rentalAndLeaseKeyType": "PersistentUnlimited",
"rentalDuration": "5000"
}
]
}In the Setup directory there is a playreadylicense.json already created with the default template.
In the config.json.example there is an extra parameter called disabled-options in the first Content Key Policy for a FairPlay sample. It won't be used in the scripts.
The output of each script will be saved in this file located in the src folder. The file will contain all the information required to test the different features on each players, including ingest URLs, manifest URLs, token, licence URLs, licence keys, and captions.
The file is also consumed by the index page of the sample player to generate the links to the different content.
{
"VOD": {
"clear": [],
"DRMOpen": [],
"DRMToken": [],
"encryptionOpen": [],
"encryptionToken": [],
"subtitle": "",
"DRMOpenKIDCENC": "",
"DRMOpenKIDCBCS": "",
"DRMTokenKIDCENC": "",
"DRMTokenKIDCBCS": ""
},
"LiveStream": {
"mode": "",
"ingestURLs": [],
"clear": [],
"DRMOpen": [],
"DRMToken": [],
"encryptionOpen": [],
"encryptionToken": [],
"DRMOpenKIDCENC": "",
"DRMOpenKIDCBCS": "",
"DRMTokenKIDCENC": "",
"DRMTokenKIDCBCS": ""
},
"WidevineLicenseURL": "",
"PlayReadyLicenseURL": "",
"FairPlayLicenseURL": "",
"FairPlayPublicCertPath": "",
"KeyDeliveryUrl": "",
"Token": ""
}What this script does:
- Creates (if they don't exist) a Resource Group, a Storage Account and an Azure Media Services Account with the names specified in the
config.jsonfile. - Creates (if it doesn't exist) a Streaming policy for using CENC encryption in DASH and HLS URLs and CBCS in HLS.
- Creates (if they don't exist) the Content Key Policies with the options specified in the
CKPsection of theconfig.jsonfor:- Open DRM
- Tokenized DRM
- Open ClearKey
- Tokenized ClearKey
Requirements:
The following fields must be filled in the config.json file:
ResourceGroupStorageAccountMediaServiceAccountLocationCKPtokentypekeyTypekeyissueraudienceduration
Run:
.\setup.ps1What this script does:
- Creates asset.
- Uploads the file.
- Creates the transform with the selected preset in the
config.json. - Runs a new job to transform the created asset and saves the result into an output asset.
- Creates a transform with the preset AudioAnalyzer.
- Runs a new job with the AudioAnalyzer preset transform and downloads the generated
trancript.vttinto thesrcfolder. - Generates the streaming locators for:
- Clear VOD
- Open MultiDRM VOD
- Tokenized MultiDRM VOD
- Open ClearKey VOD
- Tokenized ClearKey VOD
- Gets all the URLs from the streaming locators and saves them into
output.jsonfile. - Extracts license URLs from the manifest. To extract them, it performs the following steps:
- Downloads the DASH DRM protected manifest from the generated URL.
- Opens the manifest and finds the XPath /MPD/Period/AdaptationSet/ContentProtection/laurl/licenseUrl. This node contains the license URL for Widevine.
- The license URLs for PlayReady are generated with the host of Widevine’s license URL, plus /PlayReady/.
- The license URLs for FairPlay are generated with the host of Widevine’s license URL, plus /FairPlay/.
- Gets the content keys and saves their IDs into the
output.json. - Ask whether the user wants to start the default streaming endpoint.
Requirements:
setup.ps1executed beforehand.- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccountVODfilePathpreset
Run:
.\setup-vod.ps1This script does creates the live event with the name specified in the config.json file.
Requirements:
setup.ps1executed before- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccountliveStreamliveEventNameencodingTypepresetNamemode(in order to change the mode, runsetup-live.ps1again with the new configuration)
Run:
.\setup-live.ps1What this script does:
- Creates a new asset.
- Creates a new live output.
- Generates the streaming locators for:
- Clear Live stream
- Open DRM Live stream
- Tokenized DRM Live stream
- Open ClearKey Live stream
- Tokenized ClearKey Live stream
- Starts the default streaming endpoint.
- Starts the live event.
- Saves the ingest URLs which are to be used in your streaming software of choice, and where you'll need to provide them in order to start the live stream. If your software awaits for a password, enter
default. - The script now waits for the user to connect to an ingest URL.
- Saves the playback URLs in the
output.jsonfile. - Extracts license URLs from manifest. To extract them, it performs the following steps:
- Downloads the DASH DRM protected manifest from the generated URL.
- Opens the manifest and finds the XPath /MPD/Period/AdaptationSet/ContentProtection/laurl/licenseUrl. This node contains the license URL for Widevine.
- The license URLs for PlayReady are generated with the host of Widevine’s license URL, plus /PlayReady/.
- The license URLs for FairPlay are generated with the host of Widevine’s license URL, plus /FairPlay/.
- Gets the content keys and save their IDs into the
output.json.
Requirements:
setup.ps1executed beforehandsetup-live.ps1executed beforehand- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccountliveStreamliveEventNameassetNameencodingTypeliveOutputNamemode
Run:
.\start-live.ps1What this script does:
- Stops the live event.
- Deletes the live output.
- Deletes the asset.
- Removes the ingest URLs, the playback URLs and the content key IDs from the
output.jsonfile.
Requirements:
setup.ps1executed beforehand.setup-live.ps1executed beforehand.start-live.ps1executed beforehand.- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccountliveStreamliveEventNameassetNameliveOutputNameliveTranscription
Run:
.\stop-live.ps1What this script does:
- Starts the default streaming endpoint.
Requirements:
setup.ps1executed beforehand.- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccount
Run:
.\start-endpoint.ps1What this script does:
- Stops the Live Event if running.
- Stops the default Streaming Endpoint.
Requirements:
setup.ps1executed beforehand.- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountMediaServiceAccount
Run:
.\stop-endpoint.ps1This script deletes the resource group indicated in the config.json file.
Requirements:
setup.ps1executed beforehand.- The following fields must be filled in the
config.jsonfile:ResourceGroup
Run:
.\delete.ps1What this script does:
- Enables the storage account specified in
config.jsonfile to host a static website. - Uploads to the blob storage the samples.
- Uploads to the blob the output.json.
- Prints the URL to access the static website.
Requirements:
setup.ps1executed beforehand- The following fields must be filled in the
config.jsonfile:ResourceGroupStorageAccountFairPlayPublicCertPathOnly if FairPlay is configured.
Optional parameters:
- output: --output, upload only output.json and exclude the samples.
- samples: --samples, upload only samples and exclude the output.json.
Run:
.\upload-samples.ps1To upload only output.json:
.\upload-samples.ps1 --outputTo upload only samples:
.\upload-samples.ps1 --samples