abrizer 0.3.0 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b2cc86e1f64991ede59039402b26923049110110
4
- data.tar.gz: 03522fe0d4fdf46fd41387356969cf416a84a524
3
+ metadata.gz: 56c129ae5143fedefa8b41cd5c98ccf2a370bf72
4
+ data.tar.gz: 6162f79282a5576b77bdc9b74cf6c7ff0c74044b
5
5
  SHA512:
6
- metadata.gz: 7034f59f985cda22b3fd31f6f4f4cbe2574d7e45b80a00b89aa61ba0cb8c83e92ae8d6e18d21473457f6d41ac596a61c5714b232666dfdfc0add5d0cb8e311e9
7
- data.tar.gz: 1486ff06789e71d6d9e29d7a9825318ff1fb564b2b08ba2de3a08f8b52159e5088cb5fafa908a19d814afba69949fda88c405af4698bcbeef5131faec1c91a73
6
+ metadata.gz: a14b4b77761e7f0cd2de95264f2232856cb3da83c431be859b602567491762baeda3eae4855bfd66094be2f9dd5091cee548accaa08f9f800d504c89415bd439
7
+ data.tar.gz: 0c36ba67ab3d170df18fe87b748f6de4bf96e930fe97b6beef316bfd50ca0c14bdc10610e92900808faedcc7050dd3fbd92a0891fe46035542e21ad965ac3c12
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
  /tmp/
10
10
  /.byebug_history
11
11
  /.vagrant
12
+ /ansible/development-playbook.retry
data/Vagrantfile CHANGED
@@ -4,7 +4,12 @@
4
4
  Vagrant.configure("2") do |config|
5
5
  config.vm.box = "boxcutter/centos72"
6
6
 
7
- config.vm.synced_folder '.', '/vagrant' #, type: 'nfs', mount_options: ['nolock', 'rw', 'vers=3', 'tcp', 'actimeo=2']
7
+ # Create a private network, which allows host-only access to the machine
8
+ # using a specific IP.
9
+ config.vm.network "private_network", ip: "192.168.33.40"
10
+
11
+ config.vm.synced_folder '.', '/vagrant', type: 'nfs', mount_options: ['nolock']
12
+
8
13
  config.vm.network "forwarded_port", guest: 80, host: 8088,
9
14
  auto_correct: true
10
15
 
@@ -7,14 +7,17 @@
7
7
  gather_facts: yes
8
8
  roles:
9
9
  - role: basic-setup
10
- - role: apache
11
10
  - role: franklinkim.environment
12
11
  environment_config:
13
12
  PATH: /usr/local/bento4/bin:/usr/bin:/usr/local/bin
13
+ - role: apache
14
14
  - role: ffmpeg
15
15
  build_dir: /root/ffmpeg_build
16
16
  source_dir: /root/ffmpeg_sources
17
17
  - role: rvm_io.rvm1-ruby
18
18
  rvm1_rubies:
19
19
  - 2.3.3
20
+ - role: rvm-setup
21
+ users:
22
+ - vagrant
20
23
  - role: bento4
@@ -9,6 +9,11 @@
9
9
  line: 'Header set Access-Control-Allow-Origin "*"'
10
10
  # regexp: '<Directory "/var/www/html">'
11
11
  insertafter: '<Directory "/var/www/html">'
12
+ - name: enable range requests
13
+ lineinfile:
14
+ dest: /etc/httpd/conf/httpd.conf
15
+ line: 'Header set Access-Control-Allow-Headers Range'
16
+ insertafter: 'Header set Access-Control-Allow-Origin "*"'
12
17
  - name: remove firewall
13
18
  yum:
14
19
  name: firewalld
@@ -21,3 +26,7 @@
21
26
  force: yes
22
27
  - name: restart httpd
23
28
  service: name=httpd state=restarted
29
+ - name: enable httpd
30
+ service:
31
+ name: httpd
32
+ enabled: yes
@@ -38,3 +38,6 @@
38
38
  - zlib-devel
39
39
  - tree
40
40
  - jq
41
+ - unzip
42
+ - ImageMagick
43
+ - jpegoptim
@@ -12,3 +12,7 @@
12
12
  file: path=/usr/local/bento4/ state=directory
13
13
  - name: move bento4
14
14
  shell: mv ~/Bento4-SDK-1-5-0-613.x86_64-unknown-linux/* /usr/local/bento4/.
15
+ - name: set permissions on /usr/local/bento4/
16
+ file:
17
+ path: /usr/local/bento4/
18
+ mode: "u=rwx,go=rx"
@@ -0,0 +1,9 @@
1
+ ---
2
+ - name: add users to rvm group
3
+ command: /bin/bash -lc 'rvm group add rvm {{item}}'
4
+ with_items: "{{users}}"
5
+ - name: auto-dotfiles
6
+ command: /bin/bash -lc 'rvm get stable --auto-dotfiles'
7
+ - name: rvm fix-permissions system
8
+ command: /bin/bash -lc 'rvm fix-permissions :rvm'
9
+ # - TODO: name: fix bundler permissions
data/exe/abrizer CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'abrizer'
3
3
  require 'abrizer/cli'
4
- require 'byebug'
4
+ # require 'byebug'
5
5
  Abrizer::CLI.start(ARGV)
@@ -2,6 +2,7 @@ module Abrizer
2
2
  class Adaptation
3
3
 
4
4
  include FilepathHelpers
5
+ include DebugSettings
5
6
 
6
7
  attr_reader :width, :height, :bitrate
7
8
 
@@ -12,10 +13,11 @@ module Abrizer
12
13
  end
13
14
 
14
15
  def ffmpeg_cmd(input, output_directory, pass)
15
- cmd = %Q|ffmpeg -y -i #{input} -vf \
16
- scale='#{width}:trunc(#{width}/dar/2)*2',setsar=1 \
16
+ cmd = %Q|ffmpeg -y #{debug_settings} \
17
+ -i #{input} -vf \
18
+ yadif,scale='#{width}:trunc(#{width}/dar/2)*2',setsar=1 \
17
19
  -an -c:v libx264 -x264opts 'keyint=48:min-keyint=48:no-scenecut' \
18
- -b:v #{bitrate}k -preset faster |
20
+ -b:v #{bitrate}k -preset faster -pix_fmt yuv420p |
19
21
  if pass == 2
20
22
  cmd += %Q| -maxrate #{constrained_bitrate}k -bufsize #{bitrate}k -pass 2 #{filepath(input, output_directory)} |
21
23
  else
@@ -49,5 +51,13 @@ module Abrizer
49
51
  "Width: #{@width}, Height: #{@height}, Bitrate: #{@bitrate}"
50
52
  end
51
53
 
54
+ def to_json
55
+ MultiJson.dump(to_hash)
56
+ end
57
+
58
+ def to_hash
59
+ {width: @width, height: @height, bitrate: @bitrate}
60
+ end
61
+
52
62
  end
53
63
  end
@@ -0,0 +1,20 @@
1
+ module Abrizer
2
+ class AdaptationsFile
3
+
4
+ include FilepathHelpers
5
+
6
+ def initialize(filepath, output_directory)
7
+ @filepath = filepath
8
+ @output_directory = output_directory
9
+ end
10
+
11
+ def adaptations
12
+ adapt = Abrizer::AdaptationFinder.new(@filepath).adaptations
13
+ adapt_dump = adapt.map{|a| a.to_hash}
14
+ File.open(adaptations_filepath, 'w') do |fh|
15
+ fh.puts MultiJson.dump(adapt_dump)
16
+ end
17
+ adapt
18
+ end
19
+ end
20
+ end
data/lib/abrizer/all.rb CHANGED
@@ -4,19 +4,24 @@ module Abrizer
4
4
  def initialize(filename, output_dir, base_url)
5
5
  @filename = filename
6
6
  @output_directory = output_dir
7
+ FileUtils.mkdir_p @output_directory
7
8
  @base_url = base_url
8
9
  end
9
10
 
10
11
  def run
12
+ Abrizer::FfprobeFile.new(@filename, @output_directory).run
13
+ Abrizer::AdaptationsFile.new(@filename, @output_directory).adaptations
11
14
  Abrizer::Processor.process(@filename, @output_directory)
12
15
  Abrizer::ProgressiveMp4.new(@filename, @output_directory).create
13
- Abrizer::ProgressiveVp9.new(@filename, @output_directory).create
16
+ # Abrizer::ProgressiveVp9.new(@filename, @output_directory).create
17
+ Abrizer::ProgressiveMp3.new(@filename, @output_directory).create
14
18
  Abrizer::PackageDashBento.new(@filename, @output_directory).package
15
19
  Abrizer::PackageHlsBento.new(@filename, @output_directory).package
16
20
  Abrizer::Captions.new(@filename, @output_directory).copy
17
21
  Abrizer::Sprites.new(@filename, @output_directory).create
18
22
  Abrizer::TemporaryPoster.new(@output_directory).copy
19
23
  Abrizer::Canvas.new(@filename, @output_directory, @base_url).create
24
+ Abrizer::Data.new(@filename, @output_directory, @base_url).create
20
25
  Abrizer::Cleaner.new(@filename, @output_directory).clean
21
26
  end
22
27
 
@@ -3,17 +3,22 @@ module Abrizer
3
3
  class Canvas
4
4
 
5
5
  include FilepathHelpers
6
+ include IdentifierHelpers
7
+ include InformationHelpers
8
+ include ReadAdaptations
6
9
 
7
10
  # TODO: allow control of items/versions listed on canvas
8
11
  def initialize(filepath, output_directory, base_url)
9
- @filename = filepath
12
+ @filepath = filepath
10
13
  @output_directory = output_directory
11
14
  @base_url = base_url
12
- finder = AdaptationFinder.new(@filename)
13
- @adaptations = finder.adaptations
15
+ # finder = AdaptationFinder.new(@filename)
16
+ # @adaptations = finder.adaptations
17
+ read_adaptations
14
18
  end
15
19
 
16
20
  def create
21
+ FileUtils.mkdir_p output_directory unless File.exist? output_directory
17
22
  File.open(canvas_filepath, 'w') do |fh|
18
23
  fh.puts create_json
19
24
  end
@@ -143,8 +148,7 @@ module Abrizer
143
148
 
144
149
  def captions_item(json)
145
150
  # TODO: update captions for multiple captions
146
- captions_file = File.join output_directory, 'vtt/captions.vtt'
147
- if File.exist? captions_file
151
+ if File.exist? captions_filepath
148
152
  json.child! do
149
153
  json.id vtt_id
150
154
  json.type 'Text'
@@ -178,79 +182,5 @@ module Abrizer
178
182
  end
179
183
  end
180
184
 
181
- def media_base_url
182
- File.join @base_url, output_directory_basename
183
- end
184
-
185
- def canvas_id
186
- File.join media_base_url, canvas_partial_filepath
187
- end
188
-
189
- def poster_id
190
- File.join media_base_url, poster_partial_filepath
191
- end
192
-
193
- def mpd_id
194
- File.join media_base_url, mpd_partial_filepath
195
- end
196
-
197
- def hlsts_id
198
- File.join media_base_url, hlsts_partial_filepath
199
- end
200
-
201
- def hlsts_aac_id
202
- File.join media_base_url, hlsts_aac_partial_filepath
203
- end
204
-
205
- def mp4_id
206
- File.join media_base_url, mp4_partial_filepath
207
- end
208
-
209
- def vp9_id
210
- File.join media_base_url, vp9_partial_filepath
211
- end
212
-
213
- def vtt_id
214
- File.join media_base_url, 'vtt/captions.vtt'
215
- end
216
-
217
- def sprites_id
218
- File.join media_base_url, sprites_partial_filepath
219
- end
220
-
221
- def duration
222
- informer = Abrizer::FfprobeInformer.new(mp4_filename)
223
- informer.duration.to_f
224
- end
225
-
226
- def max_width
227
- @adaptations.last.width
228
- end
229
-
230
- def min_width
231
- @adaptations.first.width
232
- end
233
-
234
- def max_height
235
- @adaptations.last.height
236
- end
237
-
238
- def min_height
239
- @adaptations.first.height
240
- end
241
-
242
- def mp4_width
243
- @adaptations[-2].width
244
- end
245
-
246
- def mp4_height
247
- @adaptations[-2].height
248
- end
249
-
250
- # TODO: DRY up with progressive_mp4.rb
251
- def mp4_filename
252
- File.join output_directory, "progressive.mp4"
253
- end
254
-
255
185
  end
256
186
  end
data/lib/abrizer/cli.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  require 'thor'
2
+
3
+ if ENV['DEBUG_ABRIZER']
4
+ require 'byebug'
5
+ end
6
+
2
7
  module Abrizer
3
8
  class CLI < Thor
4
9
 
@@ -9,6 +14,13 @@ module Abrizer
9
14
  Abrizer::All.new(filepath, output_dir, base_url).run
10
15
  end
11
16
 
17
+ desc 'ffprobe <filepath> <output_directory>', 'Save the output of ffprobe to a file as JSON'
18
+ def ffprobe(filepath, output_dir)
19
+ filepath = File.expand_path filepath
20
+ output_dir = File.expand_path output_dir
21
+ Abrizer::FfprobeFile.new(filepath, output_dir).run
22
+ end
23
+
12
24
  desc 'abr <filepath> <output_directory>', 'From file create ABR streams, includes processing MP4 adaptations for packaging'
13
25
  def abr(filepath, output_dir=nil)
14
26
  filepath = File.expand_path filepath
@@ -39,9 +51,9 @@ module Abrizer
39
51
  Abrizer::ProgressiveVp9.new(filepath, output_dir).create
40
52
  end
41
53
 
42
- desc 'adaptations <filepath>', 'Display which adaptations will be created from input file'
43
- def adaptations(filepath)
44
- adaptations = Abrizer::AdaptationFinder.new(filepath).adaptations
54
+ desc 'adaptations <filepath> <output_directory>', 'Output which adaptations will be created from input file to a JSON file and output to console'
55
+ def adaptations(filepath, output_directory=nil)
56
+ adaptations = Abrizer::AdaptationsFile.new(filepath, output_directory).adaptations
45
57
  puts adaptations
46
58
  end
47
59
 
@@ -69,6 +81,15 @@ module Abrizer
69
81
  end
70
82
  end
71
83
 
84
+ desc 'mp3 <filepath> <output_directory>', 'Create a progressive MP3 file from the audio of the original media'
85
+ def mp3(filepath, output_directory)
86
+ # TODO: repeating expanding filepath and output_directory is probably the
87
+ # most annoying thing in this library. DRY this up somehow.
88
+ filepath = File.expand_path filepath
89
+ output_dir = File.expand_path output_directory
90
+ Abrizer::ProgressiveMp3.new(filepath, output_dir).create
91
+ end
92
+
72
93
  desc 'sprites <filepath> <output_directory>', 'Create image sprites and metadata WebVTT file'
73
94
  def sprites(filepath, output_dir=nil)
74
95
  filepath = File.expand_path filepath
@@ -89,13 +110,19 @@ module Abrizer
89
110
  Abrizer::Captions.new(filepath, output_dir).copy
90
111
  end
91
112
 
92
- desc 'canvas <filepath> <output_directory> <base_url>', 'Creates a IIIF Canvas JSON-LD document as an API into the resources'
113
+ desc 'canvas <filepath_or_identifier> <output_directory> <base_url>', 'Creates a IIIF Canvas JSON-LD document as an API into the resources'
93
114
  def canvas(filepath, output_directory, base_url)
94
115
  filepath = File.expand_path filepath
95
116
  output_directory = File.expand_path output_directory
96
117
  Abrizer::Canvas.new(filepath, output_directory, base_url).create
97
118
  end
98
119
 
120
+ desc 'data <filepath_or_identifier> <output_directory> <base_url>', 'Creates a JSON file with data about the video resources.'
121
+ def data(filepath, output_directory, base_url)
122
+ output_directory = File.expand_path output_directory
123
+ Abrizer::Data.new(filepath, output_directory, base_url).create
124
+ end
125
+
99
126
  desc 'clean <filepath> <output_directory>', 'Clean up intermediary files'
100
127
  def clean(filepath, output_dir=nil)
101
128
  Abrizer::Cleaner.new(filepath, output_dir).clean
@@ -0,0 +1,163 @@
1
+ module Abrizer
2
+ # Creates a JSON file with information about the videos
3
+ class Data
4
+
5
+ include FilepathHelpers
6
+ include IdentifierHelpers
7
+ include InformationHelpers
8
+ include ReadAdaptations
9
+
10
+ def initialize(filepath, output_directory, base_url)
11
+ @filepath = filepath
12
+ # This is kind of hacky, but if the @output_directory is set then we can
13
+ # use that to look up the vp9_filepath
14
+ @output_directory = output_directory
15
+ @base_url = base_url
16
+
17
+ # This sets @filename in some cases and more importantly sets @adaptations
18
+ # based on the filepath or identifier that's passed in.
19
+ read_adaptations
20
+ end
21
+
22
+ def find_adaptations
23
+ finder = AdaptationFinder.new(@filename)
24
+ @adaptations = finder.adaptations
25
+ end
26
+
27
+ def create
28
+ FileUtils.mkdir_p output_directory unless File.exist? output_directory
29
+ File.open(data_filepath, 'w') do |fh|
30
+ fh.puts create_json
31
+ end
32
+ end
33
+
34
+ def create_json
35
+ Jbuilder.encode do |json|
36
+ json.id data_id
37
+ json.max_width max_width
38
+ json.max_height max_height
39
+ json.duration duration
40
+ json.poster do
41
+ poster(json)
42
+ end
43
+ json.video do
44
+ mpd_source(json)
45
+ hlsts_source(json)
46
+ vp9_source(json)
47
+ mp4_source(json)
48
+ end
49
+ json.audio do
50
+ mp3_source(json)
51
+ aac_source(json)
52
+ end
53
+ json.tracks do
54
+ captions(json)
55
+ end
56
+ json.sprites do
57
+ sprites(json)
58
+ end
59
+ end
60
+ end
61
+
62
+ def poster(json)
63
+ if File.exist? poster_filepath
64
+ json.child! do
65
+ json.id poster_id
66
+ json.format "image/jpg"
67
+ json.width max_width
68
+ json.height max_height
69
+ end
70
+ end
71
+ end
72
+
73
+ def mpd_source(json)
74
+ if File.exist? mpd_filepath
75
+ json.child! do
76
+ json.id mpd_id
77
+ json.format "application/dash+xml"
78
+ json.width max_width
79
+ json.height max_height
80
+ end
81
+ end
82
+ end
83
+
84
+ def hlsts_source(json)
85
+ if File.exist? hlsts_filepath
86
+ json.child! do
87
+ json.id hlsts_id
88
+ json.type "Video"
89
+ # TODO: or "vnd.apple.mpegURL"
90
+ json.format "application/x-mpegURL"
91
+ json.width max_width
92
+ json.height max_height
93
+ end
94
+ end
95
+ end
96
+
97
+ def vp9_source(json)
98
+ if File.exist? vp9_filepath
99
+ json.child! do
100
+ json.id vp9_id
101
+ json.type "Video"
102
+ #TODO: add webm codecs
103
+ json.format "video/webm"
104
+ json.width max_width
105
+ json.height max_height
106
+ end
107
+ end
108
+ end
109
+
110
+ def mp4_source(json)
111
+ if File.exist? mp4_filepath
112
+ json.child! do
113
+ json.id mp4_id
114
+ json.type "Video"
115
+ #TODO: add mp4 codecs
116
+ json.format "video/mp4"
117
+ json.width mp4_width
118
+ json.height mp4_height
119
+ end
120
+ end
121
+ end
122
+
123
+ def mp3_source(json)
124
+ if File.exist? mp3_filepath
125
+ json.child! do
126
+ json.id mp3_id
127
+ json.format 'audio/mpeg'
128
+ end
129
+ end
130
+ end
131
+
132
+ def aac_source(json)
133
+ if File.exist? hlsts_aac_filepath
134
+ json.child! do
135
+ json.id hlsts_aac_id
136
+ json.format 'audio/aac'
137
+ end
138
+ end
139
+ end
140
+
141
+ def captions(json)
142
+ if File.exist? captions_filepath
143
+ json.child! do
144
+ json.id vtt_id
145
+ json.format 'text/vtt'
146
+ json.kind 'captions'
147
+ json.label 'English captions'
148
+ json.language 'en'
149
+ end
150
+ end
151
+ end
152
+
153
+ def sprites(json)
154
+ if File.exist? sprites_filepath
155
+ json.id sprites_id
156
+ json.format 'text/vtt'
157
+ json.kind 'metadata'
158
+ json.label 'image sprite metadata'
159
+ end
160
+ end
161
+
162
+ end
163
+ end
@@ -0,0 +1,11 @@
1
+ module Abrizer
2
+ module DebugSettings
3
+
4
+ # This is useful for testing an encoding setting on just part of a video.
5
+ # This gets applied before the input video is set.
6
+ def debug_settings
7
+ ENV['ABRIZER_DEBUG_SETTINGS'] || ''
8
+ # "-ss 10 -t 10"
9
+ end
10
+ end
11
+ end
@@ -1,7 +1,9 @@
1
1
  module Abrizer
2
+ # Creates the fMP4 files that are then packaged
2
3
  class FfmpegProcessor
3
4
 
4
5
  include FilepathHelpers
6
+ include DebugSettings
5
7
 
6
8
  def initialize(filename, output_dir=nil)
7
9
  @filename = filename
@@ -18,7 +20,7 @@ module Abrizer
18
20
  end
19
21
 
20
22
  def make_directory
21
- FileUtils.mkdir output_directory unless File.exist? output_directory
23
+ FileUtils.mkdir_p output_directory unless File.exist? output_directory
22
24
  end
23
25
 
24
26
  def first_pass_adaptation
@@ -50,7 +52,7 @@ module Abrizer
50
52
  end
51
53
 
52
54
  def process_audio
53
- `ffmpeg -y -i #{@filename} -c:a libfdk_aac -b:a 128k -vn #{audio_filepath}`
55
+ `ffmpeg -y #{debug_settings} -i #{@filename} -c:a libfdk_aac -b:a 128k -vn #{audio_filepath}`
54
56
  `mp4fragment #{audio_filepath} #{audio_filepath_fragmented}`
55
57
  FileUtils.rm audio_filepath
56
58
  end
@@ -0,0 +1,17 @@
1
+ module Abrizer
2
+ class FfprobeFile
3
+
4
+ include FilepathHelpers
5
+
6
+ def initialize(filename, output_directory)
7
+ @informer = FfprobeInformer.new(filename)
8
+ @output_directory = output_directory
9
+ end
10
+
11
+ def run
12
+ File.open(ffprobe_filepath, 'w') do |fh|
13
+ fh.puts @informer.json_result
14
+ end
15
+ end
16
+ end
17
+ end
@@ -34,10 +34,22 @@ module Abrizer
34
34
  File.basename @filename, extname
35
35
  end
36
36
 
37
+ def ffprobe_filepath
38
+ File.join output_directory, 'ffprobe.json'
39
+ end
40
+
41
+ def adaptations_filepath
42
+ File.join output_directory, 'adaptations.json'
43
+ end
44
+
37
45
  def poster_partial_filepath
38
46
  'poster.jpg'
39
47
  end
40
48
 
49
+ def poster_filepath
50
+ File.join output_directory, poster_partial_filepath
51
+ end
52
+
41
53
  def mpd_partial_filepath
42
54
  'fmp4/stream.mpd'
43
55
  end
@@ -78,6 +90,18 @@ module Abrizer
78
90
  File.join output_directory, vp9_partial_filepath
79
91
  end
80
92
 
93
+ def mp3_partial_filepath
94
+ 'progressive.mp3'
95
+ end
96
+
97
+ def mp3_filepath
98
+ File.join output_directory, mp3_partial_filepath
99
+ end
100
+
101
+ def captions_filepath
102
+ File.join output_directory, 'vtt/captions.vtt'
103
+ end
104
+
81
105
  def canvas_partial_filepath
82
106
  'canvas.json'
83
107
  end
@@ -86,6 +110,14 @@ module Abrizer
86
110
  File.join output_directory, canvas_partial_filepath
87
111
  end
88
112
 
113
+ def data_partial_filepath
114
+ 'data.json'
115
+ end
116
+
117
+ def data_filepath
118
+ File.join output_directory, data_partial_filepath
119
+ end
120
+
89
121
  def sprites_partial_filepath
90
122
  'sprites/sprites.vtt'
91
123
  end
@@ -0,0 +1,53 @@
1
+ module Abrizer
2
+ module IdentifierHelpers
3
+
4
+ def media_base_url
5
+ File.join @base_url, output_directory_basename
6
+ end
7
+
8
+ def canvas_id
9
+ File.join media_base_url, canvas_partial_filepath
10
+ end
11
+
12
+ def data_id
13
+ File.join media_base_url, data_partial_filepath
14
+ end
15
+
16
+ def poster_id
17
+ File.join media_base_url, poster_partial_filepath
18
+ end
19
+
20
+ def mpd_id
21
+ File.join media_base_url, mpd_partial_filepath
22
+ end
23
+
24
+ def hlsts_id
25
+ File.join media_base_url, hlsts_partial_filepath
26
+ end
27
+
28
+ def hlsts_aac_id
29
+ File.join media_base_url, hlsts_aac_partial_filepath
30
+ end
31
+
32
+ def mp4_id
33
+ File.join media_base_url, mp4_partial_filepath
34
+ end
35
+
36
+ def vp9_id
37
+ File.join media_base_url, vp9_partial_filepath
38
+ end
39
+
40
+ def mp3_id
41
+ File.join media_base_url, mp3_partial_filepath
42
+ end
43
+
44
+ def vtt_id
45
+ File.join media_base_url, 'vtt/captions.vtt'
46
+ end
47
+
48
+ def sprites_id
49
+ File.join media_base_url, sprites_partial_filepath
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ module Abrizer
2
+ module InformationHelpers
3
+
4
+ def duration
5
+ informer = Abrizer::FfprobeInformer.new(mp4_filepath)
6
+ informer.duration.to_f
7
+ end
8
+
9
+ def max_width
10
+ @adaptations.last.width
11
+ end
12
+
13
+ def min_width
14
+ @adaptations.first.width
15
+ end
16
+
17
+ def max_height
18
+ @adaptations.last.height
19
+ end
20
+
21
+ def min_height
22
+ @adaptations.first.height
23
+ end
24
+
25
+ def mp4_width
26
+ @adaptations[-2].width
27
+ end
28
+
29
+ def mp4_height
30
+ @adaptations[-2].height
31
+ end
32
+
33
+ end
34
+ end
@@ -37,7 +37,7 @@ module Abrizer
37
37
  end
38
38
 
39
39
  def make_directory
40
- FileUtils.mkdir dash_directory unless File.exist? dash_directory
40
+ FileUtils.mkdir_p dash_directory unless File.exist? dash_directory
41
41
  end
42
42
 
43
43
  def dash_directory
@@ -39,7 +39,7 @@ module Abrizer
39
39
  end
40
40
 
41
41
  def make_directory
42
- FileUtils.mkdir hls_directory unless File.exist? hls_directory
42
+ FileUtils.mkdir_p hls_directory unless File.exist? hls_directory
43
43
  end
44
44
 
45
45
  def hls_directory
@@ -0,0 +1,21 @@
1
+ module Abrizer
2
+ class ProgressiveMp3
3
+
4
+ include FilepathHelpers
5
+ include DebugSettings
6
+
7
+ def initialize(filepath, output_directory)
8
+ @filepath = filepath
9
+ @output_directory = output_directory
10
+ end
11
+
12
+ def create
13
+ `#{ffmpeg_cmd}`
14
+ end
15
+
16
+ def ffmpeg_cmd
17
+ "ffmpeg -y #{debug_settings} -i #{@filepath} -vn -c:a libmp3lame -b:a 128k #{mp3_filepath}"
18
+ end
19
+
20
+ end
21
+ end
@@ -26,11 +26,9 @@ module Abrizer
26
26
  end
27
27
 
28
28
  def ffmpeg_cmd
29
- "ffmpeg -y -i #{input_video_filepath} -i #{audio_filepath_fragmented} -c:v copy -c:a copy #{static_filepath}"
30
- end
31
-
32
- def static_filepath
33
- File.join output_directory, "progressive.mp4"
29
+ "ffmpeg -y -i #{input_video_filepath} -i #{audio_filepath_fragmented} -c:v copy -c:a copy #{mp4_filepath} -movflags faststart"
30
+ # Previously used command:
31
+ # "ffmpeg -y -i #{@filename} -profile:v high -pix_fmt yuv420p -movflags faststart -b:v #{@adaptation.bitrate}k #{mp4_filepath}"
34
32
  end
35
33
 
36
34
  end
@@ -2,6 +2,7 @@ module Abrizer
2
2
  class ProgressiveVp9
3
3
 
4
4
  include FilepathHelpers
5
+ include DebugSettings
5
6
 
6
7
  def initialize(filename, output_dir=nil)
7
8
  @filename = filename
@@ -17,7 +18,7 @@ module Abrizer
17
18
  end
18
19
 
19
20
  def make_directory
20
- FileUtils.mkdir @output_directory unless File.exist? @output_directory
21
+ FileUtils.mkdir_p @output_directory unless File.exist? @output_directory
21
22
  end
22
23
 
23
24
  def find_adaptation
@@ -35,23 +36,22 @@ module Abrizer
35
36
  end
36
37
 
37
38
  def ffmpeg_cmd_pass1
38
- "ffmpeg -y -i #{@filename} -c:v libvpx-vp9 -b:v #{bitrate}k -c:a libvorbis \
39
- -vf scale='#{@adaptation.width}:trunc(#{@adaptation.width}/dar/2)*2',setsar=1 \
40
- -speed 4 -tile-columns 6 -frame-parallel 1 \
39
+ "ffmpeg -y #{debug_settings} -i #{@filename} -c:v libvpx-vp9 -crf 10 -b:v #{bitrate*1.1}k -c:a libvorbis \
40
+ -vf yadif,scale='#{@adaptation.width}:trunc(#{@adaptation.width}/dar/2)*2',setsar=1 \
41
+ -speed 4 -tile-columns 6 -frame-parallel 1 -pix_fmt yuv420p \
41
42
  -pass 1 -passlogfile ffmpeg2pass-webm -f webm /dev/null"
42
43
  end
43
44
 
44
45
  def ffmpeg_cmd_pass2
45
- "ffmpeg -y -i #{@filename} -c:v libvpx-vp9 -b:v #{bitrate}k -c:a libvorbis \
46
- -vf scale='#{@adaptation.width}:trunc(#{@adaptation.width}/dar/2)*2',setsar=1 \
46
+ "ffmpeg -y #{debug_settings} -i #{@filename} -c:v libvpx-vp9 -crf 10 -b:v #{bitrate*1.1}k -c:a libvorbis \
47
+ -vf yadif,scale='#{@adaptation.width}:trunc(#{@adaptation.width}/dar/2)*2',setsar=1 \
47
48
  -speed 1 -tile-columns 6 -frame-parallel 1 -auto-alt-ref 1 -lag-in-frames 25 \
48
- -pass 2 -passlogfile ffmpeg2pass-webm -y #{static_filepath}"
49
+ -pass 2 -passlogfile ffmpeg2pass-webm -pix_fmt yuv420p #{static_filepath}"
49
50
  end
50
51
 
51
52
  def static_filepath
52
53
  File.join output_directory, "progressive-vp9.webm"
53
54
  end
54
55
 
55
-
56
56
  end
57
57
  end
@@ -0,0 +1,34 @@
1
+ module Abrizer
2
+ module ReadAdaptations
3
+
4
+
5
+
6
+ def read_adaptations
7
+ # Either we have a filepath to an original or we make the assumption we
8
+ # really have an identifier instead of a filepath and we use that
9
+ # identifier to look for an adaptations.json file. Failing finding the
10
+ # adaptations.json file we just use the adaptations based on the
11
+ # vp9_filepath.
12
+ if File.exist?(File.expand_path(@filepath)) && !File.directory?(@filepath)
13
+ @filename = @filepath
14
+ find_adaptations
15
+ elsif File.exist? adaptations_filepath
16
+ # assume we have an identifier and look up for the adaptations file
17
+ adaptations_json = File.read adaptations_filepath
18
+ adaptations = MultiJson.load adaptations_json
19
+ # TODO: There ought to be a class that recreates an Adaptation instance
20
+ # based on the adaptations.json file. For now we fake it with a
21
+ # OpenStruct.
22
+ @adaptations = adaptations.map do |a|
23
+ OpenStruct.new(a)
24
+ end
25
+ elsif File.exist? vp9_filepath
26
+ # assume we just got an identifier and look for the webm
27
+ @filename = vp9_filepath
28
+ find_adaptations
29
+ else
30
+ raise "Neither original file or VP9 version exist."
31
+ end
32
+ end
33
+ end
34
+ end
@@ -18,6 +18,37 @@ module Abrizer
18
18
  def create
19
19
  processor = VideoSprites::Processor.new(@filename, @output_directory, @options)
20
20
  processor.process
21
+ FileUtils.chmod_R "go+r", @output_directory
22
+ optimize_images
23
+ end
24
+
25
+ def optimize_images
26
+ optimize_sprites
27
+ optimize_individual_images
28
+ end
29
+
30
+ def optimize_sprites
31
+ `jpegoptim #{sprite_paths.join(' ')}`
32
+ end
33
+
34
+ def sprite_paths
35
+ Dir.glob(sprites_glob)
36
+ end
37
+
38
+ def sprites_glob
39
+ File.join @output_directory, "*.jpg"
40
+ end
41
+
42
+ def optimize_individual_images
43
+ `jpegoptim #{individual_image_paths.join(' ')}`
44
+ end
45
+
46
+ def individual_image_paths
47
+ Dir.glob(individual_image_glob)
48
+ end
49
+
50
+ def individual_image_glob
51
+ File.join @output_directory, "images/*.jpg"
21
52
  end
22
53
 
23
54
  end
@@ -14,6 +14,8 @@ module Abrizer
14
14
 
15
15
  def copy
16
16
  FileUtils.cp first_image_filepath, poster_image_filepath
17
+ `jpegoptim #{poster_image_filepath}`
18
+ FileUtils.chmod "ugo+r", poster_image_filepath
17
19
  end
18
20
 
19
21
  end
@@ -1,3 +1,3 @@
1
1
  module Abrizer
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/abrizer.rb CHANGED
@@ -4,23 +4,32 @@ MultiJson.use :yajl
4
4
  MultiJson.dump_options = {pretty: true}
5
5
  require 'jbuilder'
6
6
  require 'video_sprites'
7
+ require 'ostruct'
7
8
  require "abrizer/version"
8
9
  require 'abrizer/filepath_helpers'
10
+ require 'abrizer/read_adaptations'
11
+ require 'abrizer/debug_settings'
12
+ require 'abrizer/identifier_helpers'
13
+ require 'abrizer/information_helpers'
9
14
  require 'abrizer/package_dash_shaka'
10
15
  require 'abrizer/package_hls_shaka'
11
16
  require 'abrizer/package_dash_bento'
12
17
  require 'abrizer/package_hls_bento'
13
18
  require 'abrizer/adaptation'
14
19
  require 'abrizer/adaptation_finder'
20
+ require 'abrizer/adaptations_file'
15
21
  require 'abrizer/ffmpeg_processor'
16
22
  require 'abrizer/ffprobe_informer'
23
+ require 'abrizer/ffprobe_file'
17
24
  require 'abrizer/processor'
18
25
  require 'abrizer/cleaner'
19
26
  require 'abrizer/progressive_mp4'
20
27
  require 'abrizer/progressive_vp9'
28
+ require 'abrizer/progressive_mp3'
21
29
  require 'abrizer/sprites'
22
30
  require 'abrizer/captions'
23
31
  require 'abrizer/canvas'
32
+ require 'abrizer/data'
24
33
  require 'abrizer/temporary_poster'
25
34
  require 'abrizer/all'
26
35
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abrizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Ronallo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-19 00:00:00.000000000 Z
11
+ date: 2017-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -152,7 +152,6 @@ files:
152
152
  - Rakefile
153
153
  - Vagrantfile
154
154
  - abrizer.gemspec
155
- - ansible/development-playbook.retry
156
155
  - ansible/development-playbook.yml
157
156
  - ansible/development.ini
158
157
  - ansible/roles/apache/tasks/main.yml
@@ -187,6 +186,7 @@ files:
187
186
  - ansible/roles/franklinkim.environment/tasks/config.yml
188
187
  - ansible/roles/franklinkim.environment/tasks/main.yml
189
188
  - ansible/roles/franklinkim.environment/tests/main.yml
189
+ - ansible/roles/rvm-setup/tasks/main.yml
190
190
  - ansible/roles/rvm_io.rvm1-ruby/.gitignore
191
191
  - ansible/roles/rvm_io.rvm1-ruby/.travis.yml
192
192
  - ansible/roles/rvm_io.rvm1-ruby/LICENSE
@@ -205,21 +205,29 @@ files:
205
205
  - lib/abrizer.rb
206
206
  - lib/abrizer/adaptation.rb
207
207
  - lib/abrizer/adaptation_finder.rb
208
+ - lib/abrizer/adaptations_file.rb
208
209
  - lib/abrizer/all.rb
209
210
  - lib/abrizer/canvas.rb
210
211
  - lib/abrizer/captions.rb
211
212
  - lib/abrizer/cleaner.rb
212
213
  - lib/abrizer/cli.rb
214
+ - lib/abrizer/data.rb
215
+ - lib/abrizer/debug_settings.rb
213
216
  - lib/abrizer/ffmpeg_processor.rb
217
+ - lib/abrizer/ffprobe_file.rb
214
218
  - lib/abrizer/ffprobe_informer.rb
215
219
  - lib/abrizer/filepath_helpers.rb
220
+ - lib/abrizer/identifier_helpers.rb
221
+ - lib/abrizer/information_helpers.rb
216
222
  - lib/abrizer/package_dash_bento.rb
217
223
  - lib/abrizer/package_dash_shaka.rb
218
224
  - lib/abrizer/package_hls_bento.rb
219
225
  - lib/abrizer/package_hls_shaka.rb
220
226
  - lib/abrizer/processor.rb
227
+ - lib/abrizer/progressive_mp3.rb
221
228
  - lib/abrizer/progressive_mp4.rb
222
229
  - lib/abrizer/progressive_vp9.rb
230
+ - lib/abrizer/read_adaptations.rb
223
231
  - lib/abrizer/sprites.rb
224
232
  - lib/abrizer/temporary_poster.rb
225
233
  - lib/abrizer/version.rb
@@ -243,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
243
251
  version: '0'
244
252
  requirements: []
245
253
  rubyforge_project:
246
- rubygems_version: 2.6.6
254
+ rubygems_version: 2.5.2
247
255
  signing_key:
248
256
  specification_version: 4
249
257
  summary: Creates MPEG-DASH and HLS streams from a video file.
@@ -1 +0,0 @@
1
- localhost