-
Notifications
You must be signed in to change notification settings - Fork 51
/
derivative.rb
132 lines (108 loc) · 4.5 KB
/
derivative.rb
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
class Derivative < ActiveFedora::Base
include ActiveFedora::Associations
class_attribute :url_handler
belongs_to :masterfile, :class_name=>'MasterFile', :property=>:is_derivation_of
# These fields do not fit neatly into the Dublin Core so until a long
# term solution is found they are stored in a simple datastream in a
# relatively flat structure.
#
# The only meaningful value at the moment is the url, which points to
# the stream location. The other two are just stored until a migration
# strategy is required.
has_metadata name: "descMetadata", :type => ActiveFedora::SimpleDatastream do |d|
d.field :location_url, :string
d.field :hls_url, :string
d.field :duration, :string
d.field :track_id, :string
d.field :hls_track_id, :string
end
delegate_to 'descMetadata', [:location_url, :hls_url, :duration, :track_id, :hls_track_id], unique: true
has_metadata name: 'encoding', type: EncodingProfileDocument
def self.url_handler
url_handler_class = Avalon::Configuration['streaming']['server'].to_s.classify
@url_handler ||= UrlHandler.const_get(url_handler_class.to_sym)
end
# Getting the track ID from the fragment is not great but it does reduce the number
# of calls to Matterhorn
def self.create_from_master_file(masterfile, markup)
# Looks for an existing derivative of the same quality
# and adds the track URL to it
quality = markup.tags.quality.first.split('-')[1] unless markup.tags.quality.empty?
derivative = nil
masterfile = MasterFile.find(masterfile.pid)
masterfile.derivatives.each do |d|
derivative = d if d.encoding.quality.first == quality
end
# If same quality derivative doesn't exist, create one
if derivative.blank?
derivative = Derivative.create
derivative.duration = markup.duration.first
derivative.encoding.mime_type = markup.mimetype.first
derivative.encoding.quality = quality
derivative.encoding.audio.audio_bitrate = markup.audio.a_bitrate.first
derivative.encoding.audio.audio_codec = markup.audio.a_codec.first
unless markup.video.empty?
derivative.encoding.video.video_bitrate = markup.video.v_bitrate.first
derivative.encoding.video.video_codec = markup.video.v_codec.first
derivative.encoding.video.resolution = markup.video.resolution.first
end
end
if markup.tags.tag.include? "hls"
derivative.hls_track_id = markup.track_id
derivative.hls_url = markup.url.first
else
derivative.track_id = markup.track_id
derivative.location_url = markup.url.first
end
derivative.masterfile = masterfile
derivative.save
derivative
end
def url_hash
h = Digest::MD5.new
h << location_url
h.hexdigest
end
def tokenized_url(token, mobile=false)
#uri = URI.parse(url.first)
uri = streaming_url(mobile)
"#{uri.to_s}?token=#{masterfile.mediapackage_id}-#{token}".html_safe
end
def streaming_url(is_mobile=false)
# We need to tweak the RTMP stream to reflect the right format for AMS.
# That means extracting the extension from the end and placing it just
# after the application in the URL
protocol = is_mobile ? 'http' : 'rtmp'
# Example input: /avalon/mp4:98285a5b-603a-4a14-acc0-20e37a3514bb/b3d5663d-53f1-4f7d-b7be-b52fd5ca50a3/MVI_0057.mp4
regex = %r{^
/(.+) # application (avalon)
/(?:(.+):)? # prefix (mp4:)
([0-9a-f-]{36}) # media_id (98285a5b-603a-4a14-acc0-20e37a3514bb)
/([0-9a-f-]{36}) # stream_id (b3d5663d-53f1-4f7d-b7be-b52fd5ca50a3)
/(.+?) # filename (MVI_0057)
(?:\.(.+))?$ # extension (mp4)
}x
uri = URI.parse(location_url)
(application, prefix, media_id, stream_id, filename, extension) = uri.path.scan(regex).flatten
if extension.nil? or prefix.nil?
prefix = extension = [extension,prefix].find { |thing| not thing.nil? }
end
template = ERB.new(self.class.url_handler.patterns[protocol][format])
result = File.join(Avalon::Configuration['streaming']["#{protocol}_base"],template.result(binding))
end
def format
case
when (not encoding.video.empty?)
"video"
when (not encoding.audio.empty?)
"audio"
else
"other"
end
end
def delete
Rubyhorn.client.delete_track(masterfile.workflow_id, track_id) if track_id.present?
Rubyhorn.client.delete_hls_track(masterfile.workflow_id, hls_track_id) if hls_track_id.present?
super
end
end