Update Service is a way of updating fields in a data element right before the graphics is taken on air, or during on air time. This happens on the server side, and typical usage is updating scores, stock prices, statistics etc. The script being run is invoked by Media Sequencer on different actions: take, read, cue and update. The script being invoked gets a copy of the fields in the data element (the payload), it can manipulate the fields and return a modified payload. The modified payload is then used by Media Sequencer when sending the playout commands to the Viz Engine. The modified payload is not saved in the Pilot database. There are 3 ways of invoking an update service:

  1. Using the Vizrt Pilot Update Service to execute javascript templates written in Template Builder.

  2. Implementing custom script runner on an external web server.

  3. Using the VB script script runner in Pilot (for templates created in Template Wizard).

This section contains the following topics:

Enabling Update Service in a Template

Enter the Template Properties page:

image-20250106-082920.png

The Update Service section has 4 available options:

  • None. No update service is used.

  • Pilot Update Service: Lets the Pilot Update Service either auto-update the template, or run the onUpdate event handler in the internal template script (see below). In this case, the javascript in the onUpdate event is executed on the server side by the Pilot Edge Script Runner.

  • VBScript (legacy): Enabled if the template is created with Template Wizard and the template contains a VBScript.

  • External: Use this to specify a URL to an external update service.

Pilot Update Service with Javascript in Template Builder

When an update script is enabled for a template, the Media Sequencer representation (VDOM) of the master template contains a <live_update> node. This node contains URLs to the update service responsible for updating the payload. The result is put into VDOM and sent to the Viz Engine, but not saved back to the Viz Pilot database.

Viz Pilot Update Service

The Viz Pilot Update Service is automatically installed together with Pilot Data Server. Make sure this service runs and is responsive and reachable from Media Sequencer. The default port is 1991 for HTTP and 1992 for HTTPS. This service executes the onUpdate part of the template script. To determine when the script runner should be invoked by Media Sequencer and control the behavior, the following properties can be set in the Update Script section of Template Properties:

image-20250221-115436.png
  • Pilot Update Service: Determines that the Pilot Update Service should be used to update data.

    • Auto-update: Lets the Update Service refresh all field links to external data with the latest content. No script is executed.

    • Template script: The onUpdate() in the internal template script should be executed by the Update Service.

  • Action: Determines on which Media Sequencer actions the script should be invoked.

    • take: To get the graphics on air.

    • read: Used to preview the graphics on an external Viz Engine (Viz Trio for example).

    • update: Explicitly update data in an element being on air in the renderer, without starting in-animations.

    • cue: Setting graphics in the first frame of the animation in the renderer.

  • Timeout: For all actions, specifies the amount of time in milliseconds Media Sequencer waits for the response from the Update Service, before it continues with the operation.

  • Update regularly: For the take action, the Update Service can also be invoked on regular intervals while the graphics are on air. The interval is decided by the live_update_interval database parameter. The default and minimum value is 2 seconds. 

Note: If Update regularly is checked, the update script action runs with the take action on subsequent updates. However, if update is also checked, the action script is called with update as an argument. This means you can differentiate the script behavior based on whether the Media Sequencer action is take or update.

Auto Update

To auto update the data without writing scripts, the fields to update need to be connected to a feed entry through the field linking. The workflow is:

  • The Template Designer links fields in the template to content, through the feed browser or feed-backed dropdown.

  • The journalist select a feed entry and save a snapshot of the data from the feed.

  • On playout, Media Sequencer calls the auto update mechanism in the Update Service, which follows the self link in the Atom entry, to download the latest data from the feed.

Example of Atom Feed Entry with a self link used by Update Service:

<entry>
<id>1832050330902700035</id>
<link href="https://twitter.com/luna_corgi/status/1832050330902700035" rel="alternate" type="text/html"/>
<title type="text">It's finally Friday frens!</title>
<content type="text">It's finally Friday frens! I'm going to enjoy this beautiful day. What are your plans for today?</content>
<summary type="text">twitter</summary>
<media:thumbnail url="http://myserver:9090/data/media/v1/https/flowics-server.com/_vXH9hj3mlVUK4VowdEqA5CyjYA_C3iWkuc_Di26JEg.jpg"/>
<author>
<name>Luna the Corgi@luna_corgi</name>
<link href="http://myserver:9090/data/media/v1/https/flowics-server.com/_vXH9hj3mlVUK4VowdEqA5CyjYA_C3iWkuc_Di26JEg.jpg" rel="image"/>
</author>
<contributor>
<name>twitter</name>
</contributor>
<link href="http://myserver:9090/data/media/v1/https/pbs.twimg.com/ZNEhXojq54WQHSbxjd6pl8uXD4U4CKryXl8zE1tPTkg.jpg" rel="image" type="image/jpeg"/>
<published>2024-09-06T13:36:51.000+00:00</published>
<updated>2024-12-17T10:46:07.164Z</updated>
<link rel="self" type="application/atom+xml;type=entry" href="http://my-feed-server:1305/data/images/1.entry.xml"/>
</entry>

See also Data Entry - Using Feed Browsing.

Adding a Script in Template Builder

To add a script that is invoked by the Media Sequencer's Update Service mechanism, a special event needs to be implemented in the internal template script editor: onUpdate. This event is never called from within Template Builder or Viz Pilot Edge, therefore, it is only executed by the Viz Pilot Edge Script Runner service when Media Sequencer invokes it. The mechanism is invoked by Media Sequencer only if it is enabled in Template Settings. Make sure the Pilot Update Service / Template script option is enabled in the Update Service section in Template Settings (see above). In its simplest form, an update script can look like this:

vizrt.onUpdate = (fields, action) => {
fields["$02-Designation"].value = `${fields["$01-Name"].value} live from Svalbard`
}

The fields object contains a list of the fields of the payload and can be accessed as one normally accesses this object in Template scripting. Only the field values are available and can be manipulated (and not UI properties like visibility for instance). The (manipulated) fields object is automatically returned to Media Sequencer by the Viz Pilot Edge Script Runner.

Script Technology

The script language in the template editor is TypeScript. All Javascript is valid Typescript, so you can choose what you want inside the editor, but the syntax highlighting and the error checking expects Typescript. The script inside the editor is automatically compiled into Javascript and stored both as Typescript and Javascript inside the template. When a template script normally executes in the browser, it is executed through the browser’s Web API.

For Update Service scripts, it is slightly different. The script code executed inside the onUpdate method has a different execution context than the rest of the template script. While the rest of the template script executes in the web browser's javascript environment, the onUpdate part of the script executes on the server side through a node.js process. Both execution environments support the Javascript Core Language, but they serve different purposes and have different sets of APIs.

Warning: Even if the syntax highlighting inside onUpdate reports no errors in the template script editor, the code can still cause errors when executed on the server side due to being executed inside a node.js environment, and not through the browser’s Javascript API. Make sure to configure Viz Pilot Edge script runner and test the script through the Update Service.

Example - Async Fetch from REST Source

A more realistic example is where the script fetches some data from an external source and uses that to update the fields. A typical example is updating live scores and sports results. This can be done with a javascript fetch command and making the method marked as async. Here done only on take action in Media Sequencer (right before the graphics go on air):

interface Team {
name: string;
score: string;
}
 
interface GameData {
teams: Team[];
current_quarter: string;
game_clock: string;
}
 
// doUpdate() can be called both from the template itself and from
// Pilot Update Service.
async function doUpdate(fields: Payload, action: string) : Promise<void> {
try {
const response = await fetch('http://myscore-host:3000/app/score.json');
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
 
const data: GameData = await response.json()
// Log the JSON object as a string
console.log(JSON.stringify(data, null, 2));
 
processData(data, fields)
} catch (error) {
// Handle errors (e.g., network issues, JSON parsing errors)
console.error('Error fetching data:', (error as Error).message)
}
}
 
vizrt.onUpdate = async (fields, action) => {
console.log("onUpdate is called")
await doUpdate(fields, action)
}
 
// Method to process JSON data
function processData(data: GameData, fields: Payload) {
console.log("processData is called")
 
// Extract the current quarter and game clock
const currentQuarter = data.current_quarter
const gameClock = data.game_clock
// Extract the scores for each team
const [homeTeam, awayTeam] = data.teams
fields["$102"].value = homeTeam.score
fields["$202"].value = awayTeam.score
fields["$002"].value = currentQuarter + " - " + gameClock
}
 
// Simulate the "take" action update script in the browser
vizrt.onClick = async (name: string) => {
await doUpdate(vizrt.fields, "take")
}

The code above expects this JSON structure:

{
"teams": [
{ "name": "CSU", "score": "21" },
{ "name": "Longwood", "score": "10" }
],
"current_quarter": "2nd quarter",
"game_clock": "3:45"
}

Interesting points about the code above:

  • In the code example, the OnUpdate script can be tested inside the browser (client side only) as we added a button and a click event to manually execute the doUpdate method. This requires the code inside onUpdate to run in the browser and in node.js. To add a button to test the script:

    • Add a new template Tab.

    • Add an inline HTML fragment.

    • Add the following HTML:

      <button vizrt-click-name="updatebutton">TEST UPDATE</button>
  • We use the async fetch method to get data from an external host, and we convert it to JSON. We can use fetch because both the browser’s Web API and node.js, contain this method and the signature is the same. But this is not something that can be taken for granted. When using functionality outside the Javascript Core language, please check that both the browser’s Web API and node.js implement the functionality.

  • A benefit of using fetch in the onUpdate run by the server side in node.js, is that it handles headers differently (for example, CORS issues do not occur).

  • If the onUpdate method contains API calls that are not compatible with the browser’s Web API but only with node.js, the update script needs to be tested by a proper server side execution.

  • Pay special attention to the async method declaration and use of await. An async function returns a promise, and using await pauses execution until the promise resolves. This makes it possible to write script code that executes synchronously and returns with a value. The onUpdate code executed by the Pilot Update Service depends on processing everything before returning with the new payload, and forgetting an await if the method contains asynchronous code like a fetch leads to undefined behavior, as the script returns with data before the processing is done.

  • In onUpdate, the event handler works with a copy of the fields in the payload. Notice that the code executed in onUpdate does not change the template in Template Builder, nor invoke any onchanged events.

Testing the Script

To test a proper server side execution of the update script:

  • Save the template.

  • Click the test update script-button in Template Builder image-20241002-130401.png.

A new window opens, allowing you to test the script by doing a POST to the script runner URL with the source data on the left, and the returned VDF payload on the right.

image-20241002-132826.png
  1. The left window contains the VDF payload of the current data element.

  2. When clicking Update the REST end point in Pilot Update Service (as configured in the Pilot Data Server Launcher) is called with the URL to the current data element as a parameter. Pilot Update Service then loads the template script from the Pilot Data Server, executes onUpdate and returns with a new, updated payload.

  3. The action parameter simulates different actions performed by a control client on the data element. This action is sent as an argument to the update script and makes it possible to differentiate between actions in the script.

  4. The right panel contains the response from the Pilot Update Service. To check whether it performed the desired updates, look for the field values it was supposed to manipulate inside the payload. Note that the current data element in Template Builder is not updated, nor is the preview. The only result of the server side script execution is the VDF payload in this window.

  5. If the script contains logging to console or exceptions, these log messages are returned from the Pilot Script Runner along with the VDF payload and displayed here. This is useful for debugging and testing. There are 4 log types available when logging in script, they are each displayed with different colors in the log window:

    console.log("LOG")
    console.info("INFO")
    console.warn("WARN")
    console.error("ERROR")

External Update Service 

It is fully possible to write a custom update service and omit the usage of the template script and Viz Pilot Edge Script Runner. In Template Builder, enter Template Settings for the template and enable the External option under Update Service.

  • Specify the URL to the external update service. 

  • Specify the Media Sequencer actions that invoke the update service. Only one URL can be specified for all actions.

Implementing a Custom Server

On the server side, to implement a custom Update Service, a web service should respond to the URL specified in the template. The service must accept an HTTP(S) POST request on a given endpoint with a Content-Type of application/vnd.vizrt.payload+xml. The service should only modify field values, and not add or remove fields. The service must return an updated payload, or the same payload that was posted if there are no changes. In order to implement an external update service, you need to parse and return a Viz Data Format (VDF) document to Media Sequencer. The document is posted to the external update service by Media Sequencer.

See Also

  • For a detailed description on how Media Sequencer handles Update Service scripts, see Live Update Support in the Media Sequencer Administrator Guide (go to http://localhost:8580/mse_manual/dispatch_element%20actor.html#live-update-support on the host where Media Sequencer is installed). For a description of the Viz Data Format (VDF), go to the web interface of Pilot Data Server and locate the link to the specification.