Qualify API Usage

The primary focus of this document is the submission of jobs to the Qualify Service API. This involves the submission of a job, the monitoring of the progress of that job, and the collection/processing of the results.

Prior to submitting a job, the user must have created a Project and a Template which shall be the target of the job.

In this example, the following project has been created:

A few notes about this project:

The project ID is specified in the URL. In this case, the URL specifies:

https://cloud.telestream.net/console/qualify/projects/2ca1cf136ff119d49bcb8330b013304d/settings

The ID of this project (Demo Project) is: 2ca1cf136ff119d49bcb8330b013304d

This value shall be used in the API submission.

Also recall (as mentioned above); that the project defines WHERE (Provider and Region) this job shall be run. In this case, this project has been defined to run in AWS in the US-EAST-1 region.

IE:

The ‘Default Template’ setting is unused and can be ignored. It is used only a shortcut for the job submission User Interface. This setting has no meaning/relevance when performing an API submission.

Once a Project has been defined with the desired configuration; the user must define a Template (or reference an existing Template) that shall be used to perform the ‘Work’ associated with this job.

Recall from the initial definition that a Template is a ‘user configurable set of test parameters’.

The creation and definition of a Template is beyond the scope of this document. Once a template has been defined with the specific conditions desired for testing; the ID of the template is required in order to submit a job.

In this example, the following Template (which was already defined in the current account) shall be used as desired Template for the new API job:

As with the Project, the URL defines the ID of the Template. In the example above, the URL of:

https://cloud.telestream.net/console/qualify/templates/8a5aafb4d4c8866ca0f0d65d896faef5

Indicates that the ID of this template is: 8a5aafb4d4c8866ca0f0d65d896faef5

Based upon the two images above (in which we have displayed the Project and Template which are the desired targets of the new job); we know:

ID of desired Project: 2ca1cf136ff119d49bcb8330b013304d

ID of desired Template: 8a5aafb4d4c8866ca0f0d65d896faef5

Submitting a Qualify Job

The Postman application (www.postman.com) application shall be used to illustrate/perform the API interactions with the Qualify Service.

Postman has been pre-configured so that the API Key is present for authorization (this is discussed in the API Keys/Authorization section above).

The endpoint URL for submitting a new job is:

https://api.cloud.telestream.net/qualify/v1.0/jobs

This is a POST request which includes the following as the POST BODY:

{
    "url": "\<string\>",
    "template_id": "\<string\>",
    "project_id": "\<string\>"
}

The fields in the body are defined as follows:

‘url’ the Presigned URL to the source file that is to be consumed by the Qualify Service during this job

‘template_id’ the Identifier of the desired template that is the target of this job

‘project_id’ the Identifier of the desired project for this job

An example of the POST Body which targets the Template and Project outlined above (via their IDs) along with a specific input file is:

{
    "url": "https://XXXXXXXXXXXXXXXXXXXXXXX.amazonaws.com/Source/demo_black_at_5sec.mpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKZZZZZZZZZZZZ/20210831/us-east-2/s3/aws4_request&X-Amz-Date=20210831T132734Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=aa56b86ccdd95c5417548a1a9c388960c00195d26997cec1ea6e574305f36709",
    "template_id": "8a5aafb4d4c8866ca0f0d65d896faef5",
    "project_id": "2ca1cf136ff119d49bcb8330b013304d"
}

When this POST request is sent, a successful job indication shall be denoted by a 201 return code and the following response body:

{
    "id": "325a184cb8b19f2261bba37a2be57f0c",
    "created_at": "2021-08-31T14:07:35.980101838Z",
    "updated_at": "2021-08-31T14:07:35.980102118Z",
    "status": "queued",
    "url": "https://XXXXXXXXXXXXXXXXXXXXXXX.amazonaws.com/Source/demo_black_at_5sec.mpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKZZZZZZZZZZZZ/20210831/us-east-2/s3/aws4_request&X-Amz-Date=20210831T132734Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=aa56b86ccdd95c5417548a1a9c388960c00195d26997cec1ea6e574305f36709",
    "project_id": "2ca1cf136ff119d49bcb8330b013304d",
    "project_name": "Demo Project",
    "template_id": "8a5aafb4d4c8866ca0f0d65d896faef5",
    "template_name": "Max Freeze Frames 5",
    "file_name": "demo_black_at_5sec.mpg"
}

Within the response body, the fields are defined as follows:

  • “id” this is the Identifier of the new job. This value shall be used to query subsequent job status information
  • “created_at” and “updated_at” these correspond to the creation date and the last updated time (all in UTC times)
  • “status” corresponds to the current job status. (NOTE: The possible values present for ‘status’ are discussed above in the JOB Results section).
  • “url” this is a copy of the URL provided during the initial submit call
  • “project_id” this is the Identifier of the project this job indicated in the initial submit call
  • “project_name” this is the name of the project whose ID was specified in the initial submit call
  • “template_id” this is the Identifier of the template that this job indicated in the initial submit call
  • “template_name” this is the name of the template whose ID was specified in the initial submit call
  • “file_name” this is the base file name parsed from the input URL

Querying for Status/Results of a Qualify Job

Once a job has been accepted for processing, the following GET request allows a user to ask the API for status/results of the specific job:

https://api.cloud.telestream.net/qualify/v2.1/jobs/325a184cb8b19f2261bba37a2be57f0c

NOTE: The value ‘ 325a184cb8b19f2261bba37a2be57f0c ‘ was taken from the results of the Create Job POST query above.

The results of the query above will be a JSON document which details the current status/progress of the job.

A small fragment of the JSON returned for the above query is:

{
    "id": "325a184cb8b19f2261bba37a2be57f0c",
    "created_at": "2021-08-31T14:07:36Z",
    "updated_at": "2021-08-31T14:08:03Z",
    "status": "success",
    "state": "warning",
    "progress": 100,
.
.
.
}

This query can be repeated until the “status” field in the job returns one of the designated values which implies that job has completed. As stated above, the value of the “status” field will be one of:

  • Queued implies that the job has been accepted and is awaiting processing.
  • Downloading implies that the source file(s) are currently being localized to the instance used for this job.
  • Processing implies that the current job is ‘in-process’ or being worked upon.
  • Success implies that the current job has completed successfully.
  • Error implies that the current job was unable to complete due to a problem processing the job.
  • Cancelled implies that the job was previously in-process; but was cancelled/stopped by a user request

NOTE: It is highly recommended that a Client not repeated call this method in a short interval. There is no reason to query this endpoint any more than once every 15 to 30 seconds.

The pseudocode below illustrates the proper way to ask for the status of a job:

While (job is not done)
{
		Job = Get job (job id)

		If (job status == “error” or “cancelled” or “success”)
		Then
			Job is done
		Else
			Wait 15 seconds
}

If (job.status =success)
{
		ProcessJobResults (job)
}

An example of a fully populated job status for a Completed and Successful job is shown below:

{

    "id": "325a184cb8b19f2261bba37a2be57f0c",
    "created_at": "2021-08-31T14:07:36Z",
    "updated_at": "2021-08-31T14:08:03Z",
    "status": "success",
    "state": "warning",
    "progress": 100,
    "url": "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.amazonaws.com/Source/demo_black_at_5sec.mpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAXXXXXXXXXXXXXX/20210831/us-east-2/s3/aws4_request&X-Amz-Date=20210831T132734Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=aa56b86ccdd95c5417548a1a9c388960c00195d26997cec1ea6e574305f36709",
    "alerts": [
        {
            "id": "UNSET",
            "description": "Freeze Frame detected",
            "level": "warning",
            "start_timecode": "00:00:05;00",
            "end_timecode": "00:00:09;29"
        }
    ],

    "file_info": {
        "Audio": [
            {
                "Bit Depth": 16,
                "Bit Rate": 256000,
                "Channel Order": "L R",
                "Channels": 2,
                "Duration": "00:00:35.127",
                "Format": "MPEG Audio",
                "Language": "Undefined",
                "Sample Count": 1686106,
                "Sample Rate": 48000,
                "Track": 0
            }

        ],

        "Audio Processed As": [
            {
                "Bit Depth": 16,
                "Bit Rate": 1536000,
                "Channel Order": "L R",
                "Channels": 2,
                "Duration": "00:00:35.127",
                "Format": "PCM, 16-Bit Little-Endian Signed Integer",
                "Language": "Undefined",
                "Sample Count": 1686106,
                "Sample Rate": 48000,
                "Track": 0
            }

        ],

        "Container": {
            "File Bit Rate": 9082759,
            "File Size": 39881260,
            "Format Name": "MPEG-2 Program Stream",
            "Operational Pattern": "",
            "RIP Packet Present": "Not Present",
            "Start Timecode": "00:00:00:00",
            "Stream Count": 2,
            "Vendor": ""
        },

        "Video": [

            {
                "Active Format Description": 0,
                "Alpha Channel": "Not Present",
                "Bit Depth": 8,
                "Bit Rate": 8000000,
                "Buffer Size": 1835008,
                "Chroma Subsampling": "4:2:0",
                "Coded Interlace Mode": "",
                "Color Space": {
                    "Color primaries": "ITU-R BT.601-6 (525)",
                    "Matrix coefficients": "ITU-R BT.601-6",
                    "Transfer characteristics": "ITU-R BT.601-6"
                },
                "Duration": "00:00:35;02",
                "Entropy Coding Mode": "",
                "Field Order": "Upper field first",
                "Format": "MPEG-2",
                "Frame Aspect Ratio": "4:3 (1.33)",
                "Frame Count": 1052,
                "Frame Rate": "29.97",
                "Height": 480,
                "Level": "Main",
                "Pixel Aspect Ratio": "8:9 (0.89)",
                "Profile": "Main",
                "TV Rating": "",
                "Track": 0,
                "Video Range": "Nominal",
                "Width": 720
            }
        ]
    },

    "project_id": "2ca1cf136ff119d49bcb8330b013304d",
    "project_name": "Demo Project",
    "template_id": "8a5aafb4d4c8866ca0f0d65d896faef5",
    "template_name": "Max Freeze Frames 5",
    "file_name": "demo_black_at_5sec.mpg"
}

A few things of note in this JSON result:

The Timecode values which are displayed are always relative to the timecode/framerate of the source.

"status": "success",
"progress": 100,

The final “status” indicates success this implies the job completed successfully (the progress of 100 indicates this as well). The Progress field will be updated (growing from 0 to 100) as the job is in process. A job with a final status of ‘success’ will always have the progress set to 100.

"state": "warning",

This implies that the result of the job was the Warning state. This was determined based upon the criteria of the tests outlined in the selected Template. In this particular Template (named: ‘Max Freeze Frames 5’); the rules were that a repeated sequence of the same frame five (5) times or more should
generate a warning.

The specific information about the ALERT raised is contained in the following
JSON block:

"alerts": [
        {
            "id": "UNSET",
            "description": "Freeze Frame detected",
            "level": "warning",
            "start_timecode": "00:00:05;00",
            "end_timecode": "00:00:09;29"
        }

This block gives the start and end times of the frames which generated the warning. (Again, these values are in timecode relative to the timecode/framerate of the source material).

Lastly, the "file_info" json blob shall always be generated and will contain the container/format information of the input.

Click here for full documentation of the API for the Qualify service