awslive-inputlooper 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/awslive-inputlooper +83 -0
- data/lib/awslive-common/action_type.rb +4 -0
- data/lib/awslive-common/all_exceptions.rb +9 -0
- data/lib/awslive-common/logging.rb +9 -0
- data/lib/awslive-common/start_type.rb +5 -0
- data/lib/awslive-inputlooper.rb +1 -0
- data/lib/awslive-inputlooper/input_looper.rb +216 -0
- data/lib/awslive-scheduler/input_switch_schedule_action.rb +56 -0
- data/lib/awslive-scheduler/pause_schedule_action.rb +40 -0
- data/lib/awslive-scheduler/schedule_action.rb +123 -0
- data/lib/test/awslive_input_looper_test.rb +8 -0
- data/lib/test/schedule_action_test.rb +11 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5d419767541f1dad5b2d78c48e6bfbcaa2ddd5696927db79776182257457b8fa
|
4
|
+
data.tar.gz: 3756e17fd1a8e81ff61fbeab5864bff7ec7417778a6d1e96d0f82215f3f95ea5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ebee223608ff8c27b0ce0498f180cf13cb44fd5bb0a909f067b2a0c56c95c3a91e1ee95f7e1effb3f686e51b49a73f7a4dd1e196e9cae97002a0461879e3b55
|
7
|
+
data.tar.gz: 6711775e948903d5b0d21463598c152e0fe9339c5defbf84917e0f8b7c76568b612f76a86d88f2c1b45fa9e10665c2f625391434228448a6b5284930449426a9
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "awslive-inputlooper"
|
5
|
+
require 'optimist'
|
6
|
+
|
7
|
+
|
8
|
+
global_opts = Optimist::options do
|
9
|
+
banner "AWS Live Inputlooper, helps in switching and looping the live inputs associated with Medialive channel"
|
10
|
+
opt :access_key_id, "AWS Key", :type => :string, :short => "k"
|
11
|
+
opt :secret_access_key, "AWS Secret", :type => :string, :short => "s"
|
12
|
+
opt :channel_id, "Channel Id", :type => :string, :short => "c", :required => true
|
13
|
+
opt :playlist, "Enter the list of files in comma separated fashion", :type => :string, :short => "p"
|
14
|
+
opt :loop_delay, " Enter the Delay to be induced for looping the inputs", :type => :int, :short => "d"
|
15
|
+
opt :verbose, "Enter true for verbose", :type => :string, :short => "v"
|
16
|
+
end
|
17
|
+
puts "AWS Live Inputlooper, helps in switching and looping the live inputs associated with Medialive channel"
|
18
|
+
|
19
|
+
def print_opts
|
20
|
+
puts ""
|
21
|
+
puts "Following options can be provided.."
|
22
|
+
puts "1. switch_and_loop_inputs"
|
23
|
+
puts "2. playlist_loop_alive"
|
24
|
+
puts "3. stop_playlist_loop"
|
25
|
+
puts "4. update_playlist"
|
26
|
+
puts "5. switch_playlist"
|
27
|
+
puts "6. pause_channel"
|
28
|
+
puts "7. Quit"
|
29
|
+
end
|
30
|
+
|
31
|
+
print_opts
|
32
|
+
|
33
|
+
@input_looper = Awslive::InputLooper.new(global_opts[:channel_id])
|
34
|
+
if !global_opts[:verbose].nil? && global_opts[:verbose] == "true"
|
35
|
+
@input_looper.set_log_flag(true)
|
36
|
+
else
|
37
|
+
@input_looper.set_log_flag(false)
|
38
|
+
end
|
39
|
+
while true
|
40
|
+
#cmd = ARGV.shift # get the subcommand
|
41
|
+
cmd = gets.chomp
|
42
|
+
cmd_opts = case cmd
|
43
|
+
when "switch_and_loop_inputs" # Switch and Loop Inputs
|
44
|
+
if global_opts[:playlist].nil?
|
45
|
+
puts "Please provide playlist details"
|
46
|
+
global_opts[:playlist] = gets.chomp
|
47
|
+
end
|
48
|
+
playlist = global_opts[:playlist].split(",")
|
49
|
+
puts "Switch and looping the channel #{global_opts[:channel_id]} with playlist #{playlist}"
|
50
|
+
delay = global_opts[:loop_delay].nil? ? 5 : global_opts[:loop_delay]
|
51
|
+
@input_looper.switch_and_loop_playlist(playlist, delay)
|
52
|
+
sleep 10
|
53
|
+
puts "Playlist Alive #{@input_looper.playlist_loop_alive}"
|
54
|
+
when "playlist_loop_alive"
|
55
|
+
puts @input_looper.playlist_loop_alive
|
56
|
+
when "stop_playlist_loop"
|
57
|
+
puts @input_looper.stop_playlist_loop
|
58
|
+
when "update_playlist"
|
59
|
+
puts "Enter New Playlist "
|
60
|
+
new_playist_str = gets.chomp
|
61
|
+
new_playlist = new_playist_str.split(",")
|
62
|
+
if @input_looper.playlist_loop_alive
|
63
|
+
@input_looper.update_playlist(new_playlist)
|
64
|
+
puts "Playlist updated!"
|
65
|
+
else
|
66
|
+
puts "Switch and Loop not active"
|
67
|
+
end
|
68
|
+
when "switch_playlist"
|
69
|
+
puts "Enter New Playlist "
|
70
|
+
new_playist_str = gets.chomp
|
71
|
+
new_playlist = new_playist_str.split(",")
|
72
|
+
delay = global_opts[:loop_delay].nil? ? 5 : global_opts[:loop_delay]
|
73
|
+
@input_looper.switch_playlist(new_playlist, delay )
|
74
|
+
when "pause_channel"
|
75
|
+
@input_looper.pause_channel
|
76
|
+
when "quit"
|
77
|
+
break
|
78
|
+
else
|
79
|
+
puts "Invalid command!!, try valid command"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'awslive-inputlooper/input_looper'
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# Internal Libraries
|
2
|
+
require_relative '../awslive-common/start_type'
|
3
|
+
require_relative '../awslive-common/action_type'
|
4
|
+
require_relative '../awslive-scheduler/schedule_action'
|
5
|
+
require_relative '../awslive-common/all_exceptions'
|
6
|
+
require_relative '../awslive-common/logging'
|
7
|
+
|
8
|
+
# Thrid Party Library.
|
9
|
+
require 'aws-sdk-medialive'
|
10
|
+
|
11
|
+
|
12
|
+
module Awslive
|
13
|
+
class InputLooper
|
14
|
+
include StartType
|
15
|
+
include ActionType
|
16
|
+
include AwsliveExceptions
|
17
|
+
include AwsliveLogging
|
18
|
+
|
19
|
+
INITAL_INPUT_ACTION_NAME = "Initial Channel Input"
|
20
|
+
|
21
|
+
def initialize(channel_id, playlist = nil)
|
22
|
+
credentials = Aws::SharedCredentials.new
|
23
|
+
if credentials.set?
|
24
|
+
@medialiveclient = Aws::MediaLive::Client.new(:credentials => credentials)
|
25
|
+
else
|
26
|
+
@medialiveclient = Aws::MediaLive::Client.new
|
27
|
+
end
|
28
|
+
@scheduler = Awslive::ScheduleAction.new(@medialiveclient)
|
29
|
+
@channel_id = channel_id
|
30
|
+
@playlist = playlist
|
31
|
+
@loop_thread = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def switch_and_loop_playlist(playlist, sleep_time = nil)
|
35
|
+
@loop_thread = Thread.new {
|
36
|
+
@playlist = playlist
|
37
|
+
log ("Switch input Monitoring started!!")
|
38
|
+
switch_input(true)
|
39
|
+
# AWS recommends to have 5 sec delay beteen the switches.
|
40
|
+
sleep 5
|
41
|
+
sleep_time = 5 if sleep_time.nil? || sleep_time < 5
|
42
|
+
loop do
|
43
|
+
success = switch_input
|
44
|
+
break if !success
|
45
|
+
sleep sleep_time
|
46
|
+
end
|
47
|
+
log( "Switch input Monitoring Stopped!!")
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def playlist_loop_alive
|
52
|
+
isalive = @loop_thread.nil? ? false : @loop_thread.alive?
|
53
|
+
isalive
|
54
|
+
end
|
55
|
+
|
56
|
+
def stop_playlist_loop
|
57
|
+
Thread.kill(@loop_thread) if playlist_loop_alive
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_playlist(playlist)
|
62
|
+
@playlist = playlist
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
|
66
|
+
def switch_playlist(playlist, sleep_time = nil)
|
67
|
+
if stop_playlist_loop
|
68
|
+
switch_and_loop_playlist(playlist, sleep_time)
|
69
|
+
end
|
70
|
+
return playlist_loop_alive
|
71
|
+
end
|
72
|
+
|
73
|
+
def switch_input(force_immed = nil)
|
74
|
+
# Fetching the channel information every time to know the state of the channel and input in pipeline.
|
75
|
+
channel_info = get_channel_info
|
76
|
+
channel_state = channel_info[:state]
|
77
|
+
# the switching loop will be active only when the channel is in "RUNNING" state.
|
78
|
+
if channel_state == "RUNNING"
|
79
|
+
# Identifying one static and one dyanmic input to enable the switch and loop inputs.
|
80
|
+
static_input, dynamic_input = get_valid_inputs(channel_info[:input_attachments])
|
81
|
+
|
82
|
+
if static_input.nil? || dynamic_input.nil?
|
83
|
+
log( "No Valid inputs for Switch and loop; please provision one static and one dynamic input in the Channel #{@channel_id}")
|
84
|
+
raise InvalidInputException.new("No Valid inputs; should be provisioned with one static and one dynamic Input")
|
85
|
+
end
|
86
|
+
|
87
|
+
current_input_name = get_current_input(channel_info)
|
88
|
+
current_input_action_name = get_current_action(channel_info)
|
89
|
+
sc_action = @scheduler.get_scheudle_action(@channel_id, current_input_action_name)
|
90
|
+
log( "Current input #{current_input_name} #{current_input_action_name}")
|
91
|
+
if force_immed || sc_action.nil? || is_schedule_empty?
|
92
|
+
log( "Schedule is empty or schedule does not exist; Hence creating one immediate action with static input")
|
93
|
+
data = {}
|
94
|
+
#data[:input_ref_name] = static_input[:input_attachment_name]
|
95
|
+
data[:input_ref_name] = dynamic_input[:input_attachment_name]
|
96
|
+
data[:url_path] = @playlist[0]
|
97
|
+
@scheduler.create(@channel_id, IMMEDIATE, INPUT_SWITCH, data)
|
98
|
+
return true
|
99
|
+
end
|
100
|
+
|
101
|
+
follow_schedule = @scheduler.get_follow_schedule(@channel_id, current_input_action_name)
|
102
|
+
current_url = @scheduler.get_action_url(@channel_id, current_input_action_name)
|
103
|
+
log( "current URL #{current_url} next URL #{follow_schedule}")
|
104
|
+
unless follow_schedule.nil?
|
105
|
+
follow_url = @scheduler.get_follow_action_url(@channel_id, current_input_action_name)
|
106
|
+
log("Follow URL #{follow_url}")
|
107
|
+
next_file = identify_next_input(current_url)
|
108
|
+
log( "Next URL #{next_file}")
|
109
|
+
if !follow_url[0].nil? && next_file != follow_url[0]
|
110
|
+
log( "Playlist seems to be changed, hence aligning.")
|
111
|
+
@scheduler.delete( @channel_id,[ "#{follow_schedule[:action_name]}"])
|
112
|
+
next_input_name = dynamic_input[:input_attachment_name]
|
113
|
+
log ("next input name #{next_input_name}")
|
114
|
+
data = {}
|
115
|
+
data[:follow_input] = current_input_action_name
|
116
|
+
data[:trigger_input] = next_input_name
|
117
|
+
data[:url_path] = next_file
|
118
|
+
@scheduler.create(@channel_id, FOLLOW, INPUT_SWITCH, data)
|
119
|
+
else
|
120
|
+
log( "No change in follow schedule!. not change in playlist")
|
121
|
+
return true
|
122
|
+
end
|
123
|
+
else
|
124
|
+
log("No follow Schedule!")
|
125
|
+
next_file = identify_next_input(current_url)
|
126
|
+
unless next_file.nil?
|
127
|
+
next_input_name = dynamic_input[:input_attachment_name]
|
128
|
+
log( "Next input Name #{next_input_name} #{next_file}")
|
129
|
+
data = {}
|
130
|
+
data[:follow_input] = current_input_action_name
|
131
|
+
data[:trigger_input] = next_input_name
|
132
|
+
data[:url_path] = next_file
|
133
|
+
@scheduler.create(@channel_id, FOLLOW, INPUT_SWITCH, data)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
else
|
137
|
+
log("invalid channel state #{channel_state}")
|
138
|
+
raise InvalidChannelStateException.new("Channel state Should be RUNNING, instead of #{channel_state}")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def identify_next_input(file_url)
|
143
|
+
next_file = @playlist[0]
|
144
|
+
#puts " File Url #{file_url}"
|
145
|
+
if !file_url.nil? && !file_url[0].nil?
|
146
|
+
@playlist.each_with_index do | playlist_file, index |
|
147
|
+
#puts "next file identification #{playlist_file} #{file_url[0]} #{index}"
|
148
|
+
if playlist_file == file_url[0]
|
149
|
+
if index == (@playlist.length - 1)
|
150
|
+
next_file = @playlist[0]
|
151
|
+
else
|
152
|
+
next_file = @playlist[index + 1]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
next_file
|
158
|
+
end
|
159
|
+
|
160
|
+
def is_schedule_empty?
|
161
|
+
schedule_info = @medialiveclient.describe_schedule({ :channel_id => "#{@channel_id}"})
|
162
|
+
schedule_actions = schedule_info[:schedule_actions]
|
163
|
+
schedule_actions.empty?
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_valid_inputs(inputs)
|
167
|
+
static_input = nil
|
168
|
+
dynamic_input = nil
|
169
|
+
|
170
|
+
inputs.each do | input |
|
171
|
+
next if input[:input_settings][:source_end_behavior] != "CONTINUE"
|
172
|
+
input_info = @medialiveclient.describe_input({ :input_id => "#{input[:input_id]}" })
|
173
|
+
if input_info[:input_source_type] == "STATIC"
|
174
|
+
static_input = input
|
175
|
+
elsif input_info[:input_source_type] == "DYNAMIC"
|
176
|
+
dynamic_input = input
|
177
|
+
end
|
178
|
+
if !static_input.nil? && !dynamic_input.nil?
|
179
|
+
break
|
180
|
+
end
|
181
|
+
end
|
182
|
+
puts static_input
|
183
|
+
puts dynamic_input
|
184
|
+
return static_input, dynamic_input
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def get_channel_info
|
189
|
+
@medialiveclient.describe_channel({ :channel_id => "#{@channel_id}" })
|
190
|
+
end
|
191
|
+
|
192
|
+
def get_current_input(channel_info = nil )
|
193
|
+
channel_info = get_channel_info if channel_info.nil?
|
194
|
+
current_input_name = channel_info[:pipeline_details][0][:active_input_attachment_name]
|
195
|
+
current_input_name
|
196
|
+
end
|
197
|
+
|
198
|
+
def get_current_action(channel_info = nil )
|
199
|
+
channel_info = get_channel_info if channel_info.nil?
|
200
|
+
current_action_name = channel_info[:pipeline_details][0][:active_input_switch_action_name]
|
201
|
+
current_action_name
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
def get_channel_class(channel_info = nil)
|
206
|
+
channel_info = get_channel_info if channel_info.nil?
|
207
|
+
channel_info[:channel_class]
|
208
|
+
end
|
209
|
+
|
210
|
+
def pause_channel
|
211
|
+
@scheduler.create(@channel_id, IMMEDIATE, PAUSE, get_channel_class)
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Awslive
|
2
|
+
class InputSwitchScheduleAction
|
3
|
+
|
4
|
+
FOLLOW_HASH = {
|
5
|
+
action_name: "f1",
|
6
|
+
schedule_action_start_settings: {
|
7
|
+
follow_mode_schedule_action_start_settings: {
|
8
|
+
reference_action_name: "imm",
|
9
|
+
follow_point: "END"
|
10
|
+
}
|
11
|
+
},
|
12
|
+
schedule_action_settings: {
|
13
|
+
input_switch_settings: {
|
14
|
+
input_attachment_name_reference: "input1",
|
15
|
+
url_path: []
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
IMMEDIATE_HASH = {
|
21
|
+
:action_name => "action_name",
|
22
|
+
:schedule_action_start_settings => {
|
23
|
+
:immediate_mode_schedule_action_start_settings => {}
|
24
|
+
},
|
25
|
+
:schedule_action_settings => {
|
26
|
+
:input_switch_settings => {
|
27
|
+
:input_attachment_name_reference => "input_name",
|
28
|
+
:url_path => []
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
def get_immediate_schedule_action( input_ref_name, urlpath = nil)
|
34
|
+
action_hash = IMMEDIATE_HASH.clone
|
35
|
+
action_hash[:action_name] = "#{get_action_id}"
|
36
|
+
action_hash[:schedule_action_settings][:input_switch_settings][:input_attachment_name_reference] = "#{input_ref_name}"
|
37
|
+
action_hash[:schedule_action_settings][:input_switch_settings][:url_path] = [ urlpath ] unless urlpath.nil?
|
38
|
+
action_hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_follow_schedule_action(follow_input, trigger_input, urlpath = nil)
|
42
|
+
action_hash = FOLLOW_HASH.clone
|
43
|
+
action_hash[:action_name] = "#{get_action_id}"
|
44
|
+
puts "action hash #{action_hash}"
|
45
|
+
action_hash[:schedule_action_start_settings][:follow_mode_schedule_action_start_settings][:reference_action_name] = "#{follow_input}"
|
46
|
+
action_hash[:schedule_action_settings][:input_switch_settings][:input_attachment_name_reference] = "#{trigger_input}"
|
47
|
+
action_hash[:schedule_action_settings][:input_switch_settings][:url_path] = [ urlpath ] unless urlpath.nil?
|
48
|
+
action_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_action_id
|
52
|
+
Time.now.to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Awslive
|
2
|
+
class PauseScheduleAction
|
3
|
+
|
4
|
+
PAUSE_HASH = {
|
5
|
+
:action_name => "pause",
|
6
|
+
:schedule_action_start_settings => {
|
7
|
+
:fixed_mode_schedule_action_start_settings => {
|
8
|
+
:time => "2019-12-22T14:36:01.302Z"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
:schedule_action_settings => {
|
12
|
+
:pause_state_settings => {
|
13
|
+
:pipelines => []
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
def get_pause_schedule_action(type)
|
19
|
+
action_hash = PAUSE_HASH.clone
|
20
|
+
action_hash["actionName"] = "#{get_action_id}"
|
21
|
+
exec_time = ( Time.now + 10 ).iso8601
|
22
|
+
action_hash["scheduleActionStartSettings"]["fixedModeScheduleActionStartSettings"]["time"] = "#{exec_time}"
|
23
|
+
pipelines = []
|
24
|
+
pipelines << {
|
25
|
+
pipeline_id: "PIPELINE_0"
|
26
|
+
}
|
27
|
+
if type == "STANDARD"
|
28
|
+
pipelines << {
|
29
|
+
pipeline_id: "PIPELINE_1"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
action_hash["scheduleActionSettings"]["pauseStateSettings"]["pipelines"] = pipelines
|
33
|
+
action_hash
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_action_id
|
37
|
+
Time.now.to_i
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative '../awslive-common/action_type'
|
2
|
+
require_relative '../awslive-common/start_type'
|
3
|
+
require_relative 'input_switch_schedule_action'
|
4
|
+
require_relative 'pause_schedule_action'
|
5
|
+
|
6
|
+
require 'aws-sdk-medialive'
|
7
|
+
|
8
|
+
module Awslive
|
9
|
+
class ScheduleAction
|
10
|
+
include ActionType
|
11
|
+
include StartType
|
12
|
+
|
13
|
+
def initialize(mediaclient = nil)
|
14
|
+
if !mediaclient.nil?
|
15
|
+
@mediaclient = mediaclient
|
16
|
+
else
|
17
|
+
credentials = Aws::SharedCredentials.new
|
18
|
+
@mediaclient = Aws::MediaLive::Client.new(:credentials => credentials)
|
19
|
+
end
|
20
|
+
@input_switch_schedule_action = Awslive::InputSwitchScheduleAction.new
|
21
|
+
@pause_schedule_action = Awslive::PauseScheduleAction.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_schedule(channel_id, scheduled_actions )
|
25
|
+
payload = {
|
26
|
+
channel_id: "#{channel_id}",
|
27
|
+
creates: {
|
28
|
+
schedule_actions: scheduled_actions
|
29
|
+
}
|
30
|
+
}
|
31
|
+
@mediaclient.batch_update_schedule( payload )
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(channel_id, action_names)
|
35
|
+
@mediaclient.batch_update_schedule( {
|
36
|
+
channel_id: "#{channel_id}",
|
37
|
+
deletes: {
|
38
|
+
action_names: action_names
|
39
|
+
}
|
40
|
+
} )
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_follow_schedule(channel_id, action_name)
|
45
|
+
follow_schedule = nil
|
46
|
+
response = @mediaclient.describe_schedule({channel_id: "#{channel_id}", max_results: 100 } )
|
47
|
+
loop do
|
48
|
+
response[:schedule_actions].each do | schedule_action |
|
49
|
+
unless schedule_action[:schedule_action_start_settings][:follow_mode_schedule_action_start_settings].nil?
|
50
|
+
# This is follow action
|
51
|
+
if schedule_action[:schedule_action_start_settings][:follow_mode_schedule_action_start_settings][:reference_action_name] == action_name
|
52
|
+
follow_schedule = schedule_action
|
53
|
+
break
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
break if !follow_schedule.nil? || response[:next_token].nil?
|
58
|
+
response = @mediaclient.describe_schedule({channel_id: "#{channel_id}", max_results: 100, next_token: response[:next_token] } )
|
59
|
+
end
|
60
|
+
follow_schedule
|
61
|
+
end
|
62
|
+
|
63
|
+
def create(channel_id, start_type, action_type, data)
|
64
|
+
scheduled_action = []
|
65
|
+
if action_type == INPUT_SWITCH
|
66
|
+
if start_type == IMMEDIATE
|
67
|
+
scheduled_action << @input_switch_schedule_action.get_immediate_schedule_action(data[:input_ref_name], data[:url_path])
|
68
|
+
elsif start_type == FOLLOW
|
69
|
+
scheduled_action << @input_switch_schedule_action.get_follow_schedule_action(data[:follow_input], data[:trigger_input], data[:url_path])
|
70
|
+
end
|
71
|
+
elsif action_type == PAUSE
|
72
|
+
if start_type == FIXED
|
73
|
+
scheduled_action << @pause_scheduler.get_pause_schedule_action(data[:channel_class])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
unless scheduled_action.empty?
|
77
|
+
create_response = create_schedule(channel_id, scheduled_action)
|
78
|
+
end
|
79
|
+
create_response
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_scheudle_action(channel_id, action_name)
|
83
|
+
sc_action = nil
|
84
|
+
response = @mediaclient.describe_schedule({
|
85
|
+
channel_id: "#{channel_id}", max_results: 100
|
86
|
+
})
|
87
|
+
loop do
|
88
|
+
response[:schedule_actions].each do | schedule_action |
|
89
|
+
if schedule_action[:action_name] == action_name
|
90
|
+
sc_action = schedule_action
|
91
|
+
break
|
92
|
+
end
|
93
|
+
end
|
94
|
+
break if !sc_action.nil? || response[:next_token].nil?
|
95
|
+
response = @mediaclient.describe_schedule({channel_id: "#{channel_id}", max_results: 100, next_token: response[:next_token] } )
|
96
|
+
end
|
97
|
+
sc_action
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_follow_action_url(channel_id, action_name)
|
101
|
+
url = nil
|
102
|
+
follow_schedule = get_follow_schedule(channel_id, action_name)
|
103
|
+
url = follow_schedule[:schedule_action_settings][:input_switch_settings][:url_path] unless follow_schedule.nil?
|
104
|
+
url
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_action_url(channel_id, action_name)
|
108
|
+
url = nil
|
109
|
+
follow_schedule = get_scheudle_action(channel_id, action_name)
|
110
|
+
puts "Follow Schedule #{follow_schedule}"
|
111
|
+
url = follow_schedule[:schedule_action_settings][:input_switch_settings][:url_path] unless follow_schedule.nil?
|
112
|
+
url
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_action_id
|
116
|
+
Time.now.to_i
|
117
|
+
end
|
118
|
+
|
119
|
+
def delete_all(channel_id)
|
120
|
+
@mediaclient.delete_schedule({ channel_id: channel_id })
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'awslive-inputlooper'
|
2
|
+
|
3
|
+
class AwsliveInputLooperTest
|
4
|
+
end
|
5
|
+
|
6
|
+
playlist = ["s3transition-lambda-poc/frozen_test1.mp4", "s3transition-lambda-poc/oceans.mp4", "s3transition-lambda-poc/big-bunny1.mp4", "s3transition-lambda-poc/sample1.mp4"]
|
7
|
+
looper = Awslive::InputLooper.new("2179374", playlist)
|
8
|
+
looper.switch_and_loop_playlist
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative './input-switch/put-switch/input_switch_schedule_action'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
class ScheduleActionTest
|
5
|
+
|
6
|
+
end
|
7
|
+
=end
|
8
|
+
credentials = Aws::SharedCredentials.new
|
9
|
+
medialiveclient = Aws::MediaLive::Client.new(:credentials => credentials)
|
10
|
+
input_switch_action = InputSwitchScheduleAction.new(medialiveclient)
|
11
|
+
puts input_switch_action.get_immediate_schedule_action("test")
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: awslive-inputlooper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maheshwaran G
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aws-sdk-medialive
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.40'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.40'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: optimist
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: AWS live Input Looper gem helps in switching & looping live inputs in
|
70
|
+
AWS Medialive channel, enabling VOD playlist as live in a sequence / circular loop
|
71
|
+
fashion
|
72
|
+
email:
|
73
|
+
- pgmaheshwaran@gmail.com
|
74
|
+
executables:
|
75
|
+
- awslive-inputlooper
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files: []
|
78
|
+
files:
|
79
|
+
- bin/awslive-inputlooper
|
80
|
+
- lib/awslive-common/action_type.rb
|
81
|
+
- lib/awslive-common/all_exceptions.rb
|
82
|
+
- lib/awslive-common/logging.rb
|
83
|
+
- lib/awslive-common/start_type.rb
|
84
|
+
- lib/awslive-inputlooper.rb
|
85
|
+
- lib/awslive-inputlooper/input_looper.rb
|
86
|
+
- lib/awslive-scheduler/input_switch_schedule_action.rb
|
87
|
+
- lib/awslive-scheduler/pause_schedule_action.rb
|
88
|
+
- lib/awslive-scheduler/schedule_action.rb
|
89
|
+
- lib/test/awslive_input_looper_test.rb
|
90
|
+
- lib/test/schedule_action_test.rb
|
91
|
+
homepage: https://github.com/ooyala/awslive-input-looper
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata:
|
95
|
+
homepage_uri: https://github.com/ooyala/awslive-input-looper
|
96
|
+
source_code_uri: https://github.com/ooyala/awslive-input-looper
|
97
|
+
changelog_uri: https://github.com/ooyala/awslive-input-looper
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubygems_version: 3.1.2
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: AWS live Input Looper gem helps in switching & looping live inputs in AWS
|
117
|
+
Medialive channel, enabling VOD playlist as live in a sequence / circular loop fashion
|
118
|
+
test_files: []
|