From afa5e58b151194978213defdd17bdd6579e30e64 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 6 Feb 2026 14:14:26 +0000 Subject: [PATCH 01/12] adr: Add role naming convention ADR --- docs/README.md | 1 + docs/adr/0047-role-naming-convention.md | 100 ++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 docs/adr/0047-role-naming-convention.md diff --git a/docs/README.md b/docs/README.md index 2280bfd8..69a52afd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -82,5 +82,6 @@ For more information on how we use ADRs, see [here](./adr/README.md). | [0043](./adr/0043-signalling-retention-time.md) | Signalling retention time | | [0044](./adr/0044-signalling-timeouts.md) | Signalling timeout periods | | [0046](./adr/0046-governance.md) | Governance | +| [0047](./adr/0047-role-naming-convention.md) | Role Naming Convention | \* Note: ADR 0004a was the unintended result of a number clash in the early development of TAMS which wasn't caught before publication diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md new file mode 100644 index 00000000..04e7fc0c --- /dev/null +++ b/docs/adr/0047-role-naming-convention.md @@ -0,0 +1,100 @@ +--- +status: proposed +--- +# Role Naming Convention + +## Context and Problem Statement + +Each item in the collection of a multi-essence Source or Flow has a `role`, intended as a description of that item's purpose in the collection. +Roles are intended to be human-readable, however it is useful for clients and systems to make sense of them too. +It would be useful to have some recommendations about how to use roles. + +One part of that recommendation should be the editorial purpose of an item: for example programme audio, audio description or commentary. +Or main video, signed video or clean-feed without graphics. + +## Decision Drivers + +* Roles must be set when creating a multi-essence collection. +* When viewing a multi-essence Source or Flow, only the list of IDs collected and roles are available: getting formats and tags requires another query. +* Items in a collection serve a variety of different purposes, and it is useful to have some commonality. + +## Considered Options + +* Option 1a: Provide guidance on how the free-text field `role` should be used +* Option 1b: Replace `role` with a number of additional controlled fields +* Option 2a: Represent editorial purpose using DVB component descriptors +* Option 2b: Represent editorial purpose using roles from MPEG-DASH +* Option 2c: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation +* Option 2d: Represent purpose of content using a list, as with tags + +## Decision Outcome + +Chosen option: Option 1a and Option 2d, because this allows `role` to be free-form and evolve over time, and avoids a breaking change to the specification or unduly constraining it. +While this prevents clients from being able to automatically determine the purpose of each item in a collection, in many cases the role merely serves to change what the user is shown and they are left to make the decisions. +In cases where it matters which elements of a collection are picked up (for example packaging content for distribution) the correct items should be identified by some more rigorous method anyway (for example creating a multi-essence Flow of just the items required). + +### Implementation + +{Once the proposal has been implemented, add a link to the relevant PRs here} + + +## Pros and Cons of the Options + +### Option 1a: Provide guidance on how the free-text field `role` should be used + +Write an Application Note suggesting a naming convention for the `role` field, and that clients may also choose to query the members of the collection and consider their labels/tags directly instead. + +* Good, because it avoids a breaking change to the specification, instead only creating guidance +* Good, because it makes `role` open-ended, allowing space for future change and expansion +* Bad, because it does not constrain the use of `role`, and clients may have to rely on human intervention + +### Option 1b: Replace `role` with a number of additional controlled fields + +Change the specification to remove `role` and replace it with a more precise set of fields conveying the purpose of each element in the collection. + +* Good, because it constrains and precisely describes what each item in a collection is for. +* Bad, because it requires a breaking change to the API, to provide a capability that can be achieved another way. +* Bad, because it requires work to fully specify all the possible purposes an item in a collection can fulfil. +* Bad, because it then constrains TAMS and requires a change as new purposes are identified. + +### Option 2a: Represent editorial purpose using DVB component descriptors + +DVB uses the `stream_content`, `stream_content_ext` and `component_type` fields in the `component_descriptor` to describe the type of a Service. +These are described in [ETSI EN 300 468 pp 60-70](https://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.19.01_60/en_300468v011901p.pdf). +TAMS could use the same descriptors, or their names. + +* Good, because it is part of an established standard +* Bad, because the component types are represented as hex bytes (for carriage in the SDT table) and would need human-readable names +* Bad, because many of the types also include technical characteristics of content, making them unsuitable for use in Sources +* Bad, because the list is focused on distribution, so cannot contain aspects such as clean-feed video + +### Option 2b: Represent editorial purpose using MPEG-DASH roles + +MPEG-DASH contains a role attribute for an `AdaptationSet`, which describes the purose of that particular track. +A number of values for that attribute are given in the specification (see ISO/IEC 23009-1:2022 section 5.8.5.5), covering the `main` content along with others such as `alternate`, `supplementary`, `commentary`, `description`, etc. +TAMS could use these descriptors for the table directly. + +* Good, because it is part of an established standard +* Neutral, because the example use cases identified above could be represented, however some would be ambiguous, such as using `alternate` for clean-feed video +* Bad, because the list cannot be expanded beyond what is in the MPEG-DASH specification + +### Option 2c: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation + +The MovieLabs [Ontology for Media Creation](https://mc.movielabs.com/docs/ontology/) contains some definitions of the purpose of pieces of content. +Unfortunately it does not appear to represent differing purposes of video content, and for audio it refers to definitions in SMPTE ST 377-41. +It was not possible to acquire a copy of this SMPTE document at time of writing, although a version of those definitions are available in Appendix B of the [PDF version on the document](https://mc.movielabs.com/omc/Asset/Audio/ML_Ontology_Pt3C_Audio_v2.8.pdf). + +* Good, because it is part of a controlled specification. +* Bad, because it relies on a document not available to the TAMS community. +* Bad, because video is not covered in the document. + +### Option 2d: Represent purpose of content using a list, as with tags + +When describing the editorial purpose of an item in a collection, draw from a list of suggested types in an Application Note. +Allow new types to be added as they come up, in a similar process to tags. +Seed the initial list based on a combination of other specifications (including those above). + +* Good, because it captures suggested names without constraining the purposes that a Flow or Source can be used for +* Good, because inspiration can be drawn from the other documents suggested, without being constrained by tem +* Good, because it is easy to add new items to the list +* Bad, because the list is open-ended and uncontrolled, which may lead to content using a mix of names From f2d709aaa81cf5312a4e255fea3cc6137b3ef894 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 6 Feb 2026 14:16:44 +0000 Subject: [PATCH 02/12] appnote: Add description of role names Adds an AppNote describing the role naming convention and editorial purposes. --- docs/README.md | 1 + docs/appnotes/0020-role-naming-convention.md | 77 ++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 docs/appnotes/0020-role-naming-convention.md diff --git a/docs/README.md b/docs/README.md index 69a52afd..26eeb7ad 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,6 +26,7 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems | | [0018](./appnotes/0018-managing-multiple-object-instances.md) | Managing Multiple Object Instances | | [0019](./appnotes/0019-implementing-retention-management.md) | Methods of implementing retention management | +| [0020](./appnotes/0020-role-naming-convention.md) | Role Naming Convention   | ## ADRs diff --git a/docs/appnotes/0020-role-naming-convention.md b/docs/appnotes/0020-role-naming-convention.md new file mode 100644 index 00000000..1dfcede4 --- /dev/null +++ b/docs/appnotes/0020-role-naming-convention.md @@ -0,0 +1,77 @@ +# 0020: Role Naming Convention + +## Abstract + +Each item in the collection of a multi-essence Source or Flow has a `role`, intended as a description of that item's purpose in the collection. +Roles are intended to be human-readable, and clients may choose whether to get the details of each item in the collection and decide how to use it (e.g. what to present to the user) from there, or may decide to use the roles directly. +In addition there are some common structures of Flows and Sources that come up in a lot of workflows, such as those laid out in the [multi-essence collection application note](./0001-multi-mono-essence-flows-sources.md). +In these particular cases a semi-structured naming convention is useful, and this document describes an approach and captures some possible terms and their meaning. + +This approach is similar to the one taken for [storage backend labels](./0009-storage-label-format.md) and [tags](./0003-tag-names.md). + +## Role Structure + +A structured role captures multiple pieces of information: + +- The type of content (also captured in the `format` property) +- The editorial purpose of the content (may be captured in `label`, `description` or tags) +- Where necessary, a sub-identifier where multiple items fulfil a related editorial purpose (again, may be captured in `label`, `description` or tags) + +The general structure of a role is: + +```text +:: +``` + +For example a complex package of material might contain the following roles: + +```text +video:programme +video:signed:bsi +audio:programme:eng +audio:programme:fra +audio:audio_description +subtitles::eng +subtitles::fra +``` + +Here multiple languages of programme audio are provided, with the language is called out as a sub-identifier (and will also be present in the `language_code` tag). +In addition a signed version of the video and an audio description track are included. +Finally the subtitles appear in multiple languages, however there is no further editorial purpose beyond the type, so the feld is left blank. + +In a much simpler example of an A/V mux ingest, the additional information may not be necessary, and the roles could be as simple as: + +```text +video +audio +``` + +Depending on how the content is structured, the audio could take the form of a collection of mono channels, which might be described as: + +```text +audio:right +audio:left +audio:center +audio:left-surround +audio:right-surround +audio:lfe +``` + +## Editorial Purpose Names + +## Video + +| Name | Description | +| ---- | ----------- | +| `programme` | Primary, or default video for a piece of content, e.g. that will be edited or distributed on to the audience | +| `signed` | Primary video with a signer in-vision. Consider using a sub-identifier for the language code of the signer (e.g. `bsi`) | +| `cleanfeed` | Version of the video without graphics, for reversioning and re-use | + +## Audio + +| Name | Description | +| ---- | ----------- | +| `programme` | Primary, or default audio for a piece of content, e.g. that will be edited or distributed on to the audience. Consider using a sub-identifier for the language code. | +| `audio_description` | Audio description track. Consider using a sub-identifier for the language code. | +| `commentary` | Commentary track, where sent separately (e.g. from a sports event). Consider using a sub-identifier for the language code. | +| `music&effects` | Music and Effects track, where sent separately | From ec04c7b03ed2df88b090d43cff199bf16bc2caac Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 6 Feb 2026 14:18:01 +0000 Subject: [PATCH 03/12] docs: Add role-name appnote cross-refs --- docs/appnotes/0001-multi-mono-essence-flows-sources.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/appnotes/0001-multi-mono-essence-flows-sources.md b/docs/appnotes/0001-multi-mono-essence-flows-sources.md index b262a1b2..2105cfff 100644 --- a/docs/appnotes/0001-multi-mono-essence-flows-sources.md +++ b/docs/appnotes/0001-multi-mono-essence-flows-sources.md @@ -179,8 +179,8 @@ In this case, Segment timestamps will be remapped so the relationship between th ### Ingest of SRT Stream (video + stereo audio) -Stepping up to a stream containing both audio and video, packaged into a MPEG2 Transport Stream and encapsulated in SRT, three `Flow` entities are created on ingest: one for the video essence, one for the audio essence and a Multi-Flow to record the association of the mono-essence `Flows` as an ingested stream. -The Multi-Flow features a `collection` attribute that lists the `Flow IDs` in the set, each annotated with a string describing its role. +Stepping up to a stream containing both audio and video, packaged into a MPEG2 Transport Stream and encapsulated in SRT, three `Flow` entities are created on ingest: one for the video essence, one for the audio essence and a multi-essence `Flow` to record the association of the mono-essence `Flows` as an ingested stream. +The multi-essence `Flow` features a `collection` attribute that lists the `Flow IDs` in the set, each annotated with a string describing its role (see [AppNote 0020](./0020-role-names.md) for suggested role naming). Technical metadata relating to the elementary streams is used to populate the corresponding mono-essence `Flow` properties. From 3ea3404c1f53877a7cd21e3bfcbd8684059e0d5b Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Wed, 11 Feb 2026 17:38:58 +0000 Subject: [PATCH 04/12] adr: Better split editorial purpose options Splits the set of options for how to represent editorial purpose to a different numbering scheme, to make clear they are related but not interchangeable because they refer to different decisions. --- docs/adr/0047-role-naming-convention.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md index 04e7fc0c..c6237a8c 100644 --- a/docs/adr/0047-role-naming-convention.md +++ b/docs/adr/0047-role-naming-convention.md @@ -22,10 +22,13 @@ Or main video, signed video or clean-feed without graphics. * Option 1a: Provide guidance on how the free-text field `role` should be used * Option 1b: Replace `role` with a number of additional controlled fields -* Option 2a: Represent editorial purpose using DVB component descriptors -* Option 2b: Represent editorial purpose using roles from MPEG-DASH -* Option 2c: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation -* Option 2d: Represent purpose of content using a list, as with tags + +For how to represent editorial purpose (options `Pn`): + +* Option P1: Represent editorial purpose using DVB component descriptors +* Option P2: Represent editorial purpose using roles from MPEG-DASH +* Option P3: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation +* Option P4: Represent purpose of content using a list, as with tags ## Decision Outcome @@ -35,9 +38,8 @@ In cases where it matters which elements of a collection are picked up (for exam ### Implementation -{Once the proposal has been implemented, add a link to the relevant PRs here} +Implemented by - ## Pros and Cons of the Options ### Option 1a: Provide guidance on how the free-text field `role` should be used @@ -57,7 +59,9 @@ Change the specification to remove `role` and replace it with a more precise set * Bad, because it requires work to fully specify all the possible purposes an item in a collection can fulfil. * Bad, because it then constrains TAMS and requires a change as new purposes are identified. -### Option 2a: Represent editorial purpose using DVB component descriptors +## Pros and Cons of the Options - for representing editorial purpose + +### Option P1: Represent editorial purpose using DVB component descriptors DVB uses the `stream_content`, `stream_content_ext` and `component_type` fields in the `component_descriptor` to describe the type of a Service. These are described in [ETSI EN 300 468 pp 60-70](https://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.19.01_60/en_300468v011901p.pdf). @@ -68,7 +72,7 @@ TAMS could use the same descriptors, or their names. * Bad, because many of the types also include technical characteristics of content, making them unsuitable for use in Sources * Bad, because the list is focused on distribution, so cannot contain aspects such as clean-feed video -### Option 2b: Represent editorial purpose using MPEG-DASH roles +### Option P2: Represent editorial purpose using MPEG-DASH roles MPEG-DASH contains a role attribute for an `AdaptationSet`, which describes the purose of that particular track. A number of values for that attribute are given in the specification (see ISO/IEC 23009-1:2022 section 5.8.5.5), covering the `main` content along with others such as `alternate`, `supplementary`, `commentary`, `description`, etc. @@ -78,7 +82,7 @@ TAMS could use these descriptors for the table directly. * Neutral, because the example use cases identified above could be represented, however some would be ambiguous, such as using `alternate` for clean-feed video * Bad, because the list cannot be expanded beyond what is in the MPEG-DASH specification -### Option 2c: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation +### Option P3: Represent editorial purpose based on descriptions in the MovieLabs Ontology for Media Creation The MovieLabs [Ontology for Media Creation](https://mc.movielabs.com/docs/ontology/) contains some definitions of the purpose of pieces of content. Unfortunately it does not appear to represent differing purposes of video content, and for audio it refers to definitions in SMPTE ST 377-41. @@ -88,7 +92,7 @@ It was not possible to acquire a copy of this SMPTE document at time of writing, * Bad, because it relies on a document not available to the TAMS community. * Bad, because video is not covered in the document. -### Option 2d: Represent purpose of content using a list, as with tags +### Option P4: Represent purpose of content using a list, as with tags When describing the editorial purpose of an item in a collection, draw from a list of suggested types in an Application Note. Allow new types to be added as they come up, in a similar process to tags. From 77576ceab471d352de6db5f33f5b17ecc92d2cd7 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Wed, 11 Feb 2026 17:40:20 +0000 Subject: [PATCH 05/12] adr: Rework role naming options Restructures the options to use a different numbering scheme, and group related options together. Adds additional options around querying Flow/Source properties directly --- docs/adr/0047-role-naming-convention.md | 86 ++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md index c6237a8c..42dcc87b 100644 --- a/docs/adr/0047-role-naming-convention.md +++ b/docs/adr/0047-role-naming-convention.md @@ -11,17 +11,24 @@ It would be useful to have some recommendations about how to use roles. One part of that recommendation should be the editorial purpose of an item: for example programme audio, audio description or commentary. Or main video, signed video or clean-feed without graphics. +Currently this is represented in free text. ## Decision Drivers * Roles must be set when creating a multi-essence collection. * When viewing a multi-essence Source or Flow, only the list of IDs collected and roles are available: getting formats and tags requires another query. * Items in a collection serve a variety of different purposes, and it is useful to have some commonality. +* At time of writing `role` is typically `video` or `audio`, but practical applications need to represent more complex packages. ## Considered Options -* Option 1a: Provide guidance on how the free-text field `role` should be used -* Option 1b: Replace `role` with a number of additional controlled fields +For how to use the `role` field (options `Rn`): + +* Option R1: Make `role` a semi-structured field containing editorial purpose, media type and other details +* Option R2: Replace `role` with a number of additional controlled fields +* Option R3a: Use `role` as editorial purpose, use other queries for Flow/Source properties +* Option R3b: Use `role` as editorial purpose, use other queries for Flow/Source properties, surface `role` as a query param +* Option R3c: Use `role` as editorial purpose, additionally surface `format` in collection For how to represent editorial purpose (options `Pn`): @@ -40,17 +47,21 @@ In cases where it matters which elements of a collection are picked up (for exam Implemented by -## Pros and Cons of the Options +## Pros and Cons of the Options - for the `role` field -### Option 1a: Provide guidance on how the free-text field `role` should be used +### Option R1: Make `role` a semi-structured field containing editorial purpose, media type and other details -Write an Application Note suggesting a naming convention for the `role` field, and that clients may also choose to query the members of the collection and consider their labels/tags directly instead. +Write an Application Note suggesting a naming convention for the `role` field, with a structured form that captures media type, editorial purpose and additional details. +This would be similar to the approach taken in the (now deprecated) [storage label AppNote](../appnotes/0009-storage-label-format.md). +Clients could either read the collection items and identify both type and purpose, or query the members of the collection and consider their labels/tags directly instead. -* Good, because it avoids a breaking change to the specification, instead only creating guidance -* Good, because it makes `role` open-ended, allowing space for future change and expansion -* Bad, because it does not constrain the use of `role`, and clients may have to rely on human intervention +* Good, because it avoids a breaking change to the specification, instead only creating guidance. +* Good, because it makes `role` open-ended, allowing space for future change and expansion. +* Good, because it saves making additional API requests to get media type and other details of collection items. +* Bad, because it does not constrain the use of `role`, and clients may have to rely on human intervention. +* Bad, because it forces clients to handle and parse an un-enforced free-text field, which may be malformed as a result. -### Option 1b: Replace `role` with a number of additional controlled fields +### Option R2: Replace `role` with a number of additional controlled fields Change the specification to remove `role` and replace it with a more precise set of fields conveying the purpose of each element in the collection. @@ -59,6 +70,63 @@ Change the specification to remove `role` and replace it with a more precise set * Bad, because it requires work to fully specify all the possible purposes an item in a collection can fulfil. * Bad, because it then constrains TAMS and requires a change as new purposes are identified. +### Option R3a: Use `role` solely for editorial purpose, and rely on other fields for other purposes + +Use `role` primarily as a label to represent the editorial purpose of an item in a collection (broadly aligned with common usage). +Where a client wants to identify the type of a collection item, they can request the full details from the API. +For example if a collection contains multiple items of role "programme" the client could request all of those items by ID to find out one was video and one audio (or, subject to a draft ADR being accepted, make a direct query of `GET /flows?collected_by_id=...` and cross-reference the results with the collection listing). + +* Good, because it aligns with current common usage of `role`. +* Good, because it avoids a breaking change to the specification. +* Good, becuause it does not introduce a semi-structured field and force clients to handle malformed data. +* Bad, because it forces clients to make additional requests (and possibly a somewhat complex cross-reference) to locate all the data they need. + In particular a UI element displaying all the Sources in a store, the editorial purposes they contain and their media types would require an additional listing request per top-level Source. + +### Option R3b: Use `role` as editorial purpose, use other queries for Flow/Source properties, surface `role` as a query param + +As Option R3a, however `role` is added as an extra query parameter to the Flow and Source listing endpoints. +As a result, a client could request all the items of a specific role which are members of a particular collection (`GET /flows?collected_by_id=...&role=...`). + +* Good, because it aligns with current common usage of `role`. +* Good, because it avoids a breaking change to the specification. +* Good, becuause it does not introduce a semi-structured field and force clients to handle malformed data. +* Bad, because it forces clients to make additional requests to locate all the data they need. + In particular a UI element displaying all the Sources in a store, the editorial purposes they contain and their media types would require an additional listing request per top-level Source. +* Bad, because an item's role in a collection is a property of the collection, not the item, so the implementation is likely to be quite complex! + +### Option R3c: Use `role` as editorial purpose, additionally surface `format` in collection + +As Option R3a, however the `collects` property of a multi-essence Flow or Source gains an additonal property, `format` which is the `format` property of the collected item. +For example: + +```json +[ + { + "id": "f59a1785-b5bd-4829-afe0-7f65f9b335dd", + "role": "programme", + "format": "urn:x-nmos:format:video" + }, + { + "id": "7162d669-3230-4254-99d1-2c06f815d025", + "role": "programme", + "format": "urn:x-nmos:format:audio" + }, + { + "id": "2e285f91-6dff-4117-b26b-1ae749c5f5aa", + "role": "audio_description", + "format": "urn:x-nmos:format:audio" + } +] +``` + +A client can directly identify the members of the collection directly. + +* Good, because it aligns with current common usage of `role`. +* Good, becuause it does not introduce a semi-structured field and force clients to handle malformed data. +* Good, because it allows clients to get more of the salient information about a collection in a single request. + It would allow the UI element suggested above to be built from a single listing request, for example. +* Neutral, because it changes the specification, albeit in a non-breaking way. + ## Pros and Cons of the Options - for representing editorial purpose ### Option P1: Represent editorial purpose using DVB component descriptors From cda58a72d53c014da2895e2788713ccf92ab0c69 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Wed, 11 Feb 2026 17:41:21 +0000 Subject: [PATCH 06/12] adr: Rework role name outcome Expands and reworks role name decision outcome following discussion --- docs/adr/0047-role-naming-convention.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md index 42dcc87b..4b8ca6ca 100644 --- a/docs/adr/0047-role-naming-convention.md +++ b/docs/adr/0047-role-naming-convention.md @@ -39,8 +39,12 @@ For how to represent editorial purpose (options `Pn`): ## Decision Outcome -Chosen option: Option 1a and Option 2d, because this allows `role` to be free-form and evolve over time, and avoids a breaking change to the specification or unduly constraining it. -While this prevents clients from being able to automatically determine the purpose of each item in a collection, in many cases the role merely serves to change what the user is shown and they are left to make the decisions. +Chosen option: Option R3a and Option P4, because it lines up with the existing common use of `role` and allows it to evolve over time. +It also limits the changes required to the API, and while in some cases it may trigger extra API requests (e.g. to enumerate the media types of a collection), it is likely the details of those collection items will be needed anyway, so the requests would be needed. +Furthermore the TAMS API is intended not to serve as a Media Asset Manager and provide minimal library management and discovery features: through that lens the additional request burden seems reasonable and if it becomes too onerous in a particular deployment, that may indicate a MAM is required. +However Option R3c (surfacing `role` in collections) could be added later if necessary. + +Regarding editorial purposes, while Option P4 makes it harder for clients to automatically determine the purpose of each item in a collection, in many cases the role merely serves to change what the user is shown and they are left to make the decisions. In cases where it matters which elements of a collection are picked up (for example packaging content for distribution) the correct items should be identified by some more rigorous method anyway (for example creating a multi-essence Flow of just the items required). ### Implementation From b93aa3ef05afc433ad71bc1c8989d0320c89db3f Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Wed, 11 Feb 2026 17:41:40 +0000 Subject: [PATCH 07/12] appnote: Remove structure from role names Reworks the role naming convention appnote to remove semi-structured format, instead just describing editorial purpose, in line with AppNote 0047. --- docs/appnotes/0020-role-naming-convention.md | 74 ++++---------------- 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/docs/appnotes/0020-role-naming-convention.md b/docs/appnotes/0020-role-naming-convention.md index 1dfcede4..a0414c81 100644 --- a/docs/appnotes/0020-role-naming-convention.md +++ b/docs/appnotes/0020-role-naming-convention.md @@ -3,59 +3,9 @@ ## Abstract Each item in the collection of a multi-essence Source or Flow has a `role`, intended as a description of that item's purpose in the collection. -Roles are intended to be human-readable, and clients may choose whether to get the details of each item in the collection and decide how to use it (e.g. what to present to the user) from there, or may decide to use the roles directly. -In addition there are some common structures of Flows and Sources that come up in a lot of workflows, such as those laid out in the [multi-essence collection application note](./0001-multi-mono-essence-flows-sources.md). -In these particular cases a semi-structured naming convention is useful, and this document describes an approach and captures some possible terms and their meaning. +Roles are intended to be human-readable and uncontrolled, however a list of common editorial purposes and associated names is useful. -This approach is similar to the one taken for [storage backend labels](./0009-storage-label-format.md) and [tags](./0003-tag-names.md). - -## Role Structure - -A structured role captures multiple pieces of information: - -- The type of content (also captured in the `format` property) -- The editorial purpose of the content (may be captured in `label`, `description` or tags) -- Where necessary, a sub-identifier where multiple items fulfil a related editorial purpose (again, may be captured in `label`, `description` or tags) - -The general structure of a role is: - -```text -:: -``` - -For example a complex package of material might contain the following roles: - -```text -video:programme -video:signed:bsi -audio:programme:eng -audio:programme:fra -audio:audio_description -subtitles::eng -subtitles::fra -``` - -Here multiple languages of programme audio are provided, with the language is called out as a sub-identifier (and will also be present in the `language_code` tag). -In addition a signed version of the video and an audio description track are included. -Finally the subtitles appear in multiple languages, however there is no further editorial purpose beyond the type, so the feld is left blank. - -In a much simpler example of an A/V mux ingest, the additional information may not be necessary, and the roles could be as simple as: - -```text -video -audio -``` - -Depending on how the content is structured, the audio could take the form of a collection of mono channels, which might be described as: - -```text -audio:right -audio:left -audio:center -audio:left-surround -audio:right-surround -audio:lfe -``` +This functions much like [Tag Names](./0003-tag-names.md) and this list will likely grow over time. ## Editorial Purpose Names @@ -63,15 +13,21 @@ audio:lfe | Name | Description | | ---- | ----------- | -| `programme` | Primary, or default video for a piece of content, e.g. that will be edited or distributed on to the audience | -| `signed` | Primary video with a signer in-vision. Consider using a sub-identifier for the language code of the signer (e.g. `bsi`) | -| `cleanfeed` | Version of the video without graphics, for reversioning and re-use | +| `programme` | Primary, or default video for a piece of content, e.g. that will be edited or distributed on to the audience. | +| `signed` | Primary video with a signer in-vision. Consider using a label on the collected Source/Flow with the [language code](https://github.com/bbc/tams/blob/main/docs/appnotes/0003-tag-names.md#language_code) of the signer. | +| `cleanfeed` | Version of the video without graphics, for reversioning and re-use. | +| `video` | In a simple A/V mux that only contains the audio and video for an asset, the `role` provides little additional information, and calling it "video" may be sufficient. | ## Audio +_Note that in general, audio Flows and Sources should also use a [language code](https://github.com/bbc/tams/blob/main/docs/appnotes/0003-tag-names.md#language_code) label to allow clients to identify the language used._ + | Name | Description | | ---- | ----------- | -| `programme` | Primary, or default audio for a piece of content, e.g. that will be edited or distributed on to the audience. Consider using a sub-identifier for the language code. | -| `audio_description` | Audio description track. Consider using a sub-identifier for the language code. | -| `commentary` | Commentary track, where sent separately (e.g. from a sports event). Consider using a sub-identifier for the language code. | -| `music&effects` | Music and Effects track, where sent separately | +| `programme` | Primary, or default audio for a piece of content, e.g. that will be edited or distributed on to the audience. | +| `audio_description` | Audio description track. | +| `commentary` | Commentary track, where sent separately (e.g. from a sports event). | +| `music&effects` | Music and Effects track, where sent separately. | +| `audio` | In a simple A/V mux that only contains the audio and video for an asset, the `role` provides little additional information, and calling it "audio" may be sufficient. | + +In some cases it will also be appropriate to suffix channel labels for audio: for example if a stereo mix is set as two separate Flows, it may be referred to as `programme_L` and `programme_R`. From d09b4fa76f90bd75cf0d7ebfae7a299b005307a4 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 6 Feb 2026 14:17:39 +0000 Subject: [PATCH 08/12] examples: Update role names in examples Updates some of the examples to use the role names based on the appnote convention --- api/examples/flow-collection-get-200.json | 4 ++-- api/examples/flow-collection-put.json | 4 ++-- api/examples/flow-get-200-multi-container-map.json | 11 ++++++++--- api/examples/flow-get-200-multi.json | 8 ++++++-- api/examples/flow-put-multi.json | 8 ++++++-- api/schemas/collection-item.json | 2 +- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/api/examples/flow-collection-get-200.json b/api/examples/flow-collection-get-200.json index 322a3d9b..900f471f 100644 --- a/api/examples/flow-collection-get-200.json +++ b/api/examples/flow-collection-get-200.json @@ -1,11 +1,11 @@ [ { "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" + "role": "programme" }, { "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" + "role": "programme" }, { "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", diff --git a/api/examples/flow-collection-put.json b/api/examples/flow-collection-put.json index 322a3d9b..900f471f 100644 --- a/api/examples/flow-collection-put.json +++ b/api/examples/flow-collection-put.json @@ -1,11 +1,11 @@ [ { "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" + "role": "programme" }, { "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" + "role": "programme" }, { "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", diff --git a/api/examples/flow-get-200-multi-container-map.json b/api/examples/flow-get-200-multi-container-map.json index 32640c8a..785a7d9d 100644 --- a/api/examples/flow-get-200-multi-container-map.json +++ b/api/examples/flow-get-200-multi-container-map.json @@ -11,11 +11,16 @@ "flow_collection": [ { "id": "32b75860-83e5-48c9-8d6b-de46bdbc7f80", - "role": "video" + "role": "programme", + "container_mapping": { + "mp2ts_container": { + "pid": 256 + } + } }, { "id": "94996f2e-0cb5-43d3-ab6c-db5a9cf667aa", - "role": "L", + "role": "programme_L", "container_mapping": { "track_index": 1, "format_track_index": 0, @@ -26,7 +31,7 @@ }, { "id": "9ba0523e-22a0-4c69-a598-baf4be244a79", - "role": "R", + "role": "programme_R", "container_mapping": { "track_index": 2, "format_track_index": 1, diff --git a/api/examples/flow-get-200-multi.json b/api/examples/flow-get-200-multi.json index 75edd5d2..afc02fba 100644 --- a/api/examples/flow-get-200-multi.json +++ b/api/examples/flow-get-200-multi.json @@ -10,11 +10,15 @@ "flow_collection": [ { "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" + "role": "programme" }, { "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" + "role": "programme" + }, + { + "id": "c8943cb3-08df-46de-8ce8-0d7d70ed204c", + "role": "audio_description" }, { "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", diff --git a/api/examples/flow-put-multi.json b/api/examples/flow-put-multi.json index d4c92093..ba22d5c3 100644 --- a/api/examples/flow-put-multi.json +++ b/api/examples/flow-put-multi.json @@ -10,11 +10,15 @@ "flow_collection": [ { "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" + "role": "programme" }, { "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" + "role": "programme" + }, + { + "id": "c8943cb3-08df-46de-8ce8-0d7d70ed204c", + "role": "audio_description" }, { "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", diff --git a/api/schemas/collection-item.json b/api/schemas/collection-item.json index cbc157d6..d12c280e 100644 --- a/api/schemas/collection-item.json +++ b/api/schemas/collection-item.json @@ -12,7 +12,7 @@ "$ref": "uuid.json" }, "role": { - "description": "A human-readable role of the element in this collection (e.g. 'R' to denote a right audio channel in a collection of mono audio Sources)", + "description": "A string describing the purpose of this element in the collection, primarily intended to be human-readable (e.g. 'audio_description' to denote the audio description track in a multi of audio and video Sources). See the [Role Names](https://github.com/bbc/tams/blob/main/docs/appnotes/0020-role-names.md) application note for suggested names.", "type": "string" } } From 7a77684b5a0584e3987ab1ea2788f88c4d4075e0 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 15 May 2026 11:52:11 +0100 Subject: [PATCH 09/12] Add Option R3d where `role` becomes optional Also adds tag for capturing editorial purpose on Flows/Sources themselves --- docs/adr/0047-role-naming-convention.md | 15 +++++++++++++-- docs/appnotes/0003-tag-names.md | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md index 4b8ca6ca..d90eecc7 100644 --- a/docs/adr/0047-role-naming-convention.md +++ b/docs/adr/0047-role-naming-convention.md @@ -29,6 +29,7 @@ For how to use the `role` field (options `Rn`): * Option R3a: Use `role` as editorial purpose, use other queries for Flow/Source properties * Option R3b: Use `role` as editorial purpose, use other queries for Flow/Source properties, surface `role` as a query param * Option R3c: Use `role` as editorial purpose, additionally surface `format` in collection +* Option R3d: Use `role` as editorial purpose, make it optional, surface same detail in tags For how to represent editorial purpose (options `Pn`): @@ -39,10 +40,10 @@ For how to represent editorial purpose (options `Pn`): ## Decision Outcome -Chosen option: Option R3a and Option P4, because it lines up with the existing common use of `role` and allows it to evolve over time. +Chosen option: Option R3d and Option P4, because it lines up with the existing common use of `role` and allows it to evolve over time. It also limits the changes required to the API, and while in some cases it may trigger extra API requests (e.g. to enumerate the media types of a collection), it is likely the details of those collection items will be needed anyway, so the requests would be needed. Furthermore the TAMS API is intended not to serve as a Media Asset Manager and provide minimal library management and discovery features: through that lens the additional request burden seems reasonable and if it becomes too onerous in a particular deployment, that may indicate a MAM is required. -However Option R3c (surfacing `role` in collections) could be added later if necessary. +However Option R3c (surfacing `format` in collections) could be added later if necessary. Regarding editorial purposes, while Option P4 makes it harder for clients to automatically determine the purpose of each item in a collection, in many cases the role merely serves to change what the user is shown and they are left to make the decisions. In cases where it matters which elements of a collection are picked up (for example packaging content for distribution) the correct items should be identified by some more rigorous method anyway (for example creating a multi-essence Flow of just the items required). @@ -131,6 +132,16 @@ A client can directly identify the members of the collection directly. It would allow the UI element suggested above to be built from a single listing request, for example. * Neutral, because it changes the specification, albeit in a non-breaking way. +### Option R3d: Use `role` as editorial purpose, make it optional, surface same detail in tags + +As Option R3a, however `role` is no longer required in the `collects` property where it is not needed. +Additional a tag is described for editorial purpose. + +* Good, because it prevents this brittle field being relied upon +* Good, because it removes a piece of data from `CollectionItem` that is about the Flow itself +* Good, because it provides a way to put that piece of information on the Flow itself +* Bad, because it may break client implementations expecting to get a `role` field in the response + ## Pros and Cons of the Options - for representing editorial purpose ### Option P1: Represent editorial purpose using DVB component descriptors diff --git a/docs/appnotes/0003-tag-names.md b/docs/appnotes/0003-tag-names.md index cca160bd..a108c6e0 100644 --- a/docs/appnotes/0003-tag-names.md +++ b/docs/appnotes/0003-tag-names.md @@ -86,6 +86,13 @@ Status: **Deprecated** Replaced by the `created` field in Flow metadata. Contains the ISO formatted date-time when a Flow was created. +### editorial_purpose + +Status: **Proposed** + +Captures the editorial purpose of a piece of content, giving a hint about what it's for and what can be found inside. +Values are captured in [AppNote0020 Editorial Purposes](./0020-editorial-purpose.md) + ### flow_retention_offset Status: **Proposed** @@ -257,6 +264,13 @@ Status: **Experimental** Suggested as a way to build lightweight Attribute-based Access Control in [AppNote0016: Authorisation in TAMS workflows](./0016-authorisation-in-tams-workflows.md). A comma separated list of auth classes used to derive permissions on the Source. +### editorial_purpose + +Status: **Proposed** + +Captures the editorial purpose of a piece of content, giving a hint about what it's for and what can be found inside. +Values are captured in [AppNote0020 Editorial Purposes](./0020-editorial-purpose.md) + ### hls_exclude Status: **Experimental** From 06504ca371e8ab2d340259f970d4cb57d3ffae9e Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 15 May 2026 11:53:36 +0100 Subject: [PATCH 10/12] Make `role` optional on CollectionItem sem-ver: feature --- api/schemas/collection-item.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/schemas/collection-item.json b/api/schemas/collection-item.json index d12c280e..db38bcf0 100644 --- a/api/schemas/collection-item.json +++ b/api/schemas/collection-item.json @@ -3,8 +3,7 @@ "description": "Describes how an entity (Source or Flow) is collected into another entity of the same type", "type": "object", "required": [ - "id", - "role" + "id" ], "properties": { "id": { From b36b6bb47a626058dfa30c9c90d10c2f8d2af94f Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 15 May 2026 11:54:08 +0100 Subject: [PATCH 11/12] Rename AppNote0020 to be editorial purposes Switching to also using a tag for editorial purpose means the original name makes less sense. Also updates the AppNote accordingly --- docs/README.md | 2 +- ...0-role-naming-convention.md => 0020-editorial-purpose.md} | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename docs/appnotes/{0020-role-naming-convention.md => 0020-editorial-purpose.md} (92%) diff --git a/docs/README.md b/docs/README.md index 26eeb7ad..14f27946 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,7 +26,7 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems | | [0018](./appnotes/0018-managing-multiple-object-instances.md) | Managing Multiple Object Instances | | [0019](./appnotes/0019-implementing-retention-management.md) | Methods of implementing retention management | -| [0020](./appnotes/0020-role-naming-convention.md) | Role Naming Convention   | +| [0020](./appnotes/0020-editorial-purposes.md) | Editorial Purposes  | ## ADRs diff --git a/docs/appnotes/0020-role-naming-convention.md b/docs/appnotes/0020-editorial-purpose.md similarity index 92% rename from docs/appnotes/0020-role-naming-convention.md rename to docs/appnotes/0020-editorial-purpose.md index a0414c81..805c444c 100644 --- a/docs/appnotes/0020-role-naming-convention.md +++ b/docs/appnotes/0020-editorial-purpose.md @@ -1,9 +1,10 @@ -# 0020: Role Naming Convention +# 0020: Editorial Purpose ## Abstract Each item in the collection of a multi-essence Source or Flow has a `role`, intended as a description of that item's purpose in the collection. -Roles are intended to be human-readable and uncontrolled, however a list of common editorial purposes and associated names is useful. +Additionally there is an `editorial_purpose` tag, serving the same functionality. +These are intended to be human-readable and uncontrolled, however a list of common editorial purposes and associated names is useful. This functions much like [Tag Names](./0003-tag-names.md) and this list will likely grow over time. From 3a6bb79da5b9b52903efd9b55ff917edf390d761 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 15 May 2026 11:56:56 +0100 Subject: [PATCH 12/12] Add ADR considering how to map channels --- docs/README.md | 2 + docs/adr/0047-role-naming-convention.md | 2 + docs/adr/0049-channel-mapping.md | 246 ++++++++++++++++++++++ docs/adr/0050-mono-essence-collections.md | 51 +++++ 4 files changed, 301 insertions(+) create mode 100644 docs/adr/0049-channel-mapping.md create mode 100644 docs/adr/0050-mono-essence-collections.md diff --git a/docs/README.md b/docs/README.md index 14f27946..ba797a14 100644 --- a/docs/README.md +++ b/docs/README.md @@ -84,5 +84,7 @@ For more information on how we use ADRs, see [here](./adr/README.md). | [0044](./adr/0044-signalling-timeouts.md) | Signalling timeout periods | | [0046](./adr/0046-governance.md) | Governance | | [0047](./adr/0047-role-naming-convention.md) | Role Naming Convention | +| [0049](./adr/0049-channel-mapping.md) | Channel Mapping | +| [0050](./adr/0050-mono-essence-collections.md) | Mono Essence Collections | \* Note: ADR 0004a was the unintended result of a number clash in the early development of TAMS which wasn't caught before publication diff --git a/docs/adr/0047-role-naming-convention.md b/docs/adr/0047-role-naming-convention.md index d90eecc7..b31c1e32 100644 --- a/docs/adr/0047-role-naming-convention.md +++ b/docs/adr/0047-role-naming-convention.md @@ -19,6 +19,8 @@ Currently this is represented in free text. * When viewing a multi-essence Source or Flow, only the list of IDs collected and roles are available: getting formats and tags requires another query. * Items in a collection serve a variety of different purposes, and it is useful to have some commonality. * At time of writing `role` is typically `video` or `audio`, but practical applications need to represent more complex packages. +* One area of interest is mapping and representing channels, for example audio channel shuffling. + This is considered seperately in [ADR0049 Channel Mapping](./0049-channel-mapping.md). ## Considered Options diff --git a/docs/adr/0049-channel-mapping.md b/docs/adr/0049-channel-mapping.md new file mode 100644 index 00000000..bf74448b --- /dev/null +++ b/docs/adr/0049-channel-mapping.md @@ -0,0 +1,246 @@ +--- +status: "proposed" +--- +# Channel Mapping + +## Context and Problem Statement + +In the course of considering how the `role` property of a Flow collection should be used (in [ADR0047](./0047-role-naming-convention.md)) one of the use cases discussed was describing audio channels: for example how to indicate a particular Flow was the left or right channel of a stereo pair. +The various TAMS examples describe doing this using `role`, however doing so overloads a human-readable free-text field in a way that isn't ideal. +This ADR considers other approaches to capturing the same information. + +The container mapping described in [AppNote 0006](../appnotes/0006-containers-and-mappings.md) allows for a Flow to be described without essence (`container` is unset), where the essence is instead found as part of another Flow. +The example given shows an audio Flow referencing a multi-essence Flow, using the `CollectionItem` object to identify how to map essence tracks in the multi-essence Flow to each mono-essence. +When encountering such a mono-essence Flow, a player must note that `container` is not set, and search the list of Flows collected by that Flow to locate one where it is set. + +> [!NOTE] +> Note that throughout this document, the term "concrete" is used to refer to a Flow that has `container` set + +### Audio Channel Shuffling + +In the example below, to play Flow A, a player must search Flows that Flow A is collected by, and locate Flow M, which has the `CollectionItem` object. +This is an inversion of the convention when presented with a multi-essence Flow with no `container`, where the `collects` should be searched to find the Flows that make up that multi-essence Flow. + +```mermaid + block-beta + columns 4 + + space:2 + a_ci_v>"Collection Item \n Track: 1"] + a_f_v["Flow V \n Video \n container: null \n BBC1 Video"] + a_f_m-- "collects" -->a_ci_v + a_ci_v---a_f_v + + a_f_m["Flow M \n Multi \n container: video/mp2t \n BBC1 Capture"] + space:3 + + space:2 + a_ci_a>"Collection Item \n Track: 2"] + a_f_a["Flow A \n Audio \n container: null \n BBC1 Audio"] + a_f_m-- "collects" -->a_ci_a + a_ci_a---a_f_a + + classDef flow fill:#0073E6,color:#FFF + classDef collectionItem fill:#663399,color:#FFF + + class a_f_a,a_f_v,a_f_m flow + class a_ci_v,a_ci_a collectionItem +``` + +Figure 1: Simple mapping example + +However this model does not explicitly support the reverse, where Flows with essence are mapped to specific channels of another Flow, or re-mapped similar to an audio channel "shuffler". +Consider the example of _Figure 2_ where two mono-essence single-channel audio Flows are collected to form a stereo pair. +This seems theoretically possible, but is not explicitly called out in the documentation. + +```mermaid + block-beta + columns 4 + + a_f_a1["Flow A1 \n Audio \n container: audio/mp2t \n Audio 1"] + a_ci_a1>"Collection Item \n Track: 1"] + space:5 + a_f_s-- "collects" -->a_ci_a1 + a_ci_a1---a_f_a1 + + a_f_s["Flow S \n Audio \n container: null \n Stereo Audio"] + + a_f_a2["Flow A2 \n Audio \n container: audio/mp2t \n Audio 2"] + a_ci_a2>"Collection Item \n Track: 2"] + a_f_s-- "collects" -->a_ci_a2 + a_ci_a2---a_f_a2 + + classDef flow fill:#0073E6,color:#FFF + classDef collectionItem fill:#663399,color:#FFF + + class a_f_s,a_f_a1,a_f_a2 flow + class a_ci_a1,a_ci_a2 collectionItem +``` + +Figure 2: Stereo pair from discrete audio Flows + +A more complex example may be a Flow containing all 16 channels of audio from an SDI capture, multiplexed together into a single multi-essence Flow. +The user wishes to extract channels 3+4 and have them represent the Left and Right channels of a stereo pair. +In principle they can do so by adding a Flow for each audio channel (with a `collects` relationship) to the 16 channel mux, and then adding a further Flow representing the stereo pair: + +```mermaid + block-beta + + columns 7 + + space:2 + a_ci_3>"Collection Item \n Channel: 3"] + a_f_3["Flow C3 \n Audio \n container: null"] + a_ci_sl>"Collection Item \n Channel: 1"] + space:2 + + a_f_m["Flow M \n Multi \n container: video/mp2t"] + space:5 + a_f_s["Flow S1 \n Audio \n container: null"] + + space:2 + a_ci_4>"Collection Item \n Channel: 4"] + a_f_4["Flow C4 \n Audio \n container: null"] + a_ci_sr>"Collection Item \n Channel: 2"] + space:1 + + a_f_s-- "collects" -->a_ci_sl + a_f_m-- "collects" -->a_ci_4 + a_f_m-- "collects" -->a_ci_3 + a_ci_3---a_f_3 + a_ci_sl---a_f_3 + a_ci_4---a_f_4 + a_ci_sr---a_f_4 + a_f_s-- "collects" -->a_ci_sr + space:1 + + classDef flow fill:#0073E6,color:#FFF + classDef collectionItem fill:#663399,color:#FFF + + class a_f_3,a_f_4,a_f_sl,a_f_sr,a_f_m,a_f_s flow + class a_ci_3,a_ci_4,a_ci_sl,a_ci_sr collectionItem +``` + +Figure 3: Multi-stage mapping example +Note that in this diagram, every Flow has a matching Source, omitted for clarity. + +This presents a problem when a player comes to play Source S1. +It identifies that Source S1 is represented by Flow S1, gets Flow S1 and finds no `container` set. +In the previous example it then had to proceed "up" the hierarchy, however here it must apply the more common convention with multi-essence Flows, and search "down" to locate the component channels. +Once Flows C3 and C4 have been located, the player must notice the further lack of a `container` property, and search the list of Flows they are collected by. +Flow S1 can be eliminated: it also doesn't have a `container` tag, leading eventually back to Flow M. +Ideally there should be an unambiguous algorithm to locate the correct Flow (with `container` set) to play. + +In addition in _Figure 3_ Flow S1 is an Audio Flow (specifically `urn:x-nmos:format:audio`) whereas Flow M is a Multi Flow (`urn:x-nmos:format:multi`): TAMS contains no specific guidance as to which is correct in this case, and the ambiguity further complicates the matter. + +### Video Channel Mapping + +There are more limited use cases for mapping channels in video, such as where multiple tracks exist on an NLE timeline, or where TAMS is used to describe how multiple video tracks map into a container format. + +## Decision Drivers + +[AppNote 0006 Containers and Mappings](../appnotes/0006-containers-and-mappings.md#audio-track-channel-mapping) describes how to describe a Flow containing a subset of another Flow's audio channels, and notes such usage may be restricted. +The examples described work for examples such as extracted video and audio from a Flow in which they are multiplexed (corresponding to an asset elsewhere, such as a file). +However the existing documentation has some limitations: + +* There are no examples for mapping audio, e.g. the case where a concrete Flow contains stereo audio: by adding a Flow under `collects` describing each channel, and setting `container_mapping` for each Collection Item, individual channels could be assigned an ID, however there is no example or documentation. +* There is ambiguity as to whether the reverse case is possible, where a pair of concrete mono-essence audio Flows are collected as the left and right channels of a stereo pair. +* As noted above, the approach breaks down given more complex cases with multiple steps to reach the essence. +* It is not clear where Multi-essence vs Audio/Video Flows should be used. + +We should have clear guidance on how to handle these complex cases, and what players and readers are expected to do. + +## Considered Options + +* Option 1: Consider audio Flows to be indivisible into channels +* Option 2: Map down: use existing `container_mapping` only to describe single channels of a concrete Flow +* Option 3: Map bidirectionally: allow `container_mapping` to compose audio channels +* Option 4: Map bidirectionally, but require one end be concrete +* Option 5: Map down for Multi, up for Audio Flows + +## Decision Outcome + +Chosen option: "{title of option 1}", because +{Justification, e.g., only option which resolves requirements, or comes out best (see below)}. + +### Implementation + +{Once the proposal has been implemented, add a link to the relevant PRs here} + +## Pros and Cons of the Options - for Audio Mapping + +### Option 1: Consider audio Flows to be indivisible into channels + +Consider that an audio Flow containing multiple channels (such as stereo audio) cannot be divided into channels using the `collects` mechanism in TAMS. +The `container_mapping` property exists solely to allow separate tracks (such as video and stereo audio) to be described as part of a multiplex, for example representing a muxed MPEG-TS. +If dividing it further is desired, the user must carry out that division and create a series of new, independent Flows, or describe that extraction elsewhere, such as a composition format used by a Digital Audio Workstation (DAW). + +* Good, because it avoids having to add further complexity into the specification or players +* Good, because it aligns with existing usage of TAMS (and player implementations): no known implementations attempt to do what is described in _Figure 2_ +* Bad, because it means audio channel shuffling cannot be represented as a metadata-only operation, unlike the "write once, use many" approach allowed elsewhere +* Bad, because it limits a class of use case for TAMS where content is received from e.g. an SDI ingest and repackaged, which is otherwise enabled by the Source/Flow model +* Bad, because the Source/Flow hierarchy supports this operation for cases such as an A/V mux, but doesn't for audio channels, which seems unexpected + +### Option 2: Map down: use existing `container_mapping` only to describe single channels of a concrete Flow + +Update the documentation to indicate that `container_mapping` can also be used to describe a single channel within a multi-channel audio Flow, where that multi-channel Flow is concrete. +This is mapping "down", in the sense that `container_mapping` is read from a collection (with concrete essence) down to the items collected, in the same way as a video Flow might be extracted from a specific track in a muxed segment. +However the example in _Figure 2_ above is _not_ possible, and this sort of mapping should be captured elsewhere (e.g. in a composition format such as [OpenTimelineIO](../appnotes/0015-using-tams-in-opentimelineio.md)) or a new Flow should be created containing the stereo pair. +Players are not expected to be able to perform audio channel shuffling. + +* Good, because it avoids having to add further complexity into the specification or players +* Good, because it aligns with existing usage of TAMS (and player implementations): no known implementations attempt to do what is described in _Figure 2_ +* Good, because it makes channel mapping explicit in a format designed for the purpose, which can link back to TAMS Sources (or Flows) +* Bad, because it means audio channel shuffling cannot be represented as a metadata-only operation, unlike the "write once, use many" approach allowed elsewhere +* Bad, because the Source/Flow hierarchy supports this operation for cases such as an A/V mux, but doesn't for audio channels, which seems unexpected +* Bad, because it may lead to audio channel mappings being stored in a more brittle way, such as using `role` + +### Option 3: Map bidirectionally: allow `container_mapping` to compose audio channels + +Update the documentation to indicate that `container_mapping` can be used both to describe a single channel within a concrete multi-channel audio Flow, and how to combine a number of concrete single-channel Flows into a multi-channel Flow. +As a result, _Figure 2_ becomes possible in TAMS, as theoretically does _Figure 3_. +However for the latter to work a player or reader must conduct a somewhat complex process to find concrete Flows: given a Flow to play it may be necessary to explore both `collects` and `collected_by` to find suitable concrete essence. + +* Good, because it explicitly and flexibly expresses channel mappings +* Good, because it clarifies a behaviour that seems like it should already work in TAMS +* Good, because it allows complex shuffling behaviours to be expressed as a metadata operation +* Bad, because it increases complexity in every conformant player to select and extract audio channels from multi-channel essence segments +* Bad, because it also increases the complexity of locating concrete Flows, since a player/reader may need to extensively traverse the graph to locate suitable essence +* Bad, because there is no way to understand these collections in the Source graph + +### Option 4: Map bidirectionally, but require one end be concrete + +As for Option 3, except in this case if a `CollectionItem` has a `container_mapping` then at least one of the Flow that is collected, or the Flow it is collected by must be concrete. +In this case the approach in _Figure 3_ is no longer possible, however a version could be implemented if Flows C3 and C4 were made concrete, and re-used objects from Flow M (with `container_mapping` set on each of C3 and C4 to indicate how to extract the correct track). + +Pros and cons are as for Option 3, except: + +* Good (compared to Option 3), because it simplifies the process of finding a concrete Flow +* Neutral, because it constrains the flexibility allowed in channel mapping, but not significantly + +### Option 5: Map down for Multi, up for Audio Flows + +As Option C3, except further specify that a multi-essence Flow which is not concrete should always be read by searching the Flows in `collects`, while mono-essence should look at the Flows in `collected_by`. +Note that this does not work with the example in _Figure 3_: Flow S1 would have to become multi-essence. + +Pros and cons are as for Option 3, except: + +* Good (compared to Option 3), because it simplifies the process of finding a concrete Flow +* Bad, because it overloads detail about a Flow into the format, in a way that is unintuitive + +### Option 6: Map down where the Flow `collects` other Flows + +As Option Option 3, except further specify that a non-concrete Flow that collects other Flows always has collected concrete Flows. + +Pros and cons are as for Option 3, except: + +* Good (compared to Option 3), because it simplifies the process of finding a concrete Flow +* Bad (compared to Option 3), because it may unexpectedly limit flexibility (e.g. Flow A in _Figure 2_ could not be further divided into individual channels). + +As Option 3, except further specify that if a Flow has a `collects` property but no `container` a reader should attempt to read the Flows under `collects` to find suitable essence to play. +In the example above, to play Flow S1 a player notes that `collects` is set, and tries to play each element of the collection instead, realising that to do so it then has to search `collected_by` to find an entry with a `container`. + +* Good, because it requires players to only search in one direction to find playable media +* Good, because it aligns with how multi-essence Flows work in general: if there is no `container` but there are collected Flows, they contain the essence content of the multi-essence Flow. +* Good, because it unambiguously works with the Flow S1 example above +* Bad, because it prevents multi-layer channels, however there is no clear use case for this diff --git a/docs/adr/0050-mono-essence-collections.md b/docs/adr/0050-mono-essence-collections.md new file mode 100644 index 00000000..1bc0c684 --- /dev/null +++ b/docs/adr/0050-mono-essence-collections.md @@ -0,0 +1,51 @@ +--- +status: "proposed" +--- +# Mono-Essence Collections + +## Context and Problem Statement + +In the discussion of [ADRXXXX Channel Mapping](./xxxx-channel-mapping.md) a mix of multi-essence Flows and mono-essence are used when considering multi-channel audio. + +No clear guidance is given as to when one or the other should be used, and while the answer is obvious in some cases, where audio channels are involved the answers are less obvious. + +## Considered Options + +* Option 1: Collections always require multi-essence Flows and Sources +* Option 2: Require Multi-essence Flows for Collections unless describing multi-channel audio +* Option 3: Use Multi-essence vs Audio to indicate mapping direction (option C5 above) + +## Decision Outcome + +Chosen option: "{title of option 1}", because +{Justification, e.g., only option which resolves requirements, or comes out best (see below)}. + +### Implementation + +{Once the proposal has been implemented, add a link to the relevant PRs here} + +## Pros and Cons of the Options + +### Option 1: Collections always require multi-essence Flows and Sources + +Add a requirement that `collects` is only valid for multi-essence Flows and Sources. + +* Good, because it makes the correct one to use unambiguous +* Bad, because as discussed in ADRXXXX it is useful to be able to describe the channels of multi-channel audio separately + +### Option 2: Require Multi-essence Flows for Collections unless describing multi-channel audio + +Add documentation that `collects` is possible for Flows other than multi-essence, but only where the Flow that collects them together is intrinsically playable. +For example a stereo audio Flow having breakout Flows for the left and right channels would make sense. +However all 16 channels of SDI embedded audio, or multiple tracks of video would not make sense, and must be a mutli-essence Flow. + +* Good, because it makes the correct one to less ambiguous +* Good, because it is likely to present players with Flows they can make sense of + +### Option 3: Use Multi-essence vs Audio to indicate mapping direction (option C5 in ADRXXXX) + +Use the multi-essence type to indicate that a reader should search the IDs in the Flow's `collected_by` list to find a Flow with essence (e.g. `container` property is set). +Use the mono-essence type (e.g. the Audio type) to mean searching the items the Flow `collects` to find a Flow with essence. + +* Good, because it makes the correct one to use unambiguous +* Bad, because as disussed in ADRXXXX it breaks when there are multiple layers of collections