abrizer 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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