awslive-poster 0.1.5

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d3742287968dfc632292fff675d40723273071210b07a04b7c7870f860b5630a
4
+ data.tar.gz: 444c17938173ae0fdffc01346a91bdb633b700340267756ed5c9a669c178b44b
5
+ SHA512:
6
+ metadata.gz: a222b11711b3514d3a36f6043b2e10734b23d4321c2671ebc0a7614318b48cd419bb2bf64e7e316ed729b8043bdda0781f1c3f0a858523c5a2ee9d2344f44e61
7
+ data.tar.gz: 9d6a5966eb92c0ca8e27ed1ea9a747f0c4f3c52dcb76706a5f68f4273bb78495eb940ced9cc22a1d6f66e7ce84278f5840e46973e2d17b2f60c8afc2ba26fd70
@@ -0,0 +1 @@
1
+ require 'awslive-poster/awslive_poster'
@@ -0,0 +1,155 @@
1
+ require 'aws-sdk-medialive'
2
+ require 'aws-sdk-s3'
3
+ require 'uri'
4
+
5
+ module Awslive
6
+ class Poster
7
+
8
+ class InvalidChannelState < StandardError; end
9
+ class NoFrameCaptureOutputGroup < StandardError; end
10
+ class PosterImageDoesNotExist < StandardError; end
11
+ class NoStartTimeInTag < StandardError; end
12
+
13
+ MAX_CHANNEL_START_TIME = 2 * 60
14
+
15
+ def initialize(channel_id, access_key=nil , access_secret =nil, region = nil)
16
+ credentials = Aws::SharedCredentials.new
17
+ if !access_key.nil? && !access_secret.nil?
18
+ aws_region = region.nil? ? 'us-east-1' : region
19
+ @medialiveclient = Aws::MediaLive::Client.new( :access_key_id => access_key, :secret_access_key => access_secret, :region => aws_region )
20
+ @s3 = Aws::S3::Resource.new( :access_key_id => access_key, :secret_access_key => access_secret, :region => aws_region )
21
+ elsif credentials.set?
22
+ @medialiveclient = Aws::MediaLive::Client.new(:credentials => credentials)
23
+ @s3 = Aws::S3::Resource.new(:credentials => credentials)
24
+ else
25
+ @medialiveclient = Aws::MediaLive::Client.new
26
+ @s3 = Aws::S3::Resource.new
27
+ end
28
+ @channel_id = channel_id
29
+ @last_computed_time = nil
30
+
31
+ @last_preview_url = nil
32
+ @interval = nil
33
+ end
34
+
35
+ def get_url(channel_info = nil)
36
+ if !@last_computed_time.nil? && !@last_preview_url.nil? && !@interval.nil?
37
+ threshold_gap = @interval > MAX_CHANNEL_START_TIME ? MAX_CHANNEL_START_TIME : @interval
38
+ current_time = Time.now.to_i
39
+ if current_time - @last_computed_time < threshold_gap
40
+ # quick fetch hence returning already computed preview URL.
41
+ puts "returning from cache"
42
+ return @last_preview_url
43
+ end
44
+ end
45
+ preview_url = nil
46
+ channel_info = @medialiveclient.describe_channel({ :channel_id => "#{@channel_id}" }) if channel_info.nil?
47
+ channel_state = channel_info[:state]
48
+ if channel_state == "RUNNING"
49
+ @last_computed_time = Time.now.to_i
50
+ out_group = get_framecapture_group(channel_info["encoder_settings"])
51
+ raise NoFrameCaptureOutputGroup.new("Framecapture output group should be configured!") if out_group.nil?
52
+ start_time = get_channel_start_time(channel_info)
53
+ raise NoStartTimeInTag.new("channel_start_time should be provisioned in Channel tag!") if start_time.nil?
54
+ dest_id = get_dest_info(out_group)
55
+ url = get_dest_url(dest_id, channel_info)
56
+ uri = URI(url)
57
+ modifier = get_framecapture_modifier(out_group)
58
+ @interval = get_framecapture_interval(out_group, channel_info)
59
+ seq_counter = compute_index(start_time, @interval)
60
+ suffix = uri.path[1..-1]
61
+ bucket = @s3.bucket("#{uri.host}")
62
+ obj = bucket.object("#{suffix}#{modifier}.#{seq_counter}.jpg")
63
+ if obj.exists?
64
+ preview_url = obj.presigned_url(:get)
65
+ else
66
+ raise PosterImageDoesNotExist.new("Poster Image #{suffix}#{modifier}.#{seq_counter}.jpg Does not exist!")
67
+ end
68
+ else
69
+ raise InvalidChannelState.new("Channel Need to be in running state!, current state is #{channel_state}")
70
+ end
71
+ @last_preview_url = preview_url
72
+ preview_url
73
+ end
74
+
75
+ def compute_index(start_time, interval)
76
+ channel_start_time = Time.iso8601(start_time).to_i
77
+ current_time = Time.now.utc.to_i
78
+ diff_time = current_time - channel_start_time
79
+ image_index = (diff_time / interval.to_i).to_i
80
+ index = image_index.to_s.rjust(5,'0')
81
+ index
82
+ end
83
+
84
+ def get_channel_start_time(channel_info)
85
+ start_time = channel_info.tags["channel_start_time"]
86
+ start_time
87
+ end
88
+
89
+ def get_framecapture_group(encode_setting)
90
+ out_grp = nil
91
+ outputgroups = encode_setting["output_groups"] rescue nil
92
+ unless outputgroups.nil?
93
+ outputgroups.each do | output |
94
+ if !output["output_group_settings"]["frame_capture_group_settings"].nil?
95
+ out_grp = output
96
+ break if !out_grp.nil?
97
+ end
98
+ end
99
+ end
100
+ out_grp
101
+ end
102
+
103
+ def get_dest_info(out_grp)
104
+ dest = nil
105
+ if !out_grp["output_group_settings"]["frame_capture_group_settings"].nil?
106
+ dest = out_grp["output_group_settings"]["frame_capture_group_settings"]["destination"]["destination_ref_id"] rescue nil
107
+ end
108
+ dest
109
+ end
110
+
111
+ def get_dest_url(dest_info, channel_info)
112
+ url = nil
113
+ if !channel_info["destinations"].nil?
114
+ channel_info["destinations"].each do | dest |
115
+ if dest["id"] == dest_info
116
+ url = dest["settings"][0]["url"]
117
+ break if !url.nil?
118
+ end
119
+ end
120
+ end
121
+ url
122
+ end
123
+
124
+ def get_framecapture_modifier(out_grp)
125
+ modifier = out_grp["outputs"][0]["output_settings"]["frame_capture_output_settings"]["name_modifier"] rescue nil
126
+ modifier
127
+ end
128
+
129
+ def get_framecapture_interval(out_grp, channel_info)
130
+ interval = nil
131
+ video_desc_name = out_grp["outputs"][0]["video_description_name"]
132
+ if !video_desc_name.nil?
133
+ video_desc_info = get_video_description_info(video_desc_name, channel_info)
134
+ if !video_desc_info.nil?
135
+ interval = video_desc_info["codec_settings"]["frame_capture_settings"]["capture_interval"]
136
+ end
137
+ end
138
+ interval
139
+ end
140
+
141
+ def get_video_description_info(desc_name, channel_info)
142
+ video_info = nil
143
+ videos_desc = channel_info["encoder_settings"]["video_descriptions"]
144
+ if !videos_desc.nil?
145
+ videos_desc.each do | description |
146
+ if description["name"] == desc_name
147
+ video_info = description
148
+ break
149
+ end
150
+ end
151
+ end
152
+ video_info
153
+ end
154
+ end
155
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awslive-poster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Maheshwaran G
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-15 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: aws-sdk-s3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.40'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.40'
69
+ description: Utility that generates the Poster Image URL for the running AWS medialive
70
+ channel
71
+ email:
72
+ - maheshwarang@ooyala.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - lib/awslive-poster.rb
78
+ - lib/awslive-poster/awslive_poster.rb
79
+ homepage: https://github.com/cloudaffair/awslive-poster
80
+ licenses:
81
+ - MIT
82
+ metadata:
83
+ homepage_uri: https://github.com/cloudaffair/awslive-poster
84
+ source_code_uri: https://github.com/cloudaffair/awslive-poster
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.1.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Utility that generates the Poster Image URL for the running AWS medialive
104
+ channel
105
+ test_files: []