From 0b0ab0abc493c9eeee8bcb1e14ef9c3c2f8c75f9 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 20 May 2025 11:47:25 +0100 Subject: [PATCH 01/22] Flow profiles draft app note --- docs/appnotes/00xx-using-flow-profiles.md | 89 +++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/appnotes/00xx-using-flow-profiles.md diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md new file mode 100644 index 00000000..350c976b --- /dev/null +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -0,0 +1,89 @@ +# 00xx: DRAFT: Using Flow Profiles + +## Abstract + +The TAMS API is deliberately agnostic to the format of the media which it is managing to allow for future compatibility with new formats without needing to change the API specification. +This provides challenges for interoperability and workflows such as edit by reference where standard media formats are required across multiple sources. + +This document describes how flow profiles can be used within the TAMS API to simplify workflows while maintaining the flexibility of the core API. + +## Challenges + +### House formats + +Within a customer implementation of TAMS it is expected that there would be limited number of recommended formats for users to work in. +Typically this could include a target format for the high quality media and standardised formats for proxy media and images. +These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. + +The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier it defines one or more common formats for all the systems to utilise. + +### Edit by reference flow matching + +For edit by reference workflows there is a need both to create new sources and flows for the new item and also combine the segments together to create the new edit. + +If the source content is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. +However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. +Currently the TAMS API does provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. +The more sources involved in this process, the harder this becomes. + +## TAMS Profiles within the API + +The TAMS profile model is split into a number of stages: + +* The list profiles end point which describes the recommended profiles supported by the store +* The ability to supply a profile when creating a flow and the de-normalisation of the technical details at the point of creation +* The ability to query flows for a given profile to easily and quickly find the required media type + +### Profiles endpoint + +It is possible to create, view, edit and delete profiles via the dedicated API calls under the TAMS service end point (/services/profiles). +These profiles hold all the technical parameters required to create a flow in a single location. +For a system looking to ingest standardised content into TAMS then it would expect to create content matching one or more profiles as defined in the endpoint. + +The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. +This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS profile metadata + +### Creating a flow using a profile + +When creating a flow the generating system has two options: + +1. Specify all the technical characteristics of the flow including the wrapper, codec and essence parameters alongside the non-technical parameters such as label and description +2. Provide just the technical profile for the flow and non-technical parameters required + +When using the second option on submission of the create flow request, the store will then read the metadata for a given profile and use this to populate the metadata for the flow. +This de-normalisation of the technical parameters means that on the read side the flows created via both mechanisms have the same technical parameters available. +Additionally if the decision is made to change a standard profile in the future then this does not affect the existing flows as the parameters have already been replicated and should remain unchanged to reflect the media actually being stored. + +Flows that have been created from a profile will include the parameter indicating which profile they were created from. +This differentiates them from the flows that have been created with the technical characteristics directly. + +### Query flows using a profile + +The get flows endpoint has the ability to query for flows with a given profile. When combined with other query parameters such as source id then this means it is easy to start matching content formats. + +For example on an edit by reference workflow it would be possible to read the profile endpoint for the recommended profiles that content should have. This then simplifies the process of creating the required flows and sources for the new content item. The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. If the source content has additional non standard flows then these could be ignored. + +## Recommended TAMS profiles + +To aid interoperabity a set of recommended profiles is hosted as part of the API specification Github respository. These are profiles which have been tested and used in real workflows and are recommended as a starting point for implementors building a new store. It is recommended that tools which write to the TAMS API try and support as many of the recommended profiles of their target content types as possible. + +Additional recommened profiles will be added to the repository as new use cases are identified or new media formats added. + +## Suggested metadata fields in the profile end point + +- Identifier (format to be decided) +- Type (video/audio/image/data) +- Label +- Description +- Version (recommended to increment when changing) +- Created/Created by +- Modified/Modified by +- Tags +- Technical characteristics (first level flow properties such as codec, wrapper, target chunk length etc, plus essence parameters) +- Preferred (needs thinking about how to indicate this is the prefered high res or prefered proxy etc) + + + + + + From b1150d399ee85c7ecda970046fef6b0c0af55201 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 20 May 2025 11:49:23 +0100 Subject: [PATCH 02/22] Formatting improvements --- docs/appnotes/00xx-using-flow-profiles.md | 27 ++++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md index 350c976b..73000dfb 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -11,19 +11,19 @@ This document describes how flow profiles can be used within the TAMS API to sim ### House formats -Within a customer implementation of TAMS it is expected that there would be limited number of recommended formats for users to work in. -Typically this could include a target format for the high quality media and standardised formats for proxy media and images. +Within a customer implementation of TAMS it is expected that there would be limited number of recommended formats for users to work in. +Typically this could include a target format for the high quality media and standardised formats for proxy media and images. These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier it defines one or more common formats for all the systems to utilise. ### Edit by reference flow matching -For edit by reference workflows there is a need both to create new sources and flows for the new item and also combine the segments together to create the new edit. +For edit by reference workflows there is a need both to create new sources and flows for the new item and also combine the segments together to create the new edit. -If the source content is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. -However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. -Currently the TAMS API does provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. +If the source content is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. +However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. +Currently the TAMS API does provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. The more sources involved in this process, the harder this becomes. ## TAMS Profiles within the API @@ -40,7 +40,7 @@ It is possible to create, view, edit and delete profiles via the dedicated API c These profiles hold all the technical parameters required to create a flow in a single location. For a system looking to ingest standardised content into TAMS then it would expect to create content matching one or more profiles as defined in the endpoint. -The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. +The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS profile metadata ### Creating a flow using a profile @@ -50,8 +50,8 @@ When creating a flow the generating system has two options: 1. Specify all the technical characteristics of the flow including the wrapper, codec and essence parameters alongside the non-technical parameters such as label and description 2. Provide just the technical profile for the flow and non-technical parameters required -When using the second option on submission of the create flow request, the store will then read the metadata for a given profile and use this to populate the metadata for the flow. -This de-normalisation of the technical parameters means that on the read side the flows created via both mechanisms have the same technical parameters available. +When using the second option on submission of the create flow request, the store will then read the metadata for a given profile and use this to populate the metadata for the flow. +This de-normalisation of the technical parameters means that on the read side the flows created via both mechanisms have the same technical parameters available. Additionally if the decision is made to change a standard profile in the future then this does not affect the existing flows as the parameters have already been replicated and should remain unchanged to reflect the media actually being stored. Flows that have been created from a profile will include the parameter indicating which profile they were created from. @@ -61,11 +61,16 @@ This differentiates them from the flows that have been created with the technica The get flows endpoint has the ability to query for flows with a given profile. When combined with other query parameters such as source id then this means it is easy to start matching content formats. -For example on an edit by reference workflow it would be possible to read the profile endpoint for the recommended profiles that content should have. This then simplifies the process of creating the required flows and sources for the new content item. The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. If the source content has additional non standard flows then these could be ignored. +For example on an edit by reference workflow it would be possible to read the profile endpoint for the recommended profiles that content should have. +This then simplifies the process of creating the required flows and sources for the new content item. +The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. +If the source content has additional non standard flows then these could be ignored. ## Recommended TAMS profiles -To aid interoperabity a set of recommended profiles is hosted as part of the API specification Github respository. These are profiles which have been tested and used in real workflows and are recommended as a starting point for implementors building a new store. It is recommended that tools which write to the TAMS API try and support as many of the recommended profiles of their target content types as possible. +To aid interoperabity a set of recommended profiles is hosted as part of the API specification Github respository. +These are profiles which have been tested and used in real workflows and are recommended as a starting point for implementors building a new store. +It is recommended that tools which write to the TAMS API try and support as many of the recommended profiles of their target content types as possible. Additional recommened profiles will be added to the repository as new use cases are identified or new media formats added. From d8680fe8d9e8fc6c414049bf80698e955a13249c Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 3 Jun 2025 16:24:01 +0100 Subject: [PATCH 03/22] Incorporating changes from Mark --- docs/appnotes/00xx-using-flow-profiles.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md index 73000dfb..740427c2 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -2,7 +2,7 @@ ## Abstract -The TAMS API is deliberately agnostic to the format of the media which it is managing to allow for future compatibility with new formats without needing to change the API specification. +The TAMS API is deliberately agnostic to the format of the media which it is managing, to allow for future compatibility with new formats without needing to change the API specification. This provides challenges for interoperability and workflows such as edit by reference where standard media formats are required across multiple sources. This document describes how flow profiles can be used within the TAMS API to simplify workflows while maintaining the flexibility of the core API. @@ -15,7 +15,8 @@ Within a customer implementation of TAMS it is expected that there would be limi Typically this could include a target format for the high quality media and standardised formats for proxy media and images. These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. -The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier it defines one or more common formats for all the systems to utilise. +The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier. +House formats define one or more common formats for all the systems to utilise. ### Edit by reference flow matching @@ -23,14 +24,14 @@ For edit by reference workflows there is a need both to create new sources and f If the source content is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. -Currently the TAMS API does provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. +Currently the TAMS API does not provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. The more sources involved in this process, the harder this becomes. ## TAMS Profiles within the API The TAMS profile model is split into a number of stages: -* The list profiles end point which describes the recommended profiles supported by the store +* An end-point to list and describe the available profiles supported by the store * The ability to supply a profile when creating a flow and the de-normalisation of the technical details at the point of creation * The ability to query flows for a given profile to easily and quickly find the required media type @@ -38,7 +39,7 @@ The TAMS profile model is split into a number of stages: It is possible to create, view, edit and delete profiles via the dedicated API calls under the TAMS service end point (/services/profiles). These profiles hold all the technical parameters required to create a flow in a single location. -For a system looking to ingest standardised content into TAMS then it would expect to create content matching one or more profiles as defined in the endpoint. +A system looking to ingest standardised content into TAMS would create content matching one or more profiles as defined in the endpoint. The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS profile metadata From 2a686d6384ffe20c8e61750ee030288c8f6ba7de Mon Sep 17 00:00:00 2001 From: johnbilt <164537346+johnbilt@users.noreply.github.com> Date: Wed, 4 Jun 2025 17:26:12 +0100 Subject: [PATCH 04/22] Update docs/appnotes/00xx-using-flow-profiles.md Updated wording Co-authored-by: James Sandford --- docs/appnotes/00xx-using-flow-profiles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md index 73000dfb..9183e0f7 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -11,7 +11,7 @@ This document describes how flow profiles can be used within the TAMS API to sim ### House formats -Within a customer implementation of TAMS it is expected that there would be limited number of recommended formats for users to work in. +Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. Typically this could include a target format for the high quality media and standardised formats for proxy media and images. These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. From c7a9347dff61bfe3303eb8fde941e3d281d43a18 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Fri, 6 Jun 2025 09:54:40 +0100 Subject: [PATCH 05/22] Combining changes --- docs/appnotes/00xx-using-flow-profiles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md index 740427c2..110a37d1 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -11,7 +11,7 @@ This document describes how flow profiles can be used within the TAMS API to sim ### House formats -Within a customer implementation of TAMS it is expected that there would be limited number of recommended formats for users to work in. +Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. Typically this could include a target format for the high quality media and standardised formats for proxy media and images. These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. From 1e71dbddcb21701bcb52c8cd21ffad03112d1851 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Fri, 6 Jun 2025 11:55:26 +0100 Subject: [PATCH 06/22] Initial profile examples --- api/examples/flow-put-profile.json | 11 +++++++++ api/examples/profiles-get-200.json | 39 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 api/examples/flow-put-profile.json create mode 100644 api/examples/profiles-get-200.json diff --git a/api/examples/flow-put-profile.json b/api/examples/flow-put-profile.json new file mode 100644 index 00000000..d00dcc0e --- /dev/null +++ b/api/examples/flow-put-profile.json @@ -0,0 +1,11 @@ +{ + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", + "description": "audio capture web", + "label": "capture_1", + "tags": { + "input_quality": "web", + "_tams_segmentation_rate": "375/8" + }, + "profile_id": "329b98d6-adeb-418c-8eaf-eca14edc1706" +} \ No newline at end of file diff --git a/api/examples/profiles-get-200.json b/api/examples/profiles-get-200.json new file mode 100644 index 00000000..65bb18a1 --- /dev/null +++ b/api/examples/profiles-get-200.json @@ -0,0 +1,39 @@ +[ + { + "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", + "urn": "urn:x-tam:profile:video_50m_1920p50_ts", + "label": "profile_label", + "description": "profile_description", + "created_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "tags": { + "_ffmpeg_command": "...." + }, + "flow_metadata": { + "format": "urn:x-nmos:format:video", + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "segment_duration": { + "numerator": 6, + "denominator": 1 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 25, + "denominator": 1 + }, + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } + } +] \ No newline at end of file From 6770a5d784e1328f9d9a6f218f4a6503a5e154c3 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 29 Jul 2025 15:51:26 +0100 Subject: [PATCH 07/22] First set of profile schema changes --- api/TimeAddressableMediaStore.yaml | 232 +++++++++++++++++- api/examples/profile-get-200-image.json | 24 ++ api/examples/profile-get-200-video.json | 37 +++ api/examples/profile-put-200.json | 37 +++ api/examples/profile-put.json | 35 +++ api/examples/profiles-get-200.json | 92 ++++--- api/schemas/flow-audio.json | 2 +- .../{flow-core.json => flow-common.json} | 47 +--- api/schemas/flow-data.json | 2 +- api/schemas/flow-get.json | 26 ++ api/schemas/flow-image.json | 2 +- api/schemas/flow-multi.json | 32 +-- api/schemas/flow-put.json | 37 +++ api/schemas/flow-technical.json | 53 ++++ api/schemas/flow-video.json | 2 +- api/schemas/flow.json | 12 - api/schemas/profile.json | 53 ++++ 17 files changed, 603 insertions(+), 122 deletions(-) create mode 100644 api/examples/profile-get-200-image.json create mode 100644 api/examples/profile-get-200-video.json create mode 100644 api/examples/profile-put-200.json create mode 100644 api/examples/profile-put.json rename api/schemas/{flow-core.json => flow-common.json} (64%) create mode 100644 api/schemas/flow-get.json create mode 100644 api/schemas/flow-put.json create mode 100644 api/schemas/flow-technical.json delete mode 100644 api/schemas/flow.json create mode 100644 api/schemas/profile.json diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index 040555d1..328fba32 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -146,6 +146,200 @@ paths: $ref: schemas/storage-backends-list.json example: $ref: examples/storage-backends-get-200.json + /service/profiles: + head: + summary: Profile Backend Information + description: Return profile backends path headers + operationId: HEAD_profiles + tags: + - Profiles + parameters: + - name: profile_id + in: query + description: Filter on source identifier. + schema: + $ref: '#/components/schemas/uuid' + - name: urn + in: query + description: Filter on profile that have the given urn. + schema: + type: string + - name: format + in: query + description: Filter on profile format. + schema: + $ref: '#/components/schemas/contentformat' + - name: codec + in: query + description: Filter on profile codec. + schema: + $ref: '#/components/schemas/mimetype' + - name: label + in: query + description: Filter on profiles that have the given label. + schema: + type: string + - $ref: '#/components/parameters/trait_resource_paged_key' + - $ref: '#/components/parameters/trait_paged_limit' + responses: + "200": + description: "" + headers: + Link: + description: Provides references to cursors for paging. Only the 'rel' attribute with value 'next' and a link to the next page is currently supported. If 'next' is not present then it is the last page. + schema: + type: string + X-Paging-Limit: + description: Identifies the current limit being used for paging. This may not match the requested value if the requested value was too high for the implementation + schema: + type: integer + X-Paging-NextKey: + description: Opaque string that can be supplied to the `page` query parameter to get the next page of results. + schema: + type: string + content: + application/json: + schema: + type: string + "400": + description: Bad request. Invalid query options. + get: + summary: Profile Backend Information + description: List of profiles supported by the store instance for use when creating flows. + operationId: GET_profiles + tags: + - Profiles + parameters: + - name: profile_id + in: query + description: Filter on source identifier. + schema: + $ref: '#/components/schemas/uuid' + - name: urn + in: query + description: Filter on profile that have the given urn. + schema: + type: string + - name: format + in: query + description: Filter on profile format. + schema: + $ref: '#/components/schemas/contentformat' + - name: codec + in: query + description: Filter on profile codec. + schema: + $ref: '#/components/schemas/mimetype' + - name: label + in: query + description: Filter on profiles that have the given label. + schema: + type: string + - $ref: '#/components/parameters/trait_resource_paged_key' + - $ref: '#/components/parameters/trait_paged_limit' + responses: + "200": + description: "" + headers: + Link: + description: Provides references to cursors for paging. Only the 'rel' attribute with value 'next' and a link to the next page is currently supported. If 'next' is not present then it is the last page. + schema: + type: string + X-Paging-Limit: + description: Identifies the current limit being used for paging. This may not match the requested value if the requested value was too high for the implementation + schema: + type: integer + X-Paging-NextKey: + description: Opaque string that can be supplied to the `page` query parameter to get the next page of results. + schema: + type: string + content: + application/json: + example: + $ref: examples/profiles-get-200.json + schema: + type: array + items: + $ref: "schemas/profile.json" + "400": + description: Bad request. Invalid query options. + /service/profiles/{profileId}: + parameters: + - name: profileId + in: path + required: true + schema: + $ref: '#/components/schemas/uuid' + description: The profile identifier. + head: + summary: Profile Details + description: Return profile path headers + operationId: HEAD_profiles-profileId + tags: + - Profiles + responses: + "200": + $ref: '#/components/responses/trait_resource_info_head_200' + "404": + $ref: '#/components/responses/trait_resource_info_head_404' + get: + summary: Profile Details + description: Returns profile metadata. + operationId: GET_profiles-profileId + tags: + - Profiles + responses: + "200": + description: "" + content: + application/json: + schema: + $ref: schemas/profile.json + examples: + video: + summary: Video Profile + value: + $ref: examples/profile-get-200-video.json + jpegimage: + summary: Image Profile + value: + $ref: examples/profile-get-200-image.json + "404": + description: The requested flow does not exist. + post: + summary: Create Profile + description: | + Create a new profile to be used when creating flows with the matching metadata. + + It is not possible to update an existing profile as this would mean it no longer matches flows that have + already been created using it. If a change to a profile is required then a new profile should be created + with the updated information and new flows reference this new profile. + + Attempting to update an existing profiles should return a 400 error. + operationId: POST_profiles-profileId + tags: + - Profiles + requestBody: + content: + application/json: + example: + $ref: examples/profile-put.json + schema: + $ref: schemas/profile.json + required: true + responses: + "201": + description: The flow has been created. + content: + application/json: + example: + $ref: examples/profile-put-200.json + schema: + $ref: schemas/profile.json + "400": + description: Bad request. Invalid profile JSON or profile already exists. + "404": + description: The requested Flow ID in the path is invalid. /service/webhooks: head: summary: List Webhook URLs @@ -672,6 +866,11 @@ paths: description: Filter on flow codec. schema: $ref: '#/components/schemas/mimetype' + - name: profile_id + in: query + description: Filter on profile identifier. + schema: + $ref: '#/components/schemas/uuid' - name: label in: query description: Filter on flows that have the given label. @@ -757,6 +956,11 @@ paths: description: Filter on flow codec. schema: $ref: '#/components/schemas/mimetype' + - name: profile_id + in: query + description: Filter on profile identifier. + schema: + $ref: '#/components/schemas/uuid' - name: label in: query description: Filter on flows that have the given label. @@ -815,7 +1019,7 @@ paths: schema: type: array items: - $ref: "schemas/flow.json" + $ref: "schemas/flow-get.json" "400": description: Bad request. Invalid query options. /flows/{flowId}: @@ -877,7 +1081,7 @@ paths: content: application/json: schema: - $ref: schemas/flow.json + $ref: schemas/flow-get.json examples: video: summary: Video Flow - H.264 Codec @@ -924,7 +1128,17 @@ paths: description: Bad request. Invalid query options. put: summary: Create or Replace Flow - description: Create or replace the flow metadata. + description: | + Create or replace the flow metadata. + + Flows can be created either by directly supplying all the required technical metadata or by referencing + an existing profile in the store. When using a profile the store will combine the supplied flow metadata + with the profile metadata such that on reading the flow a complete set of flow metadata is supplied. It + is up to the store implementation whether this is normalised on the flow creation or read-only. + + When using a profile to create a flow it is not possible to override any specific fields as this would + invalidate the link to the profile. Supplying a profile ID and technical metadata should result in a 400 + validation error operationId: PUT_flows-flowId tags: - Flows @@ -940,8 +1154,12 @@ paths: summary: Multi-essence Flow value: $ref: examples/flow-put-multi.json + profile: + summary: Flow created using a profile + value: + $ref: examples/flow-put-profile.json schema: - $ref: schemas/flow.json + $ref: schemas/flow-put.json required: true responses: "201": @@ -951,7 +1169,7 @@ paths: example: $ref: examples/flow-put-201.json schema: - $ref: schemas/flow.json + $ref: schemas/flow-get.json "204": description: No content. The flow has been updated. "400": @@ -2107,7 +2325,7 @@ webhooks: - flow properties: flow: - $ref: "schemas/flow.json" + $ref: "schemas/flow-get.json" flows/updated: post: security: @@ -2136,7 +2354,7 @@ webhooks: - flow properties: flow: - $ref: "schemas/flow.json" + $ref: "schemas/flow-get.json" flows/deleted: post: security: diff --git a/api/examples/profile-get-200-image.json b/api/examples/profile-get-200-image.json new file mode 100644 index 00000000..f0d2c3e1 --- /dev/null +++ b/api/examples/profile-get-200-image.json @@ -0,0 +1,24 @@ +{ + "id": "ecf7393a-f7ba-4253-9f1a-eebeace5b7b3", + "urn": "urn:x-tam:profile:image_1920_1080_jpg", + "label": "HD JPG still image ", + "description": "1920 x 1080 JPG image", + "created_by": "tams-dev", + "created": "2013-09-09T19:01:00Z", + "tags": { + "_external_id": "1234567890" + }, + "flow_metadata": { + "format": "urn:x-tam:format:image", + "codec": "image/jpeg", + "container": "image/jpeg", + "essence_parameters": { + "frame_width": 1920, + "frame_height": 1080, + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } +} \ No newline at end of file diff --git a/api/examples/profile-get-200-video.json b/api/examples/profile-get-200-video.json new file mode 100644 index 00000000..f5b424e1 --- /dev/null +++ b/api/examples/profile-get-200-video.json @@ -0,0 +1,37 @@ +{ + "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", + "urn": "urn:x-tam:profile:video_50m_1080p50_ts", + "label": "1080p50 TS Video 50Mpbs", + "description": "50Mbps HD video", + "created_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "tags": { + "_ffmpeg_command": "...." + }, + "flow_metadata": { + "format": "urn:x-nmos:format:video", + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "segment_duration": { + "numerator": 6, + "denominator": 1 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 25, + "denominator": 1 + }, + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } +} \ No newline at end of file diff --git a/api/examples/profile-put-200.json b/api/examples/profile-put-200.json new file mode 100644 index 00000000..f5b424e1 --- /dev/null +++ b/api/examples/profile-put-200.json @@ -0,0 +1,37 @@ +{ + "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", + "urn": "urn:x-tam:profile:video_50m_1080p50_ts", + "label": "1080p50 TS Video 50Mpbs", + "description": "50Mbps HD video", + "created_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "tags": { + "_ffmpeg_command": "...." + }, + "flow_metadata": { + "format": "urn:x-nmos:format:video", + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "segment_duration": { + "numerator": 6, + "denominator": 1 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 25, + "denominator": 1 + }, + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } +} \ No newline at end of file diff --git a/api/examples/profile-put.json b/api/examples/profile-put.json new file mode 100644 index 00000000..92b9f4e1 --- /dev/null +++ b/api/examples/profile-put.json @@ -0,0 +1,35 @@ +{ + "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", + "urn": "urn:x-tam:profile:video_50m_1080p50_ts", + "label": "1080p50 TS Video 50Mpbs", + "description": "50Mbps HD video", + "tags": { + "_ffmpeg_command": "...." + }, + "flow_metadata": { + "format": "urn:x-nmos:format:video", + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "segment_duration": { + "numerator": 6, + "denominator": 1 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 25, + "denominator": 1 + }, + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } +} \ No newline at end of file diff --git a/api/examples/profiles-get-200.json b/api/examples/profiles-get-200.json index 65bb18a1..ad9d04fe 100644 --- a/api/examples/profiles-get-200.json +++ b/api/examples/profiles-get-200.json @@ -1,39 +1,63 @@ [ - { - "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", - "urn": "urn:x-tam:profile:video_50m_1920p50_ts", - "label": "profile_label", - "description": "profile_description", - "created_by": "tams-dev", - "created": "2008-05-27T18:51:00Z", - "tags": { - "_ffmpeg_command": "...." + { + "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", + "urn": "urn:x-tam:profile:video_50m_1080p50_ts", + "label": "1080p50 TS Video 50Mpbs", + "description": "50Mbps HD video", + "created_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "tags": { + "_ffmpeg_command": "...." + }, + "flow_metadata": { + "format": "urn:x-nmos:format:video", + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "segment_duration": { + "numerator": 6, + "denominator": 1 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 25, + "denominator": 1 }, - "flow_metadata": { - "format": "urn:x-nmos:format:video", - "codec": "video/h264", - "container": "video/mp2t", - "avg_bit_rate": 2479, - "segment_duration": { - "numerator": 6, - "denominator": 1 - }, - "essence_parameters": { - "frame_rate": { - "numerator": 25, - "denominator": 1 - }, - "frame_width": 1280, - "frame_height": 720, - "bit_depth": 8, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": { - "numerator": 16, - "denominator": 9 - } - } + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 } + } } + }, + { + "id": "ecf7393a-f7ba-4253-9f1a-eebeace5b7b3", + "urn": "urn:x-tam:profile:image_1920_1080_jpg", + "label": "HD JPG still image ", + "description": "1920 x 1080 JPG image", + "created_by": "tams-dev", + "created": "2013-09-09T19:01:00Z", + "tags": { + "_external_id": "1234567890" + }, + "flow_metadata": { + "format": "urn:x-tam:format:image", + "codec": "image/jpeg", + "container": "image/jpeg", + "essence_parameters": { + "frame_width": 1920, + "frame_height": 1080, + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + } + } + } ] \ No newline at end of file diff --git a/api/schemas/flow-audio.json b/api/schemas/flow-audio.json index 80d5ba09..837290b6 100644 --- a/api/schemas/flow-audio.json +++ b/api/schemas/flow-audio.json @@ -4,7 +4,7 @@ "title": "Audio Flow", "allOf": [ { - "$ref": "flow-core.json" + "$ref": "flow-technical.json" }, { "type": "object", diff --git a/api/schemas/flow-core.json b/api/schemas/flow-common.json similarity index 64% rename from api/schemas/flow-core.json rename to api/schemas/flow-common.json index d5b73aff..4f975600 100644 --- a/api/schemas/flow-core.json +++ b/api/schemas/flow-common.json @@ -1,6 +1,6 @@ { "type": "object", - "description": "Describes a Flow (common properties to all Flows, imported by type-specific specifications)", + "description": "Describes the core fields of a Flow (common properties to all Flows, imported by flow-get and flow-put specifications)", "title": "Flow Core", "required": [ "id", @@ -64,46 +64,7 @@ "description": "If set to 'true', implementations SHOULD reject client requests to update Flow metadata (other than the read_only property), Flow Segments and media objects", "type": "boolean" }, - "codec": { - "description": "A MIME type identification of the (lossy or lossless) coding used for the flow content.", - "type": "string", - "pattern": "^[^\\s\/]+/[^\\s\/]+$" - }, - "container": { - "description": "The container MIME type for flow segments.", - "type": "string", - "pattern": "^[^\\s\/]+/[^\\s\/]+$" - }, - "avg_bit_rate": { - "description": "The average bit rate of the flow segments in 1000 bits/second. A precise definition can be found in the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote.", - "type": "integer", - "minimum": 0 - }, - "max_bit_rate": { - "description": "The maximum bit rate of the flow segments in 1000 bits/second. A precise definition can be found in the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote.", - "type": "integer", - "minimum": 0 - }, - "segment_duration": { - "description": "The target flow segment duration in seconds. The duration for each segment may vary around this target value. See also the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote for how this property can be used to calculate buffer sizes.", - "type": "object", - "required": [ - "numerator" - ], - "properties": { - "numerator": { - "description": "numerator", - "type": "integer", - "exclusiveMinimum": 0 - }, - "denominator": { - "description": "denominator", - "type": "integer", - "default": 1, - "exclusiveMinimum": 0 - } - } - }, + "timerange": { "description": "The timerange of samples available in the flow, as described by the [TimeRange](../schemas/timerange#top) type", "$ref": "timerange.json" @@ -119,10 +80,6 @@ "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" } - }, - "container_mapping": { - "description": "Describes the mapping of the Flow essence from the this Flow's container", - "$ref": "container-mapping.json" } } } diff --git a/api/schemas/flow-data.json b/api/schemas/flow-data.json index c82c50c2..b700f751 100644 --- a/api/schemas/flow-data.json +++ b/api/schemas/flow-data.json @@ -4,7 +4,7 @@ "title": "Data Flow", "allOf": [ { - "$ref": "flow-core.json" + "$ref": "flow-technical.json" }, { "type": "object", diff --git a/api/schemas/flow-get.json b/api/schemas/flow-get.json new file mode 100644 index 00000000..fb8ef4f0 --- /dev/null +++ b/api/schemas/flow-get.json @@ -0,0 +1,26 @@ +{ + "type": "object", + "description": "Describes a Flow", + "title": "Flow", + "properties": { + "profile_id": { + "description": "Profile identifier that was used to create the flow.", + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + } + }, + "allOf": [ + { + "$ref": "flow-common.json" + }, + { + "oneOf": [ + { "$ref": "flow-video.json" }, + { "$ref": "flow-audio.json" }, + { "$ref": "flow-image.json" }, + { "$ref": "flow-data.json" }, + { "$ref": "flow-multi.json" } + ] + } + ] +} \ No newline at end of file diff --git a/api/schemas/flow-image.json b/api/schemas/flow-image.json index 0d2f7e47..fe5611ca 100644 --- a/api/schemas/flow-image.json +++ b/api/schemas/flow-image.json @@ -4,7 +4,7 @@ "title": "Image Flow", "allOf": [ { - "$ref": "flow-core.json" + "$ref": "flow-technical.json" }, { "type": "object", diff --git a/api/schemas/flow-multi.json b/api/schemas/flow-multi.json index 9e218f9e..10e537fd 100644 --- a/api/schemas/flow-multi.json +++ b/api/schemas/flow-multi.json @@ -2,24 +2,16 @@ "type": "object", "description": "Describes a multi-essence Flow", "title": "Multi-essence Flow", - "allOf": [ - { - "$ref": "flow-core.json" - }, - { - "type": "object", - "required": [ - "format" - ], - "properties": { - "format": { - "description": "The primary content type URN for the flow.", - "type": "string", - "enum": [ - "urn:x-nmos:format:multi" - ] - } - } + "required": [ + "format" + ], + "properties": { + "format": { + "description": "The primary content type URN for the flow.", + "type": "string", + "enum": [ + "urn:x-nmos:format:multi" + ] } - ] -} \ No newline at end of file + } +} diff --git a/api/schemas/flow-put.json b/api/schemas/flow-put.json new file mode 100644 index 00000000..fc892acf --- /dev/null +++ b/api/schemas/flow-put.json @@ -0,0 +1,37 @@ +{ + "type": "object", + "description": "Describes a Flow", + "title": "Flow", + "allOf": [ + { + "$ref": "flow-common.json" + }, + { + "oneOf": [ + { + "type": "object", + "required": [ + "profile_id" + ], + "properties": { + "profile_id": { + "description": "Profile identifier that was used to create the flow. When supplying a profile_id no technical metadata should also be provided. Doing so will result in a 400 validation error", + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + } + } + }, + { + "oneOf": [ + { "$ref": "flow-video.json" }, + { "$ref": "flow-audio.json" }, + { "$ref": "flow-image.json" }, + { "$ref": "flow-data.json" }, + { "$ref": "flow-multi.json" } + ] + } + ] + } + ], + +} \ No newline at end of file diff --git a/api/schemas/flow-technical.json b/api/schemas/flow-technical.json new file mode 100644 index 00000000..06cd682f --- /dev/null +++ b/api/schemas/flow-technical.json @@ -0,0 +1,53 @@ +{ + "type": "object", + "description": "Describes the technical characteristics of a Flow (common properties to all Flows, imported by type-specific specifications)", + "title": "Flow Core", + "properties": { + + "codec": { + "description": "A MIME type identification of the (lossy or lossless) coding used for the flow content.", + "type": "string", + "pattern": "^[^\\s\/]+/[^\\s\/]+$" + }, + "container": { + "description": "The container MIME type for flow segments.", + "type": "string", + "pattern": "^[^\\s\/]+/[^\\s\/]+$" + }, + "avg_bit_rate": { + "description": "The average bit rate of the flow segments in 1000 bits/second. A precise definition can be found in the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote.", + "type": "integer", + "minimum": 0 + }, + "max_bit_rate": { + "description": "The maximum bit rate of the flow segments in 1000 bits/second. A precise definition can be found in the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote.", + "type": "integer", + "minimum": 0 + }, + "segment_duration": { + "description": "The target flow segment duration in seconds. The duration for each segment may vary around this target value. See also the [Setting Flow Bit Rate Properties](https://github.com/bbc/tams/blob/main/docs/appnotes/0013-setting-flow-bit-rate-properties.md) AppNote for how this property can be used to calculate buffer sizes.", + "type": "object", + "required": [ + "numerator" + ], + "properties": { + "numerator": { + "description": "numerator", + "type": "integer", + "exclusiveMinimum": 0 + }, + "denominator": { + "description": "denominator", + "type": "integer", + "default": 1, + "exclusiveMinimum": 0 + } + } + }, + + "container_mapping": { + "description": "Describes the mapping of the Flow essence from the this Flow's container", + "$ref": "container-mapping.json" + } + } +} diff --git a/api/schemas/flow-video.json b/api/schemas/flow-video.json index 07ae8933..7af281ae 100644 --- a/api/schemas/flow-video.json +++ b/api/schemas/flow-video.json @@ -4,7 +4,7 @@ "title": "Video Flow", "allOf": [ { - "$ref": "flow-core.json" + "$ref": "flow-technical.json" }, { "type": "object", diff --git a/api/schemas/flow.json b/api/schemas/flow.json deleted file mode 100644 index 778191b6..00000000 --- a/api/schemas/flow.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "description": "Describes a Flow", - "title": "Flow", - "oneOf": [ - { "$ref": "flow-video.json" }, - { "$ref": "flow-audio.json" }, - { "$ref": "flow-image.json" }, - { "$ref": "flow-data.json" }, - { "$ref": "flow-multi.json" } - ] -} \ No newline at end of file diff --git a/api/schemas/profile.json b/api/schemas/profile.json new file mode 100644 index 00000000..03bcc350 --- /dev/null +++ b/api/schemas/profile.json @@ -0,0 +1,53 @@ +{ + "type": "object", + "description": "Describes a Profile", + "title": "Profile", + "required": [ + "id", + "flow_metadata" + ], + "properties": { + "id": { + "description": "Profile identifier.", + "type": "string", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + }, + "urn": { + "description": "Namespaced identifier to the profile. Centrally managed profiles will be prefixed with 'urn:x-tam:profile:'. This MUST not be used for locally created profiles", + "type": "string", + "pattern": "^urn:[A-Za-z0-9][A-Za-z0-9-]{0,31}:profile:[a-z0-9()+,\\-.:=@;$_!*'%?#]*[a-z0-9+=@$]" + }, + "label": { + "description": "Freeform string label for the profile", + "type": "string" + }, + "description": { + "description": "Freeform text describing the profile", + "type": "string" + }, + "created_by": { + "description": "A string identifier for the entity that created the profile. Implementations SHOULD set suitable default values for `created_by` based on the principal accessing the system, and MAY permit clients to edit the value, subject to suitable permissions-based limitations.", + "type": "string" + }, + "created": { + "description": "The date-time the profile was created in a given context, e.g. in the store. Implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "tags": { + "$ref": "tags.json" + }, + + "flow_metadata": { + "description": "The technical characteristics of the profile. This section will be mapped directly to all flows created using this profile.", + "type": "object", + "oneOf": [ + { "$ref": "flow-video.json" }, + { "$ref": "flow-audio.json" }, + { "$ref": "flow-image.json" }, + { "$ref": "flow-data.json" }, + { "$ref": "flow-multi.json" } + ] + } + } +} \ No newline at end of file From d3a8c229883ba2616311dd53cb2a9ad1782c7290 Mon Sep 17 00:00:00 2001 From: johnbilt <164537346+johnbilt@users.noreply.github.com> Date: Fri, 15 Aug 2025 13:48:13 +0100 Subject: [PATCH 08/22] Update docs/appnotes/00xx-using-flow-profiles.md Co-authored-by: Sam Mesterton-Gibbons --- docs/appnotes/00xx-using-flow-profiles.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/00xx-using-flow-profiles.md index 110a37d1..a8592c15 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/00xx-using-flow-profiles.md @@ -13,7 +13,7 @@ This document describes how flow profiles can be used within the TAMS API to sim Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. Typically this could include a target format for the high quality media and standardised formats for proxy media and images. -These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. +These formats are typically refered to as House formats and do not preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier. House formats define one or more common formats for all the systems to utilise. From 17e44f3771d8de70941f8a1ad1969316c03df30d Mon Sep 17 00:00:00 2001 From: johnbilt <164537346+johnbilt@users.noreply.github.com> Date: Fri, 15 Aug 2025 14:03:42 +0100 Subject: [PATCH 09/22] Update api/schemas/flow-put.json Co-authored-by: Sam Mesterton-Gibbons --- api/schemas/flow-put.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/schemas/flow-put.json b/api/schemas/flow-put.json index fc892acf..10055fc1 100644 --- a/api/schemas/flow-put.json +++ b/api/schemas/flow-put.json @@ -32,6 +32,5 @@ } ] } - ], - + ] } \ No newline at end of file From 3d4f1f7f100ff24375d8d5c8eb7394d9d58fcbf3 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 18 Nov 2025 13:11:43 +0000 Subject: [PATCH 10/22] Various updates from feedback --- api/TimeAddressableMediaStore.yaml | 20 ++++------ api/schemas/flow-common.json | 4 +- api/schemas/flow-put.json | 18 ++++----- api/schemas/flow-technical.json | 4 +- api/schemas/profile.json | 3 +- docs/README.md | 1 + ...rofiles.md => 0018-using-flow-profiles.md} | 38 ++++++------------- 7 files changed, 32 insertions(+), 56 deletions(-) rename docs/appnotes/{00xx-using-flow-profiles.md => 0018-using-flow-profiles.md} (80%) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index 328fba32..320cf3d2 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -154,11 +154,6 @@ paths: tags: - Profiles parameters: - - name: profile_id - in: query - description: Filter on source identifier. - schema: - $ref: '#/components/schemas/uuid' - name: urn in: query description: Filter on profile that have the given urn. @@ -210,11 +205,6 @@ paths: tags: - Profiles parameters: - - name: profile_id - in: query - description: Filter on source identifier. - schema: - $ref: '#/components/schemas/uuid' - name: urn in: query description: Filter on profile that have the given urn. @@ -316,6 +306,10 @@ paths: with the updated information and new flows reference this new profile. Attempting to update an existing profiles should return a 400 error. + + Tags can be created at the profile level to hold information about the profile itself. These do not form + part of the flow that is created. These are tag/value format and could be used for tasks such as version + tracking or holding encoding parameters. operationId: POST_profiles-profileId tags: - Profiles @@ -1132,11 +1126,11 @@ paths: Create or replace the flow metadata. Flows can be created either by directly supplying all the required technical metadata or by referencing - an existing profile in the store. When using a profile the store will combine the supplied flow metadata - with the profile metadata such that on reading the flow a complete set of flow metadata is supplied. It + an existing profile in the store. When using a profile, the store will use the technical details (format, + codec, essence_parameters etc.) from that profile, along with the metadata provided. It is up to the store implementation whether this is normalised on the flow creation or read-only. - When using a profile to create a flow it is not possible to override any specific fields as this would + When creating a flow using a profile it is not possible to override any specific fields as this would invalidate the link to the profile. Supplying a profile ID and technical metadata should result in a 400 validation error operationId: PUT_flows-flowId diff --git a/api/schemas/flow-common.json b/api/schemas/flow-common.json index 4f975600..4cc057d9 100644 --- a/api/schemas/flow-common.json +++ b/api/schemas/flow-common.json @@ -1,7 +1,7 @@ { "type": "object", - "description": "Describes the core fields of a Flow (common properties to all Flows, imported by flow-get and flow-put specifications)", - "title": "Flow Core", + "description": "Describes the the core fields of a Flow (common properties to all Flows, imported by flow-get and flow-put specifications)", + "title": "Flow Common", "required": [ "id", "source_id" diff --git a/api/schemas/flow-put.json b/api/schemas/flow-put.json index fc892acf..dfc3266f 100644 --- a/api/schemas/flow-put.json +++ b/api/schemas/flow-put.json @@ -10,6 +10,7 @@ "oneOf": [ { "type": "object", + "title": "Flow Profile", "required": [ "profile_id" ], @@ -21,17 +22,12 @@ } } }, - { - "oneOf": [ - { "$ref": "flow-video.json" }, - { "$ref": "flow-audio.json" }, - { "$ref": "flow-image.json" }, - { "$ref": "flow-data.json" }, - { "$ref": "flow-multi.json" } - ] - } + { "$ref": "flow-video.json" }, + { "$ref": "flow-audio.json" }, + { "$ref": "flow-image.json" }, + { "$ref": "flow-data.json" }, + { "$ref": "flow-multi.json" } ] } - ], - + ] } \ No newline at end of file diff --git a/api/schemas/flow-technical.json b/api/schemas/flow-technical.json index 06cd682f..31daa8d4 100644 --- a/api/schemas/flow-technical.json +++ b/api/schemas/flow-technical.json @@ -1,7 +1,7 @@ { "type": "object", - "description": "Describes the technical characteristics of a Flow (common properties to all Flows, imported by type-specific specifications)", - "title": "Flow Core", + "description": "Describes the technical characteristics of a Flow (imported by type-specific specifications or as part of a profile)", + "title": "Flow Technical", "properties": { "codec": { diff --git a/api/schemas/profile.json b/api/schemas/profile.json index 03bcc350..420e3588 100644 --- a/api/schemas/profile.json +++ b/api/schemas/profile.json @@ -45,8 +45,7 @@ { "$ref": "flow-video.json" }, { "$ref": "flow-audio.json" }, { "$ref": "flow-image.json" }, - { "$ref": "flow-data.json" }, - { "$ref": "flow-multi.json" } + { "$ref": "flow-data.json" } ] } } diff --git a/docs/README.md b/docs/README.md index 6a2a750a..29ded9de 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,3 +69,4 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0014](./appnotes/0014-referencing-tams-content-in-other-systems.md) | Referencing TAMS content in other systems | | [0015](./appnotes/0015-using-tams-in-opentimelineio.md) | Using TAMS in OpenTimelineIO | | [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems | +| [0018](./appnotes/0018-using-flow-profiles.md) | Using flow profiles | \ No newline at end of file diff --git a/docs/appnotes/00xx-using-flow-profiles.md b/docs/appnotes/0018-using-flow-profiles.md similarity index 80% rename from docs/appnotes/00xx-using-flow-profiles.md rename to docs/appnotes/0018-using-flow-profiles.md index 110a37d1..51b37c50 100644 --- a/docs/appnotes/00xx-using-flow-profiles.md +++ b/docs/appnotes/0018-using-flow-profiles.md @@ -1,8 +1,8 @@ -# 00xx: DRAFT: Using Flow Profiles +# 0018: Using Flow Profiles ## Abstract -The TAMS API is deliberately agnostic to the format of the media which it is managing, to allow for future compatibility with new formats without needing to change the API specification. +The TAMS API is deliberately agnostic to the format of the media which it is managing, to allow for future compatibility with new formats without needing to change the API specification. This provides challenges for interoperability and workflows such as edit by reference where standard media formats are required across multiple sources. This document describes how flow profiles can be used within the TAMS API to simplify workflows while maintaining the flexibility of the core API. @@ -11,7 +11,7 @@ This document describes how flow profiles can be used within the TAMS API to sim ### House formats -Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. +Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. Typically this could include a target format for the high quality media and standardised formats for proxy media and images. These formats are typically refered to as House formats and do no preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. @@ -22,7 +22,7 @@ House formats define one or more common formats for all the systems to utilise. For edit by reference workflows there is a need both to create new sources and flows for the new item and also combine the segments together to create the new edit. -If the source content is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. +If the content to be referenced is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. Currently the TAMS API does not provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. The more sources involved in this process, the harder this becomes. @@ -37,10 +37,14 @@ The TAMS profile model is split into a number of stages: ### Profiles endpoint -It is possible to create, view, edit and delete profiles via the dedicated API calls under the TAMS service end point (/services/profiles). +It is possible to create and view profiles via the dedicated API calls under the TAMS service end point (/services/profiles). These profiles hold all the technical parameters required to create a flow in a single location. A system looking to ingest standardised content into TAMS would create content matching one or more profiles as defined in the endpoint. +A profile should be treated as immutable, so once created it cannot be updated. +Updating a profile would cause mismatches with flows which have been already created using that profile and so breaks the model for profiles. +To update a profile a new one with a new ID should be created. + The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS profile metadata @@ -60,7 +64,8 @@ This differentiates them from the flows that have been created with the technica ### Query flows using a profile -The get flows endpoint has the ability to query for flows with a given profile. When combined with other query parameters such as source id then this means it is easy to start matching content formats. +The get flows endpoint has the ability to query for flows with a given profile. +When combined with other query parameters such as source id then this means it is easy to start matching content formats. For example on an edit by reference workflow it would be possible to read the profile endpoint for the recommended profiles that content should have. This then simplifies the process of creating the required flows and sources for the new content item. @@ -73,23 +78,4 @@ To aid interoperabity a set of recommended profiles is hosted as part of the API These are profiles which have been tested and used in real workflows and are recommended as a starting point for implementors building a new store. It is recommended that tools which write to the TAMS API try and support as many of the recommended profiles of their target content types as possible. -Additional recommened profiles will be added to the repository as new use cases are identified or new media formats added. - -## Suggested metadata fields in the profile end point - -- Identifier (format to be decided) -- Type (video/audio/image/data) -- Label -- Description -- Version (recommended to increment when changing) -- Created/Created by -- Modified/Modified by -- Tags -- Technical characteristics (first level flow properties such as codec, wrapper, target chunk length etc, plus essence parameters) -- Preferred (needs thinking about how to indicate this is the prefered high res or prefered proxy etc) - - - - - - +Additional recommened profiles will be added to the repository as new use cases are identified or new media formats added. \ No newline at end of file From f7899bb5ef10c14ef1f6586ace3492ca6771de2b Mon Sep 17 00:00:00 2001 From: johnbilt <164537346+johnbilt@users.noreply.github.com> Date: Tue, 18 Nov 2025 14:32:43 +0000 Subject: [PATCH 11/22] Update api/TimeAddressableMediaStore.yaml Co-authored-by: Georgina Shippey <9370167+GeorginaShippey@users.noreply.github.com> --- api/TimeAddressableMediaStore.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index 320cf3d2..fc72c086 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -333,7 +333,7 @@ paths: "400": description: Bad request. Invalid profile JSON or profile already exists. "404": - description: The requested Flow ID in the path is invalid. + description: The requested profile ID in the path is invalid. /service/webhooks: head: summary: List Webhook URLs From 4211448c8dd7d6df7c72a5df89a3360991fff856 Mon Sep 17 00:00:00 2001 From: johnbilt <164537346+johnbilt@users.noreply.github.com> Date: Tue, 18 Nov 2025 14:32:56 +0000 Subject: [PATCH 12/22] Update api/TimeAddressableMediaStore.yaml Co-authored-by: Georgina Shippey <9370167+GeorginaShippey@users.noreply.github.com> --- api/TimeAddressableMediaStore.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index fc72c086..97b28326 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -295,7 +295,7 @@ paths: value: $ref: examples/profile-get-200-image.json "404": - description: The requested flow does not exist. + description: The requested profile does not exist. post: summary: Create Profile description: | From d43ee0aa13afae2efc11f5e1ac3777486850b892 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 18 Nov 2025 14:51:29 +0000 Subject: [PATCH 13/22] Correct example file name --- api/TimeAddressableMediaStore.yaml | 2 +- api/examples/{profile-put-200.json => profile-post-201.json} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename api/examples/{profile-put-200.json => profile-post-201.json} (100%) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index 320cf3d2..cf4a4efe 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -327,7 +327,7 @@ paths: content: application/json: example: - $ref: examples/profile-put-200.json + $ref: examples/profile-post-201.json schema: $ref: schemas/profile.json "400": diff --git a/api/examples/profile-put-200.json b/api/examples/profile-post-201.json similarity index 100% rename from api/examples/profile-put-200.json rename to api/examples/profile-post-201.json From e5655fed7cf93b9c4b35e9d0339e103942273090 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 18 Nov 2025 14:52:07 +0000 Subject: [PATCH 14/22] Profile query clarification --- docs/appnotes/0018-using-flow-profiles.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/appnotes/0018-using-flow-profiles.md b/docs/appnotes/0018-using-flow-profiles.md index b2375c31..b3ebedaf 100644 --- a/docs/appnotes/0018-using-flow-profiles.md +++ b/docs/appnotes/0018-using-flow-profiles.md @@ -72,6 +72,8 @@ This then simplifies the process of creating the required flows and sources for The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. If the source content has additional non standard flows then these could be ignored. +From a flow created from a profile, it is possible to query via both profile ID and also the individual parameter of the flow that have been inheritied from the profile. + ## Recommended TAMS profiles To aid interoperabity a set of recommended profiles is hosted as part of the API specification Github respository. From 49ee246a38253ab33ab84d1f84ea2dd80861b14d Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 18 Nov 2025 15:04:24 +0000 Subject: [PATCH 15/22] Remove profile urn and add wording on multi-store workflows --- api/examples/profile-get-200-image.json | 1 - api/examples/profile-get-200-video.json | 1 - api/examples/profile-post-201.json | 1 - api/examples/profile-put.json | 1 - api/examples/profiles-get-200.json | 1 - api/schemas/profile.json | 5 ----- docs/appnotes/0018-using-flow-profiles.md | 17 ++++++++++++----- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/api/examples/profile-get-200-image.json b/api/examples/profile-get-200-image.json index f0d2c3e1..ec0d8a35 100644 --- a/api/examples/profile-get-200-image.json +++ b/api/examples/profile-get-200-image.json @@ -1,6 +1,5 @@ { "id": "ecf7393a-f7ba-4253-9f1a-eebeace5b7b3", - "urn": "urn:x-tam:profile:image_1920_1080_jpg", "label": "HD JPG still image ", "description": "1920 x 1080 JPG image", "created_by": "tams-dev", diff --git a/api/examples/profile-get-200-video.json b/api/examples/profile-get-200-video.json index f5b424e1..b504cf37 100644 --- a/api/examples/profile-get-200-video.json +++ b/api/examples/profile-get-200-video.json @@ -1,6 +1,5 @@ { "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", - "urn": "urn:x-tam:profile:video_50m_1080p50_ts", "label": "1080p50 TS Video 50Mpbs", "description": "50Mbps HD video", "created_by": "tams-dev", diff --git a/api/examples/profile-post-201.json b/api/examples/profile-post-201.json index f5b424e1..b504cf37 100644 --- a/api/examples/profile-post-201.json +++ b/api/examples/profile-post-201.json @@ -1,6 +1,5 @@ { "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", - "urn": "urn:x-tam:profile:video_50m_1080p50_ts", "label": "1080p50 TS Video 50Mpbs", "description": "50Mbps HD video", "created_by": "tams-dev", diff --git a/api/examples/profile-put.json b/api/examples/profile-put.json index 92b9f4e1..2b97fe17 100644 --- a/api/examples/profile-put.json +++ b/api/examples/profile-put.json @@ -1,6 +1,5 @@ { "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", - "urn": "urn:x-tam:profile:video_50m_1080p50_ts", "label": "1080p50 TS Video 50Mpbs", "description": "50Mbps HD video", "tags": { diff --git a/api/examples/profiles-get-200.json b/api/examples/profiles-get-200.json index ad9d04fe..dd873858 100644 --- a/api/examples/profiles-get-200.json +++ b/api/examples/profiles-get-200.json @@ -1,7 +1,6 @@ [ { "id": "329b98d6-adeb-418c-8eaf-eca14edc1706", - "urn": "urn:x-tam:profile:video_50m_1080p50_ts", "label": "1080p50 TS Video 50Mpbs", "description": "50Mbps HD video", "created_by": "tams-dev", diff --git a/api/schemas/profile.json b/api/schemas/profile.json index 420e3588..2a95c7a9 100644 --- a/api/schemas/profile.json +++ b/api/schemas/profile.json @@ -12,11 +12,6 @@ "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" }, - "urn": { - "description": "Namespaced identifier to the profile. Centrally managed profiles will be prefixed with 'urn:x-tam:profile:'. This MUST not be used for locally created profiles", - "type": "string", - "pattern": "^urn:[A-Za-z0-9][A-Za-z0-9-]{0,31}:profile:[a-z0-9()+,\\-.:=@;$_!*'%?#]*[a-z0-9+=@$]" - }, "label": { "description": "Freeform string label for the profile", "type": "string" diff --git a/docs/appnotes/0018-using-flow-profiles.md b/docs/appnotes/0018-using-flow-profiles.md index b3ebedaf..4dbd4ad8 100644 --- a/docs/appnotes/0018-using-flow-profiles.md +++ b/docs/appnotes/0018-using-flow-profiles.md @@ -74,10 +74,17 @@ If the source content has additional non standard flows then these could be igno From a flow created from a profile, it is possible to query via both profile ID and also the individual parameter of the flow that have been inheritied from the profile. -## Recommended TAMS profiles +## Multi-store working with profiles -To aid interoperabity a set of recommended profiles is hosted as part of the API specification Github respository. -These are profiles which have been tested and used in real workflows and are recommended as a starting point for implementors building a new store. -It is recommended that tools which write to the TAMS API try and support as many of the recommended profiles of their target content types as possible. +The UUID of a profile is assumed to be globally unique. +This is the same model as for flow, source and object ID's which should be preserved when replicating content. -Additional recommened profiles will be added to the repository as new use cases are identified or new media formats added. \ No newline at end of file +For workflows where replication of the same content formats are happening on a regular basis then it is recommended that the same profile is loaded into both stores using the same UUID. +This will mean than when flows are replicated between the stores then the profile identifier will continue to link to the metadata. + +If the profile does not existing within the destination store then the profile ID should continue to be preserved. +This will continue to allow the matching of content within the store by profile ID, plus the profile can be added later and will link to the existing content. + +For workflows including more than two orgnaisations it is recommended that one organisation takes responsibility for owning and publishing the profiles. +These profiles can then be loaded into the destination stores. +The organisation could be a single company or could be an industry body. From 7b51eb81ebc7dc8a5515d77e419050a796c92245 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 18 Nov 2025 15:34:12 +0000 Subject: [PATCH 16/22] Updated app note number --- docs/README.md | 2 +- ...{0018-using-flow-profiles.md => 0019-using-flow-profiles.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/appnotes/{0018-using-flow-profiles.md => 0019-using-flow-profiles.md} (99%) diff --git a/docs/README.md b/docs/README.md index 29ded9de..8fbb71a4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,4 +69,4 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0014](./appnotes/0014-referencing-tams-content-in-other-systems.md) | Referencing TAMS content in other systems | | [0015](./appnotes/0015-using-tams-in-opentimelineio.md) | Using TAMS in OpenTimelineIO | | [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems | -| [0018](./appnotes/0018-using-flow-profiles.md) | Using flow profiles | \ No newline at end of file +| [0019](./appnotes/0019-using-flow-profiles.md) | Using flow profiles | \ No newline at end of file diff --git a/docs/appnotes/0018-using-flow-profiles.md b/docs/appnotes/0019-using-flow-profiles.md similarity index 99% rename from docs/appnotes/0018-using-flow-profiles.md rename to docs/appnotes/0019-using-flow-profiles.md index 4dbd4ad8..f9f65b7c 100644 --- a/docs/appnotes/0018-using-flow-profiles.md +++ b/docs/appnotes/0019-using-flow-profiles.md @@ -1,4 +1,4 @@ -# 0018: Using Flow Profiles +# 0019: Using Flow Profiles ## Abstract From bb1dba0bb57294202645c68bae2f0fa8a61a4c50 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Thu, 20 Nov 2025 11:42:10 +0000 Subject: [PATCH 17/22] Formatting and consistency with recent changes --- api/TimeAddressableMediaStore.yaml | 58 +++++++++++++----------------- api/schemas/profile.json | 42 +++++++++++++--------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index c2c63059..007eaacb 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -149,29 +149,24 @@ paths: /service/profiles: head: summary: Profile Backend Information - description: Return profile backends path headers + description: Return Profile headers operationId: HEAD_profiles tags: - Profiles parameters: - - name: urn - in: query - description: Filter on profile that have the given urn. - schema: - type: string - name: format in: query - description: Filter on profile format. + description: Filter on Profile format. schema: $ref: '#/components/schemas/contentformat' - name: codec in: query - description: Filter on profile codec. + description: Filter on Profile codec. schema: $ref: '#/components/schemas/mimetype' - name: label in: query - description: Filter on profiles that have the given label. + description: Filter on Profiles that have the given label. schema: type: string - $ref: '#/components/parameters/trait_resource_paged_key' @@ -200,29 +195,24 @@ paths: description: Bad request. Invalid query options. get: summary: Profile Backend Information - description: List of profiles supported by the store instance for use when creating flows. + description: List of Profiles supported by the store instance for use when creating flows. operationId: GET_profiles tags: - Profiles parameters: - - name: urn - in: query - description: Filter on profile that have the given urn. - schema: - type: string - name: format in: query - description: Filter on profile format. + description: Filter on Profile format. schema: $ref: '#/components/schemas/contentformat' - name: codec in: query - description: Filter on profile codec. + description: Filter on Profile codec. schema: $ref: '#/components/schemas/mimetype' - name: label in: query - description: Filter on profiles that have the given label. + description: Filter on Profiles that have the given label. schema: type: string - $ref: '#/components/parameters/trait_resource_paged_key' @@ -259,11 +249,11 @@ paths: in: path required: true schema: - $ref: '#/components/schemas/uuid' - description: The profile identifier. + $ref: 'schemas/uuid.json' + description: The Profile identifier. head: summary: Profile Details - description: Return profile path headers + description: Return Profile path headers operationId: HEAD_profiles-profileId tags: - Profiles @@ -274,7 +264,7 @@ paths: $ref: '#/components/responses/trait_resource_info_head_404' get: summary: Profile Details - description: Returns profile metadata. + description: Returns Profile metadata. operationId: GET_profiles-profileId tags: - Profiles @@ -299,17 +289,16 @@ paths: post: summary: Create Profile description: | - Create a new profile to be used when creating flows with the matching metadata. + Create a new Profile to be used when creating flows with the matching metadata. - It is not possible to update an existing profile as this would mean it no longer matches flows that have - already been created using it. If a change to a profile is required then a new profile should be created - with the updated information and new flows reference this new profile. + It is not possible to update an existing Profile as this would mean it no longer matches flows that have already been created using it. + If a change to a Profile is required then a new Profile should be created with the updated information and new flows reference this new Profile. Attempting to update an existing profiles should return a 400 error. - Tags can be created at the profile level to hold information about the profile itself. These do not form - part of the flow that is created. These are tag/value format and could be used for tasks such as version - tracking or holding encoding parameters. + Tags can be created at the Profile level to hold information about the Profile itself. + These do not form part of the flow that is created. + These are tag/value format and could be used for tasks such as version tracking or holding encoding parameters. operationId: POST_profiles-profileId tags: - Profiles @@ -331,9 +320,9 @@ paths: schema: $ref: schemas/profile.json "400": - description: Bad request. Invalid profile JSON or profile already exists. + description: Bad request. Invalid Profile JSON or Profile already exists. "404": - description: The requested profile ID in the path is invalid. + description: The requested Profile ID in the path is invalid. /service/webhooks: head: summary: List Webhook URLs @@ -1305,11 +1294,12 @@ paths: It may also be possible for service implementations to detect some instances where multiple Flows should not be considered of the same Source, such as audio Flows with different numbers of tracks. Further guidance on when Flows/Sources may be considered the same/different may be found in the [Practical Guidance for Media](https://specs.amwa.tv/ms-04/releases/v1.0.0/docs/3.0._Practical_Guidance_for_Media.html) section of AMWA MS-04. - Flows can be created either by directly supplying all the required technical metadata or by referencing an existing Profile in the store. When using a Profile, the store will use the technical details (format, codec, essence_parameters etc.) from that profile, along with the metadata provided. + Flows can be created either by directly supplying all the required technical metadata or by referencing an existing Profile in the store. + When using a Profile, the store will use the technical details (format, codec, essence_parameters etc.) from that profile, along with the metadata provided. It is up to the store implementation whether this is normalised on the flow creation or read-only. - When creating a flow using a profile it is not possible to override any specific fields as this would invalidate the link to the profile. - Supplying a profile ID and technical metadata should result in a 400 validation error + When creating a flow using a Profile it is not possible to override any specific fields as this would invalidate the link to the Profile. + Supplying a Profile ID and technical metadata should result in a 400 validation error operationId: PUT_flows-flowId tags: - Flows diff --git a/api/schemas/profile.json b/api/schemas/profile.json index 2a95c7a9..198c61a9 100644 --- a/api/schemas/profile.json +++ b/api/schemas/profile.json @@ -2,41 +2,51 @@ "type": "object", "description": "Describes a Profile", "title": "Profile", - "required": [ + "required": + [ "id", "flow_metadata" ], - "properties": { - "id": { + "properties": + { + "id": + { "description": "Profile identifier.", "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" }, - "label": { - "description": "Freeform string label for the profile", + "label": + { + "description": "Freeform string label for the Profile", "type": "string" }, - "description": { - "description": "Freeform text describing the profile", + "description": + { + "description": "Freeform text describing the Profile", "type": "string" }, - "created_by": { - "description": "A string identifier for the entity that created the profile. Implementations SHOULD set suitable default values for `created_by` based on the principal accessing the system, and MAY permit clients to edit the value, subject to suitable permissions-based limitations.", + "created_by": + { + "description": "A string identifier for the entity that created the Profile. Implementations SHOULD set suitable default values for `created_by` based on the principal accessing the system, and MAY permit clients to edit the value, subject to suitable permissions-based limitations.", "type": "string" }, - "created": { - "description": "The date-time the profile was created in a given context, e.g. in the store. Implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "created": + { + "description": "The date-time the Profile was created in a given context, e.g. in the store. Implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", "type": "string", "format": "date-time" }, - "tags": { + "tags": + { + "description": "Key value is a freeform string. As Profiles are considered immutable then this also applies to tags which cannot be updated after a Profile has been created", "$ref": "tags.json" }, - - "flow_metadata": { - "description": "The technical characteristics of the profile. This section will be mapped directly to all flows created using this profile.", + "flow_metadata": + { + "description": "The technical characteristics of the Profile. This section will be mapped directly to all flows created using this Profile.", "type": "object", - "oneOf": [ + "oneOf": + [ { "$ref": "flow-video.json" }, { "$ref": "flow-audio.json" }, { "$ref": "flow-image.json" }, From dc4992d0e9e6675f9f8f68b377ee05a150ef2022 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Thu, 20 Nov 2025 16:47:18 +0000 Subject: [PATCH 18/22] Fix lint issue --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index c6cce5c6..03a14eea 100644 --- a/docs/README.md +++ b/docs/README.md @@ -103,4 +103,4 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0014](./appnotes/0014-referencing-tams-content-in-other-systems.md) | Referencing TAMS content in other systems | | [0015](./appnotes/0015-using-tams-in-opentimelineio.md) | Using TAMS in OpenTimelineIO | | [0017](./appnotes/0017-reuse-of-ids.md) | When to re-use IDs in TAMS and compatible systems | -| [0019](./appnotes/0019-using-flow-profiles.md) | Using flow profiles | \ No newline at end of file +| [0019](./appnotes/0019-using-flow-profiles.md) | Using flow profiles | From 7491aa4fa1fbe12999ed7ca6aec895c1b7ba75c1 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Fri, 21 Nov 2025 11:27:36 +0000 Subject: [PATCH 19/22] Fixes for validation errors --- api/TimeAddressableMediaStore.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api/TimeAddressableMediaStore.yaml b/api/TimeAddressableMediaStore.yaml index 007eaacb..7294a7cb 100644 --- a/api/TimeAddressableMediaStore.yaml +++ b/api/TimeAddressableMediaStore.yaml @@ -158,12 +158,12 @@ paths: in: query description: Filter on Profile format. schema: - $ref: '#/components/schemas/contentformat' + $ref: 'schemas/content-format.json' - name: codec in: query description: Filter on Profile codec. schema: - $ref: '#/components/schemas/mimetype' + $ref: 'schemas/mime-type.json' - name: label in: query description: Filter on Profiles that have the given label. @@ -204,12 +204,12 @@ paths: in: query description: Filter on Profile format. schema: - $ref: '#/components/schemas/contentformat' + $ref: 'schemas/content-format.json' - name: codec in: query description: Filter on Profile codec. schema: - $ref: '#/components/schemas/mimetype' + $ref: 'schemas/mime-type.json' - name: label in: query description: Filter on Profiles that have the given label. @@ -3014,6 +3014,8 @@ tags: - name: Flows description: | Sources which have been 'rendered' to a specific encoding/packaging format. + - name: Profiles + description: Centralised management of the technical characteristics of a flow externalDocs: url: 'https://specs.amwa.tv/ms-04/releases/v1.0.0/docs/2.3._Explanation_-_Flow.html' - name: FlowSegments From 01de27ba26b2b6862e66b2e83ecdf17ae16a9a95 Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 6 Jan 2026 11:35:52 +0000 Subject: [PATCH 20/22] Typos and spelling corrections from Dan --- docs/appnotes/0019-using-flow-profiles.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/appnotes/0019-using-flow-profiles.md b/docs/appnotes/0019-using-flow-profiles.md index f9f65b7c..8f9675ee 100644 --- a/docs/appnotes/0019-using-flow-profiles.md +++ b/docs/appnotes/0019-using-flow-profiles.md @@ -13,7 +13,7 @@ This document describes how flow profiles can be used within the TAMS API to sim Within a customer deployment of TAMS it is expected that there would be limited number of recommended formats for users to work in. Typically this could include a target format for the high quality media and standardised formats for proxy media and images. -These formats are typically refered to as House formats and do not preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. +These formats are typically referred to as House formats and do not preclude the storing of other content within the store, however it is likely to be normalised at some point to the house format. The use of house formats then makes workflows such as ingest, rendering new content after editing, generation of proxy content and edit by reference easier. House formats define one or more common formats for all the systems to utilise. @@ -31,7 +31,7 @@ The more sources involved in this process, the harder this becomes. The TAMS profile model is split into a number of stages: -* An end-point to list and describe the available profiles supported by the store +* An endpoint to list and describe the available profiles supported by the store * The ability to supply a profile when creating a flow and the de-normalisation of the technical details at the point of creation * The ability to query flows for a given profile to easily and quickly find the required media type @@ -72,7 +72,7 @@ This then simplifies the process of creating the required flows and sources for The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. If the source content has additional non standard flows then these could be ignored. -From a flow created from a profile, it is possible to query via both profile ID and also the individual parameter of the flow that have been inheritied from the profile. +From a flow created from a profile, it is possible to query via both profile ID and also the individual parameter of the flow that have been inherited from the profile. ## Multi-store working with profiles @@ -82,9 +82,9 @@ This is the same model as for flow, source and object ID's which should be prese For workflows where replication of the same content formats are happening on a regular basis then it is recommended that the same profile is loaded into both stores using the same UUID. This will mean than when flows are replicated between the stores then the profile identifier will continue to link to the metadata. -If the profile does not existing within the destination store then the profile ID should continue to be preserved. +If the profile does not exist within the destination store then the profile ID should continue to be preserved. This will continue to allow the matching of content within the store by profile ID, plus the profile can be added later and will link to the existing content. -For workflows including more than two orgnaisations it is recommended that one organisation takes responsibility for owning and publishing the profiles. +For workflows including more than two organisations it is recommended that one organisation takes responsibility for owning and publishing the profiles. These profiles can then be loaded into the destination stores. The organisation could be a single company or could be an industry body. From a270b49fbcebc964fd2117417a681437cf08b75d Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Tue, 6 Jan 2026 12:02:08 +0000 Subject: [PATCH 21/22] Encorporating feedback from Dan --- docs/appnotes/0019-using-flow-profiles.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/appnotes/0019-using-flow-profiles.md b/docs/appnotes/0019-using-flow-profiles.md index 8f9675ee..091a4d38 100644 --- a/docs/appnotes/0019-using-flow-profiles.md +++ b/docs/appnotes/0019-using-flow-profiles.md @@ -55,9 +55,8 @@ When creating a flow the generating system has two options: 1. Specify all the technical characteristics of the flow including the wrapper, codec and essence parameters alongside the non-technical parameters such as label and description 2. Provide just the technical profile for the flow and non-technical parameters required -When using the second option on submission of the create flow request, the store will then read the metadata for a given profile and use this to populate the metadata for the flow. -This de-normalisation of the technical parameters means that on the read side the flows created via both mechanisms have the same technical parameters available. -Additionally if the decision is made to change a standard profile in the future then this does not affect the existing flows as the parameters have already been replicated and should remain unchanged to reflect the media actually being stored. +When using the second option on submission of the create flow request it is simpler for the creating system. +The store is responsible for the de-normalisation of the technical parameters so that when reading from the API the flows created via both mechanisms have the same technical parameters available. Flows that have been created from a profile will include the parameter indicating which profile they were created from. This differentiates them from the flows that have been created with the technical characteristics directly. @@ -72,7 +71,8 @@ This then simplifies the process of creating the required flows and sources for The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. If the source content has additional non standard flows then these could be ignored. -From a flow created from a profile, it is possible to query via both profile ID and also the individual parameter of the flow that have been inherited from the profile. +By the nature of the TAMS API it is possible to query via both profile ID and also the individual parameters of the flow that have been inherited from the profile. +As per standard behaviour, the API should only return results which match all fields, so for this scenario the flow must have a profile ID and match the other parameters requested. ## Multi-store working with profiles From dd53166af57ed4f2013c6387d38bc70ca3c5237f Mon Sep 17 00:00:00 2001 From: John Biltcliffe Date: Wed, 7 Jan 2026 10:04:04 +0000 Subject: [PATCH 22/22] Capitalisation --- docs/appnotes/0019-using-flow-profiles.md | 88 +++++++++++------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/appnotes/0019-using-flow-profiles.md b/docs/appnotes/0019-using-flow-profiles.md index 091a4d38..0ea1bcca 100644 --- a/docs/appnotes/0019-using-flow-profiles.md +++ b/docs/appnotes/0019-using-flow-profiles.md @@ -5,7 +5,7 @@ The TAMS API is deliberately agnostic to the format of the media which it is managing, to allow for future compatibility with new formats without needing to change the API specification. This provides challenges for interoperability and workflows such as edit by reference where standard media formats are required across multiple sources. -This document describes how flow profiles can be used within the TAMS API to simplify workflows while maintaining the flexibility of the core API. +This document describes how Flow Profiles can be used within the TAMS API to simplify workflows while maintaining the flexibility of the core API. ## Challenges @@ -20,71 +20,71 @@ House formats define one or more common formats for all the systems to utilise. ### Edit by reference flow matching -For edit by reference workflows there is a need both to create new sources and flows for the new item and also combine the segments together to create the new edit. +For edit by reference workflows there is a need both to create new Sources and Flows for the new item and also combine the segments together to create the new edit. -If the content to be referenced is only coming from a one source (potentially with multiple flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing flows and then join the segments to the new flow. -However if the content for the new edit is derived from multiple sources then there is a need to match the flows from the different sources based on the technical characteristics. -Currently the TAMS API does not provide an easy method to do this, so it is necessary to compare all the flows in code to find the matches. -The more sources involved in this process, the harder this becomes. +If the content to be referenced is only coming from a one source (potentially with multiple Flows), for example a simple clip, then it is relatively easy to clone the technical parameters of the existing Flows and then join the Segments to the new Flow. +However if the content for the new edit is derived from multiple Sources then there is a need to match the Flows from the different Sources based on the technical characteristics. +Currently the TAMS API does not provide an easy method to do this, so it is necessary to compare all the Flows in code to find the matches. +The more Sources involved in this process, the harder this becomes. ## TAMS Profiles within the API -The TAMS profile model is split into a number of stages: +The TAMS Profile model is split into a number of stages: -* An endpoint to list and describe the available profiles supported by the store -* The ability to supply a profile when creating a flow and the de-normalisation of the technical details at the point of creation -* The ability to query flows for a given profile to easily and quickly find the required media type +* An endpoint to list and describe the available Profiles supported by the store +* The ability to supply a Profile when creating a Flow and the de-normalisation of the technical details to maintain read compatibility with non-Profile based Flows +* The ability to query Flows for a given Profile to easily and quickly find the required media type ### Profiles endpoint -It is possible to create and view profiles via the dedicated API calls under the TAMS service end point (/services/profiles). -These profiles hold all the technical parameters required to create a flow in a single location. -A system looking to ingest standardised content into TAMS would create content matching one or more profiles as defined in the endpoint. +It is possible to create and view Profiles via the dedicated API calls under the TAMS service end point (/services/profiles). +These Profiles hold all the technical parameters required to create a Flow in a single location. +A system looking to ingest standardised content into TAMS would create content matching one or more Profiles as defined in the endpoint. -A profile should be treated as immutable, so once created it cannot be updated. -Updating a profile would cause mismatches with flows which have been already created using that profile and so breaks the model for profiles. -To update a profile a new one with a new ID should be created. +A Profile should be treated as immutable, so once created it cannot be updated. +Updating a Profile would cause mismatches with Flows which have been already created using that Profile and so breaks the model for Profiles. +To update a Profile a new one with a new ID should be created. -The profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for flows and sources. -This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS profile metadata +The Profiles endpoint has been designed to provide extensibility of the metadata through the same tags model as for Flows and Sources. +This would enable implementations to store additional metadata such as encoding parameters alongside the TAMS Profile metadata -### Creating a flow using a profile +### Creating a Flow using a Profile -When creating a flow the generating system has two options: +When creating a Flow the generating system has two options: -1. Specify all the technical characteristics of the flow including the wrapper, codec and essence parameters alongside the non-technical parameters such as label and description -2. Provide just the technical profile for the flow and non-technical parameters required +1. Specify all the technical characteristics of the Flow including the wrapper, codec and essence parameters alongside the non-technical parameters such as label and description +2. Provide just the technical Profile for the Flow and non-technical parameters required -When using the second option on submission of the create flow request it is simpler for the creating system. -The store is responsible for the de-normalisation of the technical parameters so that when reading from the API the flows created via both mechanisms have the same technical parameters available. +When using the second option on submission of the create Flow request it is simpler for the creating system. +The store is responsible for the de-normalisation of the technical parameters so that when reading from the API the Flows created via both mechanisms have the same technical parameters available. -Flows that have been created from a profile will include the parameter indicating which profile they were created from. -This differentiates them from the flows that have been created with the technical characteristics directly. +Flows that have been created from a Profile will include the parameter indicating which Profile they were created from. +This differentiates them from the Flows that have been created with the technical characteristics directly. -### Query flows using a profile +### Query Flows using a Profile -The get flows endpoint has the ability to query for flows with a given profile. -When combined with other query parameters such as source id then this means it is easy to start matching content formats. +The get Flows endpoint has the ability to query for Flows with a given Profile. +When combined with other query parameters such as Source id then this means it is easy to start matching content formats. -For example on an edit by reference workflow it would be possible to read the profile endpoint for the recommended profiles that content should have. -This then simplifies the process of creating the required flows and sources for the new content item. -The edit process could then process each input source in turn read the available flows and match them to the destination flows using the profile tag easily. -If the source content has additional non standard flows then these could be ignored. +For example on an edit by reference workflow it would be possible to read the Profile endpoint for the recommended profiles that content should have. +This then simplifies the process of creating the required Flows and Sources for the new content item. +The edit process could then process each input source in turn read the available Flows and match them to the destination Flows using the Profile tag easily. +If the Source content has additional non standard Flows then these could be ignored. -By the nature of the TAMS API it is possible to query via both profile ID and also the individual parameters of the flow that have been inherited from the profile. -As per standard behaviour, the API should only return results which match all fields, so for this scenario the flow must have a profile ID and match the other parameters requested. +By the nature of the TAMS API it is possible to query via both Profile ID and also the individual parameters of the Flow that have been inherited from the profile. +As per standard behaviour, the API should only return results which match all fields, so for this scenario the Flow must have a profile ID and match the other parameters requested. -## Multi-store working with profiles +## Multi-store working with Profiles -The UUID of a profile is assumed to be globally unique. -This is the same model as for flow, source and object ID's which should be preserved when replicating content. +The UUID of a Profile is assumed to be globally unique. +This is the same model as for Flow, Source and Object ID's which should be preserved when replicating content. -For workflows where replication of the same content formats are happening on a regular basis then it is recommended that the same profile is loaded into both stores using the same UUID. -This will mean than when flows are replicated between the stores then the profile identifier will continue to link to the metadata. +For workflows where replication of the same content formats are happening on a regular basis then it is recommended that the same Profile is loaded into both stores using the same UUID. +This will mean than when Flows are replicated between the stores then the Profile identifier will continue to link to the metadata. -If the profile does not exist within the destination store then the profile ID should continue to be preserved. -This will continue to allow the matching of content within the store by profile ID, plus the profile can be added later and will link to the existing content. +If the Profile does not exist within the destination store then the Profile ID should continue to be preserved. +This will continue to allow the matching of content within the store by Profile ID, plus the Profile can be added later and will link to the existing content. -For workflows including more than two organisations it is recommended that one organisation takes responsibility for owning and publishing the profiles. -These profiles can then be loaded into the destination stores. +For workflows including more than two organisations it is recommended that one organisation takes responsibility for owning and publishing the Profiles. +These Profiles can then be loaded into the destination stores. The organisation could be a single company or could be an industry body.