bitmovin-ruby 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +1 -1
- data/examples/create_encoding_finished_webhook.rb +21 -0
- data/examples/dash_hls_mp4_encoding_with_manifests.rb +502 -0
- data/examples/hls_multi_codec.rb +205 -0
- data/examples/simple_dash_with_http_input.rb +216 -0
- data/examples/simple_hls_with_aes128.rb +197 -0
- data/lib/bitmovin/encoding/codec_configurations/h265_configuration.rb +1 -0
- data/lib/bitmovin/encoding/encodings/muxings/drms/drm_muxing_resource.rb +54 -0
- data/lib/bitmovin/encoding/encodings/muxings/drms/drm_muxings.rb +6 -0
- data/lib/bitmovin/encoding/encodings/muxings/drms/ts_muxing_aes_encryption.rb +5 -0
- data/lib/bitmovin/encoding/encodings/muxings/drms/ts_muxing_aes_encryption_list.rb +15 -0
- data/lib/bitmovin/encoding/encodings/muxings/drms/ts_muxing_drm_list.rb +11 -0
- data/lib/bitmovin/encoding/encodings/muxings/mp4_muxing_list.rb +1 -1
- data/lib/bitmovin/encoding/encodings/muxings/ts_muxing.rb +15 -0
- data/lib/bitmovin/encoding/encodings/stream.rb +6 -1
- data/lib/bitmovin/encoding/encodings.rb +4 -0
- data/lib/bitmovin/encoding/inputs.rb +18 -0
- data/lib/bitmovin/encoding/manifests/hls_audio_media.rb +27 -0
- data/lib/bitmovin/encoding/manifests/hls_manifest.rb +43 -0
- data/lib/bitmovin/encoding/manifests/hls_variant_stream.rb +20 -0
- data/lib/bitmovin/encoding/manifests/hls_variant_stream_list.rb +22 -0
- data/lib/bitmovin/encoding/manifests/list.rb +39 -0
- data/lib/bitmovin/encoding/manifests.rb +3 -0
- data/lib/bitmovin/encoding/outputs.rb +2 -0
- data/lib/bitmovin/version.rb +1 -1
- data/lib/bitmovin/webhooks/encoding_finished_webhook.rb +5 -0
- data/lib/bitmovin/webhooks/webhook_encryption.rb +45 -0
- data/lib/bitmovin/webhooks/webhook_resource.rb +5 -0
- data/lib/bitmovin/webhooks/webhook_signature.rb +45 -0
- data/lib/bitmovin/webhooks.rb +8 -0
- data/lib/bitmovin-ruby.rb +1 -0
- metadata +22 -3
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'bitmovin-ruby'
|
2
|
+
|
3
|
+
# CONFIGURATION
|
4
|
+
BITMOVIN_API_KEY = "YOUR API KEY HERE"
|
5
|
+
|
6
|
+
S3_INPUT_ID = "The ID of the Input"
|
7
|
+
S3_OUTPUT_ID = "The ID of the Output"
|
8
|
+
OUTPUT_PATH = "/encoding_test/bitmovin-ruby/#{Time.now.strftime("%v-%H-%M")}/"
|
9
|
+
M3U8_NAME = "playlist.m3u8"
|
10
|
+
|
11
|
+
Bitmovin.init(BITMOVIN_API_KEY)
|
12
|
+
|
13
|
+
# This will create a Input Bucket you can reuse in future encodings
|
14
|
+
# To get a list of all your S3Inputs do:
|
15
|
+
# Bitmovin::Encoding::Inputs::S3Input.list
|
16
|
+
s3_input = Bitmovin::Encoding::Inputs::S3Input.find(S3_INPUT_ID)
|
17
|
+
|
18
|
+
# This will create a Output Bucket you can reuse in future encodings
|
19
|
+
# To get a list of all your Output do:
|
20
|
+
# Bitmovin::Encoding::Outputs::S3Output.list
|
21
|
+
s3_output = Bitmovin::Encoding::Outputs::S3Output.find(S3_OUTPUT_ID)
|
22
|
+
|
23
|
+
# Please note inputs/outputs are not individual files but rather the
|
24
|
+
# Bucket you are reading/writing files to and they can be reused between encodings.
|
25
|
+
|
26
|
+
|
27
|
+
# This hash contains the H264 Codec Configurations we want to create
|
28
|
+
# Codec Configurations are similar to Inputs/Outputs in that they are configured once
|
29
|
+
# and can be reused for future encodings.
|
30
|
+
video_configs = [
|
31
|
+
{ name: "h264_360p_600", profile: "HIGH", height: 360, bitrate: 600000 },
|
32
|
+
{ name: "h264_432p_700", profile: "HIGH", height: 432, bitrate: 700000 },
|
33
|
+
{ name: "h264_576p_1050", profile: "HIGH", height: 576, bitrate: 1050000 },
|
34
|
+
{ name: "h264_720p_1380", profile: "HIGH", height: 720, bitrate: 1380000 },
|
35
|
+
{ name: "h264_720p_1800", profile: "HIGH", height: 720, bitrate: 1800000 },
|
36
|
+
{ name: "h264_1080p_2150", profile: "HIGH", height: 1080, bitrate: 2150000 },
|
37
|
+
{ name: "h264_1080p_2900", profile: "HIGH", height: 1080, bitrate: 2900000 },
|
38
|
+
{ name: "h264_2160p_4000", profile: "HIGH", height: 2160, bitrate: 4000000 },
|
39
|
+
{ name: "h264_2160p_6000", profile: "HIGH", height: 2160, bitrate: 6000000 },
|
40
|
+
{ name: "h264_2160p_8500", profile: "HIGH", height: 2160, bitrate: 8500000 },
|
41
|
+
{ name: "h264_2160p_10000", profile: "HIGH", height: 2160, bitrate: 10000000 },
|
42
|
+
|
43
|
+
{ name: "h265_360p_420", profile: "main", height: 360, bitrate: 420000 },
|
44
|
+
{ name: "h265_432p_490", profile: "main", height: 432, bitrate: 490000 },
|
45
|
+
{ name: "h265_576p_735", profile: "main", height: 576, bitrate: 735000 },
|
46
|
+
{ name: "h265_720p_966", profile: "main", height: 720, bitrate: 966000 },
|
47
|
+
{ name: "h265_720p_1260", profile: "main", height: 720, bitrate: 1260000 },
|
48
|
+
{ name: "h265_1080p_1505", profile: "main", height: 1080, bitrate: 1505000 },
|
49
|
+
{ name: "h265_1080p_2030", profile: "main", height: 1080, bitrate: 2030000 },
|
50
|
+
{ name: "h265_2160p_2800", profile: "main", height: 2160, bitrate: 2800000 },
|
51
|
+
{ name: "h265_2160p_4200", profile: "main", height: 2160, bitrate: 4200000 },
|
52
|
+
{ name: "h265_2160p_5950", profile: "main", height: 2160, bitrate: 5950000 },
|
53
|
+
{ name: "h265_2160p_7000", profile: "main", height: 2160, bitrate: 7000000 }
|
54
|
+
]
|
55
|
+
|
56
|
+
# The actual instance of the encoding task you are about to start
|
57
|
+
enc = Bitmovin::Encoding::Encodings::EncodingTask.new({
|
58
|
+
name: "VOD h264/h265 Encoding HLS"
|
59
|
+
})
|
60
|
+
enc.save!
|
61
|
+
|
62
|
+
|
63
|
+
# Let's also start the Manifest generation
|
64
|
+
manifest = Bitmovin::Encoding::Manifests::HlsManifest.new({
|
65
|
+
name: 'Test Ruby Manifest',
|
66
|
+
description: "Test encoding with ruby",
|
67
|
+
manifest_name: M3U8_NAME
|
68
|
+
})
|
69
|
+
|
70
|
+
manifest.outputs << Bitmovin::Encoding::StreamOutput.new({
|
71
|
+
output_id: s3_output.id,
|
72
|
+
output_path: OUTPUT_PATH
|
73
|
+
})
|
74
|
+
manifest.save!
|
75
|
+
|
76
|
+
create_audio!(enc, manifest, s3_input, s3_output)
|
77
|
+
|
78
|
+
# Adding Video Streams to Encoding
|
79
|
+
video_configs.each do |config|
|
80
|
+
if (config[:name].start_with?("h264"))
|
81
|
+
codec_config = Bitmovin::Encoding::CodecConfigurations::H264Configuration.new(config)
|
82
|
+
else
|
83
|
+
codec_config = Bitmovin::Encoding::CodecConfigurations::H265Configuration.new(config)
|
84
|
+
end
|
85
|
+
codec_config.save!
|
86
|
+
config = OpenStruct.new(config)
|
87
|
+
|
88
|
+
str = enc.streams.build(name: codec_config.name)
|
89
|
+
str.codec_configuration = codec_config
|
90
|
+
str.build_input_stream(input_path: INPUT_FILE_PATH, input_id: s3_input.id, selection_mode: 'AUTO')
|
91
|
+
str.conditions = {
|
92
|
+
type: "CONDITION",
|
93
|
+
attribute: "HEIGHT",
|
94
|
+
operator: "<=",
|
95
|
+
value: codec_config.height
|
96
|
+
}
|
97
|
+
str.save!
|
98
|
+
|
99
|
+
muxing = enc.muxings.fmp4.build(name: "#{codec_config.name} muxing", segment_length: 4)
|
100
|
+
muxing.streams << str.id
|
101
|
+
muxing.build_output({
|
102
|
+
output_id: s3_output.id,
|
103
|
+
output_path: File.join(OUTPUT_PATH, config.name),
|
104
|
+
acl: [{
|
105
|
+
permission: "PUBLIC_READ"
|
106
|
+
}]
|
107
|
+
})
|
108
|
+
muxing.save!
|
109
|
+
puts "Finished muxing #{muxing.name}"
|
110
|
+
|
111
|
+
# Add the Stream to the Manifest too
|
112
|
+
hls_stream = manifest.build_stream({
|
113
|
+
audio: 'audio_group',
|
114
|
+
closed_captions: 'NONE',
|
115
|
+
segmentPath: config.name,
|
116
|
+
encoding_id: enc.id,
|
117
|
+
muxing_id: muxing.id,
|
118
|
+
stream_id: str.id,
|
119
|
+
#drm_id: aes_muxing.id,
|
120
|
+
uri: config.name + '.m3u8'
|
121
|
+
})
|
122
|
+
hls_stream.save!
|
123
|
+
end
|
124
|
+
|
125
|
+
# Starting an encoding and monitoring it's status
|
126
|
+
enc.start!
|
127
|
+
|
128
|
+
while(enc.status != 'FINISHED')
|
129
|
+
puts "Encoding Status is #{enc.status}"
|
130
|
+
progress = enc.progress
|
131
|
+
if (progress > 0)
|
132
|
+
puts "Progress: #{enc.progress} %"
|
133
|
+
end
|
134
|
+
sleep 2
|
135
|
+
end
|
136
|
+
puts "Encoding finished!"
|
137
|
+
|
138
|
+
# Now that the encoding is finished we can start writing the m3u8 Manifest
|
139
|
+
manifest.start!
|
140
|
+
|
141
|
+
while(manifest.status != 'FINISHED')
|
142
|
+
puts "manifestoding Status is #{manifest.status}"
|
143
|
+
progress = manifest.progress
|
144
|
+
if (progress > 0)
|
145
|
+
puts "Progress: #{manifest.progress} %"
|
146
|
+
end
|
147
|
+
sleep 2
|
148
|
+
end
|
149
|
+
|
150
|
+
BEGIN {
|
151
|
+
# Begin is a hack to have this method available but define it at the end of the file
|
152
|
+
def create_audio!(enc, manifest, s3_input, s3_output)
|
153
|
+
|
154
|
+
# Create or load the Audio Config
|
155
|
+
#audio_config = Bitmovin::Encoding::CodecConfigurations::AacConfiguration.find("<EXISTING_AAC_CONFIG_ID>")
|
156
|
+
audio_config = Bitmovin::Encoding::CodecConfigurations::AacConfiguration.new({
|
157
|
+
name: "AAC_PROFILE_128k",
|
158
|
+
bitrate: 128000,
|
159
|
+
rate: 48000
|
160
|
+
})
|
161
|
+
audio_config.save!
|
162
|
+
#
|
163
|
+
# Adding Audio Stream to Encoding
|
164
|
+
stream_aac = enc.streams.build(name: 'audio stream')
|
165
|
+
stream_aac.codec_configuration = audio_config
|
166
|
+
stream_aac.build_input_stream(input_path: INPUT_FILE_PATH, input_id: s3_input.id, selection_mode: 'AUTO')
|
167
|
+
stream_aac.conditions = {
|
168
|
+
type: "CONDITION",
|
169
|
+
attribute: "INPUTSTREAM",
|
170
|
+
operator: "==",
|
171
|
+
value: "TRUE"
|
172
|
+
}
|
173
|
+
puts stream_aac.conditions.to_json
|
174
|
+
stream_aac.save!
|
175
|
+
|
176
|
+
# Audio Muxing
|
177
|
+
audio_muxing = enc.muxings.fmp4.build(name: 'audio-muxing', segment_length: 4)
|
178
|
+
audio_muxing.build_output({
|
179
|
+
output_id: s3_output.id,
|
180
|
+
output_path: File.join(OUTPUT_PATH, "audio/aac")
|
181
|
+
})
|
182
|
+
audio_muxing.build_output({
|
183
|
+
output_id: s3_output.id,
|
184
|
+
output_path: File.join(OUTPUT_PATH, "audio/aac"),
|
185
|
+
acl: [{
|
186
|
+
permission: "PUBLIC_READ"
|
187
|
+
}]
|
188
|
+
})
|
189
|
+
audio_muxing.streams << stream_aac.id
|
190
|
+
audio_muxing.save!
|
191
|
+
|
192
|
+
# Adding Audio Stream to HLS Manifest
|
193
|
+
audio_stream_medium = manifest.build_audio_medium({
|
194
|
+
name: "HLS Audio Media",
|
195
|
+
group_id: "audio_group",
|
196
|
+
segment_path: "audio/aac",
|
197
|
+
encoding_id: enc.id,
|
198
|
+
stream_id: stream_aac.id,
|
199
|
+
muxing_id: audio_muxing.id,
|
200
|
+
language: "en",
|
201
|
+
uri: "audio_media.m3u8"
|
202
|
+
})
|
203
|
+
audio_stream_medium.save!
|
204
|
+
end
|
205
|
+
}
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# CONFIGURATION
|
2
|
+
BITMOVIN_API_KEY = 'YOUR API KEY HERE'
|
3
|
+
|
4
|
+
HTTP_INPUT_HOST = 'your.host.com'
|
5
|
+
HTTP_INPUT_FILE_PATH = '/path/to/your/input/file.mkv'
|
6
|
+
|
7
|
+
OUTPUT_AWS_ACCESS_KEY = 'YOUR AWS_ACCESS_KEY'
|
8
|
+
OUTPUT_AWS_SECRET_KEY = 'YOUR AWS_SECRET_KEY'
|
9
|
+
|
10
|
+
BUCKET_NAME = 'YOUR BUCKET NAME HERE'
|
11
|
+
OUTPUT_PATH = 'path/to/output'
|
12
|
+
MPD_NAME = 'manifest.mpd'
|
13
|
+
|
14
|
+
# Please refer to our API spec to get available cloud regions
|
15
|
+
# https://bitmovin.com/encoding-documentation/bitmovin-api/#/reference/encoding/encodings/create-encoding
|
16
|
+
ENCODING_CLOUD_REGION = 'GOOGLE_EUROPE_WEST_1'
|
17
|
+
|
18
|
+
Bitmovin.init(BITMOVIN_API_KEY)
|
19
|
+
|
20
|
+
# This will create a http input
|
21
|
+
# To get a list of all your HTTP outputs do:
|
22
|
+
# Bitmovin::Encoding::Outputs::HttpOutput.list
|
23
|
+
http_input = Bitmovin::Encoding::Inputs::HttpInput.new({
|
24
|
+
host: HTTP_INPUT_HOST
|
25
|
+
}).save!
|
26
|
+
|
27
|
+
# For reuse set http_input_id = '<YOUR HTTP INPUT ID>' and omit creation
|
28
|
+
http_input_id = http_input.id
|
29
|
+
|
30
|
+
# This will create a Output Bucket you can reuse in future encodings
|
31
|
+
# To get a list of all your Output do:
|
32
|
+
# Bitmovin::Encoding::Outputs::S3Output.list
|
33
|
+
s3_output = Bitmovin::Encoding::Outputs::S3Output.new({
|
34
|
+
accessKey: OUTPUT_AWS_ACCESS_KEY,
|
35
|
+
secretKey: OUTPUT_AWS_SECRET_KEY,
|
36
|
+
bucketName: BUCKET_NAME
|
37
|
+
}).save!
|
38
|
+
|
39
|
+
# For reuse set s3_output_id = '<YOUR S3 OUTPUT ID>' and omit creation
|
40
|
+
s3_output_id = s3_output.id
|
41
|
+
|
42
|
+
# Codec Configurations are similar to Inputs/Outputs in that they are configured once
|
43
|
+
# and can be reused for future encodings.
|
44
|
+
codec_config_720_700 = Bitmovin::Encoding::CodecConfigurations::H264Configuration.new({
|
45
|
+
name: 'H264 1280x720 700kb/s',
|
46
|
+
profile: 'MAIN',
|
47
|
+
width: 1280,
|
48
|
+
height: 720,
|
49
|
+
bitrate: 700000
|
50
|
+
})
|
51
|
+
codec_config_720_700.save!
|
52
|
+
codec_config_720_1500 = Bitmovin::Encoding::CodecConfigurations::H264Configuration.new({
|
53
|
+
name: 'H264 1280x720 1500kb/s',
|
54
|
+
profile: 'MAIN',
|
55
|
+
width: 1280,
|
56
|
+
height: 720,
|
57
|
+
bitrate: 1500000
|
58
|
+
})
|
59
|
+
codec_config_720_1500.save!
|
60
|
+
codec_config_720_2400 = Bitmovin::Encoding::CodecConfigurations::H264Configuration.new({
|
61
|
+
name: 'H264 1280x720 2400kb/s',
|
62
|
+
profile: 'MAIN',
|
63
|
+
width: 1280,
|
64
|
+
height: 720,
|
65
|
+
bitrate: 2400000
|
66
|
+
})
|
67
|
+
codec_config_720_2400.save!
|
68
|
+
|
69
|
+
audio_config = Bitmovin::Encoding::CodecConfigurations::AacConfiguration.new({
|
70
|
+
name: 'AAC_PROFILE_128k',
|
71
|
+
bitrate: 128000,
|
72
|
+
rate: 48000
|
73
|
+
})
|
74
|
+
audio_config.save!
|
75
|
+
|
76
|
+
|
77
|
+
# The actual instance of the encoding task you are about to start
|
78
|
+
enc = Bitmovin::Encoding::Encodings::EncodingTask.new({
|
79
|
+
name: 'VOD Encoding Ruby',
|
80
|
+
cloud_region: ENCODING_CLOUD_REGION
|
81
|
+
})
|
82
|
+
enc.save!
|
83
|
+
|
84
|
+
# Stream Configuration
|
85
|
+
|
86
|
+
stream_720_700 = enc.streams.build(name: 'H264 1280x720 700kb/s')
|
87
|
+
stream_720_700.codec_configuration = codec_config_720_700
|
88
|
+
stream_720_700.build_input_stream(input_path: INPUT_FILE_PATH, input_id: http_input_id, selection_mode: 'AUTO')
|
89
|
+
stream_720_700.save!
|
90
|
+
|
91
|
+
stream_720_1500 = enc.streams.build(name: 'H264 1280x720 1500/s')
|
92
|
+
stream_720_1500.codec_configuration = codec_config_720_1500
|
93
|
+
stream_720_1500.build_input_stream(input_path: INPUT_FILE_PATH, input_id: http_input_id, selection_mode: 'AUTO')
|
94
|
+
stream_720_1500.save!
|
95
|
+
|
96
|
+
stream_720_2400 = enc.streams.build(name: 'H264 1280x720 2400/s')
|
97
|
+
stream_720_2400.codec_configuration = codec_config_720_2400
|
98
|
+
stream_720_2400.build_input_stream(input_path: INPUT_FILE_PATH, input_id: http_input_id, selection_mode: 'AUTO')
|
99
|
+
stream_720_2400.save!
|
100
|
+
|
101
|
+
stream_aac = enc.streams.build(name: 'audio stream')
|
102
|
+
stream_aac.codec_configuration = audio_config
|
103
|
+
stream_aac.build_input_stream(input_path: INPUT_FILE_PATH, input_id: http_input_id, selection_mode: 'AUTO')
|
104
|
+
stream_aac.save!
|
105
|
+
|
106
|
+
# Muxing Configuration
|
107
|
+
|
108
|
+
fmp4_muxing_720_700 = enc.muxings.fmp4.build(name: 'H264 1280x720 700kb/s', segment_length: 4)
|
109
|
+
fmp4_muxing_720_700.build_output({
|
110
|
+
output_id: s3_output_id,
|
111
|
+
output_path: File.join(OUTPUT_PATH, 'video/720_700')
|
112
|
+
})
|
113
|
+
fmp4_muxing_720_700.streams << stream_720_700.id
|
114
|
+
fmp4_muxing_720_700.save!
|
115
|
+
|
116
|
+
fmp4_muxing_720_1500 = enc.muxings.fmp4.build(name: 'H264 1280x720 1500kb/s', segment_length: 4)
|
117
|
+
fmp4_muxing_720_1500.build_output({
|
118
|
+
output_id: s3_output_id,
|
119
|
+
output_path: File.join(OUTPUT_PATH, 'video/720_1500')
|
120
|
+
})
|
121
|
+
fmp4_muxing_720_1500.streams << stream_720_1500.id
|
122
|
+
fmp4_muxing_720_1500.save!
|
123
|
+
|
124
|
+
fmp4_muxing_720_2400 = enc.muxings.fmp4.build(name: 'H264 1280x720 2400kb/s', segment_length: 4)
|
125
|
+
fmp4_muxing_720_2400.build_output({
|
126
|
+
output_id: s3_output_id,
|
127
|
+
output_path: File.join(OUTPUT_PATH, 'video/720_2400')
|
128
|
+
})
|
129
|
+
fmp4_muxing_720_2400.streams << stream_720_2400.id
|
130
|
+
fmp4_muxing_720_2400.save!
|
131
|
+
|
132
|
+
audio_muxing = enc.muxings.fmp4.build(name: 'audio-muxing', segment_length: 4)
|
133
|
+
audio_muxing.build_output({
|
134
|
+
output_id: s3_output_id,
|
135
|
+
output_path: File.join(OUTPUT_PATH, 'audio/aac')
|
136
|
+
})
|
137
|
+
audio_muxing.streams << stream_aac.id
|
138
|
+
audio_muxing.save!
|
139
|
+
|
140
|
+
|
141
|
+
# Starting an encoding and monitoring it's status
|
142
|
+
enc.start!
|
143
|
+
|
144
|
+
while enc.status != 'FINISHED' && enc.status != 'ERROR'
|
145
|
+
puts "Encoding Status is #{enc.status}"
|
146
|
+
progress = enc.progress
|
147
|
+
if progress > 0
|
148
|
+
puts "Progress: #{enc.progress} %"
|
149
|
+
end
|
150
|
+
sleep 2
|
151
|
+
end
|
152
|
+
puts "Encoding finished with status #{enc.status}!"
|
153
|
+
|
154
|
+
|
155
|
+
# Generating a DASH Manifest
|
156
|
+
puts 'Starting Manifest generation'
|
157
|
+
manifest = Bitmovin::Encoding::Manifests::DashManifest.new({
|
158
|
+
name: 'Test Ruby Manifest',
|
159
|
+
description: 'Test encoding with ruby',
|
160
|
+
manifest_name: MPD_NAME
|
161
|
+
})
|
162
|
+
|
163
|
+
manifest.outputs << Bitmovin::Encoding::StreamOutput.new({
|
164
|
+
output_id: s3_output_id,
|
165
|
+
output_path: OUTPUT_PATH
|
166
|
+
})
|
167
|
+
manifest.save!
|
168
|
+
|
169
|
+
period = manifest.build_period()
|
170
|
+
period.save!
|
171
|
+
|
172
|
+
video_adaptationset = period.build_video_adaptationset()
|
173
|
+
video_adaptationset.save!
|
174
|
+
|
175
|
+
audio_adaptationset = period.build_audio_adaptationset({lang: 'en'})
|
176
|
+
audio_adaptationset.save!
|
177
|
+
|
178
|
+
video_adaptationset.build_fmp4_representation({
|
179
|
+
encoding_id: enc.id,
|
180
|
+
muxing_id: fmp4_muxing_720_2400.id,
|
181
|
+
type: 'TEMPLATE',
|
182
|
+
segment_path: 'video/720_2400'
|
183
|
+
}).save!
|
184
|
+
video_adaptationset.build_fmp4_representation({
|
185
|
+
encoding_id: enc.id,
|
186
|
+
muxing_id: fmp4_muxing_720_1500.id,
|
187
|
+
type: 'TEMPLATE',
|
188
|
+
segment_path: 'video/720_1500'
|
189
|
+
}).save!
|
190
|
+
video_adaptationset.build_fmp4_representation({
|
191
|
+
encoding_id: enc.id,
|
192
|
+
muxing_id: fmp4_muxing_720_700.id,
|
193
|
+
type: 'TEMPLATE',
|
194
|
+
segment_path: 'video/720_700'
|
195
|
+
}).save!
|
196
|
+
|
197
|
+
audio_adaptationset.build_fmp4_representation({
|
198
|
+
encoding_id: enc.id,
|
199
|
+
muxing_id: audio_muxing.id,
|
200
|
+
name: 'Audio representation',
|
201
|
+
type: 'TEMPLATE',
|
202
|
+
segment_path: 'audio/aac'
|
203
|
+
}).save!
|
204
|
+
|
205
|
+
manifest.start!
|
206
|
+
|
207
|
+
while manifest.status != 'FINISHED' && manifest.status != 'ERROR'
|
208
|
+
puts "Manifest Status is #{manifest.status}"
|
209
|
+
progress = manifest.progress
|
210
|
+
if progress > 0
|
211
|
+
puts "Progress: #{manifest.progress} %"
|
212
|
+
end
|
213
|
+
sleep 2
|
214
|
+
end
|
215
|
+
|
216
|
+
puts "Manifest generation finished with status #{manifest.status}!"
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'bitmovin-ruby'
|
2
|
+
|
3
|
+
# CONFIGURATION
|
4
|
+
BITMOVIN_API_KEY = "YOUR API KEY HERE"
|
5
|
+
|
6
|
+
S3_INPUT_ID = "The ID of the Input"
|
7
|
+
S3_OUTPUT_ID = "The ID of the Output"
|
8
|
+
INPUT_FILE_PATH = "encoding/awolnation.mkv"
|
9
|
+
OUTPUT_PATH = "/encoding_test/bitmovin-ruby/#{Time.now.strftime("%v-%H-%M")}/"
|
10
|
+
M3U8_NAME = "playlist.m3u8"
|
11
|
+
|
12
|
+
DRM_AES_KEY = "759678DC403B3CB84125E8E0F0824CD6" # Change this to something else
|
13
|
+
DRM_AES_IV = "196E6EB871BBC09191A3995318406198"
|
14
|
+
|
15
|
+
Bitmovin.init(BITMOVIN_API_KEY)
|
16
|
+
|
17
|
+
# This will create a Input Bucket you can reuse in future encodings
|
18
|
+
# To get a list of all your S3Inputs do:
|
19
|
+
# Bitmovin::Encoding::Inputs::S3Input.list
|
20
|
+
s3_input = Bitmovin::Encoding::Inputs::S3Input.find(S3_INPUT_ID)
|
21
|
+
|
22
|
+
# This will create a Output Bucket you can reuse in future encodings
|
23
|
+
# To get a list of all your Output do:
|
24
|
+
# Bitmovin::Encoding::Outputs::S3Output.list
|
25
|
+
s3_output = Bitmovin::Encoding::Outputs::S3Output.find(S3_OUTPUT_ID)
|
26
|
+
|
27
|
+
# Please note inputs/outputs are not individual files but rather the
|
28
|
+
# Bucket you are reading/writing files to and they can be reused between encodings.
|
29
|
+
|
30
|
+
|
31
|
+
# This hash contains the H264 Codec Configurations we want to create
|
32
|
+
# Codec Configurations are similar to Inputs/Outputs in that they are configured once
|
33
|
+
# and can be reused for future encodings.
|
34
|
+
video_configs = [
|
35
|
+
{ name: "h264_720p_700",
|
36
|
+
profile: "MAIN",
|
37
|
+
height: 720,
|
38
|
+
bitrate: 700000
|
39
|
+
}, {
|
40
|
+
name: "h264_540p_500",
|
41
|
+
profile: "MAIN",
|
42
|
+
height: 540,
|
43
|
+
bitrate: 500000
|
44
|
+
}
|
45
|
+
]
|
46
|
+
|
47
|
+
# The actual instance of the encoding task you are about to start
|
48
|
+
enc = Bitmovin::Encoding::Encodings::EncodingTask.new({
|
49
|
+
name: "VOD Encoding HLS AES128 Ruby"
|
50
|
+
})
|
51
|
+
enc.save!
|
52
|
+
|
53
|
+
|
54
|
+
# Let's also start the Manifest generation
|
55
|
+
manifest = Bitmovin::Encoding::Manifests::HlsManifest.new({
|
56
|
+
name: 'Test Ruby Manifest',
|
57
|
+
description: "Test encoding with ruby",
|
58
|
+
manifest_name: M3U8_NAME
|
59
|
+
})
|
60
|
+
|
61
|
+
manifest.outputs << Bitmovin::Encoding::StreamOutput.new({
|
62
|
+
output_id: s3_output.id,
|
63
|
+
output_path: OUTPUT_PATH
|
64
|
+
})
|
65
|
+
manifest.save!
|
66
|
+
|
67
|
+
create_audio!(enc, manifest, s3_input, s3_output)
|
68
|
+
|
69
|
+
# Adding Video Streams to Encoding
|
70
|
+
video_configs.each do |config|
|
71
|
+
h264_config = Bitmovin::Encoding::CodecConfigurations::H264Configuration.new(config)
|
72
|
+
h264_config.save!
|
73
|
+
config = OpenStruct.new(config)
|
74
|
+
|
75
|
+
str = enc.streams.build(name: h264_config.name)
|
76
|
+
str.codec_configuration = h264_config
|
77
|
+
str.build_input_stream(input_path: INPUT_FILE_PATH, input_id: s3_input.id, selection_mode: 'AUTO')
|
78
|
+
str.save!
|
79
|
+
|
80
|
+
muxing = enc.muxings.ts.build(name: "#{h264_config.name} muxing", segment_length: 4)
|
81
|
+
muxing.streams << str.id
|
82
|
+
muxing.save!
|
83
|
+
|
84
|
+
aes_muxing = muxing.drms.aes.build({
|
85
|
+
key: DRM_AES_KEY,
|
86
|
+
iv: DRM_AES_IV,
|
87
|
+
method: 'AES_128',
|
88
|
+
name: "AES DRM for #{muxing.name}"
|
89
|
+
})
|
90
|
+
aes_muxing.build_output({
|
91
|
+
output_id: s3_output.id,
|
92
|
+
output_path: File.join(OUTPUT_PATH, config.name),
|
93
|
+
acl: [{
|
94
|
+
permission: "PUBLIC_READ"
|
95
|
+
}]
|
96
|
+
})
|
97
|
+
aes_muxing.save!
|
98
|
+
puts "Finished DRM Muxing"
|
99
|
+
|
100
|
+
# Add the Stream to the Manifest too
|
101
|
+
hls_stream = manifest.build_stream({
|
102
|
+
audio: 'audio_group',
|
103
|
+
closed_captions: 'NONE',
|
104
|
+
segmentPath: config.name,
|
105
|
+
encoding_id: enc.id,
|
106
|
+
muxing_id: muxing.id,
|
107
|
+
stream_id: str.id,
|
108
|
+
drm_id: aes_muxing.id,
|
109
|
+
uri: config.name + '.m3u8'
|
110
|
+
})
|
111
|
+
hls_stream.save!
|
112
|
+
end
|
113
|
+
|
114
|
+
# Starting an encoding and monitoring it's status
|
115
|
+
enc.start!
|
116
|
+
|
117
|
+
while(enc.status != 'FINISHED')
|
118
|
+
puts "Encoding Status is #{enc.status}"
|
119
|
+
progress = enc.progress
|
120
|
+
if (progress > 0)
|
121
|
+
puts "Progress: #{enc.progress} %"
|
122
|
+
end
|
123
|
+
sleep 2
|
124
|
+
end
|
125
|
+
puts "Encoding finished!"
|
126
|
+
|
127
|
+
# Now that the encoding is finished we can start writing the m3u8 Manifest
|
128
|
+
manifest.start!
|
129
|
+
|
130
|
+
while(manifest.status != 'FINISHED')
|
131
|
+
puts "manifestoding Status is #{manifest.status}"
|
132
|
+
progress = manifest.progress
|
133
|
+
if (progress > 0)
|
134
|
+
puts "Progress: #{manifest.progress} %"
|
135
|
+
end
|
136
|
+
sleep 2
|
137
|
+
end
|
138
|
+
|
139
|
+
BEGIN {
|
140
|
+
# Begin is a hack to have this method available but define it at the end of the file
|
141
|
+
def create_audio!(enc, manifest, s3_input, s3_output)
|
142
|
+
|
143
|
+
# Create or load the Audio Config
|
144
|
+
#audio_config = Bitmovin::Encoding::CodecConfigurations::AacConfiguration.find("<EXISTING_AAC_CONFIG_ID>")
|
145
|
+
audio_config = Bitmovin::Encoding::CodecConfigurations::AacConfiguration.new({
|
146
|
+
name: "AAC_PROFILE_128k",
|
147
|
+
bitrate: 128000,
|
148
|
+
rate: 48000
|
149
|
+
})
|
150
|
+
audio_config.save!
|
151
|
+
#
|
152
|
+
# Adding Audio Stream to Encoding
|
153
|
+
stream_aac = enc.streams.build(name: 'audio stream')
|
154
|
+
stream_aac.codec_configuration = audio_config
|
155
|
+
stream_aac.build_input_stream(input_path: INPUT_FILE_PATH, input_id: s3_input.id, selection_mode: 'AUTO')
|
156
|
+
stream_aac.save!
|
157
|
+
|
158
|
+
# Audio Muxing
|
159
|
+
audio_muxing = enc.muxings.ts.build(name: 'audio-muxing', segment_length: 4)
|
160
|
+
audio_muxing.build_output({
|
161
|
+
output_id: s3_output.id,
|
162
|
+
output_path: File.join(OUTPUT_PATH, "audio/aac")
|
163
|
+
})
|
164
|
+
audio_muxing.streams << stream_aac.id
|
165
|
+
audio_muxing.save!
|
166
|
+
|
167
|
+
aes_audio_muxing = audio_muxing.drms.aes.build({
|
168
|
+
key: DRM_AES_KEY,
|
169
|
+
iv: DRM_AES_IV,
|
170
|
+
method: 'AES_128',
|
171
|
+
name: "AES DRM for Audio"
|
172
|
+
})
|
173
|
+
aes_audio_muxing.build_output({
|
174
|
+
output_id: s3_output.id,
|
175
|
+
output_path: File.join(OUTPUT_PATH, "audio/aac"),
|
176
|
+
acl: [{
|
177
|
+
permission: "PUBLIC_READ"
|
178
|
+
}]
|
179
|
+
})
|
180
|
+
aes_audio_muxing.save!
|
181
|
+
puts "Finished DRM Muxing"
|
182
|
+
|
183
|
+
# Adding Audio Stream to HLS Manifest
|
184
|
+
audio_stream_medium = manifest.build_audio_medium({
|
185
|
+
name: "HLS Audio Media",
|
186
|
+
group_id: "audio_group",
|
187
|
+
segment_path: "audio/aac",
|
188
|
+
encoding_id: enc.id,
|
189
|
+
stream_id: stream_aac.id,
|
190
|
+
muxing_id: audio_muxing.id,
|
191
|
+
drm_id: aes_audio_muxing.id,
|
192
|
+
language: "en",
|
193
|
+
uri: "audio_media.m3u8"
|
194
|
+
})
|
195
|
+
audio_stream_medium.save!
|
196
|
+
end
|
197
|
+
}
|
@@ -3,6 +3,7 @@ module Bitmovin::Encoding::CodecConfigurations
|
|
3
3
|
init 'encoding/configurations/video/h265'
|
4
4
|
|
5
5
|
attr_accessor :id, :name, :description, :created_at, :modified_at
|
6
|
+
attr_accessor :width, :height
|
6
7
|
attr_accessor :name, :description, :bitrate, :rate, :profile, :bframes, :ref_frames, :qp, :max_bitrate, :min_bitrate, :bufsize, :min_gop, :max_gop, :level, :rc_lookahead, :b_adapt, :max_ctu_size, :tu_intra_depth, :tu_inter_depth, :motion_search, :sub_me, :motion_search_range, :weight_prediction_on_p_slice, :weight_prediction_on_b_slice, :sao
|
7
8
|
end
|
8
9
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Bitmovin::Encoding::Encodings::Muxings::Drms
|
2
|
+
class DrmMuxingResource < Bitmovin::Resource
|
3
|
+
attr_accessor :name, :description, :created_at, :modified_at
|
4
|
+
attr_accessor :encoding_id, :muxing_id
|
5
|
+
attr_accessor :id
|
6
|
+
attr_accessor :outputs
|
7
|
+
|
8
|
+
def initialize(encoding_id, muxing_id, hash = {})
|
9
|
+
hsh = ActiveSupport::HashWithIndifferentAccess.new(underscore_hash(hash))
|
10
|
+
@encoding_id = encoding_id
|
11
|
+
@muxing_id = muxing_id
|
12
|
+
muxing_type = self.class.name.demodulize.gsub(/(.*)Muxing.*/, '\1').downcase
|
13
|
+
encryption_type = self.class.name.demodulize.gsub(/.*Muxing(.*)Encryption/, '\1').downcase
|
14
|
+
self.class.init(File.join("/v1/encoding/encodings/", encoding_id, "muxings", muxing_type, muxing_id, "drm", encryption_type))
|
15
|
+
super(hsh)
|
16
|
+
@outputs = (hsh[:outputs] || []).map do |output|
|
17
|
+
Bitmovin::Encoding::StreamOutput.new(output)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_output(opts = {})
|
22
|
+
output = Bitmovin::Encoding::StreamOutput.new(opts)
|
23
|
+
@outputs << output
|
24
|
+
output
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def collect_attributes
|
30
|
+
val = Hash.new
|
31
|
+
ignored_variables = []
|
32
|
+
if (self.respond_to?(:ignore_fields))
|
33
|
+
ignored_variables = self.ignore_fields
|
34
|
+
end
|
35
|
+
instance_variables.each do |name|
|
36
|
+
if ignored_variables.include?(name)
|
37
|
+
next
|
38
|
+
end
|
39
|
+
if name == :@outputs
|
40
|
+
val["outputs"] = @outputs.map { |o| o.send(:collect_attributes) }
|
41
|
+
next
|
42
|
+
end
|
43
|
+
|
44
|
+
if name == :@streams
|
45
|
+
val["streams"] = @streams.map { |s| { "streamId" => s } }
|
46
|
+
next
|
47
|
+
end
|
48
|
+
json_name = ActiveSupport::Inflector.camelize(name.to_s.gsub(/@/, ''), false)
|
49
|
+
val[json_name] = instance_variable_get(name)
|
50
|
+
end
|
51
|
+
val
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|