Simple Encoding API - VoD
Overview
Simple Encoding jobs provide a quick and easy way to convert your input files into streamable content that gets automatically optimized for efficient and quality-optimized DASH/HLS delivery using Bitmovin’s Per-Title Technology. All you need is a single API call that provides the input and output location details.
Requirements
- SDK Version: 1.98.0 or higher for H264, v1.104.0 or higher for AV1
- Content Type: VoD (for livestreaming please see the Simple LIVE encoding API)
Supported Features
Input Sources:
- HTTP(S), (S)FTP, S3, GCS, Azure Blob Storage (ABS), Akamai NetStorage
Output Destinations:
- S3, GCS, Azure Blob Storage (ABS), Akamai NetStorage, Bitmovin CDN Output (Beta)
Input Characteristics:
- Video: single input (required)
- Audio: optional, including multiple inputs (eg. for multiple languages)
- Subtitles: optional, with external SRT, TTML or WebVTT files
Output Characteristics:
- Video: H264 or AV1, segmented fMP4, renditions determined by our Per-Title algorithm
- Audio: AAC only, segmented fMP4, one rendition per audio input
- Manifests: DASH / HLS
- Subtitles: WebVTT
- Thumbnails: (every 5s)
- low-res
- high-res
- Sprites (Trick Play) (every 5s)
Introduction
A Simple Encoding Job is defined by
- An input source,
- An output destination
- A pre-defined encoding template
… that’s it :)
Once a Simple Encoding Job is started, the template is converted into an actual Encoding, adapted to the input and output definition. The template is a pre-defined set of configurations the Encoding will be executed with. There are currently 2 templates available:
H264
: generates a Per-Title optimised ladder with the H264 video codecAV1
: generates a Per-Title optimised ladder with the AV1 video codec. If you don’t specify one explicitly in your configuration, H264 is used by default.
Job lifecycle
After starting the Simple Encoding Job, it goes through the following stages:
CREATED
: the Job has been created is waiting to be started.EXECUTING
: the Job is currently being executed and an Encoding is being created from it.FAILURE
: the Job could not create an Encoding, check theerrors
property for more information.RUNNING
: the Job created an encoding. At this time, an Encoding ID is available and the Encoding itself is either in state QUEUED or RUNNING.FINISHED
: the Encoding created by this job finished successfully.ERROR
: the Encoding created by this job failed, check theerrors
property for more information.CANCELED
: the Encoding has been started but subsequently canceled manually by the user.
You can retrieve status information with the Job details endpoint
Note that the Encoding created and managed by the Job has its own statuses, documented in this FAQ, and queried through the Encoding Status endpoint.
Create a Simple Encoding Job
The following examples are using an S3 bucket as Input Source, and another S3 bucket as Output Destination. An overview over all supported storage types can be found in the “Inputs & Outputs“ section below.
REST API Call
The simplest way to create a simple encoding is a plain HTTP POST request sent to the Bitmovin API or try it with this Postman Collection.
curl --location --request POST 'https://api.bitmovin.com/v1/encoding/simple/jobs/vod' \
--header 'x-api-key: YOUR_BITMOVIN_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "simple_encoding_name",
"encodingTemplate": "H264",
"inputs": [
{
"url": "s3://my-bucket/path/file.mp4",
"credentials": {
"accessKey": "S3_INPUT_ACCESS_KEY",
"secretKey": "S3_INPUT_SECRET_KEY"
}
}
],
"outputs": [
{
"url": "s3://my-bucket/path/to/destination/folder/{uuid}/",
"credentials": {
"accessKey": "S3_OUTPUT_ACCESS_KEY",
"secretKey": "S3_OUTPUT_SECRET_KEY"
}
}
]
}'
Bitmovin OpenAPI SDK
Beyond a plain HTTP POST, you can use any of the Bitmovin SDKs to start your job. The following code sample is the equivalent of the REST API call above, but using the Bitmovin OpenAPI Java SDK.
// define input
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("s3://my-bucket/path/file.mp4");
// input credentials
var inputCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
inputCredentials.setAccessKey(S3_INPUT_ACCESS_KEY);
inputCredentials.setSecretKey(S3_INPUT_SECRET_KEY);
input.setCredentials(inputCredentials);
// define output
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("s3://my-bucket/path/to/destination/folder/{uuid}/");
// output credentials
var outputCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
outputCredentials.setAccessKey(S3_OUTPUT_ACCESS_KEY);
outputCredentials.setSecretKey(S3_OUTPUT_SECRET_KEY);
output.setCredentials(outputCredentials);
// put it all together
SimpleEncodingVodJobRequest simpleEncodingJob = new SimpleEncodingVodJobRequest();
simpleEncodingJob.setEncodingTemplate(EncodingTemplate.H264)
simpleEncodingJob.addInputsItem(input);
simpleEncodingJob.addOutputsItem(output);
// call the API
api.encoding.simple.jobs.vod.(simpleEncodingJob);
Input Types
Video & Audio
As inputs you can provide one or multiple files:
- an input containing a single video and audio track, or
- a single input containing a single video only track, together with one or multiple inputs containing a single audio only track each, and
- one or more subtitle files. You differentiate between them by using the
inputType
property on each input in theinputs
array.
Single Input:
var input = new SimpleEncodingVodJobUrlInput();
input.setCredentials(inputCredentials);
input.setUrl("s3://my-bucket/path/file-with-video-and-audio.mp4");
input.setLanguage("en");
Multiple Inputs:
If you want to process more than one input (e.g. multiple audio tracks in addition to the video track), you must specify which input type each file provides, by stating VIDEO
or AUDIO
. Any audio tracks present in VIDEO
inputs will be ignored, as will any video track in AUDIO
inputs.
From each AUDIO
input, only the first audio track will be processed. To add different audio tracks (e.g. different language versions), they need to be provided in separate input files:
var videoInput = new SimpleEncodingVodJobUrlInput();
videoInput.setUrl("https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov");
videoInput.setInputType(SimpleEncodingVodJobInputType.VIDEO);
// define audio input
var audioInput1 = new SimpleEncodingVodJobUrlInput();
audioInput1.setUrl("s3://my-bucket/path/audio-en.mp4");
audioInput1.setInputType(SimpleEncodingVodJobInputType.AUDIO);
audioInput1.setLanguage("en");
// define audio input
var audioInput2 = new SimpleEncodingVodJobUrlInput();
audioInput2.setUrl("s3://my-bucket/path/audio-de.mp4");
audioInput2.setInputType(SimpleEncodingVodJobInputType.AUDIO);
audioInput2.setLanguage("de");
At least one input is required that provides a video track. This needs to be done either by providing a single input without
inputType
specified (in which case it is assumed to contain the video track and one audio track) or with an input explicitly set toinputType=VIDEO
(alongside one or multiple audio inputs).The Simple Encoding API cannot be used for audio-only encodings. On the other hand, video-only jobs are possible by having an input file that contains no audio track, or specifying aninputType=VIDEO
with it if it does.ℹ Audio language (optional): Even though it is not mandatory, we recommend always setting a language on audio inputs (and inputs without an
inputType
specified) to provide an indication of the available languages that players can choose from, which will exposed through the relevant mechanisms and labels in the DASH and HLS manifests. The language code must be compliant with BCP 47. If you do not explicitly set a language, the labelund
(undefined) will be used instead.Any language tag defined in the source stream itself will not be retrieved and propagated.
Subtitles & Closed Captions
SUBTITLE
and CLOSED_CAPTION
are also supported input types. Both work in a very similar way but there is a distinction in their usage, intent and goal for the viewer.
- Subtitles are mostly used to translate spoken audio as text on the screen (usually into a different language),
- Closed Captions are specifically used to support and improve the accessibility for the deaf and hard-of-hearing audience and are using the same language as spoken in the audio track. Furthermore, they usually include additional indications of sound effects and other noises - for example “car honks” - or speaker changes (“person A speaks followed by person B answering”), thus supporting deaf and hard-of-hearing people in following the content.
Both input types have to be valid SRT
, TTML
, or WebVTT
files, indicated by their file extensions .srt
, .ttml
, or .vtt
. It is required to specify their inputType
as well as a language
for each. The language code must be compliant with BCP 47. The Simple Encoding Job will convert all provided subtitles/closed captions to WebVTT and add them to the DASH and HLS manifests using the language as label.
// define closed captions
var closedCaptionsInputEn = new SimpleEncodingVodJobUrlInput();
closedCaptionsInputEn.setUrl("https://download.blender.org/demo/movies/ToS/subtitles/TOS-en.srt");
closedCaptionsInputEn.setLanguage("en");
closedCaptionsInputEn.setInputType(SimpleEncodingVodJobInputType.CLOSED_CAPTION);
// define subtitles
var subtitleInputEn = new SimpleEncodingVodJobUrlInput();
subtitleInputEn.setUrl("https://download.blender.org/demo/movies/ToS/subtitles/TOS-en.srt");
subtitleInputEn.setLanguage("en");
subtitleInputEn.setInputType(SimpleEncodingVodJobInputType.SUBTITLE);
Inputs & Outputs
The structure of both input and output is very similar, consisting of a property url depending on the storage type defined by the scheme
, and an optional set of credentials to access the storage solution:
{
"url": "scheme://path",
"credentials": {...}
}
While the URL for an input definition has to point to a specific file, the URL for the output definition has to point to a folder or path, in which all the generated output files will be stored.
When defining an output URL, you can use a couple of placeholders that will be replaced at run-time:
{uuid}
will be replaced with a unique identifier. We recommend using this placeholder to ensure that every job has a unique output path, in so doing avoiding files being overwritten by subsequent jobs{asset}
is replaced by the basename of the first video source file provided
HTTP/HTTPS (Input only)
http://<host>[:<port>]/path/file.mp4
https://<host>[:<port>]/path/file.mp4
The port defaults to 80 if it is not provided. It is possible to either provide no credentials (for unauthenticated access) or username
and password
for basic authentication.
Unauthenticated:
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("https://<host>[:<port>]/path/file.mp4");
BasicAuth:
var inputCredentials = new SimpleEncodingVodJobUsernamePasswordCredentials();
inputCredentials.setUsername("USERNAME");
inputCredentials.setPassword("PASSWORD");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("https://<host>[:<port>]/path/file.mp4");
input.setCredentials(inputCredentials);
(S)FTP (Input only)
ftp://<host>[:<port>]/path/file.mp4
sftp://<host>[:<port>]/path/file.mp4
The port defaults to 21 (ftp) or 22 (sftp) if it is not provided. It is possible to either provide no credentials (for unauthenticated access) or with a username
and password
combination.
Unauthenticated:
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("ftp://<host>[:<port>]/path/file.mp4");
BasicAuth:
var inputCredentials = new SimpleEncodingVodJobUsernamePasswordCredentials();
inputCredentials.setUsername("USERNAME");
inputCredentials.setPassword("PASSWORD");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("ftp://<host>[:<port>]/path/file.mp4");
input.setCredentials(inputCredentials);
AWS S3
- Input
s3://<my-bucket>/path/file.mp4
- Output
s3://<my-bucket>/path/to/destination/folder/{uuid}/
Credentials for S3 URLs are mandatory and can be provided via AWS access/secret keys or role-based authentication. Generic S3 is currently not supported.
Access/Secret Key:
var inputKeyCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
inputKeyCredentials.setAccessKey("ACCESSKEYHERE");
inputKeyCredentials.setSecretKey("SECRETKEYHERE");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("s3://my-bucket/path/file.mp4");
input.setCredentials(inputKeyCredentials);
var outputKeyCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
outputKeyCredentials.setAccessKey("ACCESSKEYHERE");
outputKeyCredentials.setSecretKey("SECRETKEYHERE");
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("s3://my-bucket/path/to/destination/folder/{uuid}/");
output.setCredentials(outputKeyCredentials);
Role-based:
var roleBasedCredentials = new SimpleEncodingVodJobS3RoleBasedCredentials();
roleBasedCredentials.setRoleArn("arn:aws:iam::123456789012:role/OurS3AccessRole");
roleBasedCredentials.setUseExternalId(true);
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("s3://my-bucket/path/file.mp4");
input.setCredentials(roleBasedCredentials);
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("s3://my-bucket/path/to/destination/folder/");
output.setCredentials(roleBasedCredentials);
useExternalId
(default: false) is an optional property and controls if the customer’s orgId
should be used as externalId
when assuming the AWS role, or not. Its an additional security measure to prevent unauthorized users assume a role by obtaining the role ARN somehow. For more details, please see S3 Role-Based Input for details about the externalId, and be aware that the simple encoding API only supports the externalIdMode
GLOBAL
.
Google Cloud Storage (GCS)
- Input
gcs://<my-bucket>/path/file.mp4
- Output
gcs://<my-bucket>/path/to/destination/folder/{uuid}/
Credentials for GCS URLs are mandatory and can be provided as HMAC keys or a service account.
HMAC Keys
var inputKeyCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
inputKeyCredentials.setAccessKey("ACCESS_ID");
inputKeyCredentials.setSecretKey("SECRET");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("gcs://my-bucket/path/file.mp4");
input.setCredentials(inputKeyCredentials);
var outputKeyCredentials = new SimpleEncodingVodJobAccessKeyCredentials();
outputKeyCredentials.setAccessKey("ACCESS_ID");
outputKeyCredentials.setSecretKey("SECRET");
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("gcs://my-bucket/path/to/destination/folder/{uuid}/");
output.setCredentials(outputKeyCredentials);
Service-Account Note that the service credentials provided in the following snippet are just for example. You need to obtain your service credentials from your GCP account.
var serviceAccountCredentials = new SimpleEncodingVodJobGcsServiceAccountCredentials();
serviceAccountCredentials.setServiceAccountCredentials("{\n"
+ " \"type\": \"service_account\",\n"
+ " \"project_id\": \"bitmovin\",\n"
+ " \"private_key_id\": \"abcdefghijklmnopqrstuvwxyz\",\n"
+ " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nOwdXyjRT9F4A==\\n-----END PRIVATE KEY-----\\n\",\n"
+ " \"client_email\": \"[email protected]\",\n"
+ " \"client_id\": \"10440564562784234997\",\n"
+ " \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n"
+ " \"token_uri\": \"https://oauth2.googleapis.com/token\",\n"
+ " \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n"
+ " \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/bitmovin%40bitmovin.iam.gserviceaccount.com\"\n"
+ "}");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("gcs://my-bucket/path/file.mp4");
input.setCredentials(serviceAccountCredentials);
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("gcs://my-bucket/path/to/destination/folder/{uuid}/");
output.setCredentials(serviceAccountCredentials);
Azure Blob Storage
- Input
https://<account>.blob.core.windows.net/<container>/path/file.mp4
- Output
https://<account>.blob.core.windows.net/<container>/path/to/destination/folder/{uuid}/
Credentials for Azure Blob Storage URLs are mandatory and can be provided via the storage account accesss key credentials.
var azureInputCredentials = new SimpleEncodingVodJobAzureCredentials();
azureInputCredentials.setKey("STORAGE_KEY");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("https://<account>.blob.core.windows.net/<container>/path/file.mp4");
input.setCredentials(azureInputCredentials);
var azureOutputCredentials = new SimpleEncodingVodJobAzureCredentials();
azureOutputCredentials.setKey("STORAGE_KEY");
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("https://<account>.blob.core.windows.net/<container>/path/to/destination/folder/);
output.setCredentials(azureOutputCredentials);
Akamai NetStorage
- Input
https://<host>-nsu.akamaihd.net/<CP-code>/path/file.mp4
- Output
https://<host>-nsu.akamaihd.net/<CP-code>/path/to/destination/folder/{uuid}/
Credentials for Akamai NetStorage URLs are mandatory and can be provided via username
and password
var authenticationCredentials = new SimpleEncodingVodJobUsernamePasswordCredentials();
authenticationCredentials.setUsername("USERNAME");
authenticationCredentials.setPassword("PASSWORD");
var input = new SimpleEncodingVodJobUrlInput();
input.setUrl("akamai-ns://my-akamai-host-nsu.akamaihd.net/123456/path/file.mp4");
input.setCredentials(authenticationCredentials);
var outputAuthenticationCredentials = new SimpleEncodingVodJobUsernamePasswordCredentials();
outputAuthenticationCredentials.setUsername("USERNAME");
outputAuthenticationCredentials.setPassword("PASSWORD");
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("akamai-ns://my-akamai-host-nsu.akamaihd.net/path/to/destination/folder/");
output.setCredentials(outputAuthenticationCredentials);
Bitmovin CDN Output (Beta)
(requires SDK v1.111.0 or higher) In case you have no way to host your encoded content by yourself, you can use the Bitmovin Content Delivery Network instead. It stores your encoded content in a dedicated storage, and ensures an efficient delivery of your content to your users. Therefore, no further configuration is required.
var output = new SimpleEncodingVodJobCdnOutput();
If you use this output type for the first time, it will also trigger its initial provisioning of your Bitmovin CDN resources. Therefore, it can take a couple minutes until you are able to access the files after your encoding has finished.
ℹ️ Only one Bitmovin CDN Output is allowed per Simple Encoding Job.
ℹ️ Contents written to this Output are using the
PRIVATE
ACL permission. So, your encoded content can be accessed through your CDN endpoint only.
Additional Options
Public Outputs
By default, and in accordance with best practices, the output files will be set to be private, meaning that they cannot be streamed directly from storage output. If you want public outputs, simply set makePublic
to true
in your output configuration.
var output = new SimpleEncodingVodJobUrlOutput();
output.setUrl("s3://my-bucket/path/to/destination/folder/{uuid}/");
output.setCredentials(outputCredentials);
output.setMakePublic(true);
Additional Single-file MP4
You can request to have single-file fragmented MP4 outputs generated for each rendition that the Per-Title algorithm creates, for example if you want to provide customers with an offline or download option. Each such MP4 file will contain all video and audio streams configured, but no subtitles.
SimpleEncodingVodJobRequest simpleEncodingJob = new SimpleEncodingVodJobRequest();
simpleEncodingJob.setEncodingTemplate(EncodingTemplate.H264)
simpleEncodingJob.addInputsItem(input);
simpleEncodingJob.addOutputsItem(output);
SimpleEncodingVodJobOptions options = new SimpleEncodingVodJobOptions();
options.setSingleFileOutput(true);
simpleEncodingJob.setOptions(options);
Output Folder Structure
Simple Encoding Jobs will create the following folder structure at the given destination:
The output files can be found in the following locations on every configured output:
/video
/{codec}/{width}x{height}_{bitrate}/
(multiple subfolders containing different output renditions, {codec} is set based on the template that is used: H264 or AV1)
/audio
/aac/{language}/
- if language is unique (subfolder containing audio output files)/aac/{language}_{index}/
- if language is not unique (subfolder containing audio output files)
/subtitles
(subfolder containing subtitles files)/captions
(subfolder containing captions files)/sprites
(subfolder containing generated sprites)/thumbnails
(subfolder containing generated thumbnails)/index.m3u8
(HLS manifest file)/stream.mpd
(DASH manifest file)
Known Limitations
- DRM Protection is not available.
- Encoding Templates: templates are only provided for H264 or AV1 codec outputs
- Unsupported Input Types: Anamorphic inputs (where DAR/SAR requires configuration), 3D/VR content, HDR content
- Audio
- Only AAC output is currently supported.
- Only the first audio track is extracted from each relevant individual input file.
- The input channel layout will be downmixed to STEREO (2.0) by default:
- If the source is a stereo track, it is used for output
- If the source contains a single mono track, it will be duplicated into a stereo output
- If the source contains multiple mono tracks, the first two tracks will be mapped into a stereo output
- For all other cases, the output is undetermined. The encoder will attempt to downmix the audio, but the result may not be as expected, or the job or encoding may fail.
- Video
- Filters/Transformations are not supported nor automatically applied (e.g. interlaced content remains interlaced)
- Webhooks: Once a Simple Encoding Job was successfully started, standard generic encoding webhooks can be used to track the progress of the encoding.
Updated 6 days ago