Application settings

Accurate Video Frontend

This document describes available configuration settings for Accurate Video.

Files available for configuration:

settings.js

Settings are defined in a javascript file which is deployed with the application.

Remote settings

It is possible to move a subset of the settings to a remote location using the settingsUrl setting.
The local settings file (deployed with the application) is always read first and must include backendUrl and authentication to ensure that user can be authenticated prior to fetching the remote settings.
If settingsUrl is defined the application will fetch the remote settings and merge them with the local settings.

The only constraint is that remote settings may not define backendUrl, settingsUrl nor authentication.

Using this setup

  • sensitive settings can be protected from unauthorized users
  • settings can be updated without redeploying application

Settings described

  • backendUrl - Base URL that will be called when accessing Accurate Video Adapter.
  • settingsUrl - URL to remote settings file. If omitted, only local settings are loaded. See Remote settings
  • settingsCredentials - The request credentials you want to use for the remote settings request: omit, same-origin, or include. To automatically send cookies for the current domain, this option must be provided.
  • authentication - see Authentication
  • eventBusUrl - URL to backend event bus. If omitted, it is set to backendUrl + "/eventbus"
  • endFrameInclusive - If true, backend timespans are considered end frame inclusive.
  • licenseKey - License key for Accurate Player.
  • preferredVideoShapes - Array of shape tags to load when opening a video item. First shape has highest priority.
  • showAssetView - Enable/disable asset list view.
  • showThemeSelect - Allow user to switch between dark and light theme.
  • assetSearchParams - Array of content parameters to provide when requesting a asset. see Asset Content Parameters
  • audioQc - see Audio QC
  • qc - see QC Settings
  • ingest - see Ingest
  • markers - see Markers
  • timeline - see Timeline
  • storages - see Storages
  • drm - see Drm
  • enabledApps - Optional list of paths used for limiting enabled apps. E.g. ['qc', 'promo'] will hide other apps from asset list view.
  • features - see Common features
  • assetStatus - see Asset status

Minimal changes

All settings have default values, most of them require no changes. The settings you alter will be merged which means that
complex objects are changed easily. For example, changing timeline.waveforms.vidispine.tag

timeline: {
    waveforms: {
      active: "vidispine",
      vidispine: {
        tag: "original",
        shape: null,
        sampleMin: -43,
        sampleMax: 0
      },
      ...
    }
}

only requires

timeline: {
  waveforms: {
    vidispine: {
      tag: "house-original";
    }
  }
}

QC Settings

Settings for QC route:

qc: {
  features: {
    markers: true;
  }
}
  • qc.features.markers - Default: true. Allow creating and editing markers.

Audio QC

Settings for Audio QC route

audioQc: {
  preferredVideoShapes: ["mp4", "original", "mp4-lowres", "lowres"],
  preferredAudioShapes: ["mp4-6track", "mp4-8track"]
}
  • audioQc.preferredVideoShapes - Array of shape tags to load when opening an asset. First shape has highest priority and the first matching video file will be selected.
  • audioQc.preferredAudioShapes - Array of shape tags to load when opening an asset. All audio files that have a matching shape tag will be loaded.

Ingest

Settings for the ingest route.

{
  ingest: {
    preferredVideoShapes: ["mp4", "mp4-lowres", "original"],
    preferredAudioShapes: ["aac", "6track"],
    preferredSubtitleShapes: ["original"]
  }
}
  • ingest.preferredVideoShapes - Array of shape tags available to select when ingesting a video file.
  • ingest.preferredAudioShapes - Array of shape tags available to select when ingesting an audio file.
  • ingest.preferredSubtitleShapes - Array of shape tags available to select when ingesting a subtitle file.

Markers

Settings for QC markers are used for

  • separating markers info separate groups and rows
  • defining how those groups and rows should be represented
  • mapping customer specific metadata to our internal representation
  • configuring manual or dynamic tracks to hold markers in backend.
  • controlling which rows should allow creation of markers.
exportFormats: string[],
groups: [{
  id: MarkerSettingsDynamicValue<string>,
  trackType: string,
  alwaysHide: MarkerSettingsDynamicValue<boolean>,
  alwaysShow: MarkerSettingsDynamicValue<boolean>,
  markerStyle: MarkerSettingsDynamicValue<MarkerStyle>,
  match: (marker: AvMarker) => boolean,
  order: MarkerSettingsDynamicValue<number>,
  readOnly: MarkerSettingsDynamicValue<boolean>,
  title: MarkerSettingsDynamicValue<string>,

  rows: [{
    markerType: string,
    tooltip: MarkerSettingsDynamicValue<string>,
    track: MarkerSettingsDynamicValue<string>,
    alwaysHide: MarkerSettingsDynamicValue<boolean>,
    alwaysShow: MarkerSettingsDynamicValue<boolean>,
    markerStyle: MarkerSettingsDynamicValue<markerStyle>,
    match: (marker: AvMarker) => boolean,
    order: MarkerSettingsDynamicValue<number>,
    readOnly: MarkerSettingsDynamicValue<boolean>,
    title: MarkerSettingsDynamicValue<string>
  }]
}],
markersMetadataSettings: [{
  match: (string) => boolean,
  mappings: [{
    name: string,
    description: string,
    trackId: string,
    [key: string]: string
  }]
}],
tracksMetadataSettings: [{
  match: (string) => boolean,
  mappings: [{
      name: string,
      description: string,
      [key: string]: string
  }]
}]
  • exportFormats - Export formats to enable in the marker exports menu. Defaults to ["CSV", "XML", "JSON"]
  • group.id - Identifier for the group. Note, when using a callback here, each unique id generates a new group.
  • group.alwaysHide - Hide the group from UI.
  • group.alwaysShow - Show the group and its rows even if it contains no markers.
  • group.markerStyle - Style for all markers within this group.
  • group.match - Matcher function determining if a marker matches this group.
  • group.order - Number determining the sort order between groups.
  • group.readOnly - Prevent user from creating markers for this group.
  • group.title - Title to show in timeline.
  • row.markerType - Mapped to TimeSpanDto when creating marker.
  • row.tooltip - Tooltip to show when hovering over marker.
  • row.track - Used for identifying the row. Note, when using a callback here, each unique id generates a new row.
  • row.alwaysHide - Hide the row from UI. Overrides group.alwaysHide
  • row.alwaysShow - Show the row event if it contains no markers. Overrides group.alwaysShow
  • row.markerStyle - Style for all markers within this row. Overrides group.markerStyle
  • row.match - Matcher function determining if a marker matches this row.
  • row.order - Number determining the sort order of between rows in this group.
  • row.readOnly - Prevent the user from creating markers for this row.
  • row.title - Title to show in timeline.
  • markersMetadataSettings - Array of settings used for mapping marker metadata keys between backend adapter and frontend scheme.
  • markersMetadataSettings.match - Matcher function using marker type to determine if metadata mapping should be used for a marker.
  • tracksMetadataSettings - Array of settings used for mapping track metadata keys between backend adapter and frontend scheme.
  • tracksMetadataSettings.match - Matcher function using track type to determine if metadata mapping should be used for a track.

match property

The match property is used to match a marker or a track to a settings-block. The unique id (for groups) or track (for rows) is what separates the markers into different groups and rows.

It takes a callback (marker?: AvMarker, track?: AvTrack) => boolean. Note that both marker and track may be undefined. This allows the user to separate markers and tracks in numerous ways:

// Separate on marker type
match: marker => marker && marker.type === "Baton",

// Separate on metadata fields
match: marker => marker && marker.metadata.get("trackId") !== null,

// Match all
match: () => true
markerMetadataSettings and tracksMetadataSetting

For markerMetadataSettings and tracksMetadataSetting the match property instead takes a callback (type: string) => boolean where type is the marker (or track) type.

type => type === "Baton";

MarkerSettingsDynamicValue\ type

Most of the properties use this type which is either T or a callback (marker?: AvMarker, track?: AvTrack | null) => T.

// Get tooltip from marker metadata field "name".
tooltip: marker => marker && marker.metadata.get("name"),

// Get title from marker.type
title: marker => marker && marker.type,

// Set specific title
title: "Info",

// Set row title based on track (with fallbacks)
title: (marker, track) =>
  (track && track.metadata.get("name")) ||
  (marker && marker.metadata.get("trackId")) ||
  "No track found",

Examples

Below are some examples of different marker setups.

Read-only markers
groups: [
  {
    match: marker => marker && marker.type === "Baton",
    title: "Baton",
    id: "Baton",
    readOnly: true,
    rows: [
      {
        match: () => true, // Default
        track: ({ metadata }) => metadata.get("trackId"),
        title: ({ metadata }) => metadata.get("trackId"),
        tooltip: ({ metadata }) => metadata.get("name"),
        order: ({ metadata }) => {
          switch (metadata.get("trackId")) {
            case "Info":
              return 0;
            case "Warning":
              return 1;
            case "Serious":
              return 2;
          }
          return -Infinity;
        },
        markerStyle: ({ metadata }) => {
          switch (metadata.get("trackId")) {
            case "Warning":
              return { backgroundColor: "#dd5858" };
            case "Serious":
              return { backgroundColor: "#c73535" };
          }
          return undefined;
        }
      }
    ]
  }
];

We match the group on marker type. trackId is used to separate the different rows applying order and style.

Manual markers, static track
groups: [
  {
    match: (marker, track) =>
      (marker && marker.type === "Manual") ||
      (track && track.type === "Manual"),
    title: "Manual",
    id: "Manual",
    alwaysShow: true,
    allowCreateTrack: true,
    rows: [
      {
        match: marker =>
          marker && marker.metadata.get("trackId") === "av:track:warning",
        track: "av:track:warning",
        title: "Warning",
        tooltip: ({ metadata }) => metadata.get("name"),
        order: 1,
        markerType: "Manual",
        markerStyle: { backgroundColor: "#c73535" }
      },
      {
        match: marker =>
          marker && marker.metadata.get("trackId") === "av:track:serious",
        track: "av:track:serious",
        title: "Serious",
        tooltip: ({ metadata }) => metadata.get("name"),
        order: 2,
        markerType: "Manual",
        markerStyle: { backgroundColor: "#c73535" }
      },
      {
        match: marker =>
          marker && marker.metadata.get("trackId") === "av:track:info",
        track: "av:track:info",
        title: "Info",
        tooltip: ({ metadata }) => metadata.get("name"),
        order: 0,
        markerType: "Manual"
      },
      {
        // Markers from user tracks generated in UI.
        match: (marker, track) =>
          !!(marker && marker.metadata.get("trackId")) || !!track,
        track: (marker, track) => track.id,
        title: (marker, track) => track && track.metadata.get("name"),
        tooltip: marker => marker && marker.metadata.get("name"),
        order: (marker, track) => parseInt(track && track.id, 10) ?? 4,
        markerType: "Manual",
        alwaysShow: false
      },
      {
        match: () => true, // Default
        id: marker => marker.type,
        title: marker => marker.type,
        alwaysHide: true,
        rows: []
      }
    ]
  }
];

We define the marker type "Manual". This is used in the match property on the group (to find the correct group setting for the marker) and when mapping marker metadata using markerMetadataSettings.
markerType is also set to "Manual" on each row to ensure that new markers are created with the correct type.
We define different rows using track property and match them using the trackId metadata field.

On group level allowCreateTrack is used to allow users to manually create tracks in th UI for this group.

On row level we set alwaysShow to ensure that the rows are shown even when there are no markers.

Hide by default
groups: [
  {
    match: () => true, // Default
    id: marker => marker.type,
    title: marker => marker.type,
    alwaysHide: true,
    rows: []
  }
];

The last group, the default case, matches everything and sets alwaysHide to ensure that those markers are hidden.

Row title from track
row.title: (marker, track) =>
  (track && track.metadata.get("name")) ||
  marker.metadata.get("trackId") ||
  "No track found",

Track is also passed as an argument to MarkerSettingsDynamicValue function which allows us to connect track to a row.

Mapping marker and track metadata
markersMetadataSettings: [
  {
    match: type => type === "AvMarker",
    mappings: {
      name: "av_marker_name",
      description: "av_marker_description",
      trackId: "av_marker_track_id"
    }
  }
];

We map the metadata names used in backend (e.g. av_marker_name) to the names we use in frontend (e.g. name).
This mapping is done before markers are parsed, which means the frontend name can be used in MarkerSettingsDynamicValue functions.
It is also done the other way around when we post markers to backend.

tracksMetadataSettings: [
  {
    match: type => type === "VpubTrack",
    mappings: {
      name: "av_track_name",
      description: "av_track_description"
    }
  }
];

Mapping is done in the same way for tracks.

Timeline

Settings for the timeline.

timeline: {
    waveforms: {
      active: "vidispine",
      vidispine: {
        tag: "original",
        shape: null,
        sampleMin: -43,
        sampleMax: 0
      },
      analyze: {
        url: "https://localhost:8080/",
        urlReplaceFrom: "",
        urlReplaceTo: "",
        username: "",
        password: "",
        sampleMin: -43,
        sampleMax: 0
      }
    }
}
  • waveforms - Describes how waveforms should be retrieved.
  • waveforms.active - String determining which profile to use ("vidispine" or "analyze").
  • waveforms.vidispine - Profile for fetching waveforms from Vidispine adapter.
  • waveforms.vidispine.tag - Shape tag to fetch waveform from (see Vidispine API).
  • waveforms.vidispine.shape - Shape id to fetch waveform from (see Vidispine API).
  • waveforms.vidispine.sampleMin - Adjust scaling of waveform.
  • waveforms.vidispine.sampleMax - Adjust scaling of waveform.
  • waveforms.analyze - Profile for fetching waveforms from Accurate Analyze.
  • waveforms.analyze.url - Url to Accurate Analyze.
  • waveforms.analyze.urlReplaceFrom - Regular expression or search string.
  • waveforms.analyze.urlReplaceTo - Text to replace with.
  • waveforms.analyze.username - Username to use for basic authentication when accessing Accurate Analyze. Leave empty to disable.
  • waveforms.analyze.password - Password to use for basic authentication when accessing Accurate Analyze. Leave empty to disable.
  • waveforms.analyze.sampleMin - Adjust scaling of waveform.
  • waveforms.analyze.sampleMax - Adjust scaling of waveform.

urlReplaceFrom and urlReplaceTo modifies the url that is passed to Accurate Analyze.
waveforms.analyze.url is used to as input for this replacement but it is also used as base when calling Accurate Analyze.

Storages

Settings for storages.

storages: {
  awsRegions: [
    {
      label: "us-east-2",
      value: "us-east-2"
    },
    ...
  ]
}
  • storages.awsRegions - List of AWS Regions to support. label is what we present to the user, value is the region code.

Authentication

Settings for authentication.

authentication: {
  disabled: false,
  useBasicAuth: false,
  useQueryAuth: false,
  queryAuthParam: "u",
  tokenStorageLocation: "av_jwt_token",
  keycloakConfUrl: "./assets/json/keycloak.json",
  unauthorizedRedirect: ""
}
  • disabled - (Optional, default: false) Disable authentication
  • useBasicAuth - (Optional, default: false) If basic auth should be used instead of authentication against keycloak.
  • tokenStorageLocation - (Optional, default: av_jwt_token) local storage key to store token.
  • keycloakConfUrl - (Optional, default: ./assets/json/keycloak.json) Location of keycloak adapter configuration (Keycloak OIDC JSON).
  • useQueryAuth - (Optional, default: false) If authentication token should be provided through query param. Will set
    authorizarion headers type to AV.
  • queryAuthParam - (Optional, default u) This is the query parameter to be used for authentication if useQueryParam is enabled.
  • unauthorizedRedirect - (Optional) If set, this will redirect user to another location if unauthorized or logged out. Could be
    used if AV is launched from a separate system.

Common features

Features that may span across several applications.

features: {
  assetStatus: false,
  enrichAsset: false
}
  • features.assetStatus - Default: false. Allow user to set status for an asset. See asset status.
  • features.enrichAsset - Default: false. Allow user to run enrich services like AWS Rekognition on assets.

Asset status

Settings for asset status feature. Note that feature settings.features.assetStatus is disabled by default.

assetStatus: {
  statusMetadataFieldName: "asset_status",
  commentMetadataFieldName: "asset_status_comment",
  statusSetByMetadataFieldName: "asset_status_set_by_comment",
  statuses: [
    {
      key: "in_progress",
      labels: {
        status: "In progress"
      },
      color: "#9493a0"
    },
    {
      key: "approved",
      labels: {
        status: "Approved",
        assign: "Approve"
      },
      color: "var(--AP-SUCCESS)",
    },
    {
      key: "rejected",
      labels: {
        status: "Rejected",
        assign: "Reject"
      },
      color: "var(--AP-ERROR)",
      revokable: false,
      allowComment: true
    }
  ]
}
  • statusMetadataFieldName - Name of metadata field to store status. Default "asset_status".
  • commentMetadataFieldName - Name of metadata field to store comment. Default "asset_status_comment".
  • statusSetByMetadataFieldName - Name of metadata field to store user that set the current status. Default "asset_status_set_by".
  • statuses - List of possible statuses.
  • statuses - key - Status key as defined by customer. undefined maps to an asset that has no status.
  • statuses - labels - Defines how this status should be presented in UI.
  • statuses - labels.status - Label to use when this status has been set.
  • statuses - labels.assign - Optional. Label to use in confirm button when setting this status.
  • color - Optional. Custom color for this status.
  • revokable - Default true. If false, it is not possible to change to a different status after setting this status. E.g. preventing a rejected asset from becoming approved.
  • allowComment - Optional. Allows the user to comment the status. E.g. explain why the status was rejected.

Drm - DASH/HLS Specific

Settings for configuring DRM. Only available when streaming using HLS & Dash.\
Streaming dash and HLS content is powered by shaka-player and with it comes capabilities
to support DRM.

 drm: {
   servers: {
     "com.widevine.alpha": "https://wv-keyos.licensekeyserver.com/"
   },
   streamingInterceptor: (data) => {
     return (type, request) => {
       if (type === 2) {
         request.headers.customdata = data;
       }
     }
   },
   fileSecretKey: "custom_data_xml"
 }
  • servers - list of licensing servers and drm system (for additional information see shaka-players documentation).
  • streamingInterceptor - Optional callback. Should return interceptor for shaka-players network engine, allows additional
    authentication
    capabilities
    . (Consult Accurate Player for definitions of the interceptor)
  • fileSecretKey: Optional key for metadata field on VideoFileDto, corresponding value will be used as the optional "data" parameter
    to the streamingInterceptor callback.

languages.json

Defines the languages used.

[
  {
    "code": "en",
    "label": "English"
  },

  {
    "code": "cz",
    "label": "Czech"
  },
  ...
]

profiles.json

Defines the audio profiles available in Audio QC.

[
  {
    "id": "-1",
    "name": "Profile not set",
    "tracks": ["Profile not set"],
    "noChannelInformation": true
  },
  {
    "id": "10",
    "name": "Profile 10",
    "tracks": ["Stereo", "Stereo"]
  },
  ...
]
  • id - Id used when storing profile in Accurate Video Adapter
  • name - Label to show in UI.
  • track - Array of tracks that describes the profile.

Available tracks

"Mono"
"Stereo"
"Stereo (7-8)"
"Stereo (9-10)"
"Stereo (11-12)"
"Stereo in 5.1 AES"
"5.1 SMPTE"
"5.1 AES"
"5.1 AAC"
"7.1 SMPTE"
"7.1 AES"
"7.1 AAC"
"3-6 Silent"

Constants

Constants used and their string value.

Asset Content parameters.

  • VideoFile = "video_file"
  • Metadata = "metadata"
  • Marker = "marker"
  • FileMetadata = "file_metadata"
  • SubtitleFile = "subtitle_file"
  • StillFrame = "still_frame"
  • AudioFile = "audio_file"
  • BulkyMetadata = "bulky_metadata"
Rendering using FFMPEG