From 6069666d5aec1fd600aff6bde74e95f1a6ef3df1 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 20 Mar 2025 10:31:02 +0100 Subject: [PATCH 1/8] Discuss: Event Metadata --- docs/event/metadata.md | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/event/metadata.md diff --git a/docs/event/metadata.md b/docs/event/metadata.md new file mode 100644 index 0000000..97bc79b --- /dev/null +++ b/docs/event/metadata.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 2 +--- + +# Metadata + +(🟦) Metadata fields marked with this symbol are *Opencast-managed*: they are read-only for users/external applications. All other fields can be freely changed, as long as validity checks pass. + +#### General +- `id: ID` 🟦: unique among all events. +- `title: NonBlankString`: a short title that is the main label associated with this event for users. Plain text. +- `description: string?`: user-specified, human-readable description, potentially quite long. + - TODO: Decide whether this is plain text, markdown or anything else. External apps displaying this need to know that. Some basic formatting options might be nice? +- `creators: NonBlankString[]`: The people mainly responsible for creating this video and/or presenting the talk which this video is a recording of. Should contain human-readable names and not usernames. Plain text. This is the main "who?"-information shown in the UIs; other fields in `extraMetadata` (e.g. `dct:contributor`) might be shown too, but less prominently. +- `language: LangCode?`: describes the (main) language of this event and its metadata. For example, the audio language and (if applicable) language of video content is more important than the language of available subtitles. Generally, assets can have their own language specified. +- `series: SeriesID?`: optional ID of the series this event belongs to. Must be a valid series ID of an existing series at all time. +- `owner: Username`: TODO figure out details + +#### Time-data +- `startTime: DateTime?`: Actual real life datetime when the video recording started or will start, with timezone. If this is not applicable, for example because it's a short movie, this should be undefined. UIs should use this as primary date to show for a video and if unset, fallback to `created`. +- `endTime: DateTime?`: Like `startTime`, but when the video recording stopped. Due to cutting, recording pauses and etc, the `duration` is not necessarily `end - start`. +- `duration: Milliseconds` 🟦: duration of the event. As specified in ["assets"](./assets), this needs to always match the duration of all non-internal tracks. +- `updated: Timestamp` 🟦: Timestamp of when anything about this event was last changed. +- `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`) + +#### Flags +- `explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. +- `isLive: bool` 🟦: TODO this is currently stored per track, figure out if that's useful +- `ingestUser: Username` 🟦: username of the user that created this event. Cannot be changed and is useful for tracking responsibility. +- `downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intend*. +- `listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. + +#### Extra metadata +- `extraMetadata: Map`: additional metadata that Opencast never interprets, but just stores and passes along.(1?) + - The keys of this map consists of a _namespace_ and a _field name_, separated by `:`, i.e. `ns:name`. Both parts must consist of only `a-z`, `A-Z`, `0-9`, `-` and `_`. + - The namespace `dct` is special as it refers to the Dublin Core Terms specification, e.g. `dct:rightsHolder` refers to [the `rightsHolder` property](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/rightsHolder) of DC terms. Also see [the DC mapping section below](#dublin-core-mapping). It should be avoided to set fields that already have a mapping, like `dct:title`, which is mapped to the OC core metadata `title`. + - Unlike the "extended metadata" before, using `extraMetadata` does work out of the box and does not incur any relevant performance overhead. Therefore, applications are encouraged to add useful data here, e.g. `studip:course-id`, `oc-studio:version` or `ethz:room-number`. + - There should be a community resource for collecting used fields and best practices around `extraMetadata`. That way, common requirements are identified quickly and the community can converge towards a standard. + + + +## Dublin Core mapping + +As you can see above, the event metadata is not literally a Dublin Core catalog anymore. +Dublin Core should be considered an *exchange format*, not a storage format! +Of course, standards make sense and therefore, many Opencast metadata fields correspond exactly to a Dublin Core field. +Opencast can offer an API that emits a DCC for an event. +That DCC XML is created on the fly in the API handler. + +The mapping is as follows: + +- [`identifier`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/identifier): `id` +- [`title`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/title): `title` +- [`description`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/description): `description` +- [`creator`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/creator): `creators` +- [`language`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/language): `language` +- [`isPartOf`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/isPartOf): `series` (i.e. the ID) +- [`modified`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/modified): `updated` +- [`extend`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/extent): `duration` as ISO 8601 duration +- `date` or `temporal`???: TODO combination of `startDate` and `endDate` +- `created` or `dateSubmitted` or `issued`???: TODO `created` +- Additionally, all fields in `extraMetadata` with `dct` namespace are mapped directly to the corresponding property, e.g. `dct:license` is mapped to [`license`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/license). + +TODO: Should we also define a mapping for OAIMPH? Does that make sense? + +--- + +:::danger[Open questions] + +- (1?) What values do we want to allow? `string` or string arrays are required, but maybe allow numbers? bools? Arbitrary JSON? +::: From b9c94c6e31040a73675d3057c240bccee48567e0 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 14:27:07 +0200 Subject: [PATCH 2/8] Clarify that an event's ID can be freely chosen when creating it --- docs/event/metadata.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index 97bc79b..0ef3db2 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -6,8 +6,10 @@ sidebar_position: 2 (🟦) Metadata fields marked with this symbol are *Opencast-managed*: they are read-only for users/external applications. All other fields can be freely changed, as long as validity checks pass. -#### General +### General - `id: ID` 🟦: unique among all events. + Can be chosen when creating an event, but cannot be changed afterwards. + If no ID is specified while creating an event, Opencast generates a generated unguessable ID. - `title: NonBlankString`: a short title that is the main label associated with this event for users. Plain text. - `description: string?`: user-specified, human-readable description, potentially quite long. - TODO: Decide whether this is plain text, markdown or anything else. External apps displaying this need to know that. Some basic formatting options might be nice? From 3323ba06fd78adeb6e21d04ed9251d6ad389bc8c Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 14:27:25 +0200 Subject: [PATCH 3/8] (style) Fix heading levels in event metadata --- docs/event/metadata.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index 0ef3db2..5495400 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -4,6 +4,9 @@ sidebar_position: 2 # Metadata + +## Fields + (🟦) Metadata fields marked with this symbol are *Opencast-managed*: they are read-only for users/external applications. All other fields can be freely changed, as long as validity checks pass. ### General @@ -18,21 +21,21 @@ sidebar_position: 2 - `series: SeriesID?`: optional ID of the series this event belongs to. Must be a valid series ID of an existing series at all time. - `owner: Username`: TODO figure out details -#### Time-data +### Time-data - `startTime: DateTime?`: Actual real life datetime when the video recording started or will start, with timezone. If this is not applicable, for example because it's a short movie, this should be undefined. UIs should use this as primary date to show for a video and if unset, fallback to `created`. - `endTime: DateTime?`: Like `startTime`, but when the video recording stopped. Due to cutting, recording pauses and etc, the `duration` is not necessarily `end - start`. - `duration: Milliseconds` 🟦: duration of the event. As specified in ["assets"](./assets), this needs to always match the duration of all non-internal tracks. - `updated: Timestamp` 🟦: Timestamp of when anything about this event was last changed. - `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`) -#### Flags +### Flags - `explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. - `isLive: bool` 🟦: TODO this is currently stored per track, figure out if that's useful - `ingestUser: Username` 🟦: username of the user that created this event. Cannot be changed and is useful for tracking responsibility. - `downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intend*. - `listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. -#### Extra metadata +### Extra metadata - `extraMetadata: Map`: additional metadata that Opencast never interprets, but just stores and passes along.(1?) - The keys of this map consists of a _namespace_ and a _field name_, separated by `:`, i.e. `ns:name`. Both parts must consist of only `a-z`, `A-Z`, `0-9`, `-` and `_`. - The namespace `dct` is special as it refers to the Dublin Core Terms specification, e.g. `dct:rightsHolder` refers to [the `rightsHolder` property](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/rightsHolder) of DC terms. Also see [the DC mapping section below](#dublin-core-mapping). It should be avoided to set fields that already have a mapping, like `dct:title`, which is mapped to the OC core metadata `title`. From 6ae19b6659991b42b7da7dbe518abb38f967241a Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 14:52:34 +0200 Subject: [PATCH 4/8] Specify behavior when duplicating an event --- docs/event/metadata.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index 5495400..e2a0289 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -9,10 +9,13 @@ sidebar_position: 2 (🟦) Metadata fields marked with this symbol are *Opencast-managed*: they are read-only for users/external applications. All other fields can be freely changed, as long as validity checks pass. +When *duplicating* an event, all fields are copied 1:1 unless specified otherwise. + ### General - `id: ID` 🟦: unique among all events. Can be chosen when creating an event, but cannot be changed afterwards. If no ID is specified while creating an event, Opencast generates a generated unguessable ID. + When duplicating an event, the new event gets a new unguessable ID. - `title: NonBlankString`: a short title that is the main label associated with this event for users. Plain text. - `description: string?`: user-specified, human-readable description, potentially quite long. - TODO: Decide whether this is plain text, markdown or anything else. External apps displaying this need to know that. Some basic formatting options might be nice? @@ -26,12 +29,16 @@ sidebar_position: 2 - `endTime: DateTime?`: Like `startTime`, but when the video recording stopped. Due to cutting, recording pauses and etc, the `duration` is not necessarily `end - start`. - `duration: Milliseconds` 🟦: duration of the event. As specified in ["assets"](./assets), this needs to always match the duration of all non-internal tracks. - `updated: Timestamp` 🟦: Timestamp of when anything about this event was last changed. -- `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`) + When duplicating an event, the new event has `updated = now()`, i.e. it is not copied. +- `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`). + When duplicating an event, the new event has `created = now()`, i.e. it is not copied. + ### Flags - `explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. - `isLive: bool` 🟦: TODO this is currently stored per track, figure out if that's useful - `ingestUser: Username` 🟦: username of the user that created this event. Cannot be changed and is useful for tracking responsibility. + When duplicating an event, the new event has this field set to the duplicating user. - `downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intend*. - `listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. From ca1f81d2b4702c919abbf7fc8b182d5681652a8a Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 16:37:57 +0200 Subject: [PATCH 5/8] Rename `updated` -> `modified` and specify its behavior more --- docs/event/metadata.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index e2a0289..a6a9961 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -28,8 +28,12 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis - `startTime: DateTime?`: Actual real life datetime when the video recording started or will start, with timezone. If this is not applicable, for example because it's a short movie, this should be undefined. UIs should use this as primary date to show for a video and if unset, fallback to `created`. - `endTime: DateTime?`: Like `startTime`, but when the video recording stopped. Due to cutting, recording pauses and etc, the `duration` is not necessarily `end - start`. - `duration: Milliseconds` 🟦: duration of the event. As specified in ["assets"](./assets), this needs to always match the duration of all non-internal tracks. -- `updated: Timestamp` 🟦: Timestamp of when anything about this event was last changed. - When duplicating an event, the new event has `updated = now()`, i.e. it is not copied. +- `modified: Timestamp` 🟦: Timestamp of when anything about this event was last changed. + - More precisely: at any point in time since `modified`, all fields, assets, ACL and any other part of the event data model need to have the exact same value as they have at the present moment. + Whenever anything about an event described in this data model changes, `modified` has to be set to `now()`. + - Noteworthy case: when a series is deleted and the event's `series` field is set to `null`, the event's `modified` needs to change. + - Opencast should try its best to not update `modified` when it's not necessary (e.g. when the title is set to the current value), but it is not a bug if `modified` is set to `now()` unnecessarily. + - When duplicating an event, the new event has `modified = now()`, i.e. it is not copied. - `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`). When duplicating an event, the new event has `created = now()`, i.e. it is not copied. @@ -67,7 +71,7 @@ The mapping is as follows: - [`creator`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/creator): `creators` - [`language`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/language): `language` - [`isPartOf`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/isPartOf): `series` (i.e. the ID) -- [`modified`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/modified): `updated` +- [`modified`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/modified): `modified` - [`extend`](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/extent): `duration` as ISO 8601 duration - `date` or `temporal`???: TODO combination of `startDate` and `endDate` - `created` or `dateSubmitted` or `issued`???: TODO `created` From 9a679c8f4e012c224369fae8f214189619b09037 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 15:16:52 +0200 Subject: [PATCH 6/8] (style) break more texts into bullet points --- docs/event/metadata.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index a6a9961..f36ce56 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -13,9 +13,9 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis ### General - `id: ID` 🟦: unique among all events. - Can be chosen when creating an event, but cannot be changed afterwards. - If no ID is specified while creating an event, Opencast generates a generated unguessable ID. - When duplicating an event, the new event gets a new unguessable ID. + - Can be chosen when creating an event, but cannot be changed afterwards. + - If no ID is specified while creating an event, Opencast generates a generated unguessable ID. + - When duplicating an event, the new event gets a new unguessable ID. - `title: NonBlankString`: a short title that is the main label associated with this event for users. Plain text. - `description: string?`: user-specified, human-readable description, potentially quite long. - TODO: Decide whether this is plain text, markdown or anything else. External apps displaying this need to know that. Some basic formatting options might be nice? @@ -34,8 +34,9 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis - Noteworthy case: when a series is deleted and the event's `series` field is set to `null`, the event's `modified` needs to change. - Opencast should try its best to not update `modified` when it's not necessary (e.g. when the title is set to the current value), but it is not a bug if `modified` is set to `now()` unnecessarily. - When duplicating an event, the new event has `modified = now()`, i.e. it is not copied. -- `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`). - When duplicating an event, the new event has `created = now()`, i.e. it is not copied. +- `created: Timestamp` 🟦: Timestamp of when the event was created in Opencast. It is set once when the event is first stored in Opencast's DB, and never changed again. + - This also implies that scheduled event's `created` date is when the scheduling took place, _not_ the time it is scheduled for (that would be `startDate`). + - When duplicating an event, the new event has `created = now()`, i.e. it is not copied. ### Flags From ab9cfe9ad6d012525d8eadd6873187b4971f41e1 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 15:28:55 +0200 Subject: [PATCH 7/8] Rename `ingestUser` -> `createdBy` and specify it further Since `created` and this field talk about the same event in time, they should share similarity in their name. And `ingest` is just wrong for scheduled videos. --- docs/event/metadata.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index f36ce56..cb94803 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -23,6 +23,12 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis - `language: LangCode?`: describes the (main) language of this event and its metadata. For example, the audio language and (if applicable) language of video content is more important than the language of available subtitles. Generally, assets can have their own language specified. - `series: SeriesID?`: optional ID of the series this event belongs to. Must be a valid series ID of an existing series at all time. - `owner: Username`: TODO figure out details +- `createdBy: Username` 🟦: username of the user that created this event. + - Like `created`, this refers to the moment when the event is first added to the database, not necessarily when it is ingested. + - This refers to the user with which the API request is authorized, e.g. potentially an API user and not referring to an actual human person. + - Technical field, not intended to be shown to normal users. + - Set by Opencast and cannot be changed. + - When duplicating an event, the new event has this field set to the duplicating user. ### Time-data - `startTime: DateTime?`: Actual real life datetime when the video recording started or will start, with timezone. If this is not applicable, for example because it's a short movie, this should be undefined. UIs should use this as primary date to show for a video and if unset, fallback to `created`. @@ -42,8 +48,6 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis ### Flags - `explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. - `isLive: bool` 🟦: TODO this is currently stored per track, figure out if that's useful -- `ingestUser: Username` 🟦: username of the user that created this event. Cannot be changed and is useful for tracking responsibility. - When duplicating an event, the new event has this field set to the duplicating user. - `downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intend*. - `listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. From 5249be000974cb2e5a9a9c263f5c289f5c724ca6 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 15 May 2025 16:11:57 +0200 Subject: [PATCH 8/8] Add details to `extraMetadata` and move some fields there Some fields I previously suggested were questionable in widespread usefulness so we decided to introduce them as experimental fields first. To do that, I fleshed out the `extraMetadata` section with more details. --- docs/event/metadata.md | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/docs/event/metadata.md b/docs/event/metadata.md index cb94803..08416ce 100644 --- a/docs/event/metadata.md +++ b/docs/event/metadata.md @@ -46,17 +46,37 @@ When *duplicating* an event, all fields are copied 1:1 unless specified otherwis ### Flags -- `explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. + - `isLive: bool` 🟦: TODO this is currently stored per track, figure out if that's useful -- `downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intend*. -- `listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. + ### Extra metadata -- `extraMetadata: Map`: additional metadata that Opencast never interprets, but just stores and passes along.(1?) +- `extraMetadata: Map`: additional metadata that Opencast never interprets, but just stores and passes along. - The keys of this map consists of a _namespace_ and a _field name_, separated by `:`, i.e. `ns:name`. Both parts must consist of only `a-z`, `A-Z`, `0-9`, `-` and `_`. - - The namespace `dct` is special as it refers to the Dublin Core Terms specification, e.g. `dct:rightsHolder` refers to [the `rightsHolder` property](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/rightsHolder) of DC terms. Also see [the DC mapping section below](#dublin-core-mapping). It should be avoided to set fields that already have a mapping, like `dct:title`, which is mapped to the OC core metadata `title`. + - The values of this map are arbitrary JSON values, i.e. Booleans, numbers, strings, arrays, maps or `null`. Items of arrays & maps can recursively be any JSON value as well. - Unlike the "extended metadata" before, using `extraMetadata` does work out of the box and does not incur any relevant performance overhead. Therefore, applications are encouraged to add useful data here, e.g. `studip:course-id`, `oc-studio:version` or `ethz:room-number`. - - There should be a community resource for collecting used fields and best practices around `extraMetadata`. That way, common requirements are identified quickly and the community can converge towards a standard. + +#### Community documentation + +There should be a community document for specifying rules, as well as collecting used fields and best practices around `extraMetadata`. +That way, common requirements are identified quickly and the community can converge towards a standard. + +> Official namespaces: +> - **`oc`**: reserved. +> - **`ocx`**: OC eXperimental for fields that might get promoted to core metadata field in the future. +> - `ocx:downloadable: bool`: a flag indicating whether users are allowed to download this video (i.e. tracks attached to this event). This can inform external apps whether to show a download button or to enable anti-download protection. The exact effects of this flag are deliberately unspecified, this merely states an *intent*. +> - `ocx:listed: bool`: specifies whether this event should be considered "list", meaning that users can find it via search. If it is `false`, users have to know the ID of the event (e.g. via a series or playlist) in order to access it. +> - `ocx:explicitContent: bool`: specifies whether this event contains content that is considered "explicit", like swear words or whatnot. This is required for some integrations like iTunes. +> - **`dct`**: refers to the Dublin Core Terms specification, e.g. `dct:rightsHolder` refers to [the `rightsHolder` property](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#http://purl.org/dc/terms/rightsHolder) of DC terms. It should be avoided to set fields that are already mapped from core fields, like `dct:title`, which is mapped to the OC core metadatum `title`. +> +> Community namespaces: +> - ... + +Generally, anyone should be able to add to the "Community namespaces" section via pull request against this document: +its purpose is to document what is used, not for the OC committers to control what external apps do. +In other words: a PR against that section is *not* asking for permission. + + @@ -88,5 +108,5 @@ TODO: Should we also define a mapping for OAIMPH? Does that make sense? :::danger[Open questions] -- (1?) What values do we want to allow? `string` or string arrays are required, but maybe allow numbers? bools? Arbitrary JSON? +- ... :::