diff --git a/api/Makefile b/api/Makefile index 32b8f184..0cbfa7d3 100644 --- a/api/Makefile +++ b/api/Makefile @@ -3,21 +3,28 @@ topdir:=$(realpath $(dir $(word $(NUM_OF_PARENT),$(MAKEFILE_LIST)))) all: help +lint-json: + for FILE in $(shell find . -name "*.json"); do docker run -i ghcr.io/jqlang/jq:latest < $$FILE '.' | diff $$FILE -; done -build-lint: +conform-json: + for FILE in $(shell find . -name "*.json"); do docker run -i ghcr.io/jqlang/jq:latest < $$FILE '.' > $$FILE.tmp.json && mv $$FILE.tmp.json $$FILE; done + +build-lint-oas: docker pull --platform linux/amd64 stoplight/spectral:6.10 >/dev/null 2>/dev/null || true DOCKER_BUILDKIT=1 docker build --platform linux/amd64 -f Dockerfile.multi --target oaslint -t tams_api_oaslint:local . # Work around https://github.com/stoplightio/spectral/issues/2819 using the bundled spec -lint: build-lint docs/TimeAddressableMediaStore_bundled.yaml +lint-oas: build-lint-oas docs/TimeAddressableMediaStore_bundled.yaml docker run --platform linux/amd64 --rm -v $(topdir):/api tams_api_oaslint:local lint --fail-severity=warn /api/docs/TimeAddressableMediaStore_bundled.yaml +lint: lint-oas lint-json + build-bundle: docker pull redocly/cli:latest >/dev/null 2>/dev/null || true DOCKER_BUILDKIT=1 docker build -f Dockerfile.multi --target bundle -t tams_api_bundle:local . docs/TimeAddressableMediaStore_bundled.yaml: build-bundle - docker run --rm tams_api_bundle:local bundle /data/TimeAddressableMediaStore.yaml > $@ + docker run --rm tams_api_bundle:local bundle /data/TimeAddressableMediaStore.yaml > $@ render: docs/TimeAddressableMediaStore_bundled.yaml @@ -37,10 +44,11 @@ mock-server-healthy: help: @echo "tams-api" - @echo "make lint - Lint API specification document" + @echo "make lint - Lint API specification document, and json files" + @echo "make conform-json - Conform JSON files to linter" @echo "make render - Generate HTML rendered version of OpenAPI document" @echo "make mock-server-up - Start a mock API server on http://localhost:4010" @echo "make mock-server-down - Stop the mock API server" @echo "make mock-server-healthy - Connect to mock API server, confirm it is working" -.PHONY: all build-lint lint build-bundle render mock-server-up mock-server-down mock-server-healthy help +.PHONY: all lint-json conform-json build-lint-oas lint-oas lint build-bundle render mock-server-up mock-server-down mock-server-healthy help diff --git a/api/examples/deletion-request-get-200.json b/api/examples/deletion-request-get-200.json index 58a4bceb..9a3f1908 100644 --- a/api/examples/deletion-request-get-200.json +++ b/api/examples/deletion-request-get-200.json @@ -1,12 +1,12 @@ { - "id": "9f0187c1-419c-44d2-8269-e869ba409462", - "flow_id": "d14c70ad-6c59-4092-b51f-b75f6edf04e3", - "timerange_to_delete": "[1537349337:0_1537349347:21333333)", - "timerange_remaining": "[1537349339:0_1537349347:21333333)", - "delete_flow": true, - "created": "2018-12-10T15:40:08.339376+00:00", - "updated": "2018-12-10T15:40:09.339393+00:00", - "expiry": "2018-12-11T15:40:09.339393+00:00", - "created_by": "tams-dev", - "status": "started" -} \ No newline at end of file + "id": "9f0187c1-419c-44d2-8269-e869ba409462", + "flow_id": "d14c70ad-6c59-4092-b51f-b75f6edf04e3", + "timerange_to_delete": "[1537349337:0_1537349347:21333333)", + "timerange_remaining": "[1537349339:0_1537349347:21333333)", + "delete_flow": true, + "created": "2018-12-10T15:40:08.339376+00:00", + "updated": "2018-12-10T15:40:09.339393+00:00", + "expiry": "2018-12-11T15:40:09.339393+00:00", + "created_by": "tams-dev", + "status": "started" +} diff --git a/api/examples/deletion-requests-get-200.json b/api/examples/deletion-requests-get-200.json index c67af57d..ce053b53 100644 --- a/api/examples/deletion-requests-get-200.json +++ b/api/examples/deletion-requests-get-200.json @@ -1,52 +1,52 @@ [ - { - "id": "9f0187c1-419c-44d2-8269-e869ba409462", - "flow_id": "d14c70ad-6c59-4092-b51f-b75f6edf04e3", - "timerange_to_delete": "[1537349337:0_1537349347:21333333)", - "timerange_remaining": "[1537349339:0_1537349347:21333333)", - "delete_flow": true, - "created": "2018-12-10T15:40:08.339376+00:00", - "updated": "2018-12-10T15:40:09.339393+00:00", - "expiry": "2018-12-11T15:40:09.339393+00:00", - "created_by": "tams-dev", - "status": "started" - }, - { - "id": "58b3793e-c9ad-4a7f-b680-e823685bb52d", - "flow_id": "58b3793e-c9ad-4a7f-b680-e823685bb52d", - "timerange_to_delete": "[0:0_1000:0)", - "timerange_remaining": "[900:0_1000:0)", - "delete_flow": false, - "created": "2018-12-10T15:40:08.339376+00:00", - "updated": "2018-12-10T15:40:09.339393+00:00", - "expiry": "2018-12-11T15:40:09.339393+00:00", - "created_by": "tams-dev", - "status": "started" - }, - { - "id": "3f04ae16-8b78-4426-9ccf-85ddaf908937", - "flow_id": "f43619e9-6333-438d-95b3-1e89f426d920", - "timerange_to_delete": "[0:0_1000:0)", - "timerange_remaining": "[900:0_1000:0)", - "delete_flow": false, - "created": "2018-12-10T15:40:08.339376+00:00", - "updated": "2018-12-10T15:18:52.426792+00:00", - "expiry": "2018-12-11T15:40:09.339393+00:00", - "created_by": "tams-dev", - "status": "error", - "error": { - "type": "TAMSError", - "summary": "Flow delete failed because ...", - "traceback": [ - "Exception: The flow segment could not be deleted", - "The above exception was the direct cause of the following exception:", - "", - "", - "Traceback (most recent call last):", - " ", - "TAMSError: Unable to continue" - ], - "time": "2018-12-10T15:18:52.426792+00:00" - } + { + "id": "9f0187c1-419c-44d2-8269-e869ba409462", + "flow_id": "d14c70ad-6c59-4092-b51f-b75f6edf04e3", + "timerange_to_delete": "[1537349337:0_1537349347:21333333)", + "timerange_remaining": "[1537349339:0_1537349347:21333333)", + "delete_flow": true, + "created": "2018-12-10T15:40:08.339376+00:00", + "updated": "2018-12-10T15:40:09.339393+00:00", + "expiry": "2018-12-11T15:40:09.339393+00:00", + "created_by": "tams-dev", + "status": "started" + }, + { + "id": "58b3793e-c9ad-4a7f-b680-e823685bb52d", + "flow_id": "58b3793e-c9ad-4a7f-b680-e823685bb52d", + "timerange_to_delete": "[0:0_1000:0)", + "timerange_remaining": "[900:0_1000:0)", + "delete_flow": false, + "created": "2018-12-10T15:40:08.339376+00:00", + "updated": "2018-12-10T15:40:09.339393+00:00", + "expiry": "2018-12-11T15:40:09.339393+00:00", + "created_by": "tams-dev", + "status": "started" + }, + { + "id": "3f04ae16-8b78-4426-9ccf-85ddaf908937", + "flow_id": "f43619e9-6333-438d-95b3-1e89f426d920", + "timerange_to_delete": "[0:0_1000:0)", + "timerange_remaining": "[900:0_1000:0)", + "delete_flow": false, + "created": "2018-12-10T15:40:08.339376+00:00", + "updated": "2018-12-10T15:18:52.426792+00:00", + "expiry": "2018-12-11T15:40:09.339393+00:00", + "created_by": "tams-dev", + "status": "error", + "error": { + "type": "TAMSError", + "summary": "Flow delete failed because ...", + "traceback": [ + "Exception: The flow segment could not be deleted", + "The above exception was the direct cause of the following exception:", + "", + "", + "Traceback (most recent call last):", + " ", + "TAMSError: Unable to continue" + ], + "time": "2018-12-10T15:18:52.426792+00:00" } -] \ No newline at end of file + } +] diff --git a/api/examples/flow-collection-get-200.json b/api/examples/flow-collection-get-200.json index 322a3d9b..4b0244f8 100644 --- a/api/examples/flow-collection-get-200.json +++ b/api/examples/flow-collection-get-200.json @@ -1,14 +1,14 @@ [ - { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" - }, - { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" - }, - { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "role": "subtitles" - } + { + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "role": "video" + }, + { + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "role": "audio" + }, + { + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "role": "subtitles" + } ] diff --git a/api/examples/flow-collection-put.json b/api/examples/flow-collection-put.json index 322a3d9b..4b0244f8 100644 --- a/api/examples/flow-collection-put.json +++ b/api/examples/flow-collection-put.json @@ -1,14 +1,14 @@ [ - { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" - }, - { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" - }, - { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "role": "subtitles" - } + { + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "role": "video" + }, + { + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "role": "audio" + }, + { + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "role": "subtitles" + } ] diff --git a/api/examples/flow-get-200-audio-aac-multi.json b/api/examples/flow-get-200-audio-aac-multi.json index cf1e2930..d1f2cbcc 100644 --- a/api/examples/flow-get-200-audio-aac-multi.json +++ b/api/examples/flow-get-200-audio-aac-multi.json @@ -1,30 +1,30 @@ { - "id": "94996f2e-0cb5-43d3-ab6c-db5a9cf667aa", - "source_id": "1f0bdb2d-e8f3-4d2d-9b27-b71ff0728ed1", - "generation": 1, - "created": "2018-03-06T09:10:22Z", - "metadata_updated": "2018-03-06T09:12:22Z", - "segments_updated": "2018-03-06T11:14:32Z", - "description": "audio capture web", - "label": "capture_1", - "format": "urn:x-nmos:format:audio", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "quality": "web" - }, - "codec": "audio/aac", - "avg_bit_rate": 128, - "essence_parameters": { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 24, - "codec_parameters": { - "coded_frame_size": 1024, - "mp4_oti": 2 - } - }, - "collected_by": [ - "8159b781-6033-42e8-b3a1-8a879af5e1aa" - ] -} \ No newline at end of file + "id": "94996f2e-0cb5-43d3-ab6c-db5a9cf667aa", + "source_id": "1f0bdb2d-e8f3-4d2d-9b27-b71ff0728ed1", + "generation": 1, + "created": "2018-03-06T09:10:22Z", + "metadata_updated": "2018-03-06T09:12:22Z", + "segments_updated": "2018-03-06T11:14:32Z", + "description": "audio capture web", + "label": "capture_1", + "format": "urn:x-nmos:format:audio", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "quality": "web" + }, + "codec": "audio/aac", + "avg_bit_rate": 128, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 24, + "codec_parameters": { + "coded_frame_size": 1024, + "mp4_oti": 2 + } + }, + "collected_by": [ + "8159b781-6033-42e8-b3a1-8a879af5e1aa" + ] +} diff --git a/api/examples/flow-get-200-audio-aac.json b/api/examples/flow-get-200-audio-aac.json index 87aac973..c84c9eba 100644 --- a/api/examples/flow-get-200-audio-aac.json +++ b/api/examples/flow-get-200-audio-aac.json @@ -1,31 +1,31 @@ { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", - "generation": 1, - "created": "2018-03-06T09:10:22Z", - "metadata_updated": "2018-03-06T09:12:22Z", - "segments_updated": "2018-03-06T11:14:32Z", - "description": "audio capture web", - "label": "capture_1", - "format": "urn:x-nmos:format:audio", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "web" - }, - "codec": "audio/aac", - "container": "video/mp2t", - "avg_bit_rate": 128, - "essence_parameters": { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 24, - "codec_parameters": { - "coded_frame_size": 1024, - "mp4_oti": 2 - } - }, - "collected_by": [ - "e85efab4-993b-4ad6-9af3-4cd8d0d38860" - ] -} \ No newline at end of file + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", + "generation": 1, + "created": "2018-03-06T09:10:22Z", + "metadata_updated": "2018-03-06T09:12:22Z", + "segments_updated": "2018-03-06T11:14:32Z", + "description": "audio capture web", + "label": "capture_1", + "format": "urn:x-nmos:format:audio", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "web" + }, + "codec": "audio/aac", + "container": "video/mp2t", + "avg_bit_rate": 128, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 24, + "codec_parameters": { + "coded_frame_size": 1024, + "mp4_oti": 2 + } + }, + "collected_by": [ + "e85efab4-993b-4ad6-9af3-4cd8d0d38860" + ] +} diff --git a/api/examples/flow-get-200-audio-wav.json b/api/examples/flow-get-200-audio-wav.json index 2d5c2ac7..5b0b37a9 100644 --- a/api/examples/flow-get-200-audio-wav.json +++ b/api/examples/flow-get-200-audio-wav.json @@ -1,27 +1,27 @@ { - "id": "fd25a9fc-3b58-4dc1-93d4-81c52b206562", - "source_id": "8af9d4a3-aff7-44e8-b384-d2bfc0b93533", - "generation": 0, - "created": "2025-02-24T11:33:46Z", - "metadata_updated": "2025-02-24T11:33:46Z", - "segments_updated": "2025-02-24T11:48:22Z", - "description": "Radio off-air recording", - "label": "Radio off-air", - "format": "urn:x-nmos:format:audio", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "contribution" - }, - "codec": "audio/x-raw-int", - "container": "audio/wav", - "avg_bit_rate": 192, - "essence_parameters": { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 16, - "unc_parameters": { - "unc_type": "interleaved" - } + "id": "fd25a9fc-3b58-4dc1-93d4-81c52b206562", + "source_id": "8af9d4a3-aff7-44e8-b384-d2bfc0b93533", + "generation": 0, + "created": "2025-02-24T11:33:46Z", + "metadata_updated": "2025-02-24T11:33:46Z", + "segments_updated": "2025-02-24T11:48:22Z", + "description": "Radio off-air recording", + "label": "Radio off-air", + "format": "urn:x-nmos:format:audio", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "contribution" + }, + "codec": "audio/x-raw-int", + "container": "audio/wav", + "avg_bit_rate": 192, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 16, + "unc_parameters": { + "unc_type": "interleaved" } -} \ No newline at end of file + } +} diff --git a/api/examples/flow-get-200-data-ttml.json b/api/examples/flow-get-200-data-ttml.json index 2673bb7a..e65ccd01 100644 --- a/api/examples/flow-get-200-data-ttml.json +++ b/api/examples/flow-get-200-data-ttml.json @@ -1,15 +1,15 @@ { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", - "format": "urn:x-nmos:format:data", - "generation": 0, - "created": "2023-12-14T16:34:58.131620", - "codec": "application/ttml+xml", - "container": "application/ttml+xml", - "essence_parameters": { - "data_type": "urn:x-tams:data:subtitle" - }, - "collected_by": [ - "e85efab4-993b-4ad6-9af3-4cd8d0d38860" - ] -} \ No newline at end of file + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", + "format": "urn:x-nmos:format:data", + "generation": 0, + "created": "2023-12-14T16:34:58.131620", + "codec": "application/ttml+xml", + "container": "application/ttml+xml", + "essence_parameters": { + "data_type": "urn:x-tams:data:subtitle" + }, + "collected_by": [ + "e85efab4-993b-4ad6-9af3-4cd8d0d38860" + ] +} diff --git a/api/examples/flow-get-200-image-jpeg.json b/api/examples/flow-get-200-image-jpeg.json index 451ad2ee..aa4b8efe 100644 --- a/api/examples/flow-get-200-image-jpeg.json +++ b/api/examples/flow-get-200-image-jpeg.json @@ -1,29 +1,26 @@ { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf33", - "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186e", - "generation": 0, - "created": "2008-05-27T18:51:00Z", - "metadata_updated": "2023-09-14T09:45:26Z", - "segments_updated": "2023-09-14T09:45:26Z", - "description": "Big Buck Bunny", - "label": "bbb", - "format": "urn:x-tam:format:image", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "codec": "image/jpeg", - "container": "image/jpeg", - "essence_parameters": - { - "frame_width": 1280, - "frame_height": 720, - "aspect_ratio": - { - "numerator": 16, - "denominator": 9 - } - }, - "collected_by": - [ - "e85efab4-993b-4ad6-9af3-4cd8d0d38861" - ] -} \ No newline at end of file + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf33", + "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186e", + "generation": 0, + "created": "2008-05-27T18:51:00Z", + "metadata_updated": "2023-09-14T09:45:26Z", + "segments_updated": "2023-09-14T09:45:26Z", + "description": "Big Buck Bunny", + "label": "bbb", + "format": "urn:x-tam:format:image", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "codec": "image/jpeg", + "container": "image/jpeg", + "essence_parameters": { + "frame_width": 1280, + "frame_height": 720, + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + } + }, + "collected_by": [ + "e85efab4-993b-4ad6-9af3-4cd8d0d38861" + ] +} diff --git a/api/examples/flow-get-200-multi-container-map.json b/api/examples/flow-get-200-multi-container-map.json index 32640c8a..db0859a4 100644 --- a/api/examples/flow-get-200-multi-container-map.json +++ b/api/examples/flow-get-200-multi-container-map.json @@ -1,39 +1,39 @@ { - "id": "8159b781-6033-42e8-b3a1-8a879af5e1aa", - "source_id": "3a24e39d-c6cf-4632-8c9e-36a8d305f007", - "format": "urn:x-nmos:format:multi", - "generation": 0, - "created": "2024-04-25T15:56:00.0Z", - "tags": { - "ingested_by": "ingest_service_api" + "id": "8159b781-6033-42e8-b3a1-8a879af5e1aa", + "source_id": "3a24e39d-c6cf-4632-8c9e-36a8d305f007", + "format": "urn:x-nmos:format:multi", + "generation": 0, + "created": "2024-04-25T15:56:00.0Z", + "tags": { + "ingested_by": "ingest_service_api" + }, + "container": "video/mp2t", + "flow_collection": [ + { + "id": "32b75860-83e5-48c9-8d6b-de46bdbc7f80", + "role": "video" }, - "container": "video/mp2t", - "flow_collection": [ - { - "id": "32b75860-83e5-48c9-8d6b-de46bdbc7f80", - "role": "video" - }, - { - "id": "94996f2e-0cb5-43d3-ab6c-db5a9cf667aa", - "role": "L", - "container_mapping": { - "track_index": 1, - "format_track_index": 0, - "mp2ts_container": { - "pid": 257 - } - } - }, - { - "id": "9ba0523e-22a0-4c69-a598-baf4be244a79", - "role": "R", - "container_mapping": { - "track_index": 2, - "format_track_index": 1, - "mp2ts_container": { - "pid": 258 - } - } + { + "id": "94996f2e-0cb5-43d3-ab6c-db5a9cf667aa", + "role": "L", + "container_mapping": { + "track_index": 1, + "format_track_index": 0, + "mp2ts_container": { + "pid": 257 } - ] + } + }, + { + "id": "9ba0523e-22a0-4c69-a598-baf4be244a79", + "role": "R", + "container_mapping": { + "track_index": 2, + "format_track_index": 1, + "mp2ts_container": { + "pid": 258 + } + } + } + ] } diff --git a/api/examples/flow-get-200-multi.json b/api/examples/flow-get-200-multi.json index 75edd5d2..9558a1b5 100644 --- a/api/examples/flow-get-200-multi.json +++ b/api/examples/flow-get-200-multi.json @@ -1,24 +1,24 @@ { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", - "format": "urn:x-nmos:format:multi", - "generation": 0, - "created": "2023-12-14T16:34:58.131620", - "tags": { - "ingested_by": "ingest_service_api" + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", + "format": "urn:x-nmos:format:multi", + "generation": 0, + "created": "2023-12-14T16:34:58.131620", + "tags": { + "ingested_by": "ingest_service_api" + }, + "flow_collection": [ + { + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "role": "video" }, - "flow_collection": [ - { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" - }, - { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" - }, - { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "role": "subtitles" - } - ] + { + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "role": "audio" + }, + { + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "role": "subtitles" + } + ] } diff --git a/api/examples/flow-get-200-video-h264-mxf.json b/api/examples/flow-get-200-video-h264-mxf.json index 885c0ca1..879daa5e 100644 --- a/api/examples/flow-get-200-video-h264-mxf.json +++ b/api/examples/flow-get-200-video-h264-mxf.json @@ -1,47 +1,47 @@ { - "id": "1491ecfb-813d-4453-9554-e417d03161ba", - "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", - "generation": 1, - "created": "2026-02-24T09:35:25Z", - "metadata_updated": "2026-02-24T09:36:02Z", - "segments_updated": "2026-02-24T15:38:21Z", - "description": "Video Flow in a MXF container, H264 codec", - "label": "VFX Render - Proxy Quality", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "web" + "id": "1491ecfb-813d-4453-9554-e417d03161ba", + "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", + "generation": 1, + "created": "2026-02-24T09:35:25Z", + "metadata_updated": "2026-02-24T09:36:02Z", + "segments_updated": "2026-02-24T15:38:21Z", + "description": "Video Flow in a MXF container, H264 codec", + "label": "VFX Render - Proxy Quality", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "web" + }, + "codec": "video/h264", + "container": "application/mxf", + "avg_bit_rate": 6000, + "essence_parameters": { + "frame_rate": { + "numerator": 50, + "denominator": 1 }, - "codec": "video/h264", - "container": "application/mxf", - "avg_bit_rate": 6000, - "essence_parameters": { - "frame_rate": { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 8, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 2, - "horiz_chroma_subs": 2, - "avc_parameters": { - "profile": 100, - "level": 31, - "flags": 0 - } + "frame_width": 1920, + "frame_height": 1080, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + }, + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "vert_chroma_subs": 2, + "horiz_chroma_subs": 2, + "avc_parameters": { + "profile": 100, + "level": 31, + "flags": 0 } -} \ No newline at end of file + } +} diff --git a/api/examples/flow-get-200-video-h264-vfr.json b/api/examples/flow-get-200-video-h264-vfr.json index 3b1c851e..c0aa158b 100644 --- a/api/examples/flow-get-200-video-h264-vfr.json +++ b/api/examples/flow-get-200-video-h264-vfr.json @@ -45,4 +45,4 @@ "collected_by": [ "e85efab4-993b-4ad6-9af3-4cd8d0d38860" ] -} \ No newline at end of file +} diff --git a/api/examples/flow-get-200-video-h264.json b/api/examples/flow-get-200-video-h264.json index 4f1fc28a..e58411ce 100644 --- a/api/examples/flow-get-200-video-h264.json +++ b/api/examples/flow-get-200-video-h264.json @@ -1,60 +1,50 @@ { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "generation": 0, - "created": "2008-05-27T18:51:00Z", - "metadata_updated": "2023-09-14T09:45:26Z", - "segments_updated": "2023-09-14T09:45:26Z", - "description": "Big Buck Bunny", - "label": "bbb", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "contribution" + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "generation": 0, + "created": "2008-05-27T18:51:00Z", + "metadata_updated": "2023-09-14T09:45:26Z", + "segments_updated": "2023-09-14T09:45:26Z", + "description": "Big Buck Bunny", + "label": "bbb", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "contribution" + }, + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "essence_parameters": { + "frame_rate": { + "numerator": 24, + "denominator": 1 }, - "codec": "video/h264", - "container": "video/mp2t", - "avg_bit_rate": 2479, - "segment_duration": { - "numerator": 10 + "frame_width": 1280, + "frame_height": 720, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 }, - "essence_parameters": - { - "frame_rate": - { - "numerator": 24, - "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 - }, - "pixel_aspect_ratio": - { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 2, - "horiz_chroma_subs": 2, - "avc_parameters": - { - "profile": 100, - "level": 31, - "flags": 0 - } + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 }, - "collected_by": - [ - "e85efab4-993b-4ad6-9af3-4cd8d0d38860" - ] -} \ No newline at end of file + "component_type": "YCbCr", + "vert_chroma_subs": 2, + "horiz_chroma_subs": 2, + "avc_parameters": { + "profile": 100, + "level": 31, + "flags": 0 + } + }, + "collected_by": [ + "e85efab4-993b-4ad6-9af3-4cd8d0d38860" + ] +} diff --git a/api/examples/flow-get-200-video-jpeg-jp2.json b/api/examples/flow-get-200-video-jpeg-jp2.json index e8a5976d..dd7dfb60 100644 --- a/api/examples/flow-get-200-video-jpeg-jp2.json +++ b/api/examples/flow-get-200-video-jpeg-jp2.json @@ -1,46 +1,46 @@ { - "id": "49628282-d3c6-4faa-a31f-d35cff98b26c", - "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", - "generation": 0, - "created": "2026-02-24T09:25:32Z", - "metadata_updated": "2026-02-24T09:36:54Z", - "segments_updated": "2026-02-24T14:29:14Z", - "description": "Video Flow in a JP2 container, JPEG-2000 codec, single frame segments", - "label": "VFX Render - Full Quality, single frame", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "intermediate" + "id": "49628282-d3c6-4faa-a31f-d35cff98b26c", + "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", + "generation": 0, + "created": "2026-02-24T09:25:32Z", + "metadata_updated": "2026-02-24T09:36:54Z", + "segments_updated": "2026-02-24T14:29:14Z", + "description": "Video Flow in a JP2 container, JPEG-2000 codec, single frame segments", + "label": "VFX Render - Full Quality, single frame", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "intermediate" + }, + "codec": "video/jp2", + "container": "image/jp2", + "avg_bit_rate": 250000, + "segment_duration": { + "numerator": 1, + "denominator": 50 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 50, + "denominator": 1 }, - "codec": "video/jp2", - "container": "image/jp2", - "avg_bit_rate": 250000, - "segment_duration": { - "numerator": 1, - "denominator": 50 + "frame_width": 1920, + "frame_height": 1080, + "bit_depth": 10, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 }, - "essence_parameters": { - "frame_rate": { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 10, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 1, - "horiz_chroma_subs": 2 - } -} \ No newline at end of file + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "vert_chroma_subs": 1, + "horiz_chroma_subs": 2 + } +} diff --git a/api/examples/flow-get-200-video-jpeg-mxf.json b/api/examples/flow-get-200-video-jpeg-mxf.json index 88bb1651..548ee95a 100644 --- a/api/examples/flow-get-200-video-jpeg-mxf.json +++ b/api/examples/flow-get-200-video-jpeg-mxf.json @@ -1,45 +1,45 @@ { - "id": "1a670176-5b40-433b-9d66-8f90efc026b6", - "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", - "generation": 0, - "created": "2026-02-24T09:35:25Z", - "metadata_updated": "2026-02-24T09:35:25Z", - "segments_updated": "2026-02-24T14:28:11Z", - "description": "Video Flow in a MXF container, JPEG-2000 codec", - "label": "VFX Render - Full Quality", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "intermediate" + "id": "1a670176-5b40-433b-9d66-8f90efc026b6", + "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", + "generation": 0, + "created": "2026-02-24T09:35:25Z", + "metadata_updated": "2026-02-24T09:35:25Z", + "segments_updated": "2026-02-24T14:28:11Z", + "description": "Video Flow in a MXF container, JPEG-2000 codec", + "label": "VFX Render - Full Quality", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "intermediate" + }, + "codec": "video/jp2", + "container": "application/mxf", + "avg_bit_rate": 250000, + "segment_duration": { + "numerator": 60 + }, + "essence_parameters": { + "frame_rate": { + "numerator": 50, + "denominator": 1 }, - "codec": "video/jp2", - "container": "application/mxf", - "avg_bit_rate": 250000, - "segment_duration": { - "numerator": 60 + "frame_width": 1920, + "frame_height": 1080, + "bit_depth": 10, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 }, - "essence_parameters": { - "frame_rate": { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 10, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 1, - "horiz_chroma_subs": 2 - } -} \ No newline at end of file + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "vert_chroma_subs": 1, + "horiz_chroma_subs": 2 + } +} diff --git a/api/examples/flow-get-200-video-raw.json b/api/examples/flow-get-200-video-raw.json index 9333ee1a..4773951f 100644 --- a/api/examples/flow-get-200-video-raw.json +++ b/api/examples/flow-get-200-video-raw.json @@ -1,45 +1,45 @@ { - "id": "0fde9c11-da9d-434a-a113-d3b20a2cf251", - "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "generation": 0, - "created": "2018-03-06T09:10:22Z", - "metadata_updated": "2018-03-06T09:12:22Z", - "segments_updated": "2018-03-06T11:14:32Z", - "description": "video capture", - "label": "capture_1", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "intermediate" + "id": "0fde9c11-da9d-434a-a113-d3b20a2cf251", + "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "generation": 0, + "created": "2018-03-06T09:10:22Z", + "metadata_updated": "2018-03-06T09:12:22Z", + "segments_updated": "2018-03-06T11:14:32Z", + "description": "video capture", + "label": "capture_1", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "intermediate" + }, + "codec": "video/raw", + "container": "video/quicktime", + "avg_bit_rate": 1658880, + "essence_parameters": { + "frame_rate": { + "numerator": 50, + "denominator": 1 }, - "codec": "video/raw", - "container": "video/quicktime", - "avg_bit_rate": 1658880, - "essence_parameters": { - "frame_rate": { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 8, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "unc_parameters": { - "unc_type": "UYVY" - }, - "vert_chroma_subs": 1, - "horiz_chroma_subs": 2 - } -} \ No newline at end of file + "frame_width": 1920, + "frame_height": 1080, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + }, + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "unc_parameters": { + "unc_type": "UYVY" + }, + "vert_chroma_subs": 1, + "horiz_chroma_subs": 2 + } +} diff --git a/api/examples/flow-put-201.json b/api/examples/flow-put-201.json index fb67ff94..260af008 100644 --- a/api/examples/flow-put-201.json +++ b/api/examples/flow-put-201.json @@ -1,27 +1,24 @@ { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", - "generation": 1, - "segments_updated": "2018-03-06T11:14:32Z", - "description": "audio capture web", - "label": "capture_1", - "format": "urn:x-nmos:format:audio", - "tags": - { - "input_quality": "web" - }, - "codec": "audio/aac", - "container": "video/mp2t", - "avg_bit_rate": 128, - "essence_parameters": - { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 24, - "codec_parameters": - { - "coded_frame_size": 1024, - "mp4_oti": 2 - } + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", + "generation": 1, + "segments_updated": "2018-03-06T11:14:32Z", + "description": "audio capture web", + "label": "capture_1", + "format": "urn:x-nmos:format:audio", + "tags": { + "input_quality": "web" + }, + "codec": "audio/aac", + "container": "video/mp2t", + "avg_bit_rate": 128, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 24, + "codec_parameters": { + "coded_frame_size": 1024, + "mp4_oti": 2 } -} \ No newline at end of file + } +} diff --git a/api/examples/flow-put-multi.json b/api/examples/flow-put-multi.json index d4c92093..d27934ad 100644 --- a/api/examples/flow-put-multi.json +++ b/api/examples/flow-put-multi.json @@ -1,24 +1,24 @@ { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", - "description": "SRT Feed 1", - "label": "OB Truck A Mix Out", - "format": "urn:x-nmos:format:multi", - "tags": { - "ingested_by": "ingest_service_api" + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "source_id": "a77d0061-0878-4e8a-a114-772d03f952c1", + "description": "SRT Feed 1", + "label": "OB Truck A Mix Out", + "format": "urn:x-nmos:format:multi", + "tags": { + "ingested_by": "ingest_service_api" + }, + "flow_collection": [ + { + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "role": "video" }, - "flow_collection": [ - { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "role": "video" - }, - { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "role": "audio" - }, - { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "role": "subtitles" - } - ] + { + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "role": "audio" + }, + { + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "role": "subtitles" + } + ] } diff --git a/api/examples/flow-put.json b/api/examples/flow-put.json index cff83cc6..79b67c36 100644 --- a/api/examples/flow-put.json +++ b/api/examples/flow-put.json @@ -1,26 +1,23 @@ { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", - "generation": 1, - "description": "audio capture web", - "label": "capture_1", - "format": "urn:x-nmos:format:audio", - "tags": - { - "input_quality": "web" - }, - "codec": "audio/aac", - "container": "video/mp2t", - "avg_bit_rate": 128, - "essence_parameters": - { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 24, - "codec_parameters": - { - "coded_frame_size": 1024, - "mp4_oti": 2 - } + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", + "generation": 1, + "description": "audio capture web", + "label": "capture_1", + "format": "urn:x-nmos:format:audio", + "tags": { + "input_quality": "web" + }, + "codec": "audio/aac", + "container": "video/mp2t", + "avg_bit_rate": 128, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 24, + "codec_parameters": { + "coded_frame_size": 1024, + "mp4_oti": 2 } -} \ No newline at end of file + } +} diff --git a/api/examples/flow-segment-partial-failure.json b/api/examples/flow-segment-partial-failure.json index 2c2ad691..e457834d 100644 --- a/api/examples/flow-segment-partial-failure.json +++ b/api/examples/flow-segment-partial-failure.json @@ -1,24 +1,24 @@ { - "failed_segments": [ - { - "object_id": "76f6821b-f85b-4297-af65-dde6a25448a0", - "timerange": "[0:0_10:0)", - "error": { - "type": "TAMSError", - "summary": "Flow segment created failed because ...", - "traceback": [ - "Exception: The flow segment could not be created", - "The above exception was the direct cause of the following exception:", - "Traceback (most recent call last):", - " ", - "TAMSError: Unable to continue" - ], - "time": "2018-12-10T15:18:52.426792+00:00" - } - }, - { - "object_id": "d2a3f8d9-4b8c-4a0a-9d0d-3d3e3e3e3e3e", - "timerange": "[28:0_30:0)" - } - ] -} \ No newline at end of file + "failed_segments": [ + { + "object_id": "76f6821b-f85b-4297-af65-dde6a25448a0", + "timerange": "[0:0_10:0)", + "error": { + "type": "TAMSError", + "summary": "Flow segment created failed because ...", + "traceback": [ + "Exception: The flow segment could not be created", + "The above exception was the direct cause of the following exception:", + "Traceback (most recent call last):", + " ", + "TAMSError: Unable to continue" + ], + "time": "2018-12-10T15:18:52.426792+00:00" + } + }, + { + "object_id": "d2a3f8d9-4b8c-4a0a-9d0d-3d3e3e3e3e3e", + "timerange": "[28:0_30:0)" + } + ] +} diff --git a/api/examples/flow-segment-post.json b/api/examples/flow-segment-post.json index 6e286050..3367afc6 100644 --- a/api/examples/flow-segment-post.json +++ b/api/examples/flow-segment-post.json @@ -1,4 +1,4 @@ { - "object_id": "99c27f3f-ab67-47ae-8dd3-e5c146912b50", - "timerange": "[20:0_21:0)" + "object_id": "99c27f3f-ab67-47ae-8dd3-e5c146912b50", + "timerange": "[20:0_21:0)" } diff --git a/api/examples/flow-segments-get-200-multiple-urls.json b/api/examples/flow-segments-get-200-multiple-urls.json index 7046edd0..cdbdbf22 100644 --- a/api/examples/flow-segments-get-200-multiple-urls.json +++ b/api/examples/flow-segments-get-200-multiple-urls.json @@ -1,47 +1,44 @@ [ - { - "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "timerange": "[100:0_110:0)", - "get_urls": - [ - { - "label": "main_store", - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" - }, - { - "label": "another_store", - "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/846023d3-612d-5014-bc47-88f6eb2d04bb" - } - ] - }, - { - "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", - "timerange": "[110:0_120:0)", - "get_urls": - [ - { - "label": "main_store", - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" - }, - { - "label": "another_store", - "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/25be83fc-11d1-5743-9d47-6865cef5ea35" - } - ] - }, - { - "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", - "timerange": "[120:0_130:0)", - "get_urls": - [ - { - "label": "main_store", - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321" - }, - { - "label": "another_store", - "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8b785422-6a82-5d60-b25a-f77e0a748321" - } - ] - } -] \ No newline at end of file + { + "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "timerange": "[100:0_110:0)", + "get_urls": [ + { + "label": "main_store", + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" + }, + { + "label": "another_store", + "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/846023d3-612d-5014-bc47-88f6eb2d04bb" + } + ] + }, + { + "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", + "timerange": "[110:0_120:0)", + "get_urls": [ + { + "label": "main_store", + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" + }, + { + "label": "another_store", + "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/25be83fc-11d1-5743-9d47-6865cef5ea35" + } + ] + }, + { + "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", + "timerange": "[120:0_130:0)", + "get_urls": [ + { + "label": "main_store", + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321" + }, + { + "label": "another_store", + "url": "https://another_store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8b785422-6a82-5d60-b25a-f77e0a748321" + } + ] + } +] diff --git a/api/examples/flow-segments-get-200-object-timerange.json b/api/examples/flow-segments-get-200-object-timerange.json index 047ad10d..366021ae 100644 --- a/api/examples/flow-segments-get-200-object-timerange.json +++ b/api/examples/flow-segments-get-200-object-timerange.json @@ -1,37 +1,34 @@ [ - { - "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "timerange": "[0:0_10:0)", - "object_timerange": "[0:0_10:0)", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" - } - ] - }, - { - "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", - "timerange": "[10:0_20:0)", - "object_timerange": "[150:0_200:0)", - "ts_offset": "-100:0", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" - } - ] - }, - { - "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "timerange": "[20:0_30:0)", - "object_timerange": "[0:0_30:0)", - "ts_offset": "0:0", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" - } - ] - } -] \ No newline at end of file + { + "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "timerange": "[0:0_10:0)", + "object_timerange": "[0:0_10:0)", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" + } + ] + }, + { + "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", + "timerange": "[10:0_20:0)", + "object_timerange": "[150:0_200:0)", + "ts_offset": "-100:0", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" + } + ] + }, + { + "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "timerange": "[20:0_30:0)", + "object_timerange": "[0:0_30:0)", + "ts_offset": "0:0", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" + } + ] + } +] diff --git a/api/examples/flow-segments-get-200.json b/api/examples/flow-segments-get-200.json index 53c4cd94..1e444fb7 100644 --- a/api/examples/flow-segments-get-200.json +++ b/api/examples/flow-segments-get-200.json @@ -1,32 +1,29 @@ [ - { - "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "timerange": "[0:0_10:0)", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" - } - ] - }, - { - "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", - "timerange": "[10:0_20:0)", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" - } - ] - }, - { - "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", - "timerange": "[20:0_30:0)", - "get_urls": - [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321" - } - ] - } -] \ No newline at end of file + { + "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "timerange": "[0:0_10:0)", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" + } + ] + }, + { + "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", + "timerange": "[10:0_20:0)", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35" + } + ] + }, + { + "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", + "timerange": "[20:0_30:0)", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321" + } + ] + } +] diff --git a/api/examples/flow-storage-post-201-wav.json b/api/examples/flow-storage-post-201-wav.json index 8580d868..662e83a2 100644 --- a/api/examples/flow-storage-post-201-wav.json +++ b/api/examples/flow-storage-post-201-wav.json @@ -1,25 +1,25 @@ { - "media_objects": [ - { - "object_id": "e0a3df95-d7f5-4991-be40-500aa22a1ce3", - "put_url": { - "url": "https://example.com/tams/object-proxy/500aa22a1ce3", - "content-type": "audio/wav" - } - }, - { - "object_id": "89f565ce-edd1-49fd-b6b7-900b6e4b545f", - "put_url": { - "url": "https://example.com/tams/object-proxy/900b6e4b545f", - "content-type": "audio/wav" - } - }, - { - "object_id": "45342cb7-5fc0-4223-b2a8-de05c16453d1", - "put_url": { - "url": "https://example.com/tams/object-proxy/de05c16453d1", - "content-type": "audio/wav" - } - } - ] + "media_objects": [ + { + "object_id": "e0a3df95-d7f5-4991-be40-500aa22a1ce3", + "put_url": { + "url": "https://example.com/tams/object-proxy/500aa22a1ce3", + "content-type": "audio/wav" + } + }, + { + "object_id": "89f565ce-edd1-49fd-b6b7-900b6e4b545f", + "put_url": { + "url": "https://example.com/tams/object-proxy/900b6e4b545f", + "content-type": "audio/wav" + } + }, + { + "object_id": "45342cb7-5fc0-4223-b2a8-de05c16453d1", + "put_url": { + "url": "https://example.com/tams/object-proxy/de05c16453d1", + "content-type": "audio/wav" + } + } + ] } diff --git a/api/examples/flow-storage-post-201.json b/api/examples/flow-storage-post-201.json index 839b7b48..faacbde3 100644 --- a/api/examples/flow-storage-post-201.json +++ b/api/examples/flow-storage-post-201.json @@ -1,74 +1,74 @@ { - "media_objects": [ - { - "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "a94cee18-1a40-5676-b788-1ac74c8a26e9", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/a94cee18-1a40-5676-b788-1ac74c8a26e9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "9d2b1d66-d785-5dcd-82d8-70d37d39259e", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/9d2b1d66-d785-5dcd-82d8-70d37d39259e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "e3a116a0-416c-5530-ae79-58f2ecea31cb", - "put_url": { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/e3a116a0-416c-5530-ae79-58f2ecea31cb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "8859eec0-cf59-54b2-8572-51ffb755b369", - "put_url": { - "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8859eec0-cf59-54b2-8572-51ffb755b369?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "5b143aae-fa75-50b4-9cba-b7c0676dba15", - "put_url": { - "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/5b143aae-fa75-50b4-9cba-b7c0676dba15?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "028ce16f-96ab-5334-bf3c-db95fdc73b17", - "put_url": { - "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/028ce16f-96ab-5334-bf3c-db95fdc73b17?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - }, - { - "object_id": "8264b3d3-d903-58b1-ab28-0ea164a22d2b", - "put_url": { - "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8264b3d3-d903-58b1-ab28-0ea164a22d2b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", - "content-type": "video/mp2t" - } - } - ] + "media_objects": [ + { + "object_id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "25be83fc-11d1-5743-9d47-6865cef5ea35", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/25be83fc-11d1-5743-9d47-6865cef5ea35?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "8b785422-6a82-5d60-b25a-f77e0a748321", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/8b785422-6a82-5d60-b25a-f77e0a748321?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "a94cee18-1a40-5676-b788-1ac74c8a26e9", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/a94cee18-1a40-5676-b788-1ac74c8a26e9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "9d2b1d66-d785-5dcd-82d8-70d37d39259e", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/9d2b1d66-d785-5dcd-82d8-70d37d39259e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "e3a116a0-416c-5530-ae79-58f2ecea31cb", + "put_url": { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/e3a116a0-416c-5530-ae79-58f2ecea31cb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "8859eec0-cf59-54b2-8572-51ffb755b369", + "put_url": { + "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8859eec0-cf59-54b2-8572-51ffb755b369?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "5b143aae-fa75-50b4-9cba-b7c0676dba15", + "put_url": { + "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/5b143aae-fa75-50b4-9cba-b7c0676dba15?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "028ce16f-96ab-5334-bf3c-db95fdc73b17", + "put_url": { + "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/028ce16f-96ab-5334-bf3c-db95fdc73b17?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + }, + { + "object_id": "8264b3d3-d903-58b1-ab28-0ea164a22d2b", + "put_url": { + "url": "https://store.example.com/tams-c6b8e7cc-edd3-5f6d-9d79-4467d06eb8bf/8264b3d3-d903-58b1-ab28-0ea164a22d2b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=0&X-Amz-Date=20230316T120329Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=0", + "content-type": "video/mp2t" + } + } + ] } diff --git a/api/examples/flow-storage-post-object_ids.json b/api/examples/flow-storage-post-object_ids.json index ea4a6826..56a6c75d 100644 --- a/api/examples/flow-storage-post-object_ids.json +++ b/api/examples/flow-storage-post-object_ids.json @@ -1,7 +1,6 @@ { - "object_ids": - [ - "846023d3-612d-5014-bc47-88f6eb2d04bb", - "25be83fc-11d1-5743-9d47-6865cef5ea35" - ] + "object_ids": [ + "846023d3-612d-5014-bc47-88f6eb2d04bb", + "25be83fc-11d1-5743-9d47-6865cef5ea35" + ] } diff --git a/api/examples/flow-storage-post.json b/api/examples/flow-storage-post.json index 8e4079f3..59f9a5dc 100644 --- a/api/examples/flow-storage-post.json +++ b/api/examples/flow-storage-post.json @@ -1,3 +1,3 @@ { - "limit": 50 -} \ No newline at end of file + "limit": 50 +} diff --git a/api/examples/flow-tags-get-200.json b/api/examples/flow-tags-get-200.json index b16ff9f3..5e061ce4 100644 --- a/api/examples/flow-tags-get-200.json +++ b/api/examples/flow-tags-get-200.json @@ -1,3 +1,3 @@ { - "input_quality": "web" -} \ No newline at end of file + "input_quality": "web" +} diff --git a/api/examples/flows-get-200.json b/api/examples/flows-get-200.json index 3678ecf5..8dcb2b00 100644 --- a/api/examples/flows-get-200.json +++ b/api/examples/flows-get-200.json @@ -1,264 +1,122 @@ [ - { - "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "generation": 0, - "created": "2008-05-27T18:51:00Z", - "metadata_updated": "2023-09-14T09:45:26Z", - "segments_updated": "2023-09-14T09:45:26Z", - "description": "Big Buck Bunny", - "label": "bbb", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "contribution" - }, - "codec": "video/h264", - "container": "video/mp2t", - "avg_bit_rate": 2479, - "essence_parameters": - { - "frame_rate": - { - "numerator": 24, - "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 - }, - "pixel_aspect_ratio": - { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 2, - "horiz_chroma_subs": 2, - "avc_parameters": - { - "profile": 100, - "level": 31, - "flags": 0 - } - } + { + "id": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "generation": 0, + "created": "2008-05-27T18:51:00Z", + "metadata_updated": "2023-09-14T09:45:26Z", + "segments_updated": "2023-09-14T09:45:26Z", + "description": "Big Buck Bunny", + "label": "bbb", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "contribution" }, - { - "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", - "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", - "generation": 1, - "created": "2018-03-06T09:10:22Z", - "metadata_updated": "2018-03-06T09:12:22Z", - "segments_updated": "2018-03-06T11:14:32Z", - "description": "audio capture web", - "label": "capture_1", - "format": "urn:x-nmos:format:audio", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "web" - }, - "codec": "audio/aac", - "container": "video/mp2t", - "avg_bit_rate": 128, - "essence_parameters": - { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 24, - "codec_parameters": - { - "coded_frame_size": 1024, - "mp4_oti": 2 - } - } - }, - { - "id": "0fde9c11-da9d-434a-a113-d3b20a2cf251", - "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "generation": 0, - "created": "2018-03-06T09:10:22Z", - "metadata_updated": "2018-03-06T09:12:22Z", - "segments_updated": "2018-03-06T11:14:32Z", - "description": "video capture", - "label": "capture_1", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "intermediate" - }, - "codec": "video/raw", - "container": "video/quicktime", - "avg_bit_rate": 1658880, - "essence_parameters": - { - "frame_rate": - { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 8, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": - { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": - { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "unc_parameters": - { - "unc_type": "UYVY" - }, - "vert_chroma_subs": 1, - "horiz_chroma_subs": 2 - } - }, - { - "id": "1a670176-5b40-433b-9d66-8f90efc026b6", - "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", - "generation": 0, - "created": "2026-02-24T09:35:25Z", - "metadata_updated": "2026-02-24T09:35:25Z", - "segments_updated": "2026-02-24T14:28:11Z", - "description": "Video Flow in a MXF container, JPEG-2000 codec", - "label": "VFX Render - Full Quality", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "intermediate" - }, - "codec": "video/jp2", - "container": "application/mxf", - "avg_bit_rate": 250000, - "essence_parameters": - { - "frame_rate": - { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 10, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": - { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": - { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 1, - "horiz_chroma_subs": 1 - } + "codec": "video/h264", + "container": "video/mp2t", + "avg_bit_rate": 2479, + "essence_parameters": { + "frame_rate": { + "numerator": 24, + "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 + }, + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "vert_chroma_subs": 2, + "horiz_chroma_subs": 2, + "avc_parameters": { + "profile": 100, + "level": 31, + "flags": 0 + } + } + }, + { + "id": "6101df05-06bb-41b8-8af4-cf7cd33df209", + "source_id": "41d7f7eb-c48d-4513-9b37-17b418d26d7f", + "generation": 1, + "created": "2018-03-06T09:10:22Z", + "metadata_updated": "2018-03-06T09:12:22Z", + "segments_updated": "2018-03-06T11:14:32Z", + "description": "audio capture web", + "label": "capture_1", + "format": "urn:x-nmos:format:audio", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "web" }, - { - "id": "1491ecfb-813d-4453-9554-e417d03161ba", - "source_id": "3e6201e2-4b38-402a-a08f-e2529ec98229", - "generation": 1, - "created": "2026-02-24T09:35:25Z", - "metadata_updated": "2026-02-24T09:36:02Z", - "segments_updated": "2026-02-24T15:38:21Z", - "description": "Video Flow in a MXF container, H264 codec", - "label": "VFX Render - Proxy Quality", - "format": "urn:x-nmos:format:video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": - { - "input_quality": "web" - }, - "codec": "video/h264", - "container": "application/mxf", - "avg_bit_rate": 6000, - "essence_parameters": - { - "frame_rate": - { - "numerator": 50, - "denominator": 1 - }, - "frame_width": 1920, - "frame_height": 1080, - "bit_depth": 8, - "interlace_mode": "progressive", - "colorspace": "BT709", - "transfer_characteristic": "SDR", - "aspect_ratio": - { - "numerator": 16, - "denominator": 9 - }, - "pixel_aspect_ratio": - { - "numerator": 1, - "denominator": 1 - }, - "component_type": "YCbCr", - "vert_chroma_subs": 2, - "horiz_chroma_subs": 2, - "avc_parameters": - { - "profile": 100, - "level": 31, - "flags": 0 - } - } + "codec": "audio/aac", + "container": "video/mp2t", + "avg_bit_rate": 128, + "essence_parameters": { + "sample_rate": 48000, + "channels": 2, + "bit_depth": 24, + "codec_parameters": { + "coded_frame_size": 1024, + "mp4_oti": 2 + } + } + }, + { + "id": "0fde9c11-da9d-434a-a113-d3b20a2cf251", + "source_id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "generation": 0, + "created": "2018-03-06T09:10:22Z", + "metadata_updated": "2018-03-06T09:12:22Z", + "segments_updated": "2018-03-06T11:14:32Z", + "description": "video capture", + "label": "capture_1", + "format": "urn:x-nmos:format:video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "tags": { + "input_quality": "intermediate" }, - { - "id": "fd25a9fc-3b58-4dc1-93d4-81c52b206562", - "source_id": "8af9d4a3-aff7-44e8-b384-d2bfc0b93533", - "generation": 0, - "created": "2025-02-24T11:33:46Z", - "metadata_updated": "2025-02-24T11:33:46Z", - "segments_updated": "2025-02-24T11:48:22Z", - "description": "Radio off-air recording", - "label": "Radio off-air", - "format": "urn:x-nmos:format:audio", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "tags": { - "input_quality": "contribution" - }, - "codec": "audio/x-raw-int", - "container": "audio/wav", - "avg_bit_rate": 192, - "essence_parameters": { - "sample_rate": 48000, - "channels": 2, - "bit_depth": 16, - "unc_parameters": { - "unc_type": "interleaved" - } - } + "codec": "video/raw", + "container": "video/quicktime", + "avg_bit_rate": 1658880, + "essence_parameters": { + "frame_rate": { + "numerator": 50, + "denominator": 1 + }, + "frame_width": 1920, + "frame_height": 1080, + "bit_depth": 8, + "interlace_mode": "progressive", + "colorspace": "BT709", + "transfer_characteristic": "SDR", + "aspect_ratio": { + "numerator": 16, + "denominator": 9 + }, + "pixel_aspect_ratio": { + "numerator": 1, + "denominator": 1 + }, + "component_type": "YCbCr", + "unc_parameters": { + "unc_type": "UYVY" + }, + "vert_chroma_subs": 1, + "horiz_chroma_subs": 2 } -] \ No newline at end of file + } +] diff --git a/api/examples/objects-get-200.json b/api/examples/objects-get-200.json index 578aa5b9..783db6e2 100644 --- a/api/examples/objects-get-200.json +++ b/api/examples/objects-get-200.json @@ -1,15 +1,14 @@ { - "id": "846023d3-612d-5014-bc47-88f6eb2d04bb", - "referenced_by_flows": - [ - "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "0fde9c11-da9d-434a-a113-d3b20a2cf251" - ], - "first_referenced_by_flow": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", - "timerange": "[150:0_200:0)", - "get_urls": [ - { - "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" - } - ] + "id": "846023d3-612d-5014-bc47-88f6eb2d04bb", + "referenced_by_flows": [ + "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "0fde9c11-da9d-434a-a113-d3b20a2cf251" + ], + "first_referenced_by_flow": "4f79cfd1-c057-47f4-8e4d-1b126ca7bf34", + "timerange": "[150:0_200:0)", + "get_urls": [ + { + "url": "https://store.example.com/tams-e2b89b02-21e7-5f9d-aa2d-db38b01453c9/846023d3-612d-5014-bc47-88f6eb2d04bb" + } + ] } diff --git a/api/examples/service-get-200.json b/api/examples/service-get-200.json index 1dfa83bc..e02979c3 100644 --- a/api/examples/service-get-200.json +++ b/api/examples/service-get-200.json @@ -1,16 +1,15 @@ { - "name": "Example TAMS", - "description": "An example Time Addressable Media Store", - "type": "urn:x-tams:service.example", - "api_version": "1.0", - "service_version": "tams.1.10.0-da88b8b", - "event_stream_mechanisms": - [ - { - "name": "webhooks", - "docs": "https://bbc.github.io/tams/7.0/index.html#/operations/POST_webhooks" - } - ], - "min_object_timeout": "600:0", - "min_presigned_url_timeout": "610:0" -} \ No newline at end of file + "name": "Example TAMS", + "description": "An example Time Addressable Media Store", + "type": "urn:x-tams:service.example", + "api_version": "1.0", + "service_version": "tams.1.10.0-da88b8b", + "event_stream_mechanisms": [ + { + "name": "webhooks", + "docs": "https://bbc.github.io/tams/7.0/index.html#/operations/POST_webhooks" + } + ], + "min_object_timeout": "600:0", + "min_presigned_url_timeout": "610:0" +} diff --git a/api/examples/service-post.json b/api/examples/service-post.json index 6e5ad3ee..7c506a3a 100644 --- a/api/examples/service-post.json +++ b/api/examples/service-post.json @@ -1,4 +1,4 @@ { - "name": "Updated Name", - "description": "Updated description" -} \ No newline at end of file + "name": "Updated Name", + "description": "Updated description" +} diff --git a/api/examples/source-get-200-basic.json b/api/examples/source-get-200-basic.json index ac6e1d40..21f2355f 100644 --- a/api/examples/source-get-200-basic.json +++ b/api/examples/source-get-200-basic.json @@ -1,13 +1,13 @@ { - "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "format": "urn:x-nmos:format:video", - "label": "bbb", - "description": "Big Buck Bunny video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "created": "2008-05-27T18:51:00Z", - "updated": "2008-05-27T18:51:00Z", - "collected_by": [ - "86761f3a-5998-4cfe-9a89-8459bcb8ea52" - ] -} \ No newline at end of file + "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "format": "urn:x-nmos:format:video", + "label": "bbb", + "description": "Big Buck Bunny video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "updated": "2008-05-27T18:51:00Z", + "collected_by": [ + "86761f3a-5998-4cfe-9a89-8459bcb8ea52" + ] +} diff --git a/api/examples/source-get-200-multi.json b/api/examples/source-get-200-multi.json index 7bf1cbd8..4ad9dc56 100644 --- a/api/examples/source-get-200-multi.json +++ b/api/examples/source-get-200-multi.json @@ -1,20 +1,20 @@ { - "id": "86761f3a-5998-4cfe-9a89-8459bcb8ea52", - "format": "urn:x-nmos:format:multi", - "label": "bbb", - "description": "Big Buck Bunny", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "created": "2008-05-27T18:51:00Z", - "updated": "2008-05-27T18:51:00Z", - "source_collection": [ - { - "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "role": "video" - }, - { - "id": "7ba3fed1-3fd3-4f0e-8488-92c4ffe13838", - "role": "audio" - } - ] -} \ No newline at end of file + "id": "86761f3a-5998-4cfe-9a89-8459bcb8ea52", + "format": "urn:x-nmos:format:multi", + "label": "bbb", + "description": "Big Buck Bunny", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "updated": "2008-05-27T18:51:00Z", + "source_collection": [ + { + "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "role": "video" + }, + { + "id": "7ba3fed1-3fd3-4f0e-8488-92c4ffe13838", + "role": "audio" + } + ] +} diff --git a/api/examples/sources-get-200.json b/api/examples/sources-get-200.json index 8faabde7..24be22ed 100644 --- a/api/examples/sources-get-200.json +++ b/api/examples/sources-get-200.json @@ -1,48 +1,45 @@ [ - { + { + "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", + "format": "urn:x-nmos:format:video", + "label": "bbb", + "description": "Big Buck Bunny video", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "updated": "2008-05-27T18:51:00Z", + "collected_by": [ + "86761f3a-5998-4cfe-9a89-8459bcb8ea52" + ] + }, + { + "id": "86761f3a-5998-4cfe-9a89-8459bcb8ea52", + "format": "urn:x-nmos:format:multi", + "label": "bbb", + "description": "Big Buck Bunny", + "created_by": "tams-dev", + "updated_by": "tams-dev", + "created": "2008-05-27T18:51:00Z", + "updated": "2008-05-27T18:51:00Z", + "source_collection": [ + { "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "format": "urn:x-nmos:format:video", - "label": "bbb", - "description": "Big Buck Bunny video", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "created": "2008-05-27T18:51:00Z", - "updated": "2008-05-27T18:51:00Z", - "collected_by": - [ - "86761f3a-5998-4cfe-9a89-8459bcb8ea52" - ] - }, - { - "id": "86761f3a-5998-4cfe-9a89-8459bcb8ea52", - "format": "urn:x-nmos:format:multi", - "label": "bbb", - "description": "Big Buck Bunny", - "created_by": "tams-dev", - "updated_by": "tams-dev", - "created": "2008-05-27T18:51:00Z", - "updated": "2008-05-27T18:51:00Z", - "source_collection": - [ - { - "id": "2aa143ac-0ab7-4d75-bc32-5c00c13d186f", - "role": "video" - }, - { - "id": "7ba3fed1-3fd3-4f0e-8488-92c4ffe13838", - "role": "audio" - } - ] - }, - { + "role": "video" + }, + { "id": "7ba3fed1-3fd3-4f0e-8488-92c4ffe13838", - "format": "urn:x-nmos:format:audio", - "description": "Big Buck Bunny audio", - "created": "2008-05-27T18:51:00Z", - "updated": "2008-05-27T18:51:00Z", - "collected_by": - [ - "86761f3a-5998-4cfe-9a89-8459bcb8ea52" - ] - } -] \ No newline at end of file + "role": "audio" + } + ] + }, + { + "id": "7ba3fed1-3fd3-4f0e-8488-92c4ffe13838", + "format": "urn:x-nmos:format:audio", + "description": "Big Buck Bunny audio", + "created": "2008-05-27T18:51:00Z", + "updated": "2008-05-27T18:51:00Z", + "collected_by": [ + "86761f3a-5998-4cfe-9a89-8459bcb8ea52" + ] + } +] diff --git a/api/examples/storage-backends-get-200.json b/api/examples/storage-backends-get-200.json index 29197d84..65b8e8ce 100644 --- a/api/examples/storage-backends-get-200.json +++ b/api/examples/storage-backends-get-200.json @@ -1,21 +1,21 @@ [ - { - "id": "60af2ab4-e8a5-4c65-a09b-d35983680315", - "label": "example-store-name", - "store_type": "http_object_store", - "provider": "example-cloud-provider", - "region": "eu-west-1", - "availability_zone": "a", - "store_product": "example-storage-product", - "default_storage": true - }, - { - "id": "323367fd-21bb-4f2e-ad38-faf048c4ccfc", - "label": "example-alternative-store-name", - "store_type": "http_object_store", - "provider": "example-cloud-provider", - "region": "eu-west-2", - "availability_zone": "a", - "store_product": "example-storage-product" - } -] \ No newline at end of file + { + "id": "60af2ab4-e8a5-4c65-a09b-d35983680315", + "label": "example-store-name", + "store_type": "http_object_store", + "provider": "example-cloud-provider", + "region": "eu-west-1", + "availability_zone": "a", + "store_product": "example-storage-product", + "default_storage": true + }, + { + "id": "323367fd-21bb-4f2e-ad38-faf048c4ccfc", + "label": "example-alternative-store-name", + "store_type": "http_object_store", + "provider": "example-cloud-provider", + "region": "eu-west-2", + "availability_zone": "a", + "store_product": "example-storage-product" + } +] diff --git a/api/examples/webhook-get-200-list.json b/api/examples/webhook-get-200-list.json index eb0e963d..df2b470c 100644 --- a/api/examples/webhook-get-200-list.json +++ b/api/examples/webhook-get-200-list.json @@ -1,12 +1,12 @@ [ - { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "url": "https://hook.example.com", - "api_key_name": "Authorization", - "events": [ - "flows/created", - "flows/updated" - ], - "status": "started" - } -] \ No newline at end of file + { + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "url": "https://hook.example.com", + "api_key_name": "Authorization", + "events": [ + "flows/created", + "flows/updated" + ], + "status": "started" + } +] diff --git a/api/examples/webhook-get-200.json b/api/examples/webhook-get-200.json index 065723c1..67b1d7b4 100644 --- a/api/examples/webhook-get-200.json +++ b/api/examples/webhook-get-200.json @@ -1,10 +1,10 @@ { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "url": "https://hook.example.com", - "api_key_name": "Authorization", - "events": [ - "flows/created", - "flows/updated" - ], - "status": "started" -} \ No newline at end of file + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "url": "https://hook.example.com", + "api_key_name": "Authorization", + "events": [ + "flows/created", + "flows/updated" + ], + "status": "started" +} diff --git a/api/examples/webhook-post.json b/api/examples/webhook-post.json index f470d195..0578db5d 100644 --- a/api/examples/webhook-post.json +++ b/api/examples/webhook-post.json @@ -1,9 +1,9 @@ { - "url": "https://hook.example.com", - "api_key_name": "Authorization", - "api_key_value": "Bearer 21238dksdjqwpqscj9", - "events": [ - "flows/created", - "flows/updated" - ] -} \ No newline at end of file + "url": "https://hook.example.com", + "api_key_name": "Authorization", + "api_key_value": "Bearer 21238dksdjqwpqscj9", + "events": [ + "flows/created", + "flows/updated" + ] +} diff --git a/api/examples/webhook-put.json b/api/examples/webhook-put.json index f7fb7fa8..fdbc1dbd 100644 --- a/api/examples/webhook-put.json +++ b/api/examples/webhook-put.json @@ -1,11 +1,11 @@ { - "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", - "url": "https://hook.example.com", - "api_key_name": "Authorization", - "api_key_value": "Bearer 21238dksdjqwpqscj9", - "events": [ - "flows/created", - "flows/updated" - ], - "status": "created" -} \ No newline at end of file + "id": "e85efab4-993b-4ad6-9af3-4cd8d0d38860", + "url": "https://hook.example.com", + "api_key_name": "Authorization", + "api_key_value": "Bearer 21238dksdjqwpqscj9", + "events": [ + "flows/created", + "flows/updated" + ], + "status": "created" +} diff --git a/api/schemas/collection-item.json b/api/schemas/collection-item.json index 991a85c9..17445015 100644 --- a/api/schemas/collection-item.json +++ b/api/schemas/collection-item.json @@ -1,19 +1,19 @@ { - "title": "Collection Item", - "description": "Describes how an entity (Source or Flow) is collected into another entity of the same type", - "type": "object", - "required": [ - "id", - "role" - ], - "properties": { - "id": { - "description": "Source or Flow Identifier of the member of this collection. Sources MUST only collect Sources, and Flows MUST only collect Flows. Must already be registered in this service instance", - "$ref": "uuid.json" - }, - "role": { - "description": "A human-readable role of the element in this collection (e.g. 'R' to denote a right audio channel in a collection of mono audio Sources)", - "type": "string" - } + "title": "Collection Item", + "description": "Describes how an entity (Source or Flow) is collected into another entity of the same type", + "type": "object", + "required": [ + "id", + "role" + ], + "properties": { + "id": { + "description": "Source or Flow Identifier of the member of this collection. Sources MUST only collect Sources, and Flows MUST only collect Flows. Must already be registered in this service instance", + "$ref": "uuid.json" + }, + "role": { + "description": "A human-readable role of the element in this collection (e.g. 'R' to denote a right audio channel in a collection of mono audio Sources)", + "type": "string" } -} \ No newline at end of file + } +} diff --git a/api/schemas/container-mapping.json b/api/schemas/container-mapping.json index 10cecdbf..d1492b57 100644 --- a/api/schemas/container-mapping.json +++ b/api/schemas/container-mapping.json @@ -1,72 +1,72 @@ { - "title": "Container Mapping", - "description": "Defines the location of Flow essence data in a container track", - "type": "object", - "properties": { - "track_index": { - "description": "A zero-based and sequential track index in the container. This assumes a reliable ordering of tracks", + "title": "Container Mapping", + "description": "Defines the location of Flow essence data in a container track", + "type": "object", + "properties": { + "track_index": { + "description": "A zero-based and sequential track index in the container. This assumes a reliable ordering of tracks", + "type": "integer", + "minimum": 0 + }, + "format_track_index": { + "description": "A zero-based and sequential track index in the container for a particular Flow format. A container with a video and 2 audio tracks would have a format_track_index 0 for the video Flow and format_track_index 0 and 1 for the audio Flows. This assumes a reliable ordering of tracks for each Flow format", + "type": "integer", + "minimum": 0 + }, + "audio_track": { + "description": "Mapping for channels in audio tracks to the Flow channels", + "type": "object", + "properties": { + "channel_numbers": { + "description": "Array of (zero-based) container channel numbers in Flow order", + "type": "array", + "minItems": 1, + "items": { "type": "integer", "minimum": 0 + } }, - "format_track_index": { - "description": "A zero-based and sequential track index in the container for a particular Flow format. A container with a video and 2 audio tracks would have a format_track_index 0 for the video Flow and format_track_index 0 and 1 for the audio Flows. This assumes a reliable ordering of tracks for each Flow format", - "type": "integer", - "minimum": 0 - }, - "audio_track": { - "description": "Mapping for channels in audio tracks to the Flow channels", - "type": "object", - "properties": { - "channel_numbers": { - "description": "Array of (zero-based) container channel numbers in Flow order", - "type": "array", - "minItems": 1, - "items": { - "type": "integer", - "minimum": 0 - } - }, - "channel_range": { - "description": "Inclusive range of (zero-based) container channel numbers", - "type": "string", - "pattern": "^[0-9]+_[0-9]+$" - } - } - }, - "mp2ts_container": { - "description": "Mapping to MPEG-2 Transport Stream containers, ISO/IEC 13818-1 or ITU-T Recommendation H.222.0", - "type": "object", - "properties": { - "pid": { - "description": "The packet ID for the elementary stream packets", - "type": "integer" - } - } - }, - "mxf_container": { - "description": "Mapping to Material Exchange Format containers, SMPTE ST 377-1", - "type": "object", - "properties": { - "package_uid": { - "description": "The package UID. Either a SMPTE UMID URN or UUID URN", - "type": "string", - "pattern": "^urn:smpte:umid:[0-9a-fA-F]{8}(.[0-9a-fA-F]{8}){7}$|^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" - }, - "track_id": { - "description": "The track ID in the package", - "type": "integer" - } - } + "channel_range": { + "description": "Inclusive range of (zero-based) container channel numbers", + "type": "string", + "pattern": "^[0-9]+_[0-9]+$" + } + } + }, + "mp2ts_container": { + "description": "Mapping to MPEG-2 Transport Stream containers, ISO/IEC 13818-1 or ITU-T Recommendation H.222.0", + "type": "object", + "properties": { + "pid": { + "description": "The packet ID for the elementary stream packets", + "type": "integer" + } + } + }, + "mxf_container": { + "description": "Mapping to Material Exchange Format containers, SMPTE ST 377-1", + "type": "object", + "properties": { + "package_uid": { + "description": "The package UID. Either a SMPTE UMID URN or UUID URN", + "type": "string", + "pattern": "^urn:smpte:umid:[0-9a-fA-F]{8}(.[0-9a-fA-F]{8}){7}$|^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" }, - "isobmff_container": { - "description": "Mapping to ISO Base Media File Format (e.g. MP4 and MOV) containers, ISO/IEC 14496-12", - "type": "object", - "properties": { - "track_id": { - "description": "The track ID", - "type": "integer" - } - } + "track_id": { + "description": "The track ID in the package", + "type": "integer" + } + } + }, + "isobmff_container": { + "description": "Mapping to ISO Base Media File Format (e.g. MP4 and MOV) containers, ISO/IEC 14496-12", + "type": "object", + "properties": { + "track_id": { + "description": "The track ID", + "type": "integer" } + } } + } } diff --git a/api/schemas/content-format.json b/api/schemas/content-format.json index 9b0ba74f..6e591a08 100644 --- a/api/schemas/content-format.json +++ b/api/schemas/content-format.json @@ -1,13 +1,13 @@ { - "title": "Content Format", - "description": "Identifies the content format for a Flow or Source using a URN string", - "type": "string", - "format": "uri", - "enum": [ - "urn:x-nmos:format:video", - "urn:x-tam:format:image", - "urn:x-nmos:format:audio", - "urn:x-nmos:format:data", - "urn:x-nmos:format:multi" - ] - } \ No newline at end of file + "title": "Content Format", + "description": "Identifies the content format for a Flow or Source using a URN string", + "type": "string", + "format": "uri", + "enum": [ + "urn:x-nmos:format:video", + "urn:x-tam:format:image", + "urn:x-nmos:format:audio", + "urn:x-nmos:format:data", + "urn:x-nmos:format:multi" + ] +} diff --git a/api/schemas/deletion-request.json b/api/schemas/deletion-request.json index 88362b31..5aa84d87 100644 --- a/api/schemas/deletion-request.json +++ b/api/schemas/deletion-request.json @@ -1,67 +1,67 @@ { - "title": "Deletion Request", - "description": "Describes an ongoing deletion request", - "type": "object", - "required": [ - "id", - "flow_id", - "timerange_to_delete", - "delete_flow", - "status" - ], - "properties": { - "id": { - "description": "Deletion Request ID", - "$ref": "uuid.json" - }, - "flow_id": { - "description": "ID of the Flow to which the deletion request relates", - "$ref": "uuid.json" - }, - "timerange_to_delete": { - "description": "The timerange of Flow Segments to be deleted in this request, as described by the [TimeRange](#/schemas/timerange) type", - "$ref": "timerange.json" - }, - "timerange_remaining": { - "description": "The timerange of Flow Segments not yet deleted by this request, as described by the [TimeRange](#/schemas/timerange) type", - "$ref": "timerange.json" - }, - "delete_flow": { - "description": "Whether the Flow should be deleted once the timerange has been", - "type": "boolean" - }, - "created": { - "description": "Date/Time when this deletion request was created", - "type": "string", - "format": "date-time" - }, - "created_by": { - "description": "A string identifier for the entity that created the deletion request. Service implementations SHOULD set suitable default values for `created_by` based on the principal accessing the system.", - "type": "string" - }, - "updated": { - "description": "Date/Time when this deletion request was updated", - "type": "string", - "format": "date-time" - }, - "expiry": { - "description": "Date/Time when this deletion request will be deleted", - "type": "string", - "format": "date-time" - }, - "status": { - "description": "Status of the delete request", - "type": "string", - "enum": [ - "created", - "started", - "done", - "error" - ] - }, - "error": { - "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", - "$ref": "error.json" - } + "title": "Deletion Request", + "description": "Describes an ongoing deletion request", + "type": "object", + "required": [ + "id", + "flow_id", + "timerange_to_delete", + "delete_flow", + "status" + ], + "properties": { + "id": { + "description": "Deletion Request ID", + "$ref": "uuid.json" + }, + "flow_id": { + "description": "ID of the Flow to which the deletion request relates", + "$ref": "uuid.json" + }, + "timerange_to_delete": { + "description": "The timerange of Flow Segments to be deleted in this request, as described by the [TimeRange](#/schemas/timerange) type", + "$ref": "timerange.json" + }, + "timerange_remaining": { + "description": "The timerange of Flow Segments not yet deleted by this request, as described by the [TimeRange](#/schemas/timerange) type", + "$ref": "timerange.json" + }, + "delete_flow": { + "description": "Whether the Flow should be deleted once the timerange has been", + "type": "boolean" + }, + "created": { + "description": "Date/Time when this deletion request was created", + "type": "string", + "format": "date-time" + }, + "created_by": { + "description": "A string identifier for the entity that created the deletion request. Service implementations SHOULD set suitable default values for `created_by` based on the principal accessing the system.", + "type": "string" + }, + "updated": { + "description": "Date/Time when this deletion request was updated", + "type": "string", + "format": "date-time" + }, + "expiry": { + "description": "Date/Time when this deletion request will be deleted", + "type": "string", + "format": "date-time" + }, + "status": { + "description": "Status of the delete request", + "type": "string", + "enum": [ + "created", + "started", + "done", + "error" + ] + }, + "error": { + "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", + "$ref": "error.json" } -} \ No newline at end of file + } +} diff --git a/api/schemas/error.json b/api/schemas/error.json index 9ec1ed3a..afd85c7c 100644 --- a/api/schemas/error.json +++ b/api/schemas/error.json @@ -1,30 +1,32 @@ { - "title": "Error status metadata", - "description": "Provides more information for an error status.", - "type": "object", - "required": [ - "type", "summary", "time" - ], - "properties": { - "type": { - "description": "The error type name.", - "type": "string" - }, - "summary": { - "description": "Summary description of the error and causes.", - "type": "string" - }, - "traceback": { - "description": "Stack trace leading to error (as a list of strings)", - "type": "array", - "items": { - "type": "string" - } - }, - "time": { - "description": "Time at which the error ocurred, to aid in log correlation", - "type": "string", - "format": "date-time" - } + "title": "Error status metadata", + "description": "Provides more information for an error status.", + "type": "object", + "required": [ + "type", + "summary", + "time" + ], + "properties": { + "type": { + "description": "The error type name.", + "type": "string" + }, + "summary": { + "description": "Summary description of the error and causes.", + "type": "string" + }, + "traceback": { + "description": "Stack trace leading to error (as a list of strings)", + "type": "array", + "items": { + "type": "string" + } + }, + "time": { + "description": "Time at which the error ocurred, to aid in log correlation", + "type": "string", + "format": "date-time" } -} \ No newline at end of file + } +} diff --git a/api/schemas/event-stream-common.json b/api/schemas/event-stream-common.json index 13a1474d..a8a19adb 100644 --- a/api/schemas/event-stream-common.json +++ b/api/schemas/event-stream-common.json @@ -1,22 +1,22 @@ { - "title": "Event Stream Mechanism", - "description": "Describes an event stream mechanism available in this service instance", - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "description": "Name of this type of event stream mechanism. Must be unique. Any name defined in this specification is reserved", - "type": "string" - }, - "docs": { - "description": "Location (e.g. a URL) at which documentation for this event stream mechanism may be found", - "type": "string" - }, - "config": { - "type": "object", - "description": "Configuration options required to make use of this mechanism" - } + "title": "Event Stream Mechanism", + "description": "Describes an event stream mechanism available in this service instance", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "Name of this type of event stream mechanism. Must be unique. Any name defined in this specification is reserved", + "type": "string" + }, + "docs": { + "description": "Location (e.g. a URL) at which documentation for this event stream mechanism may be found", + "type": "string" + }, + "config": { + "type": "object", + "description": "Configuration options required to make use of this mechanism" } -} \ No newline at end of file + } +} diff --git a/api/schemas/flow-audio.json b/api/schemas/flow-audio.json index b4d30010..4dee0205 100644 --- a/api/schemas/flow-audio.json +++ b/api/schemas/flow-audio.json @@ -1,108 +1,87 @@ { - "title": "Audio Flow", - "description": "Describes an audio Flow", - "type": "object", - "allOf": - [ - { - "$ref": "flow-core.json" + "title": "Audio Flow", + "description": "Describes an audio Flow", + "type": "object", + "allOf": [ + { + "$ref": "flow-core.json" + }, + { + "type": "object", + "required": [ + "format", + "essence_parameters", + "codec" + ], + "properties": { + "format": { + "description": "The primary content type URN for the Flow.", + "type": "string", + "enum": [ + "urn:x-nmos:format:audio" + ] }, - { - "type": "object", - "required": - [ - "format", - "essence_parameters", - "codec" - ], - "properties": - { - "format": - { - "description": "The primary content type URN for the Flow.", - "type": "string", - "enum": - [ - "urn:x-nmos:format:audio" - ] + "essence_parameters": { + "title": "Audio Flow Essence Parameters", + "description": "Describes the parameters of the essence inside this audio Flow", + "type": "object", + "required": [ + "sample_rate", + "channels" + ], + "additionalProperties": false, + "properties": { + "sample_rate": { + "description": "The fixed number of samples per second.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "channels": { + "description": "The channel count.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "bit_depth": { + "description": "The number of significant bits used to represent the audio sample. The minumum number of bytes then equals `round_up(bit_depth / 8)`. If codec is `audio/x-raw-int` bit_depth must be set. If codec is `audio/x-raw-float` bit_depth must be set to 32 or 64", + "type": "integer", + "exclusiveMinimum": 0 + }, + "codec_parameters": { + "title": "Audio Codec Parameters", + "type": "object", + "required": [], + "properties": { + "coded_frame_size": { + "description": "The fixed number of samples per coded audio frame.", + "type": "integer" }, - "essence_parameters": - { - "title": "Audio Flow Essence Parameters", - "description": "Describes the parameters of the essence inside this audio Flow", - "type": "object", - "required": - [ - "sample_rate", - "channels" - ], - "additionalProperties": false, - "properties": - { - "sample_rate": - { - "description": "The fixed number of samples per second.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "channels": - { - "description": "The channel count.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "bit_depth": - { - "description": "The number of significant bits used to represent the audio sample. The minumum number of bytes then equals `round_up(bit_depth / 8)`. If codec is `audio/x-raw-int` bit_depth must be set. If codec is `audio/x-raw-float` bit_depth must be set to 32 or 64", - "type": "integer", - "exclusiveMinimum": 0 - }, - "codec_parameters": - { - "title": "Audio Codec Parameters", - "type": "object", - "required": - [], - "properties": - { - "coded_frame_size": - { - "description": "The fixed number of samples per coded audio frame.", - "type": "integer" - }, - "mp4_oti": - { - "description": "The MPEG-4 Object Type Identification. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#mpeg-4_audio", - "type": "integer" - } - } - }, - "unc_parameters": - { - "title": "Uncompressed Audio Parameters", - "type": "object", - "required": - [ - "unc_type" - ], - "properties": - { - "unc_type": - { - "description": "The uncompressed audio multi-channel representation type. If codec is `audio/x-raw-int` or `audio/x-raw-float`, unc_type must be set.", - "type": "string", - "enum": - [ - "interleaved", - "planar", - "pairs" - ] - } - } - } - } + "mp4_oti": { + "description": "The MPEG-4 Object Type Identification. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#mpeg-4_audio", + "type": "integer" } + } + }, + "unc_parameters": { + "title": "Uncompressed Audio Parameters", + "type": "object", + "required": [ + "unc_type" + ], + "properties": { + "unc_type": { + "description": "The uncompressed audio multi-channel representation type. If codec is `audio/x-raw-int` or `audio/x-raw-float`, unc_type must be set.", + "type": "string", + "enum": [ + "interleaved", + "planar", + "pairs" + ] + } + } } + } } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/flow-collection.json b/api/schemas/flow-collection.json index fa6cd71a..4e6dc6b0 100644 --- a/api/schemas/flow-collection.json +++ b/api/schemas/flow-collection.json @@ -1,21 +1,23 @@ { - "title": "Flow Collection", - "description": "Describes how Flows are collected into another Flow", - "type": "array", - "items": { + "title": "Flow Collection", + "description": "Describes how Flows are collected into another Flow", + "type": "array", + "items": { + "type": "object", + "title": "Flow Collection Item", + "allOf": [ + { + "$ref": "collection-item.json" + }, + { "type": "object", - "title": "Flow Collection Item", - "allOf": [ - { "$ref": "collection-item.json" }, - { - "type": "object", - "properties": { - "container_mapping": { - "description": "Describes the mapping of the Flow essence from this Flow collection's container", - "$ref": "container-mapping.json" - } - } - } - ] - } + "properties": { + "container_mapping": { + "description": "Describes the mapping of the Flow essence from this Flow collection's container", + "$ref": "container-mapping.json" + } + } + } + ] + } } diff --git a/api/schemas/flow-core.json b/api/schemas/flow-core.json index ba8a8146..369aa14a 100644 --- a/api/schemas/flow-core.json +++ b/api/schemas/flow-core.json @@ -1,153 +1,124 @@ { - "title": "Flow Core", - "description": "Describes a Flow (common properties to all Flows, imported by type-specific specifications)", - "type": "object", - "required": - [ - "id", - "source_id" - ], - "properties": - { - "id": - { - "description": "Flow identifier", - "$ref": "uuid.json" - }, - "source_id": - { - "description": "Source identifier", - "$ref": "uuid.json" - }, - "label": - { - "description": "Freeform string label for the Flow. This should be a very short, human-readable label that may be displayed in listings of Flows.", - "type": "string" - }, - "description": - { - "description": "Freeform text describing the Flow. This should be a human-readable description that may be showed in detailed views of Flows. The description should be longer and more detailed than `label`.", - "type": "string" - }, - "created_by": - { - "description": "A string identifier for the entity that created the Flow. Service 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" - }, - "updated_by": - { - "description": "A string identifier for the entity that updated the Flow metadata most recently. Service implementations SHOULD set suitable default values for `updated_by` based on the principal accessing the system, and MAY permit clients to edit the value, subject to suitable permissions-based limitations.", - "type": "string" - }, - "tags": - { - "description": "Key value is a freeform string. WARNING: When updating a Flow with `tags` set, `tags` will be replaced with the provided dictionary. `tags` WILL NOT be merged with the provided values. When `tags` is not set in the request, `tags` will be unset (i.e. set to `{}`). To update individual tags, clients should use the [Create or Update Flow Tag](#/operations/PUT_flows-flowId-tags-name) endpoint.", - "$ref": "tags.json" - }, - "metadata_version": - { - "description": "A change to the Flow metadata, not including metadata_version, metadata_updated, segments_updated, or Segments, results in a new version. If the metadata_version for Flow instances is identical then the metadata is identical. Service implementations SHOULD set suitable default values for `metadata_version` whenever Flow metadata is changed and `metadata_version` is either not set by the client, or set to it's existing value. Service implementations MAY permit clients to edit the value, subject to suitable permissions-based limitations. Where media is transfered between TAMS service instances without changing the Flow metadata, clients SHOULD maintain the `metadata_version`. To support this, service implementations SHOULD always accept the setting of `metadata_version` by the client on initial Flow creation. Service implementations SHOULD update this field where metadata is updated via child endpoints. Note that this specification places no requirements on incremental versioning. Service implementations may, for example, choose to use hashes or date-time version identifiers.", - "type": "string" - }, - "generation": - { - "description": "An indication of how many lossy encodings the Flow content has been through. This parameter provides a hint to clients as to which is the \"highest qualty\" Flow available to them. A Flow with a higher generation may contain less of the original information than a Flow with a lower generation. Where a Flow is captured straight from the orginating device (e.g. camera/microphone) in its highest quality, and there is no possibility of the content becoming available in a higher quality (e.g. via capture from ST2110 or SDI), it SHOULD have a `generation` of `0`. Where the originating device outputs multiple qualities of the Source, `generation` should represent the encoding processes each has been through as accurately as possible.", - "type": "integer", - "minimum": 0 - }, - "created": - { - "description": "The date-time the Flow was created in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "type": "string", - "format": "date-time" - }, - "metadata_updated": - { - "description": "The date-time the Flow metadata was updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "type": "string", - "format": "date-time" - }, - "segments_updated": - { - "description": "The date-time the Flow Segments were updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "type": "string", - "format": "date-time" - }, - "read_only": - { - "description": "If set to 'true', service implementations SHOULD reject client requests to update Flow metadata (other than the read_only property), and Flow Segments. Service implementations should also reject requests to the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage) endpoint for the Flow, and requests to delete the Flow.", - "type": "boolean" - }, - "codec": - { - "description": "A MIME type identification of the (lossy or lossless) coding used for the Flow content. Note that the `type` component of the container MIME type (i.e. the component before the `/`) may be different to the `type` component of the codec MIME type. e.g. An audio Flow may have `audio/aac` coded content may be wrapped in a `video/mp2t` container. Mime types from the [IANA registry](https://www.iana.org/assignments/media-types/media-types.xhtml) should be preferred. Where multiple MIME types are possible, the most common should be preferred. Where this is insufficient, the maintainers of the TAMS repository may create an application note advising which MIME type to use.", - "$ref": "mime-type.json" - }, - "container": - { - "description": "The container MIME type for Flow Segments. Note that the `type` component of the container MIME type (i.e. the component before the `/`) may be different to the `type` component of the codec MIME type. e.g. An audio Flow may have `audio/aac` coded content may be wrapped in a `video/mp2t` container. Where multiple types exist for a subtype (e.g. `video/mp4`, `audio/mp4`, `application/mp4`), the closest MIME type to the Flow `format` should be used (e.g. `audio/mp4` for a Flow `format` of `urn:x-nmos:format:audio`). Mime types from the [IANA registry](https://www.iana.org/assignments/media-types/media-types.xhtml) should be preferred. Where multiple MIME types are possible, the most common should be preferred. Where this is insufficient, the maintainers of the TAMS repository may create an application note advising which MIME type to use. Where the Flow does not reference any Media Object(s) directly (e.g. an empty Multi Flow that serves only to collect related mono-essence Flows that do reference Media Objects), this property MUST NOT be set.", - "$ref": "mime-type.json" - }, - "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) type. Service implementations MUST ignore this if given in a PUT request, and instead manage it internally.", - "$ref": "timerange.json" - }, - "flow_collection": - { - "description": "List of Flows that are collected together by this Flow.", - "$ref": "flow-collection.json" - }, - "collected_by": - { - "type": "array", - "description": "Flows that reference this Flow to include it in a collection. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "items": - { - "$ref": "uuid.json" - } - }, - "container_mapping": - { - "description": "Describes the mapping of the Flow essence from the this Flow's container", - "$ref": "container-mapping.json" + "title": "Flow Core", + "description": "Describes a Flow (common properties to all Flows, imported by type-specific specifications)", + "type": "object", + "required": [ + "id", + "source_id" + ], + "properties": { + "id": { + "description": "Flow identifier", + "$ref": "uuid.json" + }, + "source_id": { + "description": "Source identifier", + "$ref": "uuid.json" + }, + "label": { + "description": "Freeform string label for the Flow. This should be a very short, human-readable label that may be displayed in listings of Flows.", + "type": "string" + }, + "description": { + "description": "Freeform text describing the Flow. This should be a human-readable description that may be showed in detailed views of Flows. The description should be longer and more detailed than `label`.", + "type": "string" + }, + "created_by": { + "description": "A string identifier for the entity that created the Flow. Service 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" + }, + "updated_by": { + "description": "A string identifier for the entity that updated the Flow metadata most recently. Service implementations SHOULD set suitable default values for `updated_by` based on the principal accessing the system, and MAY permit clients to edit the value, subject to suitable permissions-based limitations.", + "type": "string" + }, + "tags": { + "description": "Key value is a freeform string. WARNING: When updating a Flow with `tags` set, `tags` will be replaced with the provided dictionary. `tags` WILL NOT be merged with the provided values. When `tags` is not set in the request, `tags` will be unset (i.e. set to `{}`). To update individual tags, clients should use the [Create or Update Flow Tag](#/operations/PUT_flows-flowId-tags-name) endpoint.", + "$ref": "tags.json" + }, + "metadata_version": { + "description": "A change to the Flow metadata, not including metadata_version, metadata_updated, segments_updated, or Segments, results in a new version. If the metadata_version for Flow instances is identical then the metadata is identical. Service implementations SHOULD set suitable default values for `metadata_version` whenever Flow metadata is changed and `metadata_version` is either not set by the client, or set to it's existing value. Service implementations MAY permit clients to edit the value, subject to suitable permissions-based limitations. Where media is transfered between TAMS service instances without changing the Flow metadata, clients SHOULD maintain the `metadata_version`. To support this, service implementations SHOULD always accept the setting of `metadata_version` by the client on initial Flow creation. Service implementations SHOULD update this field where metadata is updated via child endpoints. Note that this specification places no requirements on incremental versioning. Service implementations may, for example, choose to use hashes or date-time version identifiers.", + "type": "string" + }, + "generation": { + "description": "An indication of how many lossy encodings the Flow content has been through. This parameter provides a hint to clients as to which is the \"highest qualty\" Flow available to them. A Flow with a higher generation may contain less of the original information than a Flow with a lower generation. Where a Flow is captured straight from the orginating device (e.g. camera/microphone) in its highest quality, and there is no possibility of the content becoming available in a higher quality (e.g. via capture from ST2110 or SDI), it SHOULD have a `generation` of `0`. Where the originating device outputs multiple qualities of the Source, `generation` should represent the encoding processes each has been through as accurately as possible.", + "type": "integer", + "minimum": 0 + }, + "created": { + "description": "The date-time the Flow was created in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "metadata_updated": { + "description": "The date-time the Flow metadata was updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "segments_updated": { + "description": "The date-time the Flow Segments were updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "read_only": { + "description": "If set to 'true', service implementations SHOULD reject client requests to update Flow metadata (other than the read_only property), and Flow Segments. Service implementations should also reject requests to the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage) endpoint for the Flow, and requests to delete the Flow.", + "type": "boolean" + }, + "codec": { + "description": "A MIME type identification of the (lossy or lossless) coding used for the Flow content. Note that the `type` component of the container MIME type (i.e. the component before the `/`) may be different to the `type` component of the codec MIME type. e.g. An audio Flow may have `audio/aac` coded content may be wrapped in a `video/mp2t` container. Mime types from the [IANA registry](https://www.iana.org/assignments/media-types/media-types.xhtml) should be preferred. Where multiple MIME types are possible, the most common should be preferred. Where this is insufficient, the maintainers of the TAMS repository may create an application note advising which MIME type to use.", + "$ref": "mime-type.json" + }, + "container": { + "description": "The container MIME type for Flow Segments. Note that the `type` component of the container MIME type (i.e. the component before the `/`) may be different to the `type` component of the codec MIME type. e.g. An audio Flow may have `audio/aac` coded content may be wrapped in a `video/mp2t` container. Where multiple types exist for a subtype (e.g. `video/mp4`, `audio/mp4`, `application/mp4`), the closest MIME type to the Flow `format` should be used (e.g. `audio/mp4` for a Flow `format` of `urn:x-nmos:format:audio`). Mime types from the [IANA registry](https://www.iana.org/assignments/media-types/media-types.xhtml) should be preferred. Where multiple MIME types are possible, the most common should be preferred. Where this is insufficient, the maintainers of the TAMS repository may create an application note advising which MIME type to use. Where the Flow does not reference any Media Object(s) directly (e.g. an empty Multi Flow that serves only to collect related mono-essence Flows that do reference Media Objects), this property MUST NOT be set.", + "$ref": "mime-type.json" + }, + "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) type. Service implementations MUST ignore this if given in a PUT request, and instead manage it internally.", + "$ref": "timerange.json" + }, + "flow_collection": { + "description": "List of Flows that are collected together by this Flow.", + "$ref": "flow-collection.json" + }, + "collected_by": { + "type": "array", + "description": "Flows that reference this Flow to include it in a collection. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "items": { + "$ref": "uuid.json" + } + }, + "container_mapping": { + "description": "Describes the mapping of the Flow essence from the this Flow's container", + "$ref": "container-mapping.json" } -} \ No newline at end of file + } +} diff --git a/api/schemas/flow-data.json b/api/schemas/flow-data.json index 3dd84beb..7561b3ff 100644 --- a/api/schemas/flow-data.json +++ b/api/schemas/flow-data.json @@ -1,47 +1,39 @@ { - "title": "Data Flow", - "description": "Describes a data Flow", - "type": "object", - "allOf": - [ - { - "$ref": "flow-core.json" + "title": "Data Flow", + "description": "Describes a data Flow", + "type": "object", + "allOf": [ + { + "$ref": "flow-core.json" + }, + { + "type": "object", + "required": [ + "format", + "essence_parameters", + "codec" + ], + "properties": { + "format": { + "description": "The primary content type URN for the Flow.", + "type": "string", + "enum": [ + "urn:x-nmos:format:data" + ] }, - { - "type": "object", - "required": - [ - "format", - "essence_parameters", - "codec" - ], - "properties": - { - "format": - { - "description": "The primary content type URN for the Flow.", - "type": "string", - "enum": - [ - "urn:x-nmos:format:data" - ] - }, - "essence_parameters": - { - "title": "Data Flow Essence Parameters", - "description": "Describes the parameters of the essence inside this data Flow", - "type": "object", - "additionalProperties": false, - "properties": - { - "data_type": - { - "description": "The type of information encoded in the Flow, identified using a URN. e.g. The data_type may be urn:x-tams:data:bounding-box, and the codec `application/json`.", - "type": "string" - } - } - } + "essence_parameters": { + "title": "Data Flow Essence Parameters", + "description": "Describes the parameters of the essence inside this data Flow", + "type": "object", + "additionalProperties": false, + "properties": { + "data_type": { + "description": "The type of information encoded in the Flow, identified using a URN. e.g. The data_type may be urn:x-tams:data:bounding-box, and the codec `application/json`.", + "type": "string" } + } } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/flow-image.json b/api/schemas/flow-image.json index 3705aa2f..dcc15b1d 100644 --- a/api/schemas/flow-image.json +++ b/api/schemas/flow-image.json @@ -1,69 +1,69 @@ { - "title": "Image Flow", - "description": "Describes a still image Flow, for use by thumbnail tracks etc", - "type": "object", - "allOf": [ - { - "$ref": "flow-core.json" + "title": "Image Flow", + "description": "Describes a still image Flow, for use by thumbnail tracks etc", + "type": "object", + "allOf": [ + { + "$ref": "flow-core.json" + }, + { + "type": "object", + "required": [ + "format", + "essence_parameters", + "codec" + ], + "properties": { + "format": { + "description": "The primary content type URN for the Flow.", + "type": "string", + "enum": [ + "urn:x-tam:format:image" + ] }, - { - "type": "object", - "required": [ - "format", - "essence_parameters", - "codec" - ], - "properties": { - "format": { - "description": "The primary content type URN for the Flow.", - "type": "string", - "enum": [ - "urn:x-tam:format:image" - ] + "essence_parameters": { + "title": "Image Flow Essence Parameters", + "description": "Describes the parameters of the essence inside this image Flow", + "type": "object", + "required": [ + "frame_width", + "frame_height" + ], + "additionalProperties": false, + "properties": { + "frame_width": { + "description": "The width of the picture in pixels.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "frame_height": { + "description": "The height of the picture in pixels.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "aspect_ratio": { + "description": "The display aspect ratio. i.e. display_width / display_height", + "type": "object", + "required": [ + "numerator", + "denominator" + ], + "properties": { + "numerator": { + "description": "numerator", + "type": "integer", + "exclusiveMinimum": 0 }, - "essence_parameters": { - "title": "Image Flow Essence Parameters", - "description": "Describes the parameters of the essence inside this image Flow", - "type": "object", - "required": [ - "frame_width", - "frame_height" - ], - "additionalProperties": false, - "properties": { - "frame_width": { - "description": "The width of the picture in pixels.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "frame_height": { - "description": "The height of the picture in pixels.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "aspect_ratio": { - "description": "The display aspect ratio. i.e. display_width / display_height", - "type": "object", - "required": [ - "numerator", - "denominator" - ], - "properties": { - "numerator": { - "description": "numerator", - "type": "integer", - "exclusiveMinimum": 0 - }, - "denominator": { - "description": "denominator", - "type": "integer", - "exclusiveMinimum": 0 - } - } - } - } + "denominator": { + "description": "denominator", + "type": "integer", + "exclusiveMinimum": 0 } + } } + } } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/flow-multi.json b/api/schemas/flow-multi.json index 3fe24ceb..f0b51000 100644 --- a/api/schemas/flow-multi.json +++ b/api/schemas/flow-multi.json @@ -1,30 +1,25 @@ { - "title": "Multi-essence Flow", - "description": "Describes a multi-essence Flow", - "type": "object", - "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" - ] - } - } + "title": "Multi-essence Flow", + "description": "Describes a multi-essence Flow", + "type": "object", + "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" + ] } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/flow-segment-bulk-failure.json b/api/schemas/flow-segment-bulk-failure.json index 6a727608..544b44c3 100644 --- a/api/schemas/flow-segment-bulk-failure.json +++ b/api/schemas/flow-segment-bulk-failure.json @@ -1,34 +1,35 @@ { - "title": "Failed Segments", - "description": "List of Segments that have failed to register", - "type": "object", - "required": [ - "failed_segments" - ], - "properties": { - "failed_segments": { - "description": "The list of Segments which have failed to register with the service instance", - "type": "array", - "items": { - "description": "Failed Segment details", - "type": "object", - "required": [ - "object_id" - ], - "properties": { - "object_id": { - "description": "The Object ID of the Segment which has failed to register with the service instance", - "type": "string" }, - "timerange": { - "description": "The timerange of Segment that has failed, as described by the [TimeRange](#/schemas/timerange) type", - "$ref": "timerange.json" - }, - "error": { - "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", - "$ref": "error.json" - } - } - } + "title": "Failed Segments", + "description": "List of Segments that have failed to register", + "type": "object", + "required": [ + "failed_segments" + ], + "properties": { + "failed_segments": { + "description": "The list of Segments which have failed to register with the service instance", + "type": "array", + "items": { + "description": "Failed Segment details", + "type": "object", + "required": [ + "object_id" + ], + "properties": { + "object_id": { + "description": "The Object ID of the Segment which has failed to register with the service instance", + "type": "string" + }, + "timerange": { + "description": "The timerange of Segment that has failed, as described by the [TimeRange](#/schemas/timerange) type", + "$ref": "timerange.json" + }, + "error": { + "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", + "$ref": "error.json" + } } + } } -} \ No newline at end of file + } +} diff --git a/api/schemas/flow-segment-post.json b/api/schemas/flow-segment-post.json index 9bbdf0a6..10dcb65b 100644 --- a/api/schemas/flow-segment-post.json +++ b/api/schemas/flow-segment-post.json @@ -1,82 +1,66 @@ { - "title": "Flow Segment Post", - "description": "Provides the location and metadata of the media files corresponding to timerange Segments of a Flow.", - "type": "object", - "required": - [ - "object_id", - "timerange" - ], - "properties": - { - "object_id": - { - "description": "The Object identifier for the Media Object.", + "title": "Flow Segment Post", + "description": "Provides the location and metadata of the media files corresponding to timerange Segments of a Flow.", + "type": "object", + "required": [ + "object_id", + "timerange" + ], + "properties": { + "object_id": { + "description": "The Object identifier for the Media Object.", + "type": "string" + }, + "ts_offset": { + "description": "The timestamp offset between the sample timestamps stored in, or inferred from, the media file and the corresponding timestamp in the Segment, ie. ts_offset = segment ts - media object ts. Assumed to be 0:0 if not set. Format as described by the [Timestamp](#/schemas/timestamp) type", + "$ref": "timestamp.json" + }, + "timerange": { + "description": "The timerange for the samples contained in the Segment. The timerange start is always inclusive. If samples have a duration then the timerange end is exclusive and covers at least the duration of the last sample. The exclusive timerange end will typically be set to the timestamp of the next sample. If the samples don't have a duration then the timerange end is inclusive. Format is described by the [TimeRange](#/schemas/timerange) type. Note that where temporal re-ordering is used, the timerange and samples refers to the presentation timeline.", + "$ref": "timerange.json" + }, + "object_timerange": { + "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline. If not given at first registration of an Object, defaults to `timerange - ts_offset` on the assumption that the Flow Segment uses the entire Media Object. Clients should not set this when Media Objects are re-used. Service implementations should reject requests where `object_timerange` is set to a value that conflicts with the existing Media Object metadata.", + "$ref": "timerange.json" + }, + "last_duration": { + "description": "The difference between the exclusive end of the `timerange` and the last sample timestamp. Format as described by the [Timestamp](#/schemas/timestamp) type, but cannot be negative", + "$ref": "timestamp.json" + }, + "sample_offset": { + "description": "The start of the Segment represented as a count of samples from the start of the Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. Assumed to be 0 if not set. Must be set if the Flow Segment doesn't start at the beginning of the Media Object. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", + "type": "integer", + "deprecated": true + }, + "sample_count": { + "description": "The count of samples in the Segment (which may be fewer than in the Object). The count could be less than expected given the Segment duration and rate if there are gaps. If not set, every sample from sample_offset onwards is used. Must be set if the Flow Segment doesn't use the entire Media Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", + "type": "integer", + "deprecated": true + }, + "get_urls": { + "description": "A list of URLs to which a GET request can be made to directly retrieve the contents of the Media Object. This is required by the `http_object_store` Storage Backend type, which is the only one currently described. Clients may choose any URL in the list and treat them as identical, however service instances may sort the list such that the preferred URL is first. `get_urls` should only be used to add uncontrolled URLs. URLs for the provided object_id controlled by the service instance will be populated automatically by the service instance.", + "type": "array", + "items": { + "type": "object", + "required": [ + "url", + "label" + ], + "properties": { + "url": { + "description": "A URL to which a GET request can be made to directly retrieve the contents of the Media Object. Clients should include credentials if the provide URL is on the same origin as the API endpoint", "type": "string" - }, - "ts_offset": - { - "description": "The timestamp offset between the sample timestamps stored in, or inferred from, the media file and the corresponding timestamp in the Segment, ie. ts_offset = segment ts - media object ts. Assumed to be 0:0 if not set. Format as described by the [Timestamp](#/schemas/timestamp) type", - "$ref": "timestamp.json" - }, - "timerange": - { - "description": "The timerange for the samples contained in the Segment. The timerange start is always inclusive. If samples have a duration then the timerange end is exclusive and covers at least the duration of the last sample. The exclusive timerange end will typically be set to the timestamp of the next sample. If the samples don't have a duration then the timerange end is inclusive. Format is described by the [TimeRange](#/schemas/timerange) type. Note that where temporal re-ordering is used, the timerange and samples refers to the presentation timeline.", - "$ref": "timerange.json" - }, - "object_timerange": - { - "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline. If not given at first registration of an Object, defaults to `timerange - ts_offset` on the assumption that the Flow Segment uses the entire Media Object. Clients should not set this when Media Objects are re-used. Service implementations should reject requests where `object_timerange` is set to a value that conflicts with the existing Media Object metadata.", - "$ref": "timerange.json" - }, - "last_duration": - { - "description": "The difference between the exclusive end of the `timerange` and the last sample timestamp. Format as described by the [Timestamp](#/schemas/timestamp) type, but cannot be negative", - "$ref": "timestamp.json" - }, - "sample_offset": - { - "description": "The start of the Segment represented as a count of samples from the start of the Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. Assumed to be 0 if not set. Must be set if the Flow Segment doesn't start at the beginning of the Media Object. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", - "type": "integer", - "deprecated": true - }, - "sample_count": - { - "description": "The count of samples in the Segment (which may be fewer than in the Object). The count could be less than expected given the Segment duration and rate if there are gaps. If not set, every sample from sample_offset onwards is used. Must be set if the Flow Segment doesn't use the entire Media Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", - "type": "integer", - "deprecated": true - }, - "get_urls": - { - "description": "A list of URLs to which a GET request can be made to directly retrieve the contents of the Media Object. This is required by the `http_object_store` Storage Backend type, which is the only one currently described. Clients may choose any URL in the list and treat them as identical, however service instances may sort the list such that the preferred URL is first. `get_urls` should only be used to add uncontrolled URLs. URLs for the provided object_id controlled by the service instance will be populated automatically by the service instance.", - "type": "array", - "items": - { - "type": "object", - "required": - [ - "url", - "label" - ], - "properties": - { - "url": - { - "description": "A URL to which a GET request can be made to directly retrieve the contents of the Media Object. Clients should include credentials if the provide URL is on the same origin as the API endpoint", - "type": "string" - }, - "label": - { - "description": "Label identifying this URL. Service implementations should reject any requests using labels that are already associated with Storage Backends. Service implementations should reject any requests containing multiple `get_urls` with the same `label`.", - "type": "string" - } - } - } - }, - "key_frame_count": - { - "description": "The number of key frames in the Media Object. This should be set greater than zero when the Media Object contains key frames that serve as a stream access point", - "type": "integer" + }, + "label": { + "description": "Label identifying this URL. Service implementations should reject any requests using labels that are already associated with Storage Backends. Service implementations should reject any requests containing multiple `get_urls` with the same `label`.", + "type": "string" + } } + } + }, + "key_frame_count": { + "description": "The number of key frames in the Media Object. This should be set greater than zero when the Media Object contains key frames that serve as a stream access point", + "type": "integer" } + } } diff --git a/api/schemas/flow-segment.json b/api/schemas/flow-segment.json index 3de8b525..ecbe0a0b 100644 --- a/api/schemas/flow-segment.json +++ b/api/schemas/flow-segment.json @@ -1,58 +1,49 @@ { - "type": "object", - "description": "Provides the location and metadata of the media files corresponding to timerange segments of a Flow.", - "title": "Flow Segment", - "allOf": - [ - { - "type": "object", - "required": - [ - "object_id", - "timerange" - ], - "properties": - { - "object_id": - { - "description": "The object store identifier for the Media Object.", - "type": "string" - }, - "ts_offset": - { - "description": "The timestamp offset between the sample timestamps stored in the media file and the corresponding timestamp in the Segment, ie. ts_offset = segment ts - media object ts. Assumed to be 0:0 if not set. Format as described by the [Timestamp](#/schemas/timestamp) type", - "$ref": "timestamp.json" - }, - "timerange": - { - "description": "The timerange for the samples contained in the Segment. The timerange start is always inclusive. If samples have a duration then the timerange end is exclusive and covers at least the duration of the last sample. The exclusive timerange end will typically be set to the timestamp of the next sample. If the samples don't have a duration then the timerange end is inclusive. Format is described by the [TimeRange](#/schemas/timerange) type. Note that where temporal re-ordering is used, the timerange and samples refers to the presentation timeline.", - "$ref": "timerange.json" - }, - "last_duration": - { - "description": "The difference between the exclusive end of the `timerange` and the last sample timestamp. Format as described by the [Timestamp](#/schemas/timestamp) type, but cannot be negative", - "$ref": "timestamp.json" - }, - "object_timerange": { - "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline.", - "$ref": "timerange.json" - }, - "sample_offset": - { - "description": "The start of the Segment represented as a count of samples from the start of the Media Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. Assumed to be 0 if not set. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", - "type": "integer", - "deprecated": true - }, - "sample_count": - { - "description": "The count of samples in the Segment (which may be fewer than in the Media Object). The count could be less than expected given the Segment duration and rate if there are gaps. If not set, every sample from sample_offset onwards is used. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", - "type": "integer", - "deprecated": true - } - } + "type": "object", + "description": "Provides the location and metadata of the media files corresponding to timerange segments of a Flow.", + "title": "Flow Segment", + "allOf": [ + { + "type": "object", + "required": [ + "object_id", + "timerange" + ], + "properties": { + "object_id": { + "description": "The object store identifier for the Media Object.", + "type": "string" }, - { - "$ref": "object-core.json" + "ts_offset": { + "description": "The timestamp offset between the sample timestamps stored in the media file and the corresponding timestamp in the Segment, ie. ts_offset = segment ts - media object ts. Assumed to be 0:0 if not set. Format as described by the [Timestamp](#/schemas/timestamp) type", + "$ref": "timestamp.json" + }, + "timerange": { + "description": "The timerange for the samples contained in the Segment. The timerange start is always inclusive. If samples have a duration then the timerange end is exclusive and covers at least the duration of the last sample. The exclusive timerange end will typically be set to the timestamp of the next sample. If the samples don't have a duration then the timerange end is inclusive. Format is described by the [TimeRange](#/schemas/timerange) type. Note that where temporal re-ordering is used, the timerange and samples refers to the presentation timeline.", + "$ref": "timerange.json" + }, + "last_duration": { + "description": "The difference between the exclusive end of the `timerange` and the last sample timestamp. Format as described by the [Timestamp](#/schemas/timestamp) type, but cannot be negative", + "$ref": "timestamp.json" + }, + "object_timerange": { + "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline.", + "$ref": "timerange.json" + }, + "sample_offset": { + "description": "The start of the Segment represented as a count of samples from the start of the Media Object. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. Assumed to be 0 if not set. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", + "type": "integer", + "deprecated": true + }, + "sample_count": { + "description": "The count of samples in the Segment (which may be fewer than in the Media Object). The count could be less than expected given the Segment duration and rate if there are gaps. If not set, every sample from sample_offset onwards is used. Note that a sample is a video frame or audio sample. A (coded) audio frame has multiple audio samples. DEPRECATED: Use object_timerange instead - see AppNote 0036. Service implementations SHOULD continue to store and return it if set.", + "type": "integer", + "deprecated": true } - ] -} \ No newline at end of file + } + }, + { + "$ref": "object-core.json" + } + ] +} diff --git a/api/schemas/flow-storage-post.json b/api/schemas/flow-storage-post.json index df85e17a..08ec3882 100644 --- a/api/schemas/flow-storage-post.json +++ b/api/schemas/flow-storage-post.json @@ -1,36 +1,36 @@ { - "title": "Flow Storage Post", - "description": "Post data for the Flow storage endpoint", - "type": "object", - "properties": { - "limit": { - "description": "Limit the number of Media Objects in each response page. Service implementations may specify their own default and maximum for the limit", - "type": "integer" - }, - "object_ids": { - "description": "Array of object_ids to use. The supplied object_ids must be new and not already in use in this TAMS service instance. A 400 response will be returned if any supplied object_id already exists.", - "type": "array", - "items": { - "type": "string" - } - }, - "storage_id": { - "description": "The Storage Backend to allocate storage in. A Storage Backend identifier as advertised at the [/service/storage-backends](#/operations/GET_storage-backends) endpoint. If not set the default, as advertised at the [/service/storage-backends](#/operations/GET_storage-backends) endpoint, will be used if available. An invalid Storage Backend identifier will result in a 400 error.", - "$ref": "uuid.json" - } + "title": "Flow Storage Post", + "description": "Post data for the Flow storage endpoint", + "type": "object", + "properties": { + "limit": { + "description": "Limit the number of Media Objects in each response page. Service implementations may specify their own default and maximum for the limit", + "type": "integer" }, - "not": { - "allOf": [ - { - "required": [ - "limit" - ] - }, - { - "required": [ - "object_ids" - ] - } - ] + "object_ids": { + "description": "Array of object_ids to use. The supplied object_ids must be new and not already in use in this TAMS service instance. A 400 response will be returned if any supplied object_id already exists.", + "type": "array", + "items": { + "type": "string" + } + }, + "storage_id": { + "description": "The Storage Backend to allocate storage in. A Storage Backend identifier as advertised at the [/service/storage-backends](#/operations/GET_storage-backends) endpoint. If not set the default, as advertised at the [/service/storage-backends](#/operations/GET_storage-backends) endpoint, will be used if available. An invalid Storage Backend identifier will result in a 400 error.", + "$ref": "uuid.json" } + }, + "not": { + "allOf": [ + { + "required": [ + "limit" + ] + }, + { + "required": [ + "object_ids" + ] + } + ] + } } diff --git a/api/schemas/flow-storage.json b/api/schemas/flow-storage.json index 4289ea9b..1942e9e7 100644 --- a/api/schemas/flow-storage.json +++ b/api/schemas/flow-storage.json @@ -18,7 +18,9 @@ "description": "The object store identifier for the Media Object.", "type": "string" }, - "put_url": { "$ref": "http-request.json" } + "put_url": { + "$ref": "http-request.json" + } } } } diff --git a/api/schemas/flow-video.json b/api/schemas/flow-video.json index 02b7e5e5..28894948 100644 --- a/api/schemas/flow-video.json +++ b/api/schemas/flow-video.json @@ -1,236 +1,243 @@ { - "title": "Video Flow", - "description": "Describes a video Flow", - "type": "object", - "allOf": [ - { - "$ref": "flow-core.json" + "title": "Video Flow", + "description": "Describes a video Flow", + "type": "object", + "allOf": [ + { + "$ref": "flow-core.json" + }, + { + "type": "object", + "required": [ + "format", + "essence_parameters", + "codec" + ], + "properties": { + "format": { + "description": "The primary content type URN for the Flow.", + "type": "string", + "enum": [ + "urn:x-nmos:format:video" + ] }, - { - "type": "object", - "required": [ - "format", - "essence_parameters", - "codec" - ], - "properties": { - "format": { - "description": "The primary content type URN for the Flow.", - "type": "string", - "enum": [ - "urn:x-nmos:format:video" - ] + "essence_parameters": { + "title": "Video Flow Essence Parameters", + "description": "Describes the parameters of the essence inside this video Flow", + "type": "object", + "required": [ + "frame_width", + "frame_height" + ], + "unevaluatedProperties": false, + "properties": { + "frame_width": { + "description": "The width of the picture in pixels.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "frame_height": { + "description": "The height of the picture in pixels.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "bit_depth": { + "description": "The number of significant bits used to represent the video component sample. If codec is `video/raw`, bit_depth must be set.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "interlace_mode": { + "description": "Interlaced video mode for frames in this Flow", + "type": "string", + "enum": [ + "progressive", + "interlaced_tff", + "interlaced_bff", + "interlaced_psf" + ] + }, + "colorspace": { + "description": "Colorspace used for the video", + "type": "string", + "enum": [ + "BT601", + "BT709", + "BT2020", + "BT2100" + ] + }, + "transfer_characteristic": { + "description": "Transfer characteristic", + "type": "string", + "enum": [ + "SDR", + "HLG", + "PQ" + ] + }, + "aspect_ratio": { + "description": "The display aspect ratio. i.e. display_width / display_height", + "type": "object", + "required": [ + "numerator", + "denominator" + ], + "properties": { + "numerator": { + "description": "numerator", + "type": "integer", + "exclusiveMinimum": 0 + }, + "denominator": { + "description": "denominator", + "type": "integer", + "exclusiveMinimum": 0 + } + } + }, + "pixel_aspect_ratio": { + "description": "The pixel aspect ratio. This is usually 1:1 (i.e. square pixels) for modern video. Some, usually older, video formats use non-square pixels e.g. some Standard Definition video. This is where that may be indicated.", + "type": "object", + "required": [ + "numerator", + "denominator" + ], + "properties": { + "numerator": { + "description": "numerator", + "type": "integer", + "exclusiveMinimum": 0 + }, + "denominator": { + "description": "denominator", + "type": "integer", + "exclusiveMinimum": 0 + } + } + }, + "component_type": { + "description": "Picture component representation.", + "type": "string", + "enum": [ + "YCbCr", + "RGB" + ] + }, + "horiz_chroma_subs": { + "description": "Horizontal chroma component sub-sampling. When unc_type is set to a YUV type, horiz_chroma_subs must be set.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "vert_chroma_subs": { + "description": "Vertical chroma component sub-sampling. When unc_type is set to a YUV type, vert_chroma_subs must be set.", + "type": "integer", + "exclusiveMinimum": 0 + }, + "unc_parameters": { + "title": "Uncompressed Video Parameters", + "type": "object", + "required": [ + "unc_type" + ], + "properties": { + "unc_type": { + "description": "Uncompressed picture packing type. If codec is `video/raw`, unc_type must be set.", + "type": "string", + "enum": [ + "planar", + "YUYV", + "UYVY", + "AYUV", + "v210", + "v216", + "RGB", + "RGBx", + "xRGB", + "BGRx", + "xBGR", + "RGBA", + "ARGB", + "BGRA", + "ABGR", + "alpha" + ] + } + } + }, + "avc_parameters": { + "title": "AVC Codec Parameters", + "type": "object", + "required": [ + "profile", + "level", + "flags" + ], + "properties": { + "profile": { + "description": "AVC / H.264 profile byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", + "type": "integer" }, - "essence_parameters": { - "title": "Video Flow Essence Parameters", - "description": "Describes the parameters of the essence inside this video Flow", - "type": "object", - "required": [ - "frame_width", - "frame_height" - ], - "unevaluatedProperties": false, - "properties": { - "frame_width": { - "description": "The width of the picture in pixels.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "frame_height": { - "description": "The height of the picture in pixels.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "bit_depth": { - "description": "The number of significant bits used to represent the video component sample. If codec is `video/raw`, bit_depth must be set.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "interlace_mode": { - "description": "Interlaced video mode for frames in this Flow", - "type": "string", - "enum": [ - "progressive", - "interlaced_tff", - "interlaced_bff", - "interlaced_psf" - ] - }, - "colorspace": { - "description": "Colorspace used for the video", - "type": "string", - "enum": [ - "BT601", - "BT709", - "BT2020", - "BT2100" - ] - }, - "transfer_characteristic": { - "description": "Transfer characteristic", - "type": "string", - "enum": [ - "SDR", - "HLG", - "PQ" - ] - }, - "aspect_ratio": { - "description": "The display aspect ratio. i.e. display_width / display_height", - "type": "object", - "required": [ - "numerator", - "denominator" - ], - "properties": { - "numerator": { - "description": "numerator", - "type": "integer", - "exclusiveMinimum": 0 - }, - "denominator": { - "description": "denominator", - "type": "integer", - "exclusiveMinimum": 0 - } - } - }, - "pixel_aspect_ratio": { - "description": "The pixel aspect ratio. This is usually 1:1 (i.e. square pixels) for modern video. Some, usually older, video formats use non-square pixels e.g. some Standard Definition video. This is where that may be indicated.", - "type": "object", - "required": [ - "numerator", - "denominator" - ], - "properties": { - "numerator": { - "description": "numerator", - "type": "integer", - "exclusiveMinimum": 0 - }, - "denominator": { - "description": "denominator", - "type": "integer", - "exclusiveMinimum": 0 - } - } - }, - "component_type": { - "description": "Picture component representation.", - "type": "string", - "enum": [ - "YCbCr", - "RGB" - ] - }, - "horiz_chroma_subs": { - "description": "Horizontal chroma component sub-sampling. When unc_type is set to a YUV type, horiz_chroma_subs must be set.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "vert_chroma_subs": { - "description": "Vertical chroma component sub-sampling. When unc_type is set to a YUV type, vert_chroma_subs must be set.", - "type": "integer", - "exclusiveMinimum": 0 - }, - "unc_parameters": { - "title": "Uncompressed Video Parameters", - "type": "object", - "required": [ - "unc_type" - ], - "properties": { - "unc_type": { - "description": "Uncompressed picture packing type. If codec is `video/raw`, unc_type must be set.", - "type": "string", - "enum": [ - "planar", - "YUYV", - "UYVY", - "AYUV", - "v210", - "v216", - "RGB", - "RGBx", - "xRGB", - "BGRx", - "xBGR", - "RGBA", - "ARGB", - "BGRA", - "ABGR", - "alpha" - ] - } - } - }, - "avc_parameters": { - "title": "AVC Codec Parameters", - "type": "object", - "required": [ - "profile", - "level", - "flags" - ], - "properties": { - "profile": { - "description": "AVC / H.264 profile byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", - "type": "integer" - }, - "level": { - "description": "AVC / H.264 level byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", - "type": "integer" - }, - "flags": { - "description": "AVC / H.264 flags byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", - "type": "integer" - } - } - }, - "frame_rate": { - "title": "Fixed Frame Rate", - "description": "The fixed number of frames per second. MUST be set if `vfr` is `false` or omitted. MUST NOT be set if `vfr` is `true`.", - "type": "object", - "required": [ - "numerator" - ], - "properties": { - "numerator": { - "description": "numerator", - "type": "integer", - "exclusiveMinimum": 0 - }, - "denominator": { - "description": "denominator", - "type": "integer", - "default": 1, - "exclusiveMinimum": 0 - } - } - }, - "vfr": { - "description": "If `true`, the frame rate of the Flow is variable and `frame_rate` MUST NOT be set. If `false` or omitted, the frame rate of the Flow is fixed and `frame_rate` MUST be set.", - "type": "boolean", - "default": false - } - }, - "if": { - "properties": { - "vfr": { - "enum": [false, null] - } - } - }, - "then": { - "required": ["frame_rate"] - }, - "else": { - "not": { - "required": ["frame_rate"] - } - } + "level": { + "description": "AVC / H.264 level byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", + "type": "integer" + }, + "flags": { + "description": "AVC / H.264 flags byte. For more information on the use of this property in codec strings, see https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#using_the_codecs_parameter", + "type": "integer" + } + } + }, + "frame_rate": { + "title": "Fixed Frame Rate", + "description": "The fixed number of frames per second. MUST be set if `vfr` is `false` or omitted. MUST NOT be set if `vfr` is `true`.", + "type": "object", + "required": [ + "numerator" + ], + "properties": { + "numerator": { + "description": "numerator", + "type": "integer", + "exclusiveMinimum": 0 + }, + "denominator": { + "description": "denominator", + "type": "integer", + "default": 1, + "exclusiveMinimum": 0 } + } + }, + "vfr": { + "description": "If `true`, the frame rate of the Flow is variable and `frame_rate` MUST NOT be set. If `false` or omitted, the frame rate of the Flow is fixed and `frame_rate` MUST be set.", + "type": "boolean", + "default": false + } + }, + "if": { + "properties": { + "vfr": { + "enum": [ + false, + null + ] + } + } + }, + "then": { + "required": [ + "frame_rate" + ] + }, + "else": { + "not": { + "required": [ + "frame_rate" + ] } + } } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/flow.json b/api/schemas/flow.json index 9a8b70a0..0548a21d 100644 --- a/api/schemas/flow.json +++ b/api/schemas/flow.json @@ -1,23 +1,22 @@ { - "title": "Flow", - "description": "Describes a Flow", - "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 + "title": "Flow", + "description": "Describes a Flow", + "type": "object", + "oneOf": [ + { + "$ref": "flow-video.json" + }, + { + "$ref": "flow-audio.json" + }, + { + "$ref": "flow-image.json" + }, + { + "$ref": "flow-data.json" + }, + { + "$ref": "flow-multi.json" + } + ] +} diff --git a/api/schemas/http-request.json b/api/schemas/http-request.json index 66e965d2..62406cef 100644 --- a/api/schemas/http-request.json +++ b/api/schemas/http-request.json @@ -1,30 +1,30 @@ { - "title": "HTTP Request", - "description": "Gives information on a particular http request a client should perform", - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "description": "The URL to make the request to. Where this URL is pre-signed, it SHALL remain valid for the timeframe advertised in [`min_presigned_url_timeout` at the `/service`](#/operations/GET_service) endpoint, which is subject to a specified minimum (see service endpoint schema).", - "type": "string" - }, - "body": { - "description": "The text of the body which needs to be included in the request", - "type": "string" - }, - "content-type": { - "description": "The content type which must be used", - "type": "string" - }, - "headers": { - "description": "Additional headers that should be included", - "type": "object", - "additionalProperties": { - "type": "string" - } - } + "title": "HTTP Request", + "description": "Gives information on a particular http request a client should perform", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "The URL to make the request to. Where this URL is pre-signed, it SHALL remain valid for the timeframe advertised in [`min_presigned_url_timeout` at the `/service`](#/operations/GET_service) endpoint, which is subject to a specified minimum (see service endpoint schema).", + "type": "string" }, - "additionalProperties": true + "body": { + "description": "The text of the body which needs to be included in the request", + "type": "string" + }, + "content-type": { + "description": "The content type which must be used", + "type": "string" + }, + "headers": { + "description": "Additional headers that should be included", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": true } diff --git a/api/schemas/mime-type.json b/api/schemas/mime-type.json index 301109df..1b3e61ce 100644 --- a/api/schemas/mime-type.json +++ b/api/schemas/mime-type.json @@ -1,6 +1,6 @@ { - "title": "MIME Type", - "description": "A Mime Type without parameters as defined in [RFC2045](https://www.rfc-editor.org/rfc/rfc2045#section-5.1) and [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1)", - "type": "string", - "pattern": "^(application|audio|font|example|image|message|model|multipart|text|video|x-(?:[0-9A-Za-z!#$%&'*+.^_`|~-]+))/([0-9A-Za-z!#$%&'*+.^_`|~-]+)$" - } \ No newline at end of file + "title": "MIME Type", + "description": "A Mime Type without parameters as defined in [RFC2045](https://www.rfc-editor.org/rfc/rfc2045#section-5.1) and [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1)", + "type": "string", + "pattern": "^(application|audio|font|example|image|message|model|multipart|text|video|x-(?:[0-9A-Za-z!#$%&'*+.^_`|~-]+))/([0-9A-Za-z!#$%&'*+.^_`|~-]+)$" +} diff --git a/api/schemas/object-core.json b/api/schemas/object-core.json index 3fb87bee..10733200 100644 --- a/api/schemas/object-core.json +++ b/api/schemas/object-core.json @@ -20,8 +20,8 @@ ], "properties": { "storage_id": { - "description": "Storage Backend identifier", - "$ref": "uuid.json" + "description": "Storage Backend identifier", + "$ref": "uuid.json" }, "url": { "description": "A URL to which a GET request can be made to directly retrieve the contents of the media object. Clients should include credentials if the provide URL is on the same origin as the API endpoint", diff --git a/api/schemas/object.json b/api/schemas/object.json index 5eba2810..a2608f4c 100644 --- a/api/schemas/object.json +++ b/api/schemas/object.json @@ -1,38 +1,38 @@ { - "title": "Object", - "unevaluatedProperties": false, - "allOf": [ - { - "type": "object", - "required": [ - "id", - "referenced_by_flows", - "timerange" - ], - "properties": { - "id": { - "description": "The Media Object identifier.", - "type": "string" - }, - "referenced_by_flows": { - "type": "array", - "description": "List of Flows that reference this Media Object via Flow Segments in this store instance.", - "items": { - "$ref": "uuid.json" - } - }, - "first_referenced_by_flow": { - "description": "The first Flow that had a Flow Segment reference the Media Object in this store instance. This Flow is also present in 'referenced_by_flows' if it is still referenced by the Flow. This property is optional and may in some implementations become unset if the Flow no longer references the media object, e.g. because it was deleted.", - "$ref": "uuid.json" - }, - "timerange": { - "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline.", - "$ref": "timerange.json" - } - } + "title": "Object", + "unevaluatedProperties": false, + "allOf": [ + { + "type": "object", + "required": [ + "id", + "referenced_by_flows", + "timerange" + ], + "properties": { + "id": { + "description": "The Media Object identifier.", + "type": "string" }, - { - "$ref": "object-core.json" + "referenced_by_flows": { + "type": "array", + "description": "List of Flows that reference this Media Object via Flow Segments in this store instance.", + "items": { + "$ref": "uuid.json" + } + }, + "first_referenced_by_flow": { + "description": "The first Flow that had a Flow Segment reference the Media Object in this store instance. This Flow is also present in 'referenced_by_flows' if it is still referenced by the Flow. This property is optional and may in some implementations become unset if the Flow no longer references the media object, e.g. because it was deleted.", + "$ref": "uuid.json" + }, + "timerange": { + "description": "The timerange covering the sample timestamps embedded in or derived from the Media Object itself, on the Media Object's timeline.", + "$ref": "timerange.json" } - ] + } + }, + { + "$ref": "object-core.json" + } + ] } diff --git a/api/schemas/objects-instances-post.json b/api/schemas/objects-instances-post.json index e4b8e81c..ce3a15d2 100644 --- a/api/schemas/objects-instances-post.json +++ b/api/schemas/objects-instances-post.json @@ -1,40 +1,40 @@ { - "type": "object", - "description": "Register a Media Object instance in the store.", - "title": "Media object registration", - "oneOf": [ - { - "description": "Request the duplication of a Media Object instance to a new Storage Backend, via it's `storage_id`.", - "title": "Controlled instance", - "type": "object", - "required": [ - "storage_id" - ], - "properties": { - "storage_id": { - "description": "Storage backend identifier", - "$ref": "uuid.json" - } - } + "type": "object", + "description": "Register a Media Object instance in the store.", + "title": "Media object registration", + "oneOf": [ + { + "description": "Request the duplication of a Media Object instance to a new Storage Backend, via it's `storage_id`.", + "title": "Controlled instance", + "type": "object", + "required": [ + "storage_id" + ], + "properties": { + "storage_id": { + "description": "Storage backend identifier", + "$ref": "uuid.json" + } + } + }, + { + "description": "Register an uncontrolled Media Object instance via its `url`.", + "title": "Uncontrolled instance", + "type": "object", + "required": [ + "url", + "label" + ], + "properties": { + "url": { + "description": "A URL to which a GET request can be made to directly retrieve the contents of the media object. Clients should include credentials if the provide URL is on the same origin as the API endpoint", + "type": "string" }, - { - "description": "Register an uncontrolled Media Object instance via its `url`.", - "title": "Uncontrolled instance", - "type": "object", - "required": [ - "url", - "label" - ], - "properties": { - "url": { - "description": "A URL to which a GET request can be made to directly retrieve the contents of the media object. Clients should include credentials if the provide URL is on the same origin as the API endpoint", - "type": "string" - }, - "label": { - "description": "Label identifying this Media Object instance. Service implementations should reject any requests using labels that are already associated with Storage Backends.", - "type": "string" - } - } + "label": { + "description": "Label identifying this Media Object instance. Service implementations should reject any requests using labels that are already associated with Storage Backends.", + "type": "string" } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/service-post.json b/api/schemas/service-post.json index 69de3cbf..b5339058 100644 --- a/api/schemas/service-post.json +++ b/api/schemas/service-post.json @@ -1,15 +1,15 @@ { - "title": "Update Service Info", - "description": "Post update to the service info", - "type": "object", - "properties": { - "name": { - "description": "The service instance name", - "type": "string" - }, - "description": { - "description": "The service instance description", - "type": "string" - } + "title": "Update Service Info", + "description": "Post update to the service info", + "type": "object", + "properties": { + "name": { + "description": "The service instance name", + "type": "string" + }, + "description": { + "description": "The service instance description", + "type": "string" } -} \ No newline at end of file + } +} diff --git a/api/schemas/service.json b/api/schemas/service.json index 416b466d..a17459a6 100644 --- a/api/schemas/service.json +++ b/api/schemas/service.json @@ -1,59 +1,48 @@ { - "title": "Service", - "description": "Provides information about the service instance", - "type": "object", - "required": - [ - "type", - "api_version", - "min_object_timeout" - ], - "properties": - { - "name": - { - "description": "The service instance name. This should be a very short, human-readable name that may be displayed in listings of Service instances.", - "type": "string" - }, - "description": - { - "description": "The service instance description. This should be a human-readable description that may be showed in detailed views of Service instances. The description should be longer and more detailed than `name`.", - "type": "string" - }, - "type": - { - "description": "The type identifier for the service instance. The value must start with 'urn:x-tams:service'", - "type": "string" - }, - "api_version": - { - "description": "The version of the TAMS API specification this service instance implements", - "type": "string", - "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" - }, - "service_version": - { - "description": "The version of software providing this service. Note: Different implementations and software houses may use different conventions for their version identification. As such, this field is intentionally permissive and intended to be informative only. Client implementations should avoid using this field to determine compatibility.", - "type": "string" - }, - "event_stream_mechanisms": - { - "description": "List the types of event stream that this service implementation supports", - "type": "array", - "items": - { - "$ref": "event-stream-common.json" - } - }, - "min_object_timeout": - { - "description": "The minimum timeframe within which a Media Object created by this service must be registered against a Flow segment before it is garbage collected. Services SHOULD allow a small grace period beyond the advertised value to account for latency in assigning the Objects and returning them to the Client. This timeout MUST be `300:0` (i.e. 5 minutes) or greater. Clients MUST be capable of reaching this minimum performance level. Clients SHOULD adapt to this value by balancing how many object URLs to request per page against how fast they will be used. Services MAY allow this value to be configured at deploy-time. Format as described by the [Timestamp](#/schemas/timestamp) type. For more infomation, see the documentation of the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage) endpoint.", - "$ref": "timestamp.json" - }, - "min_presigned_url_timeout": - { - "description": "The minimum timeframe within which pre-signed URLs generated by this Service are valid for (both for writing and reading content). This attribute MUST be set on implementations that support pre-signed URLs. Services SHOULD allow a small grace period beyond the advertised value to account for latency in generating pre-signed URLs and returning them to the Client. This timeout MUST be `30:0` (i.e. 30 second) or greater. The value of this parameter MUST be equal or less than `min_object_timeout` to avoid Objects being garbage collected while their pre-signed PUT URLs are still valid. Clients MUST be capable of reaching this minimum performance level. Clients SHOULD adapt to this value, by taking care to request URLs that will be used in a timely manner. Services MAY allow this value to be configured at deploy-time. Format as described by the [Timestamp](#/schemas/timestamp) type.", - "$ref": "timestamp.json" - } + "title": "Service", + "description": "Provides information about the service instance", + "type": "object", + "required": [ + "type", + "api_version", + "min_object_timeout" + ], + "properties": { + "name": { + "description": "The service instance name. This should be a very short, human-readable name that may be displayed in listings of Service instances.", + "type": "string" + }, + "description": { + "description": "The service instance description. This should be a human-readable description that may be showed in detailed views of Service instances. The description should be longer and more detailed than `name`.", + "type": "string" + }, + "type": { + "description": "The type identifier for the service instance. The value must start with 'urn:x-tams:service'", + "type": "string" + }, + "api_version": { + "description": "The version of the TAMS API specification this service instance implements", + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" + }, + "service_version": { + "description": "The version of software providing this service. Note: Different implementations and software houses may use different conventions for their version identification. As such, this field is intentionally permissive and intended to be informative only. Client implementations should avoid using this field to determine compatibility.", + "type": "string" + }, + "event_stream_mechanisms": { + "description": "List the types of event stream that this service implementation supports", + "type": "array", + "items": { + "$ref": "event-stream-common.json" + } + }, + "min_object_timeout": { + "description": "The minimum timeframe within which a Media Object created by this service must be registered against a Flow segment before it is garbage collected. Services SHOULD allow a small grace period beyond the advertised value to account for latency in assigning the Objects and returning them to the Client. This timeout MUST be `300:0` (i.e. 5 minutes) or greater. Clients MUST be capable of reaching this minimum performance level. Clients SHOULD adapt to this value by balancing how many object URLs to request per page against how fast they will be used. Services MAY allow this value to be configured at deploy-time. Format as described by the [Timestamp](#/schemas/timestamp) type. For more infomation, see the documentation of the [`/flows/{flowId}/storage`](#/operations/POST_flows-flowId-storage) endpoint.", + "$ref": "timestamp.json" + }, + "min_presigned_url_timeout": { + "description": "The minimum timeframe within which pre-signed URLs generated by this Service are valid for (both for writing and reading content). This attribute MUST be set on implementations that support pre-signed URLs. Services SHOULD allow a small grace period beyond the advertised value to account for latency in generating pre-signed URLs and returning them to the Client. This timeout MUST be `30:0` (i.e. 30 second) or greater. The value of this parameter MUST be equal or less than `min_object_timeout` to avoid Objects being garbage collected while their pre-signed PUT URLs are still valid. Clients MUST be capable of reaching this minimum performance level. Clients SHOULD adapt to this value, by taking care to request URLs that will be used in a timely manner. Services MAY allow this value to be configured at deploy-time. Format as described by the [Timestamp](#/schemas/timestamp) type.", + "$ref": "timestamp.json" } -} \ No newline at end of file + } +} diff --git a/api/schemas/source.json b/api/schemas/source.json index 5ec2e7cd..28a343dc 100644 --- a/api/schemas/source.json +++ b/api/schemas/source.json @@ -1,62 +1,62 @@ { - "title": "Source", - "description": "Describes a Source: an abstract representation of a piece of media as defined in \n\nSources may be elemental (and represented directly by a Flow), or may represent a collection of other Sources, e.g. a Source collecting video and audio together.", - "type": "object", - "required": [ - "id", - "format" - ], - "properties": { - "id": { - "description": "Source identifier", - "$ref": "uuid.json" - }, - "format" : { - "description": "The primary content type URN for the Source.", - "$ref": "content-format.json" - }, - "label": { - "description": "Freeform string label for the Source. This should be a very short, human-readable label that may be displayed in listings of Sources.", - "type": "string" - }, - "description": { - "description": "Freeform text describing the Source. This should be a human-readable description that may be showed in detailed views of Sources. The description should be longer and more detailed than `label`.", - "type": "string" - }, - "created_by": { - "description": "A string identifier for the entity that created the Source. Service implementations SHOULD set suitable default values for `created_by` based on the principal accessing the systems.", - "type": "string" - }, - "updated_by": { - "description": "A string identifier for the entity that updated the Source metadata most recently. Service implementations SHOULD set suitable default values for `updated_by` based on the principal accessing the system.", - "type": "string" - }, - "created": { - "description": "The date-time the Source was created in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "type": "string", - "format": "date-time" - }, - "updated": { - "description": "The date-time the Source metadata was last updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", - "type": "string", - "format": "date-time" - }, - "tags": { - "$ref": "tags.json" - }, - "source_collection": { - "description": "List of Sources that are collected together by this Source. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally. Source collections can be inferred from Flow collection definitions.", - "type": "array", - "items": { - "$ref": "collection-item.json" - } - }, - "collected_by": { - "description": "Sources that reference this Source to include it in a collection. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally. Source collections can be inferred from Flow collection definitions.", - "type": "array", - "items": { - "$ref": "uuid.json" - } - } + "title": "Source", + "description": "Describes a Source: an abstract representation of a piece of media as defined in \n\nSources may be elemental (and represented directly by a Flow), or may represent a collection of other Sources, e.g. a Source collecting video and audio together.", + "type": "object", + "required": [ + "id", + "format" + ], + "properties": { + "id": { + "description": "Source identifier", + "$ref": "uuid.json" + }, + "format": { + "description": "The primary content type URN for the Source.", + "$ref": "content-format.json" + }, + "label": { + "description": "Freeform string label for the Source. This should be a very short, human-readable label that may be displayed in listings of Sources.", + "type": "string" + }, + "description": { + "description": "Freeform text describing the Source. This should be a human-readable description that may be showed in detailed views of Sources. The description should be longer and more detailed than `label`.", + "type": "string" + }, + "created_by": { + "description": "A string identifier for the entity that created the Source. Service implementations SHOULD set suitable default values for `created_by` based on the principal accessing the systems.", + "type": "string" + }, + "updated_by": { + "description": "A string identifier for the entity that updated the Source metadata most recently. Service implementations SHOULD set suitable default values for `updated_by` based on the principal accessing the system.", + "type": "string" + }, + "created": { + "description": "The date-time the Source was created in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "updated": { + "description": "The date-time the Source metadata was last updated in a given context, e.g. in the service instance. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally", + "type": "string", + "format": "date-time" + }, + "tags": { + "$ref": "tags.json" + }, + "source_collection": { + "description": "List of Sources that are collected together by this Source. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally. Source collections can be inferred from Flow collection definitions.", + "type": "array", + "items": { + "$ref": "collection-item.json" + } + }, + "collected_by": { + "description": "Sources that reference this Source to include it in a collection. This attribute is intended to be read-only. Service implementations SHOULD ignore this if given in a PUT request, and instead manage it internally. Source collections can be inferred from Flow collection definitions.", + "type": "array", + "items": { + "$ref": "uuid.json" + } } -} \ No newline at end of file + } +} diff --git a/api/schemas/storage-backend.json b/api/schemas/storage-backend.json index 37fbb0f0..9dc211ec 100644 --- a/api/schemas/storage-backend.json +++ b/api/schemas/storage-backend.json @@ -1,30 +1,30 @@ { - "title": "Storage Backend", - "description": "Provides technical, and logic metadata about a storage backend", - "type": "object", - "properties": { - "store_type": { - "description": "The generic Storage Backend type. Used to identify the required workflow for reading and writing media. Any `store_product` should be compatible, as much is required for basic interoperability between TAMS implementations, with their associated generic `store_type`.", - "type": "string", - "enum": [ - "http_object_store" - ] - }, - "provider": { - "description": "The cloud (or other) provider of the Storage Backend", - "type": "string" - }, - "region": { - "description": "The region in the cloud this Storage Backend resides", - "type": "string" - }, - "availability_zone": { - "description": "The availability zone in the cloud region this Storage Backend resides. Note that many cloud providers randomize availability zone identifiers such that they are consistent within a cloud account, but not necessarily between accounts. Caution should be exercised when using this parameter.", - "type": "string" - }, - "store_product": { - "description": "The storage product name.", - "type": "string" - } + "title": "Storage Backend", + "description": "Provides technical, and logic metadata about a storage backend", + "type": "object", + "properties": { + "store_type": { + "description": "The generic Storage Backend type. Used to identify the required workflow for reading and writing media. Any `store_product` should be compatible, as much is required for basic interoperability between TAMS implementations, with their associated generic `store_type`.", + "type": "string", + "enum": [ + "http_object_store" + ] + }, + "provider": { + "description": "The cloud (or other) provider of the Storage Backend", + "type": "string" + }, + "region": { + "description": "The region in the cloud this Storage Backend resides", + "type": "string" + }, + "availability_zone": { + "description": "The availability zone in the cloud region this Storage Backend resides. Note that many cloud providers randomize availability zone identifiers such that they are consistent within a cloud account, but not necessarily between accounts. Caution should be exercised when using this parameter.", + "type": "string" + }, + "store_product": { + "description": "The storage product name.", + "type": "string" } -} \ No newline at end of file + } +} diff --git a/api/schemas/storage-backends-list.json b/api/schemas/storage-backends-list.json index 58fb577c..8271f57c 100644 --- a/api/schemas/storage-backends-list.json +++ b/api/schemas/storage-backends-list.json @@ -1,38 +1,38 @@ { - "title": "Storage Backends List", - "description": "Information about the storage backends available on this service instance.", - "type": "array", - "items": { - "allOf": [ - { - "$ref": "storage-backend.json" - }, - { - "required": [ - "store_type", - "provider", - "store_product", - "id" - ] - }, - { - "type": "object", - "properties": { - "id": { - "description": "Storage backend identifier", - "$ref": "uuid.json" - }, - "label": { - "description": "Freeform string label for a storage backend.", - "type": "string" - }, - "default_storage": { - "description": "If set to `true`, this is the default storage backend. The default storage backend will be used if the client does not specify a storage backend id when requesting the allocation of storage. If this parameter is not set, assume `false`. Service instances may either set one storage backend as default, or none - indicating that clients must always specify a storage backend.", - "type": "boolean" - } - } - } + "title": "Storage Backends List", + "description": "Information about the storage backends available on this service instance.", + "type": "array", + "items": { + "allOf": [ + { + "$ref": "storage-backend.json" + }, + { + "required": [ + "store_type", + "provider", + "store_product", + "id" ] - }, - "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "description": "Storage backend identifier", + "$ref": "uuid.json" + }, + "label": { + "description": "Freeform string label for a storage backend.", + "type": "string" + }, + "default_storage": { + "description": "If set to `true`, this is the default storage backend. The default storage backend will be used if the client does not specify a storage backend id when requesting the allocation of storage. If this parameter is not set, assume `false`. Service instances may either set one storage backend as default, or none - indicating that clients must always specify a storage backend.", + "type": "boolean" + } + } + } + ] + }, + "additionalProperties": false } diff --git a/api/schemas/tags.json b/api/schemas/tags.json index 3276e09d..5a94fb78 100644 --- a/api/schemas/tags.json +++ b/api/schemas/tags.json @@ -1,18 +1,18 @@ { - "title": "Tags", - "description": "Key is a freeform string. Value is a freeform string, or an array of freeform strings.", - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } -} \ No newline at end of file + "title": "Tags", + "description": "Key is a freeform string. Value is a freeform string, or an array of freeform strings.", + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } +} diff --git a/api/schemas/timerange.json b/api/schemas/timerange.json index 80223385..42ac6d56 100644 --- a/api/schemas/timerange.json +++ b/api/schemas/timerange.json @@ -1,6 +1,6 @@ { - "title": "TimeRange", - "description": "A timerange of timestamps. It is represented using one or two timestamps with inclusivity and exclusivity markers.\n\nE.g.\n* `[0:0_10:0)` represents 10 seconds of media starting at timestamp `0:0` and ending before `10:0`.\n* `(5:0_` represents a timerange starting after `5:0` and to eternity.\n* `_` without timestamps or inclusivity markers represents \"eternity\" (i.e. the entire timeline).\n* `()` without timestamps represents \"never\" (i.e. a range of zero length in no particular position).\n* `[1694429247:0_1694429248:0)` is a 1 second TAI timerange starting at 2023-09-11T10:46:50.0Z UTC.\n* `[1694429247:0]` is an instantaneous TAI timerange at 2023-09-11T10:46:50.0Z UTC.\n This is equivalent to `[1694429247:0_1694429247:0]`.\n The short syntax is preferred due to ease of identification as instantaneous.\n Instantaneous TimeRanges cannot use exclusive markers (i.e. `(` or `)`).\n* A `[` or `]` indicates that bound is inclusive, and a `(` or `)` indicates that bound is exclusive.\n\nDetails of the format can be found in the [Timestamps in TAMS](https://github.com/bbc/tams/blob/main/docs/appnotes/0008-timestamps-in-TAMS.md) application note.\n", - "type": "string", - "pattern": "^(\\[|\\()?(-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8}))?(_(-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8}))?)?(\\]|\\))?$" -} \ No newline at end of file + "title": "TimeRange", + "description": "A timerange of timestamps. It is represented using one or two timestamps with inclusivity and exclusivity markers.\n\nE.g.\n* `[0:0_10:0)` represents 10 seconds of media starting at timestamp `0:0` and ending before `10:0`.\n* `(5:0_` represents a timerange starting after `5:0` and to eternity.\n* `_` without timestamps or inclusivity markers represents \"eternity\" (i.e. the entire timeline).\n* `()` without timestamps represents \"never\" (i.e. a range of zero length in no particular position).\n* `[1694429247:0_1694429248:0)` is a 1 second TAI timerange starting at 2023-09-11T10:46:50.0Z UTC.\n* `[1694429247:0]` is an instantaneous TAI timerange at 2023-09-11T10:46:50.0Z UTC.\n This is equivalent to `[1694429247:0_1694429247:0]`.\n The short syntax is preferred due to ease of identification as instantaneous.\n Instantaneous TimeRanges cannot use exclusive markers (i.e. `(` or `)`).\n* A `[` or `]` indicates that bound is inclusive, and a `(` or `)` indicates that bound is exclusive.\n\nDetails of the format can be found in the [Timestamps in TAMS](https://github.com/bbc/tams/blob/main/docs/appnotes/0008-timestamps-in-TAMS.md) application note.\n", + "type": "string", + "pattern": "^(\\[|\\()?(-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8}))?(_(-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8}))?)?(\\]|\\))?$" +} diff --git a/api/schemas/timestamp.json b/api/schemas/timestamp.json index 15de9707..e5aad6bd 100644 --- a/api/schemas/timestamp.json +++ b/api/schemas/timestamp.json @@ -1,6 +1,6 @@ { - "title": "Timestamp", - "description": "A signed nanosecond resolution timestamp represented as \"{sign?}{seconds}:{nanoseconds}\". The intended\ninterpretation of the value is assumed to be defined elsewhere.\n\nE.g.\n* \"1:40000000\" is the timestamp of the 27th video frame for 25 Hz video with origin at \"0:0\".\n* \"1694429247:40000000\" is the TAI timestamp for a video frame at 2023-09-11T10:46:50.04Z UTC.\n\nDetails of the format can be found in the [Timestamps in TAMS](https://github.com/bbc/tams/blob/main/docs/appnotes/0008-timestamps-in-TAMS.md) application note.\n", - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8})$" -} \ No newline at end of file + "title": "Timestamp", + "description": "A signed nanosecond resolution timestamp represented as \"{sign?}{seconds}:{nanoseconds}\". The intended\ninterpretation of the value is assumed to be defined elsewhere.\n\nE.g.\n* \"1:40000000\" is the timestamp of the 27th video frame for 25 Hz video with origin at \"0:0\".\n* \"1694429247:40000000\" is the TAI timestamp for a video frame at 2023-09-11T10:46:50.04Z UTC.\n\nDetails of the format can be found in the [Timestamps in TAMS](https://github.com/bbc/tams/blob/main/docs/appnotes/0008-timestamps-in-TAMS.md) application note.\n", + "type": "string", + "pattern": "^-?(0|[1-9][0-9]*):(0|[1-9][0-9]{0,8})$" +} diff --git a/api/schemas/url-label-list.json b/api/schemas/url-label-list.json index f19811fa..596dc80b 100644 --- a/api/schemas/url-label-list.json +++ b/api/schemas/url-label-list.json @@ -1,6 +1,6 @@ { - "title": "Query String GET URL Label list", - "description": "A list of Media Object GET URL Labels, formatted for use in query string parameters", - "type": "string", - "pattern": "^([^,]+(,[^,]+)*)?$" -} \ No newline at end of file + "title": "Query String GET URL Label list", + "description": "A list of Media Object GET URL Labels, formatted for use in query string parameters", + "type": "string", + "pattern": "^([^,]+(,[^,]+)*)?$" +} diff --git a/api/schemas/url-tag-list.json b/api/schemas/url-tag-list.json index 7cbd6bb2..d0e329d0 100644 --- a/api/schemas/url-tag-list.json +++ b/api/schemas/url-tag-list.json @@ -1,6 +1,6 @@ { - "title": "Query String Tag value list", - "description": "A list of tag values, formatted for use in query string parameters", - "type": "string", - "pattern": "^([^,]+(,[^,]+)*)?$" -} \ No newline at end of file + "title": "Query String Tag value list", + "description": "A list of tag values, formatted for use in query string parameters", + "type": "string", + "pattern": "^([^,]+(,[^,]+)*)?$" +} diff --git a/api/schemas/uuid-list.json b/api/schemas/uuid-list.json index 61755a90..cf9869c1 100644 --- a/api/schemas/uuid-list.json +++ b/api/schemas/uuid-list.json @@ -1,6 +1,6 @@ { - "title": "Query String UUID list", - "description": "A list of Universally Unique Identifiers (UUIDs) as defined in [RFC9562](https://www.rfc-editor.org/rfc/rfc9562), formatted for use in query string parameters", - "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})(,[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})*$" -} \ No newline at end of file + "title": "Query String UUID list", + "description": "A list of Universally Unique Identifiers (UUIDs) as defined in [RFC9562](https://www.rfc-editor.org/rfc/rfc9562), formatted for use in query string parameters", + "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})(,[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})*$" +} diff --git a/api/schemas/uuid.json b/api/schemas/uuid.json index 72560a8c..065d98e2 100644 --- a/api/schemas/uuid.json +++ b/api/schemas/uuid.json @@ -1,6 +1,6 @@ { - "title": "UUID", - "description": "A Universally Unique Identifier (UUID) as defined in [RFC9562](https://www.rfc-editor.org/rfc/rfc9562)", - "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}$" -} \ No newline at end of file + "title": "UUID", + "description": "A Universally Unique Identifier (UUID) as defined in [RFC9562](https://www.rfc-editor.org/rfc/rfc9562)", + "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}$" +} diff --git a/api/schemas/webhook-get.json b/api/schemas/webhook-get.json index d34b781d..5e5a6fa3 100644 --- a/api/schemas/webhook-get.json +++ b/api/schemas/webhook-get.json @@ -1,33 +1,32 @@ { - "title": "Webhook Detail", - "description": "Describes a Webhook", - "type": "object", - "allOf": [ - { - "$ref": "webhook-with-id.json" + "title": "Webhook Detail", + "description": "Describes a Webhook", + "type": "object", + "allOf": [ + { + "$ref": "webhook-with-id.json" + }, + { + "type": "object", + "required": [ + "status" + ], + "properties": { + "error": { + "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", + "$ref": "error.json" }, - { - "type": "object", - "required": - [ - "status" - ], - "properties": { - "error": { - "description": "Provides more information for the error status, as described by the [Error](#/schemas/error) type", - "$ref": "error.json" - }, - "status": { - "description": "Status of the Webhook. `created` indicates the webhook has been successfully registered but is yet to begin sending events or, depending on the service implementation, the worker responsible for sending the events has yet to start. `started` indicates the webhook is active and sending events. `disabled` indicates the webhook has been disabled by a client and is not currently sending events. `error` indicates an error condition has been encountered and the webhook has been disabled by the service instance. More information about the error condition will be indicated by the service instance in the `error` parameter. Service implementations SHOULD implement appropriate retries and only enter the `error` state when absolutely necesary. A webhook in the `error` or `disabled` state may be re-enabled by a client by setting the status to `created`. A webhook in the `created` or `started` state may be disabled by a client by setting the status to `disabled`. Attempting to transition an `error` status to `disabled` SHOULD be rejected.", - "type": "string", - "enum": [ - "created", - "started", - "disabled", - "error" - ] - } - } + "status": { + "description": "Status of the Webhook. `created` indicates the webhook has been successfully registered but is yet to begin sending events or, depending on the service implementation, the worker responsible for sending the events has yet to start. `started` indicates the webhook is active and sending events. `disabled` indicates the webhook has been disabled by a client and is not currently sending events. `error` indicates an error condition has been encountered and the webhook has been disabled by the service instance. More information about the error condition will be indicated by the service instance in the `error` parameter. Service implementations SHOULD implement appropriate retries and only enter the `error` state when absolutely necesary. A webhook in the `error` or `disabled` state may be re-enabled by a client by setting the status to `created`. A webhook in the `created` or `started` state may be disabled by a client by setting the status to `disabled`. Attempting to transition an `error` status to `disabled` SHOULD be rejected.", + "type": "string", + "enum": [ + "created", + "started", + "disabled", + "error" + ] } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/webhook-post.json b/api/schemas/webhook-post.json index 242b72f4..af7e6613 100644 --- a/api/schemas/webhook-post.json +++ b/api/schemas/webhook-post.json @@ -1,27 +1,27 @@ { - "title": "Register Webhook", - "description": "Register to receive updates via webhook", - "type": "object", - "allOf": [ - { - "$ref": "webhook.json" + "title": "Register Webhook", + "description": "Register to receive updates via webhook", + "type": "object", + "allOf": [ + { + "$ref": "webhook.json" + }, + { + "type": "object", + "properties": { + "api_key_value": { + "description": "The value that the HTTP header 'api_key_name' will be set to", + "type": "string" }, - { - "type": "object", - "properties": { - "api_key_value": { - "description": "The value that the HTTP header 'api_key_name' will be set to", - "type": "string" - }, - "status": { - "description": "Status of the Webhook. `created` will register the webhook in the created state and the service instance will attempt to start sending events. `disabled` will register the webhook in a disabled state and will not send events. Assumed to be `created` if not set.", - "type": "string", - "enum": [ - "created", - "disabled" - ] - } - } + "status": { + "description": "Status of the Webhook. `created` will register the webhook in the created state and the service instance will attempt to start sending events. `disabled` will register the webhook in a disabled state and will not send events. Assumed to be `created` if not set.", + "type": "string", + "enum": [ + "created", + "disabled" + ] } - ] + } + } + ] } diff --git a/api/schemas/webhook-put.json b/api/schemas/webhook-put.json index ce33db0d..e4a07431 100644 --- a/api/schemas/webhook-put.json +++ b/api/schemas/webhook-put.json @@ -1,31 +1,30 @@ { - "title": "Modify Webhook", - "description": "Modify existing webhook", - "type": "object", - "allOf": [ - { - "$ref": "webhook-with-id.json" + "title": "Modify Webhook", + "description": "Modify existing webhook", + "type": "object", + "allOf": [ + { + "$ref": "webhook-with-id.json" + }, + { + "type": "object", + "required": [ + "status" + ], + "properties": { + "api_key_value": { + "description": "The value that the HTTP header 'api_key_name' will be set to", + "type": "string" }, - { - "type": "object", - "required": - [ - "status" - ], - "properties": { - "api_key_value": { - "description": "The value that the HTTP header 'api_key_name' will be set to", - "type": "string" - }, - "status": { - "description": "Status of the Webhook. `created` indicates the webhook has been successfully registered but is yet to begin sending events or, depending on the service implementation, the worker responsible for sending the events has yet to start. `started` indicates the webhook is active and sending events. `disabled` indicates the webhook has been disabled by a client and is not currently sending events. `error` indicates an error condition has been encountered and the webhook has been disabled by the service instance. More information about the error condition will be indicated by the service instance in the `error` parameter. Service implementations SHOULD implement appropriate retries and only enter the `error` state when absolutely necesary. A webhook in the `error` or `disabled` state may be re-enabled by a client by setting the status to `created`. A webhook in the `created` or `started` state may be disabled by a client by setting the status to `disabled`. Attempting to transition an `error` status to `disabled` SHOULD be rejected.", - "type": "string", - "enum": [ - "created", - "disabled" - ] - } - } + "status": { + "description": "Status of the Webhook. `created` indicates the webhook has been successfully registered but is yet to begin sending events or, depending on the service implementation, the worker responsible for sending the events has yet to start. `started` indicates the webhook is active and sending events. `disabled` indicates the webhook has been disabled by a client and is not currently sending events. `error` indicates an error condition has been encountered and the webhook has been disabled by the service instance. More information about the error condition will be indicated by the service instance in the `error` parameter. Service implementations SHOULD implement appropriate retries and only enter the `error` state when absolutely necesary. A webhook in the `error` or `disabled` state may be re-enabled by a client by setting the status to `created`. A webhook in the `created` or `started` state may be disabled by a client by setting the status to `disabled`. Attempting to transition an `error` status to `disabled` SHOULD be rejected.", + "type": "string", + "enum": [ + "created", + "disabled" + ] } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/webhook-with-id.json b/api/schemas/webhook-with-id.json index 4ada98cc..0aea8dba 100644 --- a/api/schemas/webhook-with-id.json +++ b/api/schemas/webhook-with-id.json @@ -1,22 +1,22 @@ { - "title": "Webhook Details", - "description": "Details of an existing registered webhook", - "type": "object", - "allOf": [ - { - "$ref": "webhook.json" - }, - { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "description": "Webhook identifier", - "$ref": "uuid.json" - } - } + "title": "Webhook Details", + "description": "Details of an existing registered webhook", + "type": "object", + "allOf": [ + { + "$ref": "webhook.json" + }, + { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "description": "Webhook identifier", + "$ref": "uuid.json" } - ] -} \ No newline at end of file + } + } + ] +} diff --git a/api/schemas/webhook.json b/api/schemas/webhook.json index e64bbccb..c966c1a8 100644 --- a/api/schemas/webhook.json +++ b/api/schemas/webhook.json @@ -1,89 +1,89 @@ { - "title": "Register Webhook", - "description": "Register to receive updates via webhook", - "type": "object", - "required": [ - "url", - "events" - ], - "properties": { - "url": { - "description": "The URL to which the service instance should make HTTP POST requests with event data", - "type": "string" - }, - "api_key_name": { - "description": "The HTTP header name that is added to the event POST", - "type": "string" - }, - "events": { - "description": "List of event types to receive", - "type": "array", - "items": { - "type": "string", - "enum": [ - "flows/created", - "flows/updated", - "flows/deleted", - "flows/segments_added", - "flows/segments_deleted", - "sources/created", - "sources/updated", - "sources/deleted" - ] - } - }, - "flow_ids": { - "description": "Limit Flow and Flow Segment events to Flows in the given list of Flow IDs", - "type": "array", - "items": { - "$ref": "uuid.json" - } - }, - "source_ids": { - "description": "Limit Flow, Flow Segment and Source events to Sources in the given list of Source IDs", - "type": "array", - "items": { - "$ref": "uuid.json" - } - }, - "flow_collected_by_ids": { - "description": "Limit Flow and Flow Segment events to those with Flow that is collected by a Flow Collection in the given list of Flow Collection IDs", - "type": "array", - "items": { - "$ref": "uuid.json" - } - }, - "source_collected_by_ids": { - "description": "Limit Flow, Flow Segment and Source events to those with Source that is collected by a Source Collection in the given list of Source Collection IDs", - "type": "array", - "items": { - "$ref": "uuid.json" - } - }, - "accept_get_urls": { - "description": "List of labels of URLs to include in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `accept_get_urls` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint, except that the labels are represented using a JSON array rather than a (comma separated list) string.", - "type": "array", - "items": { - "type": "string" - } - }, - "accept_storage_ids": { - "description": "List of labels of `storage_id`s to include in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `accept_storage_ids` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint, except that the IDs are represented using a JSON array rather than a (comma separated list) string.", - "type": "array", - "items": { - "$ref": "uuid.json" - } - }, - "presigned": { - "description": "Whether to include presigned/non-presigned URLs in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `presigned` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint.", - "type": "boolean" - }, - "verbose_storage": { - "description": "Whether to include storage metadata in the `get_urls` property in `flows/segments_added` events. This option is the same as the `verbose_storage` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint.", - "type": "boolean" - }, - "tags": { - "$ref": "tags.json" - } + "title": "Register Webhook", + "description": "Register to receive updates via webhook", + "type": "object", + "required": [ + "url", + "events" + ], + "properties": { + "url": { + "description": "The URL to which the service instance should make HTTP POST requests with event data", + "type": "string" + }, + "api_key_name": { + "description": "The HTTP header name that is added to the event POST", + "type": "string" + }, + "events": { + "description": "List of event types to receive", + "type": "array", + "items": { + "type": "string", + "enum": [ + "flows/created", + "flows/updated", + "flows/deleted", + "flows/segments_added", + "flows/segments_deleted", + "sources/created", + "sources/updated", + "sources/deleted" + ] + } + }, + "flow_ids": { + "description": "Limit Flow and Flow Segment events to Flows in the given list of Flow IDs", + "type": "array", + "items": { + "$ref": "uuid.json" + } + }, + "source_ids": { + "description": "Limit Flow, Flow Segment and Source events to Sources in the given list of Source IDs", + "type": "array", + "items": { + "$ref": "uuid.json" + } + }, + "flow_collected_by_ids": { + "description": "Limit Flow and Flow Segment events to those with Flow that is collected by a Flow Collection in the given list of Flow Collection IDs", + "type": "array", + "items": { + "$ref": "uuid.json" + } + }, + "source_collected_by_ids": { + "description": "Limit Flow, Flow Segment and Source events to those with Source that is collected by a Source Collection in the given list of Source Collection IDs", + "type": "array", + "items": { + "$ref": "uuid.json" + } + }, + "accept_get_urls": { + "description": "List of labels of URLs to include in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `accept_get_urls` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint, except that the labels are represented using a JSON array rather than a (comma separated list) string.", + "type": "array", + "items": { + "type": "string" + } + }, + "accept_storage_ids": { + "description": "List of labels of `storage_id`s to include in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `accept_storage_ids` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint, except that the IDs are represented using a JSON array rather than a (comma separated list) string.", + "type": "array", + "items": { + "$ref": "uuid.json" + } + }, + "presigned": { + "description": "Whether to include presigned/non-presigned URLs in the `get_urls` property in `flows/segments_added` events. Where multiple `get_urls` filter query parameters are provided, the included `get_urls` will match all filters. This option is the same as the `presigned` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint.", + "type": "boolean" + }, + "verbose_storage": { + "description": "Whether to include storage metadata in the `get_urls` property in `flows/segments_added` events. This option is the same as the `verbose_storage` query parameter for the [/flows/{flowId}/segments](#/operations/GET_flows-flowId-segments) API endpoint.", + "type": "boolean" + }, + "tags": { + "$ref": "tags.json" } + } }