From ec877fe924a14e15cbac3c81394f59655444e8b5 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Tue, 10 May 2022 11:46:23 +1000 Subject: [PATCH 01/13] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e40bdf..d10a0e5 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Install the required dependencies including the [Shotstack Python SDK](https://www.npmjs.com/package/shotstack-sdk) ```bash -pip3 install -r requirements.tx +pip3 install -r requirements.txt ``` ### Set your API key From e3a93a6c0114abd9522f9713104cce2b49e70935 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Tue, 10 May 2022 11:46:39 +1000 Subject: [PATCH 02/13] Fix missing URL error --- examples/status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/status.py b/examples/status.py index efc31f5..a795701 100644 --- a/examples/status.py +++ b/examples/status.py @@ -29,11 +29,11 @@ api_response = api_instance.get_render(id, data=False, merged=True) status = api_response['response']['status'] - url = api_response['response']['url'] print('Status: ' + status.upper() + '\n') if status == "done": + url = api_response['response']['url'] print(f">> Asset URL: {url}") elif status == 'failed': print(">> Something went wrong, rendering has terminated and will not continue.") From e2ec62ad6e8fd8453f4ff6e77359b6ab6d052af9 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Tue, 10 May 2022 11:47:52 +1000 Subject: [PATCH 03/13] Update Serve API path --- examples/serve-api/asset_id.py | 6 +++--- examples/serve-api/render_id.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/serve-api/asset_id.py b/examples/serve-api/asset_id.py index f8f91d7..936575f 100644 --- a/examples/serve-api/asset_id.py +++ b/examples/serve-api/asset_id.py @@ -5,10 +5,10 @@ from shotstack_sdk.api import serve_api if __name__ == "__main__": - host = "https://api.shotstack.io/stage" + host = "https://api.shotstack.io/serve/stage" - if os.getenv("SHOTSTACK_HOST") is not None: - host = os.getenv("SHOTSTACK_HOST") + if os.getenv("SHOTSTACK_SERVE_HOST") is not None: + host = os.getenv("SHOTSTACK_SERVE_HOST") configuration = shotstack.Configuration(host = host) diff --git a/examples/serve-api/render_id.py b/examples/serve-api/render_id.py index d31363d..3c09260 100644 --- a/examples/serve-api/render_id.py +++ b/examples/serve-api/render_id.py @@ -5,10 +5,10 @@ from shotstack_sdk.api import serve_api if __name__ == "__main__": - host = "https://api.shotstack.io/stage" + host = "https://api.shotstack.io/serve/stage" - if os.getenv("SHOTSTACK_HOST") is not None: - host = os.getenv("SHOTSTACK_HOST") + if os.getenv("SHOTSTACK_SERVE_HOST") is not None: + host = os.getenv("SHOTSTACK_SERVE_HOST") configuration = shotstack.Configuration(host = host) From dd8e392756a97bd9943f39837e57a907068a5989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAlexandre?= <“alex.lourenco@mail.com”> Date: Mon, 9 May 2022 19:14:40 -0700 Subject: [PATCH 04/13] Fixed serve-api requests --- examples/serve-api/asset_id.py | 13 ++++--------- examples/serve-api/render_id.py | 14 ++++---------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/examples/serve-api/asset_id.py b/examples/serve-api/asset_id.py index 936575f..7b16e2f 100644 --- a/examples/serve-api/asset_id.py +++ b/examples/serve-api/asset_id.py @@ -28,15 +28,10 @@ try: api_response = api_instance.get_asset(id) - status = api_response['response']['status'] + data = api_response['data'] - print(f"Status: {status.upper()}\n") - - if status == "failed": - print(">> Something went wrong, rendering has terminated and will not continue.") - else: - print(f">> Asset CDN URL: {api_response['response']['attributes']['url']}") - print(f">> Asset ID: {api_response['response']['attributes']['id']}") - print(f">> Render ID: {api_response['response']['attributes']['renderId']}") + print(f">> Asset CDN URL: {data['attributes']['url']}") + print(f">> Asset ID: {data['attributes']['id']}") + print(f">> Render ID: {data['attributes']['render_id']}") except Exception as e: print(f"Unable to resolve API call: {e}") \ No newline at end of file diff --git a/examples/serve-api/render_id.py b/examples/serve-api/render_id.py index 3c09260..2ac962c 100644 --- a/examples/serve-api/render_id.py +++ b/examples/serve-api/render_id.py @@ -28,15 +28,9 @@ try: api_response = api_instance.get_asset_by_render_id(id) - status = api_response['response']['status'] - - print(f"Status: {status.upper()}\n") - - if status == "failed": - print(">> Something went wrong, rendering has terminated and will not continue.") - else: - print(f">> Asset CDN URL: {api_response['response']['attributes']['url']}") - print(f">> Asset ID: {api_response['response']['attributes']['id']}") - print(f">> Render ID: {api_response['response']['attributes']['renderId']}") + for asset in api_response['data']: + print(f">> Asset CDN URL: {asset['attributes']['url']}") + print(f">> Asset ID: {asset['attributes']['id']}") + print(f">> Render ID: {asset['attributes']['render_id']}") except Exception as e: print(f"Unable to resolve API call: {e}") \ No newline at end of file From e4df67199af434c4b514cce8017456ad99abe3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAlexandre?= <“alex.lourenco@mail.com”> Date: Mon, 9 May 2022 19:24:20 -0700 Subject: [PATCH 05/13] Added status message to serve-api requests --- examples/serve-api/asset_id.py | 9 ++++++--- examples/serve-api/render_id.py | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/serve-api/asset_id.py b/examples/serve-api/asset_id.py index 7b16e2f..1fb3fa4 100644 --- a/examples/serve-api/asset_id.py +++ b/examples/serve-api/asset_id.py @@ -30,8 +30,11 @@ data = api_response['data'] - print(f">> Asset CDN URL: {data['attributes']['url']}") - print(f">> Asset ID: {data['attributes']['id']}") - print(f">> Render ID: {data['attributes']['render_id']}") + if data['attributes']['status'] == "failed": + print(">> Something went wrong, asset could not be copied.") + else: + print(f">> Asset CDN URL: {data['attributes']['url']}") + print(f">> Asset ID: {data['attributes']['id']}") + print(f">> Render ID: {data['attributes']['render_id']}") except Exception as e: print(f"Unable to resolve API call: {e}") \ No newline at end of file diff --git a/examples/serve-api/render_id.py b/examples/serve-api/render_id.py index 2ac962c..4ea7749 100644 --- a/examples/serve-api/render_id.py +++ b/examples/serve-api/render_id.py @@ -29,8 +29,11 @@ api_response = api_instance.get_asset_by_render_id(id) for asset in api_response['data']: - print(f">> Asset CDN URL: {asset['attributes']['url']}") - print(f">> Asset ID: {asset['attributes']['id']}") - print(f">> Render ID: {asset['attributes']['render_id']}") + if asset['attributes']['status'] == "failed": + print(">> Something went wrong, asset could not be copied.") + else: + print(f">> Asset CDN URL: {asset['attributes']['url']}") + print(f">> Asset ID: {asset['attributes']['id']}") + print(f">> Render ID: {asset['attributes']['render_id']}") except Exception as e: print(f"Unable to resolve API call: {e}") \ No newline at end of file From fef9a52d6d0ddd6572e87eff103c95b1a0d9b1e8 Mon Sep 17 00:00:00 2001 From: Alexandre Lourenco <104756310+AlexLourencoFreelance@users.noreply.github.com> Date: Wed, 20 Jul 2022 20:56:05 -0700 Subject: [PATCH 06/13] Bumped version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2ce141a..755bff4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -shotstack_sdk==0.0.1 +shotstack_sdk==0.2.5 From b687bbbf4b70cc87994cc74324cf857a90815870 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Fri, 9 Dec 2022 20:09:56 +1000 Subject: [PATCH 07/13] Fix float --- examples/gif.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/gif.py b/examples/gif.py index 2a36c7f..67008f3 100644 --- a/examples/gif.py +++ b/examples/gif.py @@ -33,23 +33,23 @@ "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/examples/images/pexels/pexels-photo-752036.jpeg" ] - clips = [] - start = 0.0 + clips = [] + start = 0.0 length = 1.5 soundtrack = Soundtrack( - src = "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/music/gangsta.mp3", - effect = "fadeInFadeOut" + src = "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/music/gangsta.mp3", + effect = "fadeInFadeOut" ) for image in images: imageAsset = ImageAsset(src = image) - clip = Clip( - asset = imageAsset, - start = start, - length = length, - effect = "zoomIn" + clip = Clip( + asset = imageAsset, + start = start, + length = length, + effect = "zoomIn" ) start = start + length @@ -60,19 +60,19 @@ timeline = Timeline( background = "#000000", soundtrack = soundtrack, - tracks = [track] + tracks = [track] ) output = Output( - format = "gif", - resolution = "preview", - fps = 12.0, - repeat = False + format = "gif", + resolution = "preview", + fps = 12, + repeat = False ) edit = Edit( timeline = timeline, - output = output + output = output ) try: @@ -85,4 +85,4 @@ print(">> Now check the progress of your render by running:") print(f">> python examples/status.py {id}") except Exception as e: - print(f"Unable to resolve API call: {e}") \ No newline at end of file + print(f"Unable to resolve API call: {e}") From 38139de981a3864b2bc4719c029c9c7937ff9960 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Fri, 9 Dec 2022 20:10:50 +1000 Subject: [PATCH 08/13] Add Mux destination example --- examples/mux.py | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 examples/mux.py diff --git a/examples/mux.py b/examples/mux.py new file mode 100644 index 0000000..4a43006 --- /dev/null +++ b/examples/mux.py @@ -0,0 +1,110 @@ +# Mux Demo. +# Ensure Mux credentials are configured in the Shotstack dashboard before running this demo. +# See: https://shotstack.io/docs/guide/serving-assets/destinations/mux + +import shotstack_sdk as shotstack +import os + +from shotstack_sdk.model.soundtrack import Soundtrack +from shotstack_sdk.model.image_asset import ImageAsset +from shotstack_sdk.api import edit_api +from shotstack_sdk.model.clip import Clip +from shotstack_sdk.model.track import Track +from shotstack_sdk.model.timeline import Timeline +from shotstack_sdk.model.output import Output +from shotstack_sdk.model.edit import Edit +from shotstack_sdk.model.mux_destination import MuxDestination +from shotstack_sdk.model.mux_destination_options import MuxDestinationOptions +from shotstack_sdk.model.shotstack_destination import ShotstackDestination + +if __name__ == "__main__": + host = "https://api.shotstack.io/stage" + + if os.getenv("SHOTSTACK_HOST") is not None: + host = os.getenv("SHOTSTACK_HOST") + + configuration = shotstack.Configuration(host = host) + + if os.getenv('SHOTSTACK_KEY') is None: + sys.exit("API Key is required. Set using: export SHOTSTACK_KEY=your_key_here") + + configuration.api_key['DeveloperKey'] = os.getenv('SHOTSTACK_KEY') + + with shotstack.ApiClient(configuration) as api_client: + api_instance = edit_api.EditApi(api_client) + + images = [ + "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/examples/images/pexels/pexels-photo-712850.jpeg", + "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/examples/images/pexels/pexels-photo-867452.jpeg", + "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/examples/images/pexels/pexels-photo-752036.jpeg", + ] + + clips = [] + start = 0.0 + length = 4.0 + + soundtrack = Soundtrack( + src = "https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/music/gangsta.mp3", + effect = "fadeInFadeOut", + volume = 1.0, + ) + + for image in images: + imageAsset = ImageAsset(src = image) + + clip = Clip( + asset = imageAsset, + start = start, + length = length, + effect = "zoomIn" + ) + + start = start + length + clips.append(clip) + + track = Track(clips = clips) + + timeline = Timeline( + background = "#000000", + soundtrack = soundtrack, + tracks = [track] + ) + + # Exclude from Shotstack hosting + shotstack_destination = ShotstackDestination( + exclude = True + ) + + # Send to Mux hosting + mux_destination_options = MuxDestinationOptions( + playback_policy = ["public"] + ) + mux_destination = MuxDestination( + options = mux_destination_options + ) + + output = Output( + format = "mp4", + resolution = "sd", + destinations = [ + shotstack_destination, + mux_destination + ] + ) + + edit = Edit( + timeline = timeline, + output = output + ) + + try: + api_response = api_instance.post_render(edit) + + message = api_response['response']['message'] + id = api_response['response']['id'] + + print(f"{message}\n") + print(">> Now check the progress of your render by running:") + print(f">> python examples/status.py {id}") + except Exception as e: + print(f"Unable to resolve API call: {e}") From 9e3dcef4aa6b80c767a2b872a63b9bd131ad151a Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Fri, 9 Dec 2022 20:15:23 +1000 Subject: [PATCH 09/13] Add template examples and update readme --- README.md | 11 ++++++ examples/templates/create.py | 74 ++++++++++++++++++++++++++++++++++++ examples/templates/render.py | 65 +++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 examples/templates/create.py create mode 100644 examples/templates/render.py diff --git a/README.md b/README.md index d10a0e5..7cf7607 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,14 @@ - **gif.py** - Create an animated gif that plays once. +### Template examples + +- **templates/create.py** - + Save an edit as a re-usable template with placeholders. + +- **templates/render.py** - + Render a template using merge fields to replace placeholders. + ### Polling example - **status.py** - @@ -57,6 +65,9 @@ - **serve-api/destination.py** - Shows how to exclude a render from being sent to the Shotstack hosting destination. +- **mux.py** - + Sends a rendered video to Mux hosting and excludes it from Shotstack. Requires a Mux account. + ### Installation Install the required dependencies including the [Shotstack Python SDK](https://www.npmjs.com/package/shotstack-sdk) diff --git a/examples/templates/create.py b/examples/templates/create.py new file mode 100644 index 0000000..fd19b72 --- /dev/null +++ b/examples/templates/create.py @@ -0,0 +1,74 @@ +import shotstack_sdk as shotstack +import os +import sys + +from shotstack_sdk.api import edit_api +from shotstack_sdk.model.video_asset import VideoAsset +from shotstack_sdk.model.clip import Clip +from shotstack_sdk.model.track import Track +from shotstack_sdk.model.timeline import Timeline +from shotstack_sdk.model.output import Output +from shotstack_sdk.model.edit import Edit +from shotstack_sdk.model.template import Template + + +if __name__ == '__main__': + host = 'https://api.shotstack.io/stage' + + if os.getenv('SHOTSTACK_HOST') is not None: + host = os.getenv('SHOTSTACK_HOST') + + configuration = shotstack.Configuration(host = host) + + if os.getenv('SHOTSTACK_KEY') is None: + sys.exit('API Key is required. Set using: export SHOTSTACK_KEY=your_key_here') + + configuration.api_key['DeveloperKey'] = os.getenv('SHOTSTACK_KEY') + + with shotstack.ApiClient(configuration) as api_client: + api_instance = edit_api.EditApi(api_client) + + video_asset = VideoAsset( + src = '{{ URL }}', + trim = '{{ TRIM }}' + ) + + video_clip = Clip( + asset = video_asset, + start = 0.0, + length = '{{ LENGTH }}' + ) + + track = Track(clips=[video_clip]) + + timeline = Timeline( + background = '#000000', + tracks = [track] + ) + + output = Output( + format = 'mp4', + resolution = 'sd' + ) + + edit = Edit( + timeline = timeline, + output = output + ) + + template = Template( + name = 'Trim Template', + template = edit + ) + + try: + api_response = api_instance.post_template(template) + + message = api_response['response']['message'] + id = api_response['response']['id'] + + print(f"{message}\n") + print(">> Now render the template using the id:") + print(f">> python examples/templates/render.py {id}") + except Exception as e: + print(f"Unable to resolve API call: {e}") diff --git a/examples/templates/render.py b/examples/templates/render.py new file mode 100644 index 0000000..c13dc5e --- /dev/null +++ b/examples/templates/render.py @@ -0,0 +1,65 @@ +import shotstack_sdk as shotstack +import os +import sys + +from shotstack_sdk.api import edit_api +from shotstack_sdk.model.template_render import TemplateRender +from shotstack_sdk.model.merge_field import MergeField + + +if __name__ == '__main__': + host = 'https://api.shotstack.io/stage' + + if os.getenv('SHOTSTACK_HOST') is not None: + host = os.getenv('SHOTSTACK_HOST') + + configuration = shotstack.Configuration(host = host) + + if os.getenv('SHOTSTACK_KEY') is None: + sys.exit('API Key is required. Set using: export SHOTSTACK_KEY=your_key_here') + + configuration.api_key['DeveloperKey'] = os.getenv('SHOTSTACK_KEY') + + with shotstack.ApiClient(configuration) as api_client: + api_instance = edit_api.EditApi(api_client) + + id = sys.argv[1] + + if id is None: + sys.exit(">> Please provide the UUID of the template (i.e. python examples/templates/render.py 7feabb0e-b5eb-8c5e-847d-82297dd4802a)\n") + + merge_field_url = MergeField( + find = 'URL', + replace = 'https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/footage/skater.hd.mp4' + ) + + merge_field_trim = MergeField( + find = 'TRIM', + replace = 3 + ) + + merge_field_length = MergeField( + find = 'LENGTH', + replace = 6 + ) + + template = TemplateRender( + id = id, + merge = [ + merge_field_url, + merge_field_trim, + merge_field_length + ] + ) + + try: + api_response = api_instance.post_template_render(template) + + message = api_response['response']['message'] + id = api_response['response']['id'] + + print(f"{message}\n") + print(">> Now check the progress of your render by running:") + print(f">> python examples/status.py {id}") + except Exception as e: + print(f"Unable to resolve API call: {e}") From 06e2a2a04d07603db2d8c5370da82639f3bc2534 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Fri, 9 Dec 2022 20:16:05 +1000 Subject: [PATCH 10/13] Bump version number --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 755bff4..56466b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -shotstack_sdk==0.2.5 +shotstack_sdk==0.2.6 From 347f7dd84a0b9e9e89e07d3b59a2adee9d0b01a1 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Thu, 18 Jul 2024 10:19:23 +1000 Subject: [PATCH 11/13] Use float for FPS --- examples/gif.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gif.py b/examples/gif.py index 67008f3..ae49326 100644 --- a/examples/gif.py +++ b/examples/gif.py @@ -66,7 +66,7 @@ output = Output( format = "gif", resolution = "preview", - fps = 12, + fps = 12.0, repeat = False ) From b8262bb1419a371354f598ca2d1262b2a869bea8 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Thu, 18 Jul 2024 10:20:20 +1000 Subject: [PATCH 12/13] Update SDK to latest version --- README.md | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7cf7607..fe05605 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Install the required dependencies including the [Shotstack Python SDK](https://www.npmjs.com/package/shotstack-sdk) ```bash -pip3 install -r requirements.txt +pip install -r requirements.txt ``` ### Set your API key diff --git a/requirements.txt b/requirements.txt index 56466b2..c3f5722 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -shotstack_sdk==0.2.6 +shotstack_sdk==0.2.7 From f1c4ef51eb4a7950e2a4725c51a74ca6fa4c9054 Mon Sep 17 00:00:00 2001 From: Jeff Shillitto Date: Fri, 19 Jul 2024 14:18:14 +1000 Subject: [PATCH 13/13] Bump latest SDK version --- examples/status.py | 4 +++- requirements.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/status.py b/examples/status.py index a795701..57282e5 100644 --- a/examples/status.py +++ b/examples/status.py @@ -23,7 +23,9 @@ id = sys.argv[1] if id is None: - sys.exit(">> Please provide the UUID of the render task (i.e. python examples/status.py 2abd5c11-0f3d-4c6d-ba20-235fc9b8e8b7)\n") + sys.exit(">> Please provide the UUID of the render task (i.e. python examples/status.py 2abd5c11-0f3d-4c6d-ba20-235fc9b8e8b7)\n") + + api_response = api_instance.get_render(id, data=False, merged=True) try: api_response = api_instance.get_render(id, data=False, merged=True) diff --git a/requirements.txt b/requirements.txt index c3f5722..44b64b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -shotstack_sdk==0.2.7 +shotstack_sdk==0.2.8