JavaScript tasks

A JavaScript task is created by including the JavaScript in the task definition document. To evaluate the script Vidispine uses a JavaScript engine. A number of global variables are defined for the script to use, see Common JavaScript functions.

In addition for task definitions, there is the job object.

The job object

The job object contains methods for reading and writing metadata for the job that is executing, and also for some job control.

job.getId()

Gets the id of the job that is executing.

job.log(description)

Logs a message related to the current job step.

Arguments:
  • description (string) – The message to log.
job.getData(key)

Gets the data for the given key.

Arguments:
  • key (string) – The key to use when getting the data.
job.setData(key, value)

Sets the data for the given key.

Arguments:
  • key (string) – The key to use when setting the data.
  • value (object) – The value to insert. Primitive types will be converted to a string. Arrays will be converted into a comma-separated string.
job.deleteData(key)

Removes the given key from the job data.

Arguments:
  • key (string) – The key to delete from job data.
job.fail(errorMessage)

Fails the current step, but the step will be retried (up to five times).

Arguments:
  • errorMessage (string) – The error message, which will be used to set error cause on the job.
job.fatalFail(errorMessage)

Fails the current step and job.

Arguments:
  • errorMessage (string) – The error message, which will be used to set error cause on the job.
job.getUser()

Gets the user of the job. It replaces the old way of getting the user name using job.getData("username").

job.getKeys()

Returns all the keys from the job data.

New in version 4.16.

job.containsKey(key)

Checks if the job data contains the key.

Arguments:
  • key (string) – The key to check.

New in version 4.16.

job.getDataOrDefault(key, value)

Returns the value from the job data or the given default value.

Arguments:
  • key (string) – The key to use when getting the data.
  • value (string) – The value to return if there is no job data set with the given key.

New in version 4.16.

job.getStepId()

Returns the current job step id.

New in version 5.0.

job.wait(reason)

Sets the job in WAITING state.

Arguments:
  • reason (string) – An explanation of what the job is waiting for.
job.wait(milliseconds)

Set Thread sleep

Arguments:
  • milliseconds (number) – The amount of milliseconds to sleep.
job.waitForJobs(reason, jobIds[])

Sets the job in WAITING state until all jobs in jobIds is finished.

New in version 5.4.

Arguments:
  • reason (string) – An explanation of what the job is waiting for.
  • jobIds (string[]) – An array of job ids that the job is waiting for to finish.

Pausing job execution

A JavaScript job step can pause the execution of the job by calling job.wait(). This will set the job in the WAITING job state and create a job problem of type JavascriptProblem.

To determine if the job execution can be resumed, the script is run again every minute with the variable checkProblem set to true. If the job should keep waiting, then job.wait() should be called again.

Waiting for other jobs

New in version 5.4.

If your job step needs to wait for another job to finish before continuing, the script can call job.waitForJobs(). This will set the job in the WAITING job state and create a job problem of type WaitingForJobs. Once all the jobs are finished this job step will be re-executed.

Using job.waitForJobs() can make job execution faster as the job problem will be resolved and the job marked as READY once the the dependant jobs have finished.

Example

To have the job wait and later run in wait/check mode:

if (checkProblem) {
  if (/* condition is fulfilled */ ...) {
    return;
  }
  // Call job.wait() to indicate that the job should wait more
  // See note above
  job.wait("condition still not fulfilled");

} else {
  // run step as normal
  ....

  if (/* condition is not fulfilled */ ...) {
    job.wait("waiting for condition");
    return;
  }

  // continue job execution
  ....
}

To have the job wait for other jobs to finish:

// Previous step started some jobs and stored as a comma separated list
let jobIds = job.getData('jobIds').split(',');

for (let i=0; i < jobIds.length; i++) {
    const job = api.path('job').path(jobIds[i]).get();
    if (job.status !== 'FINISHED') {
        // If we find a job that is not finished already, wait for all jobs to finish.
        // Note that this will only happen once, during next invocation of the job step
        // all the jobs will be finished.
        job.waitForJobs('Waiting for jobs to finish...', jobIds);
    }
}

// continue job execution
....

Vidinet job execution

Jobs can be submitted to Vidinet services, for execution or for cost estimates, using the Vidinet functions on the job object.

job.vidinetJob(type, instruction, settings)

Submits a job to Vidinet and sets the job in VIDINET_JOB state.

Arguments:
  • type (string) – The type of Vidinet resource to use.
  • instruction (string) – The job instruction.
  • settings (object) –

    A set of key/value pairs related to the job.

    • item - The id of the item that the job relates to.
    • shape - The id of the shape that the job relates to. Optional. Overrides tag.
    • tag - The shape of the item that the job relates to. Default is original.
    • resource - The specific Vidinet resource to submit the job to.
job.vidinetCost(type, instruction, settings)

Request a cost estimate from Vidinet.

Arguments:
  • type (string) – The type of Vidinet resource to use.
  • instruction (string) – The job instruction.
  • settings (object) –

    A set of key/value pairs related to the job.

    • item - The id of the item that the job relates to.
    • shape - The id of the shape that the job relates to. Optional. Overrides tag.
    • tag - The shape of the item that the job relates to. Default is original.
    • resource - The specific Vidinet resource to submit the job to.
Returns:

A Future<CostEstimateType> that can be used to retrieve the estimate.

Example

To submit a job to a Vidinet service that is not natively supported:

var item = ...;
var instruction = "...";

job.vidinetJob("TEST", instruction, {
    item: itemId
});

In case a cost estimate is wanted before submitting the job to Vidinet:

var item = ...;
var instruction = "...";
var settings = {
  item: itemId
};

if ("true".equals(job.getData("estimate"))) {
  var estimate = job.vidinetCost("TEST", instruction, settings);
  var result = estimate.get(); // blocking call

  var cost = result.getService().get(0).getCost();
  job.setData("app_estimated_cost", cost.getAmount());
} else {
  job.vidinetJob("TEST", instruction, settings);
}

Example: Update item metadata on import

Start by adding a new task to the import job with the script to execute.

Note

If using curl, use --data-binary instead of -d to make sure all new-line characters are kept in the script.

POST /task-definition/
Content-Type: application/xml

<TaskDefinitionListDocument xmlns="http://xml.vidispine.com/schema/vidispine">
  <task>
    <description>Updating item metadata using a JavaScript task</description>
    <script><![CDATA[
...
]]></script>
    <step>10000</step>
    <dependency>
      <previous>false</previous>
      <allPrevious>true</allPrevious>
    </dependency>
    <jobType>PLACEHOLDER_IMPORT</jobType>
    <critical>false</critical>
  </task>
</TaskDefinitionListDocument>
// Retrieve the id of the item that is being imported
var itemId = job.getData("itemId");
var shapeId = job.getData("originalShapeId");

// Retrieve the shape information
var shape = api.path("item/"+itemId+"/shape/"+shapeId).get();
var video = shape.videoComponent.length;
var audio = shape.audioComponent.length;

// Build a document with the metadata to set
var metadata = {
  "timespan": [
    {
      "start": "-INF",
      "end": "+INF",
      "field": [
        {
          "name": "title",
          "value": [
            {
              "value": "Item with "+video+" video and "+audio+" audio tracks"
            }
          ]
        }
      ]
    }
  ]
};

// Update the item metadata
var result = api.path("item/"+itemId+"/metadata").input(metadata).put();
var metadata = result.item[0].metadata;

Example: Update item metadata on import using XML

Scripts can also use ECMAScript for XML (E4X) to easily create and parse XML documents. Using E4X the above script could be written as below. Note that the XML responses from Vidispine will automatically be parsed into E4X XML objects instead of being returned as strings.

// Set the default XML namespace so that the Vidispine namespace does not have
// to be specified when retrieving properties or when building the metadata document
default xml namespace = "http://xml.vidispine.com/schema/vidispine";

// Retrieve the id of the item that is being imported
var itemId = job.getData("itemId");
var shapeId = job.getData("originalShapeId");

// Retrieve the shape information
var shape = api.path("item/"+itemId+"/shape/"+shapeId).dataType("xml").get();
var video = shape.videoComponent.length();
var audio = shape.audioComponent.length();

// Build a document with the metadata to set
var metadata = <MetadataDocument>
  <timespan start="-INF" end="+INF">
    <field>
      <name>title</name>
      <value>Item with {video} video and {audio} audio tracks</value>
    </field>
  </timespan>
</MetadataDocument>

// Update the item metadata
var result = api.path("item/"+itemId+"/metadata").input(metadata).put();
var metadata = result.item[0].metadata;