awslive-inputlooper 0.1.1
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 +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: []
|