/
encoding-h264-contentaware-constrained-helper.py
154 lines (124 loc) · 6.31 KB
/
encoding-h264-contentaware-constrained-helper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import asyncio
from datetime import timedelta
from dotenv import load_dotenv
from azure.identity.aio import DefaultAzureCredential
from azure.mgmt.media.aio import AzureMediaServices
from azure.mgmt.media.models import (
Transform,
TransformOutput,
BuiltInStandardEncoderPreset,
PresetConfigurations,
InterleaveOutput,
OnErrorType,
Priority
)
import os, random
# Import Job Helpers
from importlib.machinery import SourceFileLoader
mymodule = SourceFileLoader("encoding_job_helpers", "Common/encoding_job_helpers.py").load_module()
# Get environment variables
load_dotenv()
default_credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True)
# Get the environment variables
subscription_id = os.getenv('AZURE_SUBSCRIPTION_ID')
resource_group = os.getenv('AZURE_RESOURCE_GROUP')
account_name = os.getenv('AZURE_MEDIA_SERVICES_ACCOUNT_NAME')
# The AMS Client
print("Creating AMS Client")
client = AzureMediaServices(default_credential, subscription_id)
# Send envs to helper function
mymodule.set_account_name(account_name)
mymodule.set_resource_group(resource_group)
mymodule.set_subscription_id(subscription_id)
mymodule.create_default_azure_credential(default_credential)
mymodule.create_azure_media_services(client)
# The file you want to upload. For this example, the file is placed under Media folder.
# The file ignite.mp4 has been provided for you.
source_file = "ignite.mp4"
name_prefix = "contentAware264Constrained"
output_folder = "Output/"
# This is a random string that will be added to the naming of things so that you don't have to keep doing this during testing
uniqueness = str(random.randint(0,9999))
transform_name = 'H264EncodingContentAwareConstrained'
async def main():
async with client:
# Create a new Standard encoding Transform for H264
print(f"Creating Standard Encoding transform named: {transform_name}")
# This sample uses constraints on the CAE encoding preset to reduce the number of tracks output and resolutions to a specific range.
# First we will create a PresetConfigurations object to define the constraints that we want to use
# This allows you to configure the encoder settings to control the balance between speed and quality. Example: set Complexity as Speed for faster encoding but less compression efficiency.
presetConfig = PresetConfigurations(
complexity="Speed",
# The output includes both audio and video.
interleave_output=InterleaveOutput.INTERLEAVED_OUTPUT,
# The key frame interval in seconds. Example: set as 2 to reduce the playback buffering for some players.
key_frame_interval_in_seconds= 2,
# The maximum bitrate in bits per second (threshold for the top video layer). Example: set max_bitrate_bps as 6000000 to avoid producing very high bitrate outputs for contents with high complexity
max_bitrate_bps= 6000000,
# The minimum bitrate in bits per second (threshold for the bottom video layer). Example: set min_bitrate_bps as 200000 to have a bottom layer that covers users with low network bandwidth.
min_bitrate_bps= 200000,
#The maximum height of output video layers. Example: set max_height as 720 to produce output layers up to 720P even if the input is 4K.
max_height= 720,
# The minimum height of output video layers. Example: set min_height as 360 to avoid output layers of smaller resolutions like 180P.
min_height=270,
# The maximum number of output video layers. Example: set max_layers as 4 to make sure at most 4 output layers are produced to control the overall cost of the encoding job.
max_layers=3
)
# From SDK
# TransformOutput(*, preset, on_error=None, relative_priority=None, **kwargs) -> None
# For this snippet, we are using 'BuiltInStandardEncoderPreset'
transform_output = TransformOutput(
preset = BuiltInStandardEncoderPreset(
preset_name = "ContentAwareEncoding",
# Configurations can be used to control values used by the Content Aware Encoding Preset.
configurations = presetConfig
),
# What should we do with the job if there is an error?
on_error=OnErrorType.STOP_PROCESSING_JOB,
# What is the relative priority of this job to others? Normal, high or low?
relative_priority=Priority.NORMAL
)
print("Creating encoding transform...")
# Adding transform details
my_transform = Transform()
my_transform.description="H264 content aware encoding with configuration settings"
my_transform.outputs = [transform_output]
print(f"Creating transform {transform_name}")
try:
await client.transforms.create_or_update(
resource_group_name=resource_group,
account_name=account_name,
transform_name=transform_name,
parameters=my_transform)
print(f"{transform_name} created (or updated if it existed already). ")
print()
except:
print("There was an error creating the transform.")
input = await mymodule.get_job_input_type(source_file, {}, name_prefix, uniqueness)
output_asset_name = f"{name_prefix}-output-{uniqueness}"
job_name = f"{name_prefix}-job-{uniqueness}"
print(f"Creating the output asset (container) to encode the content into...")
output_asset = await client.assets.create_or_update(resource_group, account_name, output_asset_name, {})
if output_asset:
print("Output Asset created.")
else:
print("There was a problem creating an output asset.")
print()
print(f"Submitting the encoding job to the {transform_name} job queue...")
job = await mymodule.submit_job(transform_name, job_name, input, output_asset_name)
print(f"Waiting for encoding job - {job.name} - to finish")
job = await mymodule.wait_for_job_to_finish(transform_name, job_name)
if job.state == 'Finished':
await mymodule.download_results(output_asset_name, output_folder)
print("Downloaded results to local folder. Please review the outputs from the encoding job.")
# closing media client
print('Closing media client')
await client.close()
# closing credential client
print('Closing credential client')
await default_credential.close()
if __name__ == "__main__":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())