samvera_hls 0.3.7 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/samvera_hls/file_sets_controller_behavior.rb +6 -8
- data/app/models/concerns/samvera_hls/file_set_behavior.rb +17 -123
- data/app/services/samvera_hls/hls_output_file_service.rb +1 -1
- data/app/services/samvera_hls/hls_playlist_generator.rb +112 -0
- data/lib/samvera_hls/version.rb +1 -1
- metadata +3 -3
- data/app/models/concerns/samvera_hls/solr_document_behavior.rb +0 -112
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a93df9cd6ab9d3f5c07b1db60c93c7dd84117e2c540a93b95448db1e37c65cbb
|
4
|
+
data.tar.gz: a2b9593abfca2511bc2a9faa518a2aaaa4bddd8ffb076984fba9c884138aecc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68764a58cc6a9f5abf48a45e57df3e2b1dbb8aaa0f67f0e9427097cfcee3ea12bf4043e1c298c5adf956000f9d8fd0bc23af2fbff8b776f661b2d0416c103294
|
7
|
+
data.tar.gz: 9ce0898816f58932a48a7910a9f5f18a501230092af41ffc49100169f4b89f97be90d6b32103eb0c9b97f7130ba2a5364c1ce8b3bda5e695dc4eb3e892b2896c
|
@@ -9,23 +9,21 @@ module SamveraHls
|
|
9
9
|
|
10
10
|
def embed
|
11
11
|
response.headers["X-FRAME-OPTIONS"] = "ALLOWALL"
|
12
|
-
|
13
|
-
@
|
14
|
-
@media_partial = media_display_partial(fs)
|
12
|
+
@playlist_url = File.join("file_set",params[:id],"hls.m3u8")
|
13
|
+
@media_partial = media_display_partial(params[:id])
|
15
14
|
render layout: false
|
16
15
|
end
|
17
16
|
|
18
17
|
def master
|
19
|
-
|
20
|
-
render inline: fs.hls_master_playlist(root_url), content_type: 'application/x-mpegurl'
|
18
|
+
render inline: SamveraHls::HlsPlaylistGenerator.hls_master_playlist(params[:id],root_url), content_type: 'application/x-mpegurl'
|
21
19
|
end
|
22
20
|
|
23
21
|
def variant
|
24
|
-
|
25
|
-
render inline: fs.hls_segment_playlist(root_url,params[:format]), content_type: 'application/x-mpegurl'
|
22
|
+
render inline: SamveraHls::HlsPlaylistGenerator.hls_segment_playlist(params[:id],root_url,params[:format]), content_type: 'application/x-mpegurl'
|
26
23
|
end
|
27
24
|
|
28
|
-
def media_display_partial(
|
25
|
+
def media_display_partial(file_set_id)
|
26
|
+
file_set = SolrDocument.find(file_set_id)
|
29
27
|
base = 'file_sets/media_display'
|
30
28
|
if file_set.image?
|
31
29
|
File.join('hyrax',base,'image')
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "samvera_hls/derivatives/video_derivatives"
|
2
2
|
require "samvera_hls/derivatives/audio_derivatives"
|
3
|
+
require "uri"
|
3
4
|
|
4
5
|
module SamveraHls
|
5
6
|
module FileSetBehavior
|
@@ -7,145 +8,38 @@ module SamveraHls
|
|
7
8
|
|
8
9
|
def create_hls_derivatives(filename)
|
9
10
|
case mime_type
|
10
|
-
when *
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
hls_dir = File.join(derivative_dir,"hls")
|
15
|
-
create_video_derivates filename, hls_dir
|
11
|
+
when *audio_mime_types
|
12
|
+
create_hls_audio_derivatives filename
|
13
|
+
when *video_mime_types
|
14
|
+
create_hls_video_derivatives filename
|
16
15
|
else
|
17
16
|
return false
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
def hls_master_url
|
22
|
-
File.join("file_set",id,"hls.m3u8")
|
23
|
-
end
|
24
|
-
|
25
|
-
def hls_master_playlist root_url
|
26
|
-
root_url = root_url.gsub("/?locale=en","")
|
27
|
-
type = mime_type.split('/')[0]
|
28
|
-
defaults = hls_config[type]["default"]
|
29
|
-
playlist = "#EXTM3U\n"
|
30
|
-
playlist << "#EXT-X-VERSION:6\n"
|
31
|
-
variants.each{|variant|
|
32
|
-
next if variant.blank?
|
33
|
-
path, filename = File.split(variant)
|
34
|
-
format = filename.gsub(".m3u8","")
|
35
|
-
options = defaults.merge(hls_config[type][format])
|
36
|
-
playlist << "#EXT-X-STREAM-INF:PROGRAM-ID=1,"
|
37
|
-
playlist << "BANDWIDTH=#{options["maxrate"]},"
|
38
|
-
playlist << "CODECS=\"#{options["codec_code"]}\","
|
39
|
-
playlist << "RESOLUTION=#{options["resolution"]}\n"
|
40
|
-
playlist << File.join(root_url,variant_url(format)) + "\n"
|
41
|
-
}
|
42
|
-
playlist
|
43
|
-
end
|
44
|
-
|
45
|
-
def hls_segment_playlist root_url, format
|
46
|
-
root_url = root_url.gsub("/?locale=en","")
|
47
|
-
playlist = ""
|
48
|
-
File.open(segment_playlist_path(format),'r') {|file|
|
49
|
-
file.each_line do |line|
|
50
|
-
if line.include? ".ts" then
|
51
|
-
playlist << File.join(root_url,
|
52
|
-
segment_url_base,
|
53
|
-
timestamp.to_s,
|
54
|
-
token(line),
|
55
|
-
line).strip+"\n"
|
56
|
-
else
|
57
|
-
playlist << line.strip+"\n"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
}
|
61
|
-
playlist
|
62
|
-
end
|
63
|
-
|
64
|
-
def derivative_url(destination_name = nil)
|
65
|
-
if destination_name.nil?
|
66
|
-
@deriv_url ||= derivative_dir.gsub(Hyrax.config.derivatives_path,"")
|
67
|
-
else
|
68
|
-
path = derivative_path(destination_name)
|
69
|
-
URI("file://#{path}").to_s
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
module ClassMethods
|
74
|
-
|
75
|
-
def audio_mime_types
|
76
|
-
# audio/x-wave is the mime type that fits 0.6.0 returns for a wav file.
|
77
|
-
# audio/mpeg is the mime type that fits 0.6.0 returns for an mp3 file.
|
78
|
-
['audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/x-wave', 'audio/x-wav', 'audio/ogg', 'audio/flac','audio/x-flac', 'audio/x-aiff', 'audio/aiff', ]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
20
|
private
|
83
21
|
|
84
|
-
def
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
def variants
|
89
|
-
variants = Dir.glob(File.join(derivative_dir,"hls","*.m3u8"))
|
90
|
-
variants.map!{ |file|
|
91
|
-
name = File.split(file)[1]
|
92
|
-
}
|
22
|
+
def audio_mime_types
|
23
|
+
['audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/x-wave', 'audio/x-wav', 'audio/ogg', 'audio/flac','audio/x-flac', 'audio/x-aiff', 'audio/aiff', ]
|
93
24
|
end
|
94
|
-
|
95
|
-
|
96
|
-
File.join("file_set",id,format,"variant.m3u8")
|
25
|
+
def video_mime_types
|
26
|
+
['video/mp4', 'video/mpeg', 'video/ogg','video/webm','video.flv','video/mp1s','video/mp2p']
|
97
27
|
end
|
98
28
|
|
99
|
-
def
|
29
|
+
def create_hls_audio_derivatives filename
|
100
30
|
outputs = [
|
101
|
-
{ label: '
|
102
|
-
{ label: '
|
103
|
-
{ label: 'hls_hd', format: 'hls_hd',path: hls_dir},
|
104
|
-
{ label: 'hls', format: 'hls', path: hls_dir}]
|
31
|
+
{ label: 'hls_hd', format: 'hls_hd', id: id},
|
32
|
+
{ label: 'hls', format: 'hls', id: id}]
|
105
33
|
SamveraHls::Derivatives::AudioDerivatives.create(filename,{:outputs => outputs})
|
106
34
|
end
|
107
35
|
|
108
|
-
def
|
109
|
-
outputs = [{ label: :thumbnail, format: 'jpg', url: derivative_url('thumbnail') },
|
110
|
-
|
111
|
-
{ label: '
|
112
|
-
{ label: '
|
113
|
-
{ label: 'hls_med', format: "hls_med", path: hls_dir},
|
114
|
-
{ label: 'hls_low', format: "hls_low", path: hls_dir}]
|
36
|
+
def create_hls_video_derivatives filename
|
37
|
+
outputs = [{ label: :thumbnail, format: 'jpg', url: SamveraHls::HlsPlaylistGenerator.derivative_url(id,'thumbnail') },
|
38
|
+
{ label: 'hls_high', format: "hls_high", id: id },
|
39
|
+
{ label: 'hls_med', format: "hls_med", id: id },
|
40
|
+
{ label: 'hls_low', format: "hls_low", id: id }]
|
115
41
|
SamveraHls::Derivatives::VideoDerivatives.create(filename,{:outputs => outputs})
|
116
42
|
end
|
117
43
|
|
118
|
-
def token line
|
119
|
-
@token ||= Digest::SHA256.hexdigest("/" + File.join(segment_url_base,timestamp.to_s,line).strip[0...-9] + token_secret)
|
120
|
-
end
|
121
|
-
|
122
|
-
def timestamp
|
123
|
-
@timestamp ||= Time.now.to_i + 7200
|
124
|
-
end
|
125
|
-
|
126
|
-
def token_secret
|
127
|
-
@token_secret ||= ENV['hls_token_secret']
|
128
|
-
end
|
129
|
-
|
130
|
-
def hls_config
|
131
|
-
@hls_config ||= YAML.load_file(Rails.root.join('config','hls.yml'))
|
132
|
-
end
|
133
|
-
|
134
|
-
def segment_playlist_path format
|
135
|
-
File.join(derivative_dir,"hls",format+".m3u8")
|
136
|
-
end
|
137
|
-
|
138
|
-
def derivative_dir
|
139
|
-
File.split(derivative_path("dummy"))[0]
|
140
|
-
end
|
141
|
-
|
142
|
-
def derivative_path destination_name
|
143
|
-
derivative_path_service.derivative_path_for_reference(self, destination_name)
|
144
|
-
end
|
145
|
-
|
146
|
-
def derivative_path_service
|
147
|
-
Hyrax::DerivativePath
|
148
|
-
end
|
149
|
-
|
150
44
|
end
|
151
45
|
end
|
@@ -2,7 +2,7 @@ require 'hydra/derivatives'
|
|
2
2
|
module SamveraHls
|
3
3
|
class HlsOutputFileService < Hyrax::PersistDerivatives
|
4
4
|
def self.call( directives,temp_dir)
|
5
|
-
hls_dir = directives[:
|
5
|
+
hls_dir = SamveraHls::HlsPlaylistGenerator.hls_dir(directives[:id])
|
6
6
|
FileUtils.mkdir_p(hls_dir)
|
7
7
|
FileUtils.move(Dir.glob(temp_dir+"/*") , hls_dir)
|
8
8
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module SamveraHls
|
2
|
+
class HlsPlaylistGenerator
|
3
|
+
class <<self
|
4
|
+
|
5
|
+
def hls_master_url file_set_id
|
6
|
+
File.join("file_set",file_set_id,"hls.m3u8")
|
7
|
+
end
|
8
|
+
|
9
|
+
def hls_master_playlist file_set_id, root_url
|
10
|
+
# make sure the root url doesn't get any default params attached (e.g. locale)
|
11
|
+
parsed_url = URI::parse(root_url)
|
12
|
+
parsed_url.fragment = parsed_url.query = nil
|
13
|
+
root_url = parsed_url.to_s
|
14
|
+
|
15
|
+
type = SolrDocument.find(file_set_id).mime_type.split('/')[0]
|
16
|
+
config = hls_config[type]
|
17
|
+
return nil if config.nil?
|
18
|
+
defaults = config["default"]
|
19
|
+
playlist = "#EXTM3U\n"
|
20
|
+
playlist << "#EXT-X-VERSION:6\n"
|
21
|
+
variants(file_set_id).each do |variant|
|
22
|
+
next if variant.blank?
|
23
|
+
path, filename = File.split(variant)
|
24
|
+
format = filename.gsub(".m3u8","")
|
25
|
+
options = defaults.merge(config[format])
|
26
|
+
playlist << "#EXT-X-STREAM-INF:PROGRAM-ID=1,"
|
27
|
+
playlist << "BANDWIDTH=#{options["maxrate"]},"
|
28
|
+
playlist << "CODECS=\"#{options["codec_code"]}\","
|
29
|
+
playlist << "RESOLUTION=#{options["resolution"]}\n"
|
30
|
+
playlist << File.join(root_url,variant_url(file_set_id,format)) + "\n"
|
31
|
+
end
|
32
|
+
playlist
|
33
|
+
end
|
34
|
+
|
35
|
+
def hls_segment_playlist file_set_id, root_url, format
|
36
|
+
# make sure the root url doesn't get any default params attached (e.g. locale)
|
37
|
+
parsed_url = URI::parse(root_url)
|
38
|
+
parsed_url.fragment = parsed_url.query = nil
|
39
|
+
root_url = parsed_url.to_s
|
40
|
+
|
41
|
+
# initialize timestamp once for whole playlist
|
42
|
+
timestamp = Time.now.to_i + 7200
|
43
|
+
|
44
|
+
playlist = ""
|
45
|
+
File.open(segment_playlist_path(file_set_id, format),'r') {|file|
|
46
|
+
file.each_line do |line|
|
47
|
+
if line.include? ".ts" then
|
48
|
+
playlist << File.join(root_url,
|
49
|
+
segment_url_base(file_set_id),
|
50
|
+
timestamp.to_s,
|
51
|
+
token(file_set_id,line, timestamp),
|
52
|
+
line).strip+"\n"
|
53
|
+
else
|
54
|
+
playlist << line.strip+"\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
}
|
58
|
+
playlist
|
59
|
+
end
|
60
|
+
|
61
|
+
def hls_dir file_set_id
|
62
|
+
Hyrax::DerivativePath.derivative_path_for_reference(file_set_id,"hls").gsub(/\.hls\z/,"")
|
63
|
+
end
|
64
|
+
|
65
|
+
def derivative_url file_set_id, destination_name
|
66
|
+
derivative_path(file_set_id, destination_name).gsub(Hyrax.config.derivatives_path,"")
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def token_secret
|
72
|
+
@token_secret ||= ENV['hls_token_secret']
|
73
|
+
end
|
74
|
+
|
75
|
+
def segment_url_base id
|
76
|
+
File.join("stream",derivative_url(id, "hls"))
|
77
|
+
end
|
78
|
+
|
79
|
+
def token id, line, timestamp
|
80
|
+
@token ||= Digest::SHA256.hexdigest("/" + File.join(segment_url_base(id),timestamp.to_s,line).strip[0...-9] + token_secret)
|
81
|
+
end
|
82
|
+
|
83
|
+
def segment_playlist_path id, format
|
84
|
+
File.join(hls_dir(id),"#{format}.m3u8")
|
85
|
+
end
|
86
|
+
|
87
|
+
def hls_config
|
88
|
+
@hls_config ||= YAML.load_file(Rails.root.join('config','hls.yml'))
|
89
|
+
end
|
90
|
+
|
91
|
+
def variants id
|
92
|
+
variants = Dir.glob(File.join(hls_dir(id),"*.m3u8"))
|
93
|
+
variants.map!{ |file|
|
94
|
+
name = File.split(file)[1]
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def variant_url id, format
|
99
|
+
File.join("file_set",id,format,"variant.m3u8")
|
100
|
+
end
|
101
|
+
|
102
|
+
def derivative_path id, destination_name
|
103
|
+
derivative_path_service.derivative_path_for_reference(id, destination_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def derivative_path_service
|
107
|
+
Hyrax::DerivativePath
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/samvera_hls/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: samvera_hls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ned Henry, UCSC Library Digital Initiatives
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -45,8 +45,8 @@ files:
|
|
45
45
|
- app/assets/stylesheets/samvera-hls-styles.scss
|
46
46
|
- app/controllers/concerns/samvera_hls/file_sets_controller_behavior.rb
|
47
47
|
- app/models/concerns/samvera_hls/file_set_behavior.rb
|
48
|
-
- app/models/concerns/samvera_hls/solr_document_behavior.rb
|
49
48
|
- app/services/samvera_hls/hls_output_file_service.rb
|
49
|
+
- app/services/samvera_hls/hls_playlist_generator.rb
|
50
50
|
- app/views/_playlist.html.erb
|
51
51
|
- app/views/file_sets/embed.html.erb
|
52
52
|
- app/views/file_sets/media_display/_audio_hls.html.erb
|
@@ -1,112 +0,0 @@
|
|
1
|
-
module SamveraHls
|
2
|
-
module SolrDocumentBehavior
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
|
6
|
-
def hls_master_url
|
7
|
-
File.join("file_set",id,"hls.m3u8")
|
8
|
-
end
|
9
|
-
|
10
|
-
def hls_master_playlist root_url
|
11
|
-
root_url = root_url.gsub("/?locale=en","")
|
12
|
-
type = mime_type.split('/')[0]
|
13
|
-
defaults = hls_config[type]["default"]
|
14
|
-
playlist = "#EXTM3U\n"
|
15
|
-
playlist << "#EXT-X-VERSION:6\n"
|
16
|
-
variants.each{|variant|
|
17
|
-
next if variant.blank?
|
18
|
-
path, filename = File.split(variant)
|
19
|
-
format = filename.gsub(".m3u8","")
|
20
|
-
options = defaults.merge(hls_config[type][format])
|
21
|
-
playlist << "#EXT-X-STREAM-INF:PROGRAM-ID=1,"
|
22
|
-
playlist << "BANDWIDTH=#{options["maxrate"]},"
|
23
|
-
playlist << "CODECS=\"#{options["codec_code"]}\","
|
24
|
-
playlist << "RESOLUTION=#{options["resolution"]}\n"
|
25
|
-
playlist << File.join(root_url,variant_url(format)) + "\n"
|
26
|
-
}
|
27
|
-
playlist
|
28
|
-
end
|
29
|
-
|
30
|
-
def hls_segment_playlist root_url, format
|
31
|
-
root_url = root_url.gsub("/?locale=en","")
|
32
|
-
playlist = ""
|
33
|
-
File.open(segment_playlist_path(format),'r') {|file|
|
34
|
-
file.each_line do |line|
|
35
|
-
if ENV["RAILS_ENV"] == 'development'
|
36
|
-
this_segment_url = File.join(root_url,
|
37
|
-
segment_url_base,
|
38
|
-
line).strip
|
39
|
-
else
|
40
|
-
this_segment_url = File.join(root_url,
|
41
|
-
segment_url_base,
|
42
|
-
timestamp.to_s,
|
43
|
-
token(line),
|
44
|
-
line).strip
|
45
|
-
end
|
46
|
-
if line.include? ".ts" then
|
47
|
-
playlist << this_segment_url + "\n"
|
48
|
-
else
|
49
|
-
playlist << line.strip+"\n"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
}
|
53
|
-
playlist
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def segment_url_base
|
60
|
-
File.join("stream",derivative_url,"hls")
|
61
|
-
end
|
62
|
-
|
63
|
-
def variants
|
64
|
-
variants = Dir.glob(File.join(derivative_dir,"hls","*.m3u8"))
|
65
|
-
variants.map!{ |file|
|
66
|
-
name = File.split(file)[1]
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
|
-
def variant_url format
|
71
|
-
File.join("file_set",id,format,"variant.m3u8")
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
def token line
|
76
|
-
@token ||= Digest::SHA256.hexdigest("/" + File.join(segment_url_base,timestamp.to_s,line).strip[0...-9] + token_secret)
|
77
|
-
end
|
78
|
-
|
79
|
-
def timestamp
|
80
|
-
@timestamp ||= Time.now.to_i + 7200
|
81
|
-
end
|
82
|
-
|
83
|
-
def token_secret
|
84
|
-
if ENV["RAILS_ENV"] == 'development'
|
85
|
-
return ''
|
86
|
-
else
|
87
|
-
return @token_secret ||= ENV['hls_token_secret']
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def hls_config
|
92
|
-
@hls_config ||= YAML.load_file(Rails.root.join('config','hls.yml'))
|
93
|
-
end
|
94
|
-
|
95
|
-
def segment_playlist_path format
|
96
|
-
File.join(derivative_dir,"hls",format+".m3u8")
|
97
|
-
end
|
98
|
-
|
99
|
-
def derivative_dir
|
100
|
-
File.split(derivative_path("dummy"))[0]
|
101
|
-
end
|
102
|
-
|
103
|
-
def derivative_path destination_name
|
104
|
-
derivative_path_service.derivative_path_for_reference(self, destination_name)
|
105
|
-
end
|
106
|
-
|
107
|
-
def derivative_path_service
|
108
|
-
Hyrax::DerivativePath
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
end
|