diff --git a/v1/examples/l3rd-name/l3rd.ograf.json b/v1/examples/l3rd-name/l3rd.ograf.json index 4f7aaac..b39dca0 100644 --- a/v1/examples/l3rd-name/l3rd.ograf.json +++ b/v1/examples/l3rd-name/l3rd.ograf.json @@ -16,6 +16,25 @@ "schema": null } ], + "actionDurations": [ + { + "type": "playAction", + "duration": 1500 + }, + { + "type": "updateAction", + "duration": 400 + }, + { + "type": "stopAction", + "duration": 1100 + }, + { + "type": "customAction", + "customActionId": "highlight", + "duration": 2800 + } + ], "supportsRealTime": true, "supportsNonRealTime": true, "schema": { diff --git a/v1/examples/ograf-logo/logo.ograf.json b/v1/examples/ograf-logo/logo.ograf.json index 997bf8f..2f16980 100644 --- a/v1/examples/ograf-logo/logo.ograf.json +++ b/v1/examples/ograf-logo/logo.ograf.json @@ -6,6 +6,16 @@ "main": "graphic.mjs", "supportsRealTime": true, "supportsNonRealTime": false, + "actionDurations": [ + { + "type": "playAction", + "duration": 1000 + }, + { + "type": "stopAction", + "duration": 1000 + } + ], "author": { "name": "Markus Nygård, YLE" }, diff --git a/v1/examples/renderer-test/manifest.ograf.json b/v1/examples/renderer-test/manifest.ograf.json index 042d722..0e4afa2 100644 --- a/v1/examples/renderer-test/manifest.ograf.json +++ b/v1/examples/renderer-test/manifest.ograf.json @@ -36,5 +36,29 @@ } } } + ], + "actionDurations": [ + { + "type": "playAction", + "duration": 0 + }, + { + "type": "updateAction", + "duration": 0 + }, + { + "type": "stopAction", + "duration": 0 + }, + { + "type": "customAction", + "customActionId": "highlight", + "duration": 0 + }, + { + "type": "customAction", + "customActionId": "setColor", + "duration": 0 + } ] } diff --git a/v1/specification/docs/Specification.md b/v1/specification/docs/Specification.md index ead77b4..210532e 100644 --- a/v1/specification/docs/Specification.md +++ b/v1/specification/docs/Specification.md @@ -68,6 +68,7 @@ It consists of the following fields: | author | Author | | | An object providing information about the author of the Graphic. When provided, the object MUST contain a `name` field and MAY contain an `email` and `url` field. | | main | string | X | | Reference to the Javascript file that exports the Graphic Web Component. | | customActions | Action[] | | | An array of `Action` objects. They correspond to the custom actions that can be invoked on the Graphic. See below for details about the fields inside an `Action`. | +| actionDurations | ActionDuration[] | | | An array of `ActionDuration` objects. They describe the static animation durations of actions, expressed in milliseconds. | | supportsRealTime | boolean | X | | Indicates whether the Graphic supports real-time rendering. | | supportsNonRealTime | boolean | X | | Indicates whether the Graphic supports non-real-time rendering. If true, the Graphic MUST implement the non-real-time functions `goToTime()` and `setActionsSchedule()`. | | schema | object | | | The JSON schema definition for the `data` argument to the `load()` and `updateAction()` methods. This schema can be seen as the (public) state model of the Graphic. Properties in this schema MAY include an optional `hidden` (boolean) attribute; when `hidden` is true, the property's value SHOULD NOT be included when building a display name or label for the Graphic in a GUI (e.g. in playout or automation UIs). | @@ -125,6 +126,30 @@ In the Graphic Manifest, the `stepCount` property is used to describe the step m *Note: "step controls" are controls that allow a user to navigate between steps, such as "next step", "previous step", "go to step X", etc. +#### Action durations + +Action durations are optional metadata that allows predicting how long action animations +take. Durations are expressed as integer milliseconds. A duration of `0` means that there is no animation duration, and +a duration of `-1` indicates that the duration is dynamic or unknown. The values describe the normal animated execution +of an action, not the behavior when `skipAnimation` is set to `true`. + +The `ActionDuration` object contains the following fields: + +| Field | Type | Required | Default | Description | +|----------------|----------------------|:--------:|:-------:|-----------------------------------------------------------| +| type | string | X | | The action type. MUST be one of `playAction`, `updateAction`, `stopAction` or `customAction`. | +| duration | integer | X | | The animation duration in milliseconds. A value of `-1` indicates a dynamic or unknown duration. | +| customActionId | string | | | Required when `type` is `customAction`. MUST refer to the `id` of an Action in `customActions`. | +| steps | ActionStepDuration[] | | | Optional step-specific durations for `playAction`. | + +For non-custom actions, there MUST be at most one `ActionDuration` object per `type`. For custom actions, there MUST be +at most one `ActionDuration` object per `customActionId`. + +For `playAction`, the `steps` field MAY be used when different target steps have different animation durations. The +`step` field is zero-based, matching the `goto` field of `playAction()`. A step duration without a `step` field is the +fallback for target steps not explicitly listed. When determining the duration of a `playAction`, the matching order is: +an exact `step` match, then a fallback step duration without `step`, then the action-level `duration`. + #### Custom actions A custom action is an action that is specific for a particular Graphic. It is a mechanism to support any action diff --git a/v1/specification/json-schemas/graphics/schema.json b/v1/specification/json-schemas/graphics/schema.json index 279520a..01b4d70 100644 --- a/v1/specification/json-schemas/graphics/schema.json +++ b/v1/specification/json-schemas/graphics/schema.json @@ -60,6 +60,130 @@ "$ref": "https://ograf.ebu.io/v1/specification/json-schemas/lib/action.json" } }, + "actionDurations": { + "type": "array", + "description": "Static animation durations for actions, expressed in milliseconds.", + "items": { + "description": "Static animation duration metadata for an action.", + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "const": "playAction" + }, + "duration": { + "type": "integer", + "description": "The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown.", + "minimum": -1 + }, + "steps": { + "type": "array", + "items": { + "type": "object", + "description": "A step-specific playAction animation duration.", + "properties": { + "step": { + "type": "integer", + "description": "The zero-based target step number. When omitted, this duration applies to target steps not explicitly listed.", + "minimum": 0 + }, + "duration": { + "type": "integer", + "description": "The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown.", + "minimum": -1 + } + }, + "required": [ + "duration" + ], + "patternProperties": { + "^v_.*": {} + }, + "additionalProperties": false + } + } + }, + "required": [ + "type", + "duration" + ], + "patternProperties": { + "^v_.*": {} + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "updateAction" + }, + "duration": { + "type": "integer", + "description": "The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown.", + "minimum": -1 + } + }, + "required": [ + "type", + "duration" + ], + "patternProperties": { + "^v_.*": {} + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "stopAction" + }, + "duration": { + "type": "integer", + "description": "The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown.", + "minimum": -1 + } + }, + "required": [ + "type", + "duration" + ], + "patternProperties": { + "^v_.*": {} + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "const": "customAction" + }, + "customActionId": { + "type": "string", + "description": "The id of the custom action as defined in customActions." + }, + "duration": { + "type": "integer", + "description": "The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown.", + "minimum": -1 + } + }, + "required": [ + "type", + "customActionId", + "duration" + ], + "patternProperties": { + "^v_.*": {} + }, + "additionalProperties": false + } + ] + } + }, "supportsRealTime": { "type": "boolean", "description": "Indicates if the Graphic supports real-time rendering" diff --git a/v1/typescript-definitions/src/generated/graphics-manifest.ts b/v1/typescript-definitions/src/generated/graphics-manifest.ts index 8d2314f..481fc8a 100644 --- a/v1/typescript-definitions/src/generated/graphics-manifest.ts +++ b/v1/typescript-definitions/src/generated/graphics-manifest.ts @@ -512,6 +512,78 @@ export interface HttpsOgrafEbuIoV1SpecificationJsonSchemasGraphicsSchemaJson { * Custom Actions that can be invoked on the Graphic. */ customActions?: HttpsOgrafEbuIoV1SpecificationJsonSchemasLibActionJson[]; + /** + * Static animation durations for actions, expressed in milliseconds. + */ + actionDurations?: ( + | { + type: "playAction"; + /** + * The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. + */ + duration: number; + steps?: { + /** + * The zero-based target step number. When omitted, this duration applies to target steps not explicitly listed. + */ + step?: number; + /** + * The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. + */ + duration: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^v_.*". + */ + [k: `v_${string}`]: unknown; + }[]; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^v_.*". + */ + [k: `v_${string}`]: unknown; + } + | { + type: "updateAction"; + /** + * The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. + */ + duration: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^v_.*". + */ + [k: `v_${string}`]: unknown; + } + | { + type: "stopAction"; + /** + * The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. + */ + duration: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^v_.*". + */ + [k: `v_${string}`]: unknown; + } + | { + type: "customAction"; + /** + * The id of the custom action as defined in customActions. + */ + customActionId: string; + /** + * The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. + */ + duration: number; + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^v_.*". + */ + [k: `v_${string}`]: unknown; + } + )[]; /** * Indicates if the Graphic supports real-time rendering */ diff --git a/v1/typescript-definitions/src/generated/server-api.ts b/v1/typescript-definitions/src/generated/server-api.ts index 63fd4ba..492b72f 100644 --- a/v1/typescript-definitions/src/generated/server-api.ts +++ b/v1/typescript-definitions/src/generated/server-api.ts @@ -1557,6 +1557,46 @@ export interface components { }; /** @description Custom Actions that can be invoked on the Graphic. */ customActions?: components["schemas"]["action"][]; + /** @description Static animation durations for actions, expressed in milliseconds. */ + actionDurations?: (({ + /** @constant */ + type: "playAction"; + /** @description The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. */ + duration: number; + steps?: ({ + /** @description The zero-based target step number. When omitted, this duration applies to target steps not explicitly listed. */ + step?: number; + /** @description The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. */ + duration: number; + } & { + [key: string]: unknown; + })[]; + } & { + [key: string]: unknown; + }) | ({ + /** @constant */ + type: "updateAction"; + /** @description The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. */ + duration: number; + } & { + [key: string]: unknown; + }) | ({ + /** @constant */ + type: "stopAction"; + /** @description The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. */ + duration: number; + } & { + [key: string]: unknown; + }) | ({ + /** @constant */ + type: "customAction"; + /** @description The id of the custom action as defined in customActions. */ + customActionId: string; + /** @description The animation duration in milliseconds. A value of -1 indicates that the duration is dynamic or unknown. */ + duration: number; + } & { + [key: string]: unknown; + }))[]; /** @description Indicates if the Graphic supports real-time rendering */ supportsRealTime: boolean; /** @description Indicates if the Graphic supports non-real-time rendering. Note: If true, the Graphic must implement the 'goToTime()' and the 'setActionsSchedule()' methods. */ diff --git a/v1/typescript-definitions/src/main.ts b/v1/typescript-definitions/src/main.ts index 8751944..7ff8800 100644 --- a/v1/typescript-definitions/src/main.ts +++ b/v1/typescript-definitions/src/main.ts @@ -13,4 +13,5 @@ export { ServerApi } // Also export the GraphicsManifest types using simplified names export type GraphicsManifest = GeneratedGraphicsManifest.HttpsOgrafEbuIoV1SpecificationJsonSchemasGraphicsSchemaJson export type GraphicsManifestCustomAction = GeneratedGraphicsManifest.HttpsOgrafEbuIoV1SpecificationJsonSchemasLibActionJson +export type GraphicsManifestActionDuration = NonNullable[number]