Eluvio Content Fabric: Ingesting Media for Adaptive Bit Rate (ABR) Streaming

last revised: 2021-04-14

Basic Concepts 

In the Content Fabric, ingesting video for streaming involves two kinds of objects, Production Masters and ABR Mezzanines:

The ingest process consists of the following steps:

  1. Create a Production Master object that points to your master source files (alternately, local master source files can be uploaded to the fabric)
  2. Create an ABR Mezzanine object that points to the Production Master and adds streaming resolutions / bitrates as well as any DRM / watermarking. Once you create the mezzanine, the Content Fabric will begin transcoding.
  3. Finalize the ABR Mezzanine after transcoding has finished.
  4. (Optionally) Setting trim points and/or adding subtitles

NOTE: Although currently caption/subtitle files are added to ABR Mezzanines separately after creation, in the future this may be changed so that they are part of the original Production Master instead.

Preparation 

Find your Content Fabric private key and record it in a safe place 

  1. Navigate to the Content Fabric Browser page
  2. Enter the password you chose when first setting up your account
  3. Click on the eluv.io logo at top left
  4. Click on Profile
  5. Click on the key icon image of key icon to reveal your private key (0x… )
  6. Double-click on this value and copy
  7. IMPORTANT: Save in a safe place (a permanent file). Do not share this key. The Content Fabric is designed to be trustless - we do not keep a copy of your key and cannot reset or recover it for you. Until you save a copy of your key somewhere it only exists in your browser's local storage, which can get erased if you choose to wipe your browser history.

Download and set up the elv-client-js library 

Updating your copy of elv-client-js 

If you need to update to the latest version of elv-client-js, you can do so with:

cd elv-client-js
git pull
npm install

DEPRECATION NOTICE 

This documentation uses scripts in directory /elv-client-js/testScripts.

These will eventually be replaced by new scripts in directory /elv-client-js/utilities. To minimize disruption to existing customer workflows, the existing testScripts directory and its contents will remain for the time being, but deprecation warning messages will be added to the old scripts as corresponding replacements become available.

Differences between old and new scripts are detailed in the following Google doc:

Create a Production Master object 

The Production Master object contains links to your original source material. It is not directly playable, but is used to generate a playable Mezzanine object.

To create a Production Master, you will need the following:

Get your Production Master Content Type name and/or ID 

Each tenant of the Content Fabric has a number Content Types created for them. These provide a way of customizing the structure of your fabric objects.

If you click on Content Types on the left side you will see a list of these types, among which should be one named "TENANT_NAME - Title Master".

If you click on this item, you will see a detail screen where you can select and copy the Name and Object ID for this Content Type. When you run commands to create Production Masters, you will need to supply either the name or the ID of this content type, e.g.:

--type "TENANT_NAME - Title Master"

or

--type iq__... (your 'Title Master' content type ID - content type IDs start with "iq__")

NOTE: In the instructions below there are a number of operations done via browser. These can be done programmatically as well and we can provide code samples as needed.

Get your Production Master Library ID 

Click on Content in the left sidebar to get to your list of libraries.

Each tenant also has a number of libraries created for them, including one to hold Production Masters - it should be labeled "TENANT_NAME - Title Masters". Click on this item to see a list of objects currently in the library (initially it may be empty).

On the next screen, click on the Library Info tab to find the Library ID. When you run commands to create Production Masters, you will need to supply this ID, e.g.:

--library ilib... (your 'Title Masters' library ID - library IDs start with "ilib")

Create from a file on AWS S3 

Here is a sample command line to generate a Production Master using a file on AWS S3. Once you have the required information, substitute it into the sample below (if you do not need to attach an asset ID, you can omit the --ip-title-id line):

    cd elv-client-js

    node testScripts/CreateProductionMaster.js \
      --library ilib3xDQU7yDgZZQsmMwUrHTwzAEbbdu \
      --title "Big Buck Bunny (master)" \
      --s3-reference \
      --type "TENANT_NAME - Title Master" \
      --ip-title-id "YOUR_INTERNAL_ASSET_ID" \
      --files bbb_sunflower_1080p_60fps_stereo_abl.mp4

NOTE: Our convention in this case is to omit the "s3://" prefix and bucket name from the start of file path, i.e. use bbb_sunflower_1080p_60fps_stereo_abl.mp4 instead of s3://BUCKET_NAME/bbb_sunflower_1080p_60fps_stereo_abl.mp4. If the file is in a subdirectory, start with the name of the subdirectory, without any leading slash character (/)

Create from a local file 

Here is a sample command line to generate a Production Master using a local file. Once you have the required information, substitute it into the sample below (if you do not need to attach an asset ID, you can omit the --ip-title-id line):

    cd elv-client-js

    node testScripts/CreateProductionMaster.js \
      --library ilib3xDQU7yDgZZQsmMwUrHTwzAEbbdu \ 
      --title "Big Buck Bunny (master)" \
      --type "TENANT_NAME - Title Master" \
      --ip-title-id "YOUR_INTERNAL_ASSET_ID" \
      --files PATH_TO_YOUR_DIRECTORY/bbb_sunflower_1080p_60fps_stereo_abl.mp4

Check output from CreateProductionMaster.js script 

When you run the CreateProductionMaster.js script, the server examines the file(s) for audio and video streams, then makes a simple guess about what should be included in the mezzanine.

You should see output like the following:

Creating Production Master

Production Master
{ done: true, uploadedFiles: 1, totalFiles: 1 }

Production master object created:
        Object ID: iq__2QEH2nqrLkwZpkNoguw1RGW7hFK4
        Version Hash: hq__9v2JY21ESnsvNdwWwgJrjiw7jHWv5nXik6quVn6FUgDxbgTgJT8toxBVb1ShZZH4mcFSFcJUJJ

If you included any non-media files in the --files list, you will also see warnings at the end of the output complaining Failed to create media.Source from file. These can be ignored as long as you included at least one media file.

If the server did not find a presupplied stereo (2-channel) audio stream among the files, you will see the following warning:

WARNING: no audio stream found

If the server did not find a video stream among the files, you will see the following warning:

WARNING: no video stream found

A Production Master contains one or more Variants. A Variant is one version of the original title (this allows you to create different content versions for particular countries or distribution channels). The CreateProductionMaster.js script creates a single Variant named default.

Clicking on the Show Metadata button and drilling down into production_mastervariantsdefaultstreams will reveal what files and stream indexes the server has chosen to include in this "default" Variant.

Set Mezzanine object visibility to 'Viewable' - via browser 

In order to make the Mezzanine viewable for your site, you must set overall permission level for object to Viewable.

From the object details page, click the Content Info tab, then change the Permissions: line to Viewable.

If you cannot change the Permissions: line, make sure you are logged in to the Fabric Browser with the private key used to create the mezzanine.

Set Mezzanine object visibility to 'Viewable' - via command line 

In order to make the Mezzanine viewable using the command line, you will need to know the following:

The command to add permissions is then:

node testScript/ObjectSetPermissions.js \
  --objectId YOUR_OBJECT_ID \
  --value Viewable

Grant Group Permissions on Production Master object - via browser 

In order to let other Content Admins work with your Production Master object, you must grant group permissions to an Access Group.

From the object details page, click the blue Groups button at top - you should see a screen with the Access Group field already chosen for you, set to "TENANT_NAME Content Admins".

Check the Manage box, then click Submit.

Grant Group Permissions on Production Master object - via command line 

In order to grant group permissions via the command line, you will need to know the following:

You can find the Address of your group by clicking on the blue Groups button at top when you are browsing the details of any object. You can choose a group from the Access Group dropdown, then double-click the Address field to select it and copy to your clipboard.

The command to add permissions is then:

node testScripts/AddGroupPermissions.js \
  --objectId YOUR_OBJECT_ID \
  --groupAddress YOUR_GROUP_ADDRESS \
  --permissions manage

(If needed) Change streams on Production Master Variant 

If you need to make any changes to the Variant's stream selections (e.g. because the server did not choose the desired streams, or if you wish to add more audio streams) you can use scripts to add/edit/remove Variant streams. In order to use these scripts, you will need to look at the Production Master's existing stream information.

Display Production Master Stream Info 

You can inspect stream information for files and Variants in the fabric browser by clicking on the Show Metadata button and drilling down by clicking on productionmastersources(filename)streams and productionmastervariants(variant name)streams. (Clicking on a downward pointing triangle ▼ will expand all details for a line item, clicking on an expanded line item will collapse it)

Alternately, you can use the ProductionMasterInfo.js script, which will output a subset of this information:

node testScripts/ProductionMasterInfo.js \
  --libraryId YOUR_LIBRARY_ID  \
  --objectId YOUR_MASTER_OBJECT_ID

Add stream to Production Master Variant 

In order add a stream to a Variant, you will need to supply the following information:

The command to add the stream is then would resemble the following:

(note that --mapping, SECOND_STREAM_INDEX, and --isDefault would not always be included)

node testScripts/VariantAddStream.js \
  --libraryId YOUR_LIBRARY_ID  \
  --objectId YOUR_MASTER_OBJECT_ID  \
  --variantKey THE_VARIANT_NAME \
  --streamKey YOUR_CHOSEN_STREAM_KEY \
  --file THE_FILENAME \
  --label YOUR_EXTERNALLY_VISIBLE_STREAM_LABEL \
  --language THE_LANGUAGE_CODE \
  --streamIndex FIRST_STREAM_INDEX SECOND_STREAM_INDEX \
  --mapping THE_MAPPING \
  --isDefault

Here is a sample command with example values filled in, for the case where the master source file contains a stereo audio stream:

node testScripts/VariantAddStream.js \
  --libraryId ilib3t4Cf8pdxftVcc4Si35yZxPgN33  \
  --objectId iq__3RVmL1WdnVj7mYrKZcDUPpzstFNU  \
  --variantKey default \
  --streamKey audio-alternate \
  --file MyAlternateAudio.mp4 \
  --label "Director's commentary" \
  --language en \
  --streamIndex 0

Once you run the command, it will output the new version hash for the Production Master. You will need this value in order to create a mezzanine, unless you have more streams to add to the Variant, in which case you will need the version hash that is output by your final VariantAddStream.js command.

Edit existing stream in Production Master Variant 

The command to edit a stream is similar to the one for adding a stream. In order edit a stream in a Variant, you will need to supply the following information:

The command to edit the stream is then would resemble the following:

(note that --mapping, SECOND_STREAM_INDEX, and --isDefault would not always be included)

node testScripts/VariantEditStream.js \
  --libraryId YOUR_LIBRARY_ID  \
  --objectId YOUR_MASTER_OBJECT_ID  \
  --variantKey THE_VARIANT_NAME \
  --streamKey THE_EXISTING_STREAM_KEY \
  --file THE_FILENAME \
  --label YOUR_EXTERNALLY_VISIBLE_STREAM_LABEL \
  --language THE_LANGUAGE_CODE \
  --streamIndex FIRST_STREAM_INDEX SECOND_STREAM_INDEX \
  --mapping THE_MAPPING \
  --isDefault

Here is a sample command with example values filled in, to change the streamIndex from the previous example to 1 instead of zero:

node testScripts/VariantAddStream.js \
  --libraryId ilib3t4Cf8pdxftVcc4Si35yZxPgN33  \
  --objectId iq__3RVmL1WdnVj7mYrKZcDUPpzstFNU  \
  --variantKey default \
  --streamKey audio-alternate \
  --file MyAlternateAudio.mp4 \
  --label "Director's commentary" \
  --language en \
  --streamIndex 1

Once you run the command, it will output the new version hash for the Production Master. You will need this value in order to create a mezzanine, unless you have more streams to edit, in which case you will need the version hash that is output by your final VariantEditStream.js command.

Remove existing stream from Production Master Variant 

In order remove a stream from a Variant, you will need to supply the following information:

The command to edit the stream is then would be the following:

node testScripts/VariantRemoveStream.js \
  --libraryId YOUR_LIBRARY_ID  \
  --objectId YOUR_MASTER_OBJECT_ID  \
  --variantKey THE_VARIANT_NAME \
  --streamKey THE_EXISTING_STREAM_KEY

Once you run the command, it will output the new version hash for the Production Master. You will need this value in order to create a mezzanine, unless you have more streams to remove, in which case you will need the version hash that is output by your final VariantRemoveStream.js command.

Create a Mezzanine object 

A Mezzanine object contains transcoded media optimized for adaptive bitrate (ABR) streaming. Depending on the ABR profile you choose, it is playable via HLS and/or DASH with DRM (you also have the option to offer playout in the clear).

To create a Mezzanine, you will need the following:

NOTE: In the instructions below there are a number of operations done via browser. These can be done programmatically as well and we can provide code samples as needed.

Find the latest version hash for your Production Master 

Any script that creates and/or modifies a Production Master will output the new version hash for the object, e.g.:

Adding stream 'audio' to variant 'default'... 
Writing metadata back to object...
Finalizing object...
New version hash: hq__N8VZbpdEtRyTsuPtnczwKNi2hgFNu3F7CJEHmroPqbwEaJNwoL9tiGGLEvi7zm4ZpGmQrntWT
Done.

Version hashes always start with the characters hq__ and this value can be copied and pasted in your command terminal window.

Alternately, you can also look up the version hash in the Fabric Browser and copy from there:

In your browser, if you click on Content in the left sidebar, then click on your Title Masters library, you should be able to find your new Production Master object.

(If you are already on the page that lists objects in the library you may need to click the refresh icon image for refresh icon to see the new object)

Clicking on the object will show you details about the object. For the next step (generating a mezzanine) you will need the Latest Version Hash for the object. This value (hq__9v2JY2… for this example) can be copied by clicking on the clipboard icon as shown below. It is also listed in the output from the CreateProductionMaster.js script.

image for copy latest version hash

Get your Mezzanine Content Type name and/or ID 

Click on Content Types on the left side and click on the one named "TENANT_NAME - Title".

You will see a detail screen where you can select and copy the Name and Object ID for this Content Type. When you run commands to create Mezzanines, you will need to supply either the name or the ID of this content type, e.g.:

--type "TENANT_NAME - Title"

or

--type iq__... (your 'Title' content type ID - content type IDs start with "iq__")

Get your Mezzanine Library ID 

Click on Content in the left sidebar to get to your list of libraries.

Click on the one labeled "TENANT_NAME - Titles", then click on the Library Info tab to find the Library ID. When you run commands to create Mezzanines, you will need to supply this ID, e.g.:

--library ilib... (your 'Titles' library ID - library IDs start with "ilib")

Choose an ABR Profile 

An ABR Profile contains information on what formats, resolutions and bitrates to offer for streaming playout, as well as any DRM and/or watermarking information.

There are JSON files containing commonly used profiles in elv-client-js/testScripts/

The 4k files are specifically for offering 16:9 material at 3840x2160 resolution.

For most content we recommend using the abr_profile_drm.json file, which contains resolution ladders for a variety of aspect ratios. (For material with 16:9 aspect ratio, this file's top ladder rung is 1920x1080 @ 9.5 mbps)

The *_clear_* files are for publishing without DRM. For items that are intended to be publicly accessible, use the profiles that end in _store_unencrypted.json. If there is a chance that you might want to change the mezzanine later to have DRM, use the profiles that end in _store_encrypted.json (however, these offerings will not be playable to users without a Fabric private key that has been granted access to it).

Create the Mezzanine object 

Once you have the required information, substitute it into the sample command below (if you do not need to attach an asset ID, you can omit the --ip-title-id line):

node testScripts/CreateABRMezzanine.js --library ilib4JFY7hontNKJJmM4XnZaweTbH9tq \
  --masterHash hq__9v2JY21ESnsvNdwWwgJrjiw7jHWv5nXik6quVn6FUgDxbgTgJT8toxBVb1ShZZH4mcFSFcJUJJ \
  --title "Big Buck Bunny" \
  --type "TENANT_NAME - Title" \
  --ip-title-id "YOUR_INTERNAL_ASSET_ID" \
  --abr-profile testScripts/abr_profile_drm.json

Note in particular that the --library and --type parameters will be different from your commands to create Production Masters.

Once the object is created, transcoding will begin on the server.

Successful creation of Mezzanine object 

Your output from the previous command should look something like this:

Creating ABR Mezzanine...
Starting Mezzanine Job(s)
Library ID ilib4JFY7hontNKJJmM4XnZaweTbH9tq
Object ID iq__4N1gG59cE1YzAL3NfRs39rFVTq8q
Offering: default
Write Token: tqw_4SiNg6kktmRGmAjLXjeFzt8s8C2Lbo5Bo
Write Node: https://host-38-142-50-110.contentfabric.io/

The Object ID identifies your new Mezzanine, you will need this value for subsequent commands.

In your browser, if you click on Content in the left sidebar, then click on your Titles library, you should see your new Mezzanine object. (If you are already on the page that lists objects in the library you may need to click the refresh icon image for refresh icon to see the new object)

If you go into the "TENANT_NAME - Title Mezzanines" library in your browser you should see the new mezzanine object.

(If you are already on the object list page you may need to click the refresh icon to see the new object)

Drilling down into it, you should see some information about transcoding progress (you will not be able to play it until transcoding has finished and you have finalized the object):

image for transcoding progress

In most cases, the percentage value shown is an average of 2 values (audio percent done and video percent done). The audio generally processes much more quickly, so you will see the value climb quickly to just above 50%, then progress more slowly.

Checking Mezzanine transcoding status 

You can get detailed progress info with the following command:

node testScripts/MezzanineStatus.js --objectId YOUR_NEW_MEZ_OBJECT_ID

Your output should look something like this, listing 2 jobs (1 for audio, 1 for video):

{
  "63fe3cbf-4660-44b2-8d93-415d97e4bd88": {
    "duration": 485986884811,
    "duration_ms": 485986,
    "progress": {
      "percentage": 68.9119170984456
    },
    "run_state": "running",
    "start": "2020-03-26T18:49:28Z"
  },
  "f39c9de1-4c29-49cf-bcf9-f173bc114e73": {
    "duration": 482414420927,
    "duration_ms": 482414,
    "progress": {
      "percentage": 3.6269430051813467
    },
    "run_state": "running",
    "start": "2020-03-26T18:49:28Z"
  }
}

The "start" field is in UTC time.

Divide the "duration_ms" field by 1000 to get seconds elapsed.

Depending on the format, bitrate and complexity of the original source material, and the speed of transfer between your S3 bucket and the Content Fabric node, it can take anywhere from 1x to 8x the actual duration of the program to complete transcoding.

Once both jobs show a "run_state" of "finished", you are ready for the next step, finalization.

Finalize your Mezzanine object 

Finalizing the Mezzanine makes the transcoded media available for viewing and distributes it to other nodes in the Content Fabric.

The command to finalize is the same as for checking progress, but with an additional --finalize parameter:

node testScripts/MezzanineStatus.js --objectId YOUR_NEW_MEZ_OBJECT_ID --finalize

While the command itself should complete quickly, it can take 2-3 minutes for the finalized content to become visible in the browser. (Behind the scenes, the nodes in the fabric are distributing parts among themselves)

In the browser, click the refresh icon image for refresh icon to update your view, then click on the Display tab to see the finalized content.

Grant Group Permissions on Mezzanine object - via browser 

(Identical process as for the Production Master object)

From the object details page, click the blue Groups button at top - you should see a screen with the Access Group field already chosen for you, set to "TENANT_NAME Content Admins".

Check the Manage box, then click Submit.

Grant Group Permissions on Mezzanine object - via command line 

(Identical process as for the Production Master object)

In order to grant group permissions via the command line, you will need to know the following:

You can find the Address of your group by clicking on the blue Groups button at top when you are browsing the details of any object. You can choose a group from the Access Group dropdown, then double-click the Address field to select it and copy to your clipboard.

The command to add permissions is then:

node testScripts/AddGroupPermissions.js \
  --objectId YOUR_OBJECT_ID \
  --groupAddress YOUR_GROUP_ADDRESS \
  --permissions manage

Adding caption stream(s) to an Offering 

Caption streams are added using .vtt files.

In order to add a caption stream, you will need to know the following:

Sample command with minimal options:

    cd elv-client-js

    node testScripts/OfferingAddCaptionStream.js \
      --libraryId YOUR_MEZ_LIB_ID \
      --objectId YOUR_MEZ_OBJECT_ID \
      --lang "YOUR_LANGUAGE_CODE" \
      --label "YOUR_LABEL_FOR_PLAYER_UI" \
      --file PATH_TO_YOUR_VTT_FILE

Add the following optional parameters above the --file line if desired:

Grant Group Permissions on Mezzanine object - via browser 

(Identical process as for the Production Master object)

From the object details page, click the blue Groups button at top - you should see a screen with the Access Group field already chosen for you, set to "TENANT_NAME Content Admins".

Check the Manage box, then click Submit.

Grant Group Permissions on Mezzanine object - via command line 

(Identical process as for the Production Master object)

In order to grant group permissions via the command line, you will need to know the following:

You can find the Address of your group by clicking on the blue Groups button at top when you are browsing the details of any object. You can choose a group from the Access Group dropdown, then double-click the Address field to select it and copy to your clipboard.

The command to add permissions is then:

node testScripts/AddGroupPermissions.js \
  --objectId YOUR_OBJECT_ID \
  --groupAddress YOUR_GROUP_ADDRESS \
  --permissions manage

Duplicating an existing Offering 

A Mezzanine object contains one or more Offerings. Each Offering specifies the following information:

When the CreateABRMezzanine.js script is run, it creates a single Offering named default.

The OfferingCopy.js script allows you to duplicate an existing Offering, after which you can modify the copy to change the playout options (see "Adding / removing playout options from an Offering" section below):

node testScripts/OfferingCopy.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey default \
  --targetOfferingKey YOUR_NEW_OFFERING_NAME

(if you want to copy an Offering other than the one named default then change the end of the --offeringKey line)

Viewing Offerings other than "default" 

In the Fabric Browser, when you are on the Display tab for your Mezzanine, click on the Advanced Controls button to access additional options. The Offering pulldown menu will allow you to choose other Offerings besides "default".

Adding / removing playout options from an Offering 

You can make changes to an Offering (either the default, or one you have created via the OfferingCopy.js script) to modify playout options.

Adding Clear (DRM-free) playout option 

The OfferingAddClear.js script will add a DRM-free playout option to one Offering within your Mezzanine:

node testScripts/OfferingAddClear.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME

Removing Clear (DRM-free) playout option 

The OfferingRemoveClear.js script will remove DRM-free playout options from one Offering within your Mezzanine:

node testScripts/OfferingRemoveClear.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME

Removing DRM playout option 

The OfferingRemoveDRM.js script will remove DRM-protected playout options from one Offering within your Mezzanine:

node testScripts/OfferingRemoveDRM.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME

Displaying the resolution ladder for an Offering 

The OfferingListRungs.js script will display the resolution ladder for an existing Offering:

node testScripts/OfferingListRungs.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME

If --offeringKey is omitted then default will be assumed.

Sample output:

Listing resolution ladder rungs for all streams in offering 'default'
{
  "audio": {
    "representations": {
      "audio@128000": {
        "bit_rate": 128000,
        "media_struct_stream_key": "audio",
        "type": "RepAudio"
      }
    }
  },
  "video": {
    "representations": {
      "video_1452x1080@4900000": {
        "bit_rate": 4900000,
        "crf": 0,
        "height": 1080,
        "media_struct_stream_key": "video",
        "type": "RepVideo",
        "width": 1452
      }
      "video_726x540@1500000": {
        "bit_rate": 1500000,
        "crf": 0,
        "height": 540,
        "media_struct_stream_key": "video",
        "type": "RepVideo",
        "width": 726
      },
      "video_968x720@3375000": {
        "bit_rate": 3375000,
        "crf": 0,
        "height": 720,
        "media_struct_stream_key": "video",
        "type": "RepVideo",
        "width": 968
      }
    }
  }
}

Adding a rung to an Offering's video playout resolution ladder 

The OfferingAddVideoRung.js script will allow you to add a new rung to an Offering's video resolution ladder:

node testScripts/OfferingAddVideoRung.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME \
  --width THE_NEW_WIDTH \ 
  --height THE_NEW_HEIGHT \
  --bitrate THE_NEW_BITRATE

If you omit --offeringKey then default will be assumed.

Optionally, the --width and/or --bitrate options can be omitted, and the script will scale the existing top rung based on --height.

Note that if you supply both --width and --height but the resulting aspect ratio would differ more than 5% from the existing top rung's aspect ratio the script will halt with an error. If you would like to add anyway, add --ignoreAspectRatio to the command.

Note also that only lower quality rungs can be added to an existing Offering. The new rung's bitrate must be lower than the existing top rung, and height and width must be less than or equal to the existing top rung.

For example, if your top rung is 1920x1080 @ 9,500,000 bps:

Removing a rung from an Offering's video playout resolution ladder 

The OfferingRemoveVideoRung.js script will allow you to remove an existing rung from an Offering's video resolution ladder:

node testScripts/OfferingRemoveVideoRung.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey THE_OFFERING_NAME \
  --rungKey THE_RUNG_NAME

If you omit --offeringKey then default will be assumed.

To look up the value of --rungKey, use the OfferingListRungs.js script (see above). Video rungs are generally named "video_WIDTHxHEIGHT@BITRATE", e.g.: video_1280x720@4500000, but this is not guaranteed - use the OfferingListRungs.js script to show all the rung names.

You are not allowed to remove the top rung from the ladder, if you try the script will halt with an error.

Note that in special cases, your Offering's video stream may not be named video - if this is the case, use --streamKey STREAM_NAME to specify the actual name of the stream. (You can use the OfferingListRungs.js script to see the names of your Offering's streams)

Example Scenarios 

Adding a stereo stream created from 2 mono streams to a Production Master Variant 

In the case where the source has left and right audio stored individually as mono streams, adding a stereo stream requires using the VariantAddStream.js script and specifying the stream indexes to use, as well as the mapping type 2MONO_1STEREO.

For example, The following assumes that your source audio streams are in file 'MyMovie.mp4', at stream indexes 1 and 2, is English, and should be the default audio choice.

node testScripts/VariantAddStream.js \
  --libraryId ilib3t4Cf8pdxftVcc4Si35yZxPgN33  \
  --objectId iq__3RVmL1WdnVj7mYrKZcDUPpzstFNU  \
  --variantKey default \
  --streamKey audio \
  --file MyMovie.mp4 \
  --label English \
  --language en \
  --streamIndex 1 2 \
  --mapping 2MONO_1STEREO \
  --isDefault

For more detailed info on the individual options, please see Add stream to Production Master Variant

Adding a stereo stream created from a single mono stream to a Production Master Variant 

In the case where the source only has a single mono stream, adding a stereo stream is similar to the case where you have 2 mono channels (above), except that you would specify the same source stream index twice.

For example, The following assumes that your source audio stream is in file 'MyMovie.mp4', has stream index 1, is English, and should be the default audio choice.

node testScripts/VariantAddStream.js \
  --libraryId ilib3t4Cf8pdxftVcc4Si35yZxPgN33  \
  --objectId iq__3RVmL1WdnVj7mYrKZcDUPpzstFNU  \
  --variantKey default \
  --streamKey audio \
  --file MyMovie.mp4 \
  --label English \
  --language en \
  --streamIndex 1 1 \
  --mapping 2MONO_1STEREO \
  --isDefault

For more detailed info on the individual options, please see Add stream to Production Master Variant

Adding a 'clear playout' Offering to a DRM-protected Mezzanine 

The following assumes that you created your Mezzanine using the abr_profile_drm.json profile, which will result in a default Offering that only offers DRM playback:

 node testScripts/OfferingCopy.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey default \
  --targetOfferingKey clear-playout

node testScripts/OfferingAddClear.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey clear-playout

node testScripts/OfferingRemoveDRM.js \
  --libraryId YOUR_TITLE_LIBRARY_ID \
  --objectId YOUR_MEZ_OBJECT_ID \
  --offeringKey clear-playout      

After running the above commands, you will have an additional clear-playout Offering that has only DRM-free playout options.

Language Codes and Labels 

Below is a table of codes and labels for some of the most commonly encountered languages. To look up a language not on this list, visit the IANA Language Subtag Registry

Note that some references may capitalize letters appearing after a dash, e.g. "pt-BR" instead of "pt-br".

language code label note
Arabic ar اَلْعَرَبِيَّةُ
Bangla / Bengali bn বাংলা
Chinese (Cantonese) yue 廣東話 (spoken) for audio streams only
Chinese (Mandarin) cmn 普通话 (spoken) for audio streams only
Chinese (Simplified) zh-hans 简体中文 (written) for text streams only
Chinese (Traditional) zh-hant 繁體中文 (written) for text streams only
Danish da Dansk
Dutch nl Nederlands
Dutch (Netherlands) nl-nl Nederlands specifically as spoken/written in the Netherlands
English en English
English en-gb English (United Kingdom) specifically as spoken/written in the United Kingdom
English en English
Finnish fi Suomi
French fr Français
French (Parisian) fr-fr Français specifically as spoken/written in France
German de Deutsch
German (Germany) de-de Deutsch (Deutschland) specifically as spoken/written in Germany
Hebrew he עִבְרִית
Hindi hi हिन्दी
Indonesian id Bahasa Indonesia
Italian it Italiano
Japanese ja 日本語
Korean ko 한국어
Marathi mr मराठी
Norwegian no Norsk
Polish pl Polski
Portuguese pt Português
Portuguese (Brazil) pt-br Português (Brasil) specifically as spoken/written in Brazil
Russian ru Русский
Spanish (Castilian) es Español specifically as spoken/written in Spain
Spanish (Latin America) es-419 Español (Latinoamericano) specifically as spoken/written in Latin America
Swedish sv Svenska
Telugu te తెలుగు
Thai th ภาษาไทย
Turkish tr Türkçe