abrizer 0.4.0 → 0.5.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: 56c129ae5143fedefa8b41cd5c98ccf2a370bf72
4
- data.tar.gz: 6162f79282a5576b77bdc9b74cf6c7ff0c74044b
3
+ metadata.gz: 4d43d0ec149f4116eeb8410a53dcc50841194a3b
4
+ data.tar.gz: ecaa1720869d608df837186fc7edbc5975fa212d
5
5
  SHA512:
6
- metadata.gz: a14b4b77761e7f0cd2de95264f2232856cb3da83c431be859b602567491762baeda3eae4855bfd66094be2f9dd5091cee548accaa08f9f800d504c89415bd439
7
- data.tar.gz: 0c36ba67ab3d170df18fe87b748f6de4bf96e930fe97b6beef316bfd50ca0c14bdc10610e92900808faedcc7050dd3fbd92a0891fe46035542e21ad965ac3c12
6
+ metadata.gz: 66f82d54378336839f9864e9d2fc2ca1de68c6a976b522837a4e7f7f1a370d7f9cfcdcf9715b8618a938297ac4c38ab1abc999b225b97a2bd0e727760f6bb5ca
7
+ data.tar.gz: fc6fd76b62a2cb8f1a5e59dddbd6aaf332847e9eee452d73593503477f9fdc0bbe8d54b70f08152ca42fa1ad929a2db2e7aadb97499eb4d04a980453f240a14d
data/README.md CHANGED
@@ -28,44 +28,58 @@ Or install it yourself as:
28
28
 
29
29
  See [Vagrant](#vagrant) below for one way to install dependencies and run the scripts.
30
30
 
31
+ ## Versioning
32
+
33
+ API may change in breaking ways in minor versions until version 1.0.0 when breaking changes will update the major version number.
34
+
31
35
  ## Usage
32
36
 
33
- Abrizer knows how to run various processes which can take a master or mezzanine video and create DASH and HLS streaming formats along with other derivatives like a fallback MP4 and WebM. The gem is opinionated about what formats to create and what settings to use. The intention is to provide a relatively complete but simple solution for delivering video over HTTP.
37
+ Abrizer knows how to run various processes which can take a master or mezzanine video and create various access derivative formats including DASH and HLS streaming formats as well as fallback MP4 and WebM (VP9). The gem is opinionated about what formats to create and what settings to use. The intention is to provide a relatively complete but simple solution for delivering video over HTTP for HTML5 video.
38
+
39
+ Some steps must be run after others as they have preconditions in order for subsequent steps to run. You can see the latest full set of processes Abrizer can run by looking in `lib/abrizer/all.rb`. The initial commands before `process` need to run with the mezzanine file as input. The current order is:
34
40
 
35
- Some steps must be run after others as they have preconditions in order for subsequent steps to run. Later cleaning steps will remove intermediate and log files. You can see the latest full set of processes Abrizer can run by looking in `lib/abrizer/cli.rb` for the `abr` method. The current order is:
41
+ - `ffprobe`: Saves the output of ffprobe to `ffprobe.json`. This way the mezzanine file does not have to be present for some later steps.
42
+ - `adaptations`: Saves the precomputed adaptations that will be created in later processes to `adaptations.json`.
43
+ - `captions`: Copies over captions.
44
+ - `vp9`: Process a progressive download WebM VP9 from original. This takes a long time.
45
+ - `mp3`: Create a progressive download MP3 audio file.
46
+ - `sprites`: Create video thumbnail sprites and metadata WebVTT file retaining all the images in order for a human to later pick a poster image.
47
+ - `poster`: Copies over a temporary poster image from the output of the `sprites` command.
48
+ - `process`: Process the adaptations that will be repackaged into ABR formats. Beyond this point the remaining processes can be run without the mezzanine file present.
49
+ - `mp4`: Process a progressive download MP4 from next to highest quality adaptation.
50
+ - `package dash`: Package DASH (and HLS with fMP4) using output of `process`.
51
+ - `package hls`: Package HLS (TS) using output of `process`.
52
+ - `canvas`:
53
+ - `data`:
54
+ - `clean`: Clean out the intermediate and log files including MP4 files used for packaging but not required for delivery.
36
55
 
37
- - `process`: Process the adaptations that will be repackaged into ABR formats
38
- - `package dash`: Package DASH (and HLS with fMP4) using output of `process`
39
- - `package hls`: Package HLS (TS) using output of `process`
40
- - `mp4`: Process a progressive download MP4 from original
41
- - `vp9`: Process a progressive download WebM VP9 from original
42
- - `sprites`: Create video sprites and metadata WebVTT file retaining all the images in order for a human to later pick a poster image
43
- - `poster`: Copies over a temporary poster image from the output of the sprites
44
- - `clean`: Clean out the intermediate and log files including MP4 files used for packaging but not required for delivery
56
+ ### Media Sharing
45
57
 
46
- All of the above commands require the path to the original video file and an output directory.
58
+ The `canvas` and `data` create files that aid in sharing media. They create `canvas.json` and `data.json` files respectively. You must know the base URL that will be used to serve up the media files. The `canvas.json` is experimental support for the developing [IIIF A/V technical specification](http://iiif.io/community/groups/av/) for canvases. Note that this work is done in advance of a draft standard for including video in a IIIF manifest. The `data.json` file is a simplified version of the information about the available media.
59
+
60
+ In order to get information about the files being shared these steps either need the presence of the original video file or the presence of the `ffprobe.json` and `adaptations.json` files. In addition these information files are only useful if some media has already been processed. In other words these processes can be run without the presence of the mezzanine file if some preconditions are already met.
47
61
 
48
62
  ### Command Line
49
63
 
50
64
  From the command line you can see help with: `abrizer`
51
65
 
52
- To see help for a particular command run: `abrizer help abr`
66
+ To see help for a particular command run: `abrizer help all`
53
67
 
54
68
  You can run all steps with:
55
- `abrizer all /path/to/video.mp4 /path/to/output_directory`
69
+ `abrizer all -i /path/to/video.mp4 -o /path/to/output_directory -u http://localhost:8088/v`
56
70
 
57
71
  Or just create various adaptations needed for repackaging to DASH and HLS:
58
- `abrizer process /path/to/video.mp4 /path/to/output_directory`
72
+ `abrizer process -i /path/to/video.mp4 -o /path/to/output_directory`
59
73
 
60
74
  Then once `process` is run it is possible to do packaging to adaptive bitrate formats like DASH:
61
75
 
62
- `abrizer package dash /path/to/video.mp4 /path/to/output_directory`
76
+ `abrizer package dash -o /path/to/output_directory`
63
77
 
64
78
  The output for DASH will go in the `fmp4` directory as the fragmented MP4 can be used for both DASH (stream.mpd) and the latest HLS on iOS 10+ (master.m3u8).
65
79
 
66
80
  HLS with MPEG-2 TS files can also be created after `process` is run with the output in the `hls` directory:
67
81
 
68
- `abrizer package hls /path/to/video.mp4 /path/to/output_directory`
82
+ `abrizer package hls -o /path/to/output_directory`
69
83
 
70
84
  ### Using as a Library
71
85
 
@@ -74,18 +88,15 @@ If you simply want to run all the steps, you can use the `Abrizer::All` class li
74
88
  ```ruby
75
89
  video_path = "/path/to/video.mp4"
76
90
  output_directory = "/path/to/output_directory"
77
- Abrizer::All.new(video_path, output_directory).run
91
+ base_url = "http://localhost:8088/v"
92
+ Abrizer::All.new(video_path, output_directory, base_url).run
78
93
  ```
79
94
 
80
95
  Take a look at `lib/abrizer/all.rb` for how to use the various classes provided. You can also see more examples in `lib/abrizer/cli.rb`. All classes expect to be passed the fully expanded path.
81
96
 
82
- ### Canvas
83
-
84
- Experimental support is provided for creating a IIIF Canvas. Note that this work is done in advance of a draft standard for including video in a IIIF manifest. It can be created after other steps with `abrizer help canvas` for more information.
85
-
86
97
  ## Development
87
98
 
88
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
99
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests (when there are tests!). You can also run `bin/console` for an interactive prompt that will allow you to experiment.
89
100
 
90
101
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
91
102
 
@@ -97,7 +108,9 @@ This includes a web server that can be used for local testing of streams and vid
97
108
 
98
109
  ```shell
99
110
  cd /vagrant
100
- bundle exec exe/abrizer all test/videos/FullHDCinemaCountdown720p-8sec.mp4 tmp/countdown http://localhost:8088/v
111
+ bundle exec exe/abrizer all \
112
+ -i test/videos/FullHDCinemaCountdown720p-8sec.mp4 \
113
+ -o tmp/countdown -u http://localhost:8088/v
101
114
  ```
102
115
 
103
116
  Now visit http://localhost:8088/v/countdown/ to see the files that were created. You can then test any of the videos or streams.
data/lib/abrizer.rb CHANGED
@@ -2,37 +2,43 @@ require 'yajl'
2
2
  require 'multi_json'
3
3
  MultiJson.use :yajl
4
4
  MultiJson.dump_options = {pretty: true}
5
+
5
6
  require 'jbuilder'
6
7
  require 'video_sprites'
7
8
  require 'ostruct'
8
- require "abrizer/version"
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'
14
- require 'abrizer/package_dash_shaka'
15
- require 'abrizer/package_hls_shaka'
16
- require 'abrizer/package_dash_bento'
17
- require 'abrizer/package_hls_bento'
18
- require 'abrizer/adaptation'
19
- require 'abrizer/adaptation_finder'
20
- require 'abrizer/adaptations_file'
21
- require 'abrizer/ffmpeg_processor'
22
- require 'abrizer/ffprobe_informer'
23
- require 'abrizer/ffprobe_file'
24
- require 'abrizer/processor'
25
- require 'abrizer/cleaner'
26
- require 'abrizer/progressive_mp4'
27
- require 'abrizer/progressive_vp9'
28
- require 'abrizer/progressive_mp3'
29
- require 'abrizer/sprites'
30
- require 'abrizer/captions'
31
- require 'abrizer/canvas'
32
- require 'abrizer/data'
33
- require 'abrizer/temporary_poster'
34
- require 'abrizer/all'
35
9
 
10
+ %w[
11
+ version
12
+ errors
13
+ filepath_helpers
14
+ read_adaptations
15
+ debug_settings
16
+ identifier_helpers
17
+ information_helpers
18
+ package_dash_shaka
19
+ package_hls_shaka
20
+ package_dash_bento
21
+ package_hls_bento
22
+ adaptation
23
+ adaptation_finder
24
+ adaptations_file
25
+ ffmpeg_processor
26
+ ffprobe_informer
27
+ ffprobe_file
28
+ processor
29
+ cleaner
30
+ progressive_mp4
31
+ progressive_vp9
32
+ progressive_mp3
33
+ sprites
34
+ captions
35
+ canvas
36
+ data
37
+ temporary_poster
38
+ all
39
+ ].each do |dependency|
40
+ require "abrizer/#{dependency}"
41
+ end
36
42
 
37
43
 
38
44
  module Abrizer
@@ -19,7 +19,7 @@ module Abrizer
19
19
  -an -c:v libx264 -x264opts 'keyint=48:min-keyint=48:no-scenecut' \
20
20
  -b:v #{bitrate}k -preset faster -pix_fmt yuv420p |
21
21
  if pass == 2
22
- cmd += %Q| -maxrate #{constrained_bitrate}k -bufsize #{bitrate}k -pass 2 #{filepath(input, output_directory)} |
22
+ cmd += %Q| -maxrate #{constrained_bitrate}k -bufsize #{bitrate}k -pass 2 #{filepath(output_directory)} |
23
23
  else
24
24
  cmd += " -pass 1 -f mp4 /dev/null "
25
25
  end
@@ -31,19 +31,17 @@ module Abrizer
31
31
  @bitrate * 1.1
32
32
  end
33
33
 
34
- def outfile_basename(input)
35
- extname = File.extname input
36
- basename = File.basename input, extname
37
- "#{basename}-#{width}x#{height}-#{bitrate}"
34
+ def outfile_basename
35
+ "adaptation-#{width}x#{height}-#{bitrate}"
38
36
  end
39
37
 
40
- def filepath(input, output_directory)
41
- name = "#{outfile_basename(input)}.mp4"
38
+ def filepath(output_directory)
39
+ name = "#{outfile_basename}.mp4"
42
40
  File.join output_directory, name
43
41
  end
44
42
 
45
- def filepath_fragmented(input, output_directory)
46
- name = "#{outfile_basename(input)}-frag.mp4"
43
+ def filepath_fragmented(output_directory)
44
+ name = "#{outfile_basename}-frag.mp4"
47
45
  File.join output_directory, name
48
46
  end
49
47
 
@@ -11,9 +11,10 @@ module Abrizer
11
11
  # through our workflow, so there might be some missing.
12
12
  class AdaptationFinder
13
13
  attr_reader :adaptations, :info
14
- def initialize(filename)
15
- @filename = filename
16
- @informer = Abrizer::FfprobeInformer.new(filename)
14
+ def initialize(filepath: nil, output_directory: nil)
15
+ # TODO: raise an error if both filepath and output_directory
16
+ # are both nil.
17
+ @informer = Abrizer::FfprobeInformer.new(filepath: filepath, output_directory: output_directory)
17
18
  find_adaptations
18
19
  end
19
20
 
@@ -32,7 +33,7 @@ module Abrizer
32
33
  @adaptations = adaptations.select{|adaptation| adaptation.width <= @informer.width}
33
34
  end
34
35
 
35
- # The bitrates here are based on H.264 encoding.
36
+ # The bitrates here are based on H.264 encoding.
36
37
  def ar_4_3_adaptations
37
38
  [
38
39
  {width: 224, height: 168, bitrate: 200},
@@ -6,10 +6,11 @@ module Abrizer
6
6
  def initialize(filepath, output_directory)
7
7
  @filepath = filepath
8
8
  @output_directory = output_directory
9
+ FileUtils.mkdir_p @output_directory unless File.exist? @output_directory
9
10
  end
10
11
 
11
12
  def adaptations
12
- adapt = Abrizer::AdaptationFinder.new(@filepath).adaptations
13
+ adapt = Abrizer::AdaptationFinder.new(filepath: @filepath, output_directory: @output_directory).adaptations
13
14
  adapt_dump = adapt.map{|a| a.to_hash}
14
15
  File.open(adaptations_filepath, 'w') do |fh|
15
16
  fh.puts MultiJson.dump(adapt_dump)
data/lib/abrizer/all.rb CHANGED
@@ -1,28 +1,29 @@
1
1
  module Abrizer
2
2
  class All
3
3
 
4
- def initialize(filename, output_dir, base_url)
4
+ def initialize(filename, output_dir, base_url, vp9=false)
5
5
  @filename = filename
6
6
  @output_directory = output_dir
7
7
  FileUtils.mkdir_p @output_directory
8
8
  @base_url = base_url
9
+ @vp9 = vp9
9
10
  end
10
11
 
11
12
  def run
12
13
  Abrizer::FfprobeFile.new(@filename, @output_directory).run
13
- Abrizer::AdaptationsFile.new(@filename, @output_directory).adaptations
14
- Abrizer::Processor.process(@filename, @output_directory)
15
- Abrizer::ProgressiveMp4.new(@filename, @output_directory).create
16
- # Abrizer::ProgressiveVp9.new(@filename, @output_directory).create
17
- Abrizer::ProgressiveMp3.new(@filename, @output_directory).create
18
- Abrizer::PackageDashBento.new(@filename, @output_directory).package
19
- Abrizer::PackageHlsBento.new(@filename, @output_directory).package
14
+ Abrizer::AdaptationsFile.new(nil, @output_directory).adaptations
20
15
  Abrizer::Captions.new(@filename, @output_directory).copy
16
+ Abrizer::ProgressiveVp9.new(@filename, @output_directory).create if @vp9
17
+ Abrizer::ProgressiveMp3.new(@filename, @output_directory).create
21
18
  Abrizer::Sprites.new(@filename, @output_directory).create
22
19
  Abrizer::TemporaryPoster.new(@output_directory).copy
23
- Abrizer::Canvas.new(@filename, @output_directory, @base_url).create
24
- Abrizer::Data.new(@filename, @output_directory, @base_url).create
25
- Abrizer::Cleaner.new(@filename, @output_directory).clean
20
+ Abrizer::Processor.process(@filename, @output_directory)
21
+ Abrizer::ProgressiveMp4.new(@output_directory).create
22
+ Abrizer::PackageDashBento.new(@output_directory).package
23
+ Abrizer::PackageHlsBento.new(@output_directory).package
24
+ Abrizer::Canvas.new(@output_directory, @base_url).create
25
+ Abrizer::Data.new(@output_directory, @base_url).create
26
+ Abrizer::Cleaner.new(@output_directory).clean
26
27
  end
27
28
 
28
29
  end
@@ -5,20 +5,17 @@ module Abrizer
5
5
  include FilepathHelpers
6
6
  include IdentifierHelpers
7
7
  include InformationHelpers
8
- include ReadAdaptations
8
+ include ReadAdaptations
9
9
 
10
10
  # TODO: allow control of items/versions listed on canvas
11
- def initialize(filepath, output_directory, base_url)
12
- @filepath = filepath
11
+ def initialize(output_directory, base_url)
13
12
  @output_directory = output_directory
13
+ FileUtils.mkdir_p output_directory unless File.exist? output_directory
14
14
  @base_url = base_url
15
- # finder = AdaptationFinder.new(@filename)
16
- # @adaptations = finder.adaptations
17
15
  read_adaptations
18
16
  end
19
17
 
20
18
  def create
21
- FileUtils.mkdir_p output_directory unless File.exist? output_directory
22
19
  File.open(canvas_filepath, 'w') do |fh|
23
20
  fh.puts create_json
24
21
  end
@@ -33,7 +30,7 @@ module Abrizer
33
30
  json.height max_height
34
31
  json.duration duration
35
32
  thumbnail_json(json)
36
- media_json(json)
33
+ media_json(json) if media_content?
37
34
  end
38
35
  end
39
36
 
@@ -47,6 +44,10 @@ module Abrizer
47
44
  end
48
45
  end
49
46
 
47
+ def media_content?
48
+ all_media_paths.any? { |f| File.exist? f }
49
+ end
50
+
50
51
  def media_json(json)
51
52
  json.content do
52
53
  json.child! do
@@ -1,8 +1,7 @@
1
1
  module Abrizer
2
2
  # Copies over any WebVTT captions that are beside the original video resource
3
3
  # into the destination folder.
4
- # TODO: This may only be needed if fMP4 derivatives aren't created since
5
- # captions are copied over.
4
+ # TODO: This may only be needed if fMP4 derivatives aren't created since captions are copied over.
6
5
  # TODO: Allow for more than one captions/subtitle file to be copied over.
7
6
  class Captions
8
7
 
@@ -3,10 +3,9 @@ module Abrizer
3
3
 
4
4
  include FilepathHelpers
5
5
 
6
- def initialize(filename, output_dir=nil)
7
- @filename = filename
6
+ def initialize(output_dir)
8
7
  @output_directory = output_dir
9
- @adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
8
+ @adaptations = Abrizer::AdaptationFinder.new(output_directory: @output_directory).adaptations
10
9
  end
11
10
 
12
11
  def clean
@@ -17,7 +16,7 @@ module Abrizer
17
16
 
18
17
  def delete_adaptations(adapts)
19
18
  adapts.map do |adaptation|
20
- filepath = adaptation.filepath_fragmented(@filename, output_directory)
19
+ filepath = adaptation.filepath_fragmented(output_directory)
21
20
  FileUtils.rm filepath if File.exist? filepath
22
21
  end
23
22
  end
data/lib/abrizer/cli.rb CHANGED
@@ -7,125 +7,180 @@ end
7
7
  module Abrizer
8
8
  class CLI < Thor
9
9
 
10
- desc 'all <filepath> <output_directory> <base_url>', 'Run all processes including creating ABR streams, progressive download versions, and images and video sprites.'
11
- def all(filepath, output_dir, base_url)
12
- filepath = File.expand_path filepath
13
- output_dir = File.expand_path output_dir
14
- Abrizer::All.new(filepath, output_dir, base_url).run
15
- end
10
+ # Adapted from http://stackoverflow.com/a/24829698/620065
11
+ # Add a name for the option that allows for more variability
12
+ class << self
13
+ def add_shared_option(name, option_name, options = {})
14
+ @shared_options = {} if @shared_options.nil?
15
+ @shared_options[name] = [option_name, options]
16
+ end
16
17
 
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
18
+ def shared_options(*names)
19
+ names.each do |name|
20
+ opt = @shared_options[name]
21
+ raise "Tried to access shared option '#{option_name}' but it was not previously defined" if opt.nil?
22
+ method_option *opt
23
+ end
24
+ end
23
25
 
24
- desc 'abr <filepath> <output_directory>', 'From file create ABR streams, includes processing MP4 adaptations for packaging'
25
- def abr(filepath, output_dir=nil)
26
- filepath = File.expand_path filepath
27
- output_dir = File.expand_path output_dir
28
- Abrizer::Processor.process(filepath, output_dir)
29
- Abrizer::PackageDashBento.new(filepath, output_dir).package
30
- Abrizer::PackageHlsBento.new(filepath, output_dir).package
26
+ def input_banner
27
+ 'INPUT_FILEPATH'
28
+ end
29
+
30
+ def input_desc
31
+ 'Full or relative path to a mezzanine video file.'
32
+ end
31
33
  end
32
34
 
33
- desc 'process <filepath> <output_directory>', 'From mezzanine or preservation file create intermediary adaptations'
34
- def process(filepath, output_dir=nil)
35
- filepath = File.expand_path filepath
36
- output_dir = File.expand_path output_dir
37
- Abrizer::Processor.process(filepath, output_dir)
35
+ no_commands do
36
+ def expand_path(path)
37
+ File.expand_path path if path
38
+ end
38
39
  end
39
40
 
40
- desc 'mp4 <filepath> <output_directory>', 'Create a single progressive download version as an MP4 from the next to largest adaptation and audio. The adaptation and audio file must already exist.'
41
- def mp4(filepath, output_dir=nil)
42
- filepath = File.expand_path filepath
43
- output_dir = File.expand_path output_dir
44
- Abrizer::ProgressiveMp4.new(filepath, output_dir).create
41
+ add_shared_option :input_required, :input, aliases: '-i', type: :string, required: true, banner: input_banner, desc: input_desc + ' Input file must be present.'
42
+ add_shared_option :input_optional, :input, aliases: '-i', type: :string, required: false, banner: input_banner, desc: input_desc + ' May be used without an input file as long as preconditions are met.'
43
+ add_shared_option :output, :output, aliases: '-o', type: :string, required: true, banner: 'OUTPUT_DIRECTORY', desc: 'Full or relative path to output directory for '
44
+ add_shared_option :url, :url, aliases: '-u', type: :string, required: true, banner: 'BASE_URL', desc: 'Base URL to use in information files.'
45
+
46
+ desc 'all', 'Run all processes including creating ABR streams, progressive download version, and images and video sprites. Optionally create a VP9 progressive download version.'
47
+ shared_options :input_required, :output, :url
48
+ method_option :vp9, type: :boolean, default: false
49
+ def all
50
+ filepath = expand_path options[:input]
51
+ output_dir = expand_path options[:output]
52
+ Abrizer::All.new(filepath, output_dir, options[:url], options[:vp9]).run
45
53
  end
46
54
 
47
- desc 'vp9 <filepath> <output_directory>', 'Create a single VP9 progressive download version from the original video.'
48
- def vp9(filepath, output_dir=nil)
49
- filepath = File.expand_path filepath
50
- output_dir = File.expand_path output_dir
51
- Abrizer::ProgressiveVp9.new(filepath, output_dir).create
55
+ desc 'ffprobe', 'Save the output of ffprobe to a file as JSON'
56
+ shared_options :input_required, :output
57
+ def ffprobe
58
+ filepath = expand_path options[:input]
59
+ output_dir = expand_path options[:output]
60
+ Abrizer::FfprobeFile.new(filepath, output_dir).run
52
61
  end
53
62
 
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
63
+ desc 'adaptations', 'Output which adaptations will be created from input file to a JSON file and output to console'
64
+ shared_options :input_optional, :output
65
+ def adaptations
66
+ input = expand_path options[:input]
67
+ output = expand_path options[:output]
68
+ adaptations = Abrizer::AdaptationsFile.new(input, output).adaptations
57
69
  puts adaptations
58
70
  end
59
71
 
60
- desc 'inform <filepath>', 'Display information about the video/audio file'
61
- def inform(filepath)
62
- informer = FfprobeInformer.new(filepath)
72
+ desc 'inform', 'Display raw ffprobe information about the video/audio file'
73
+ shared_options :input_required
74
+ def inform
75
+ input = expand_path options[:input]
76
+ informer = FfprobeInformer.new(filepath: input)
63
77
  puts informer.json_result
64
78
  puts informer
65
79
  end
66
80
 
67
- desc 'package <dash_or_hls> <filepath> <output_directory>', "Package dash or hls from adaptations"
68
- def package(dash_or_hls, filepath, output_dir=nil)
69
- filepath = File.expand_path filepath
70
- output_dir = File.expand_path output_dir
71
- case dash_or_hls
72
- when "dash"
73
- Abrizer::PackageDashBento.new(filepath, output_dir).package
74
- when "hls"
75
- Abrizer::PackageHlsBento.new(filepath, output_dir).package
76
- when "all"
77
- Abrizer::PackageDashBento.new(filepath, output_dir).package
78
- Abrizer::PackageHlsBento.new(filepath, output_dir).package
79
- else
80
- puts "Not a valid packaging value. Try dash or hls."
81
- end
81
+ desc 'captions', 'Captions and subtitles files with the same basename as the video file and with a .vtt extension are copied over into the output directory'
82
+ # TODO: Make input optional if packaging includes a VTT file already.
83
+ shared_options :input_required, :output
84
+ def captions
85
+ filepath = expand_path options[:input]
86
+ output_dir = expand_path options[:output]
87
+ Abrizer::Captions.new(filepath, output_dir).copy
88
+ end
89
+
90
+ desc 'vp9', 'Create a single VP9 progressive download version from the original video.'
91
+ shared_options :input_required, :output
92
+ def vp9
93
+ filepath = expand_path options[:input]
94
+ output_dir = expand_path options[:output]
95
+ Abrizer::ProgressiveVp9.new(filepath, output_dir).create
82
96
  end
83
97
 
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
98
+ desc 'mp3', 'Create a progressive MP3 file from the audio of the original media'
99
+ shared_options :input_required, :output
100
+ def mp3
101
+ filepath = expand_path options[:input]
102
+ output_dir = expand_path options[:output]
90
103
  Abrizer::ProgressiveMp3.new(filepath, output_dir).create
91
104
  end
92
105
 
93
- desc 'sprites <filepath> <output_directory>', 'Create image sprites and metadata WebVTT file'
94
- def sprites(filepath, output_dir=nil)
95
- filepath = File.expand_path filepath
96
- output_dir = File.expand_path output_dir
106
+ desc 'sprites', 'Create image sprites and metadata WebVTT file'
107
+ shared_options :input_required, :output
108
+ def sprites
109
+ filepath = expand_path options[:input]
110
+ output_dir = expand_path options[:output]
97
111
  Abrizer::Sprites.new(filepath, output_dir).create
98
112
  end
99
113
 
100
- desc 'poster <output_directory>', 'Copy over a temporary poster image based on the sprite images'
101
- def poster(output_dir=nil)
102
- output_dir = File.expand_path output_dir
114
+ desc 'poster', 'Copy over a temporary poster image based on the sprite images'
115
+ shared_options :output
116
+ def poster
117
+ output_dir = expand_path options[:output]
103
118
  Abrizer::TemporaryPoster.new(output_dir).copy
104
119
  end
105
120
 
106
- desc 'captions <filepath> <output_directory>', 'Captions and subtitles files with the same basename as the video file and with a .vtt extension are copied over into the output directory'
107
- def captions(filepath, output_dir=nil)
108
- filepath = File.expand_path filepath
109
- output_dir = File.expand_path output_dir
110
- Abrizer::Captions.new(filepath, output_dir).copy
121
+ desc 'abr', 'From file create ABR streams, includes processing various fragmented MP4 adaptations for packaging first.'
122
+ shared_options :input_required, :output
123
+ def abr
124
+ filepath = expand_path options[:input]
125
+ output_dir = expand_path options[:output]
126
+ Abrizer::Processor.process(filepath, output_dir)
127
+ Abrizer::PackageDashBento.new(filepath, output_dir).package
128
+ Abrizer::PackageHlsBento.new(filepath, output_dir).package
129
+ end
130
+
131
+ desc 'process', 'From mezzanine or preservation file create intermediary adaptations'
132
+ shared_options :input_required, :output
133
+ def process
134
+ filepath = expand_path options[:input]
135
+ output_dir = expand_path options[:output]
136
+ Abrizer::Processor.process(filepath, output_dir)
137
+ end
138
+
139
+ desc 'mp4', 'Create a single progressive download version as an MP4 from the next to largest adaptation and audio. The adaptation and audio file must already exist.'
140
+ shared_options :output
141
+ def mp4
142
+ output_dir = expand_path options[:output]
143
+ Abrizer::ProgressiveMp4.new(output_dir).create
144
+ end
145
+
146
+ desc 'package <dash_or_hls>', "Package dash or hls from adaptations. Fragmented files, adaptions.json, and ffprobe.json must be present."
147
+ shared_options :output
148
+ def package(dash_or_hls)
149
+ output_dir = expand_path options[:output]
150
+ case dash_or_hls
151
+ when "dash"
152
+ Abrizer::PackageDashBento.new(output_dir).package
153
+ when "hls"
154
+ Abrizer::PackageHlsBento.new(output_dir).package
155
+ when "all"
156
+ Abrizer::PackageDashBento.new(output_dir).package
157
+ Abrizer::PackageHlsBento.new(output_dir).package
158
+ else
159
+ puts "Not a valid packaging value. Try dash or hls."
160
+ end
111
161
  end
112
162
 
113
- desc 'canvas <filepath_or_identifier> <output_directory> <base_url>', 'Creates a IIIF Canvas JSON-LD document as an API into the resources'
114
- def canvas(filepath, output_directory, base_url)
115
- filepath = File.expand_path filepath
116
- output_directory = File.expand_path output_directory
117
- Abrizer::Canvas.new(filepath, output_directory, base_url).create
163
+ desc 'canvas', 'Creates a IIIF Canvas JSON-LD document as an API into the resources'
164
+ shared_options :input_optional, :output, :url
165
+ def canvas
166
+ filepath = expand_path options[:input]
167
+ output_directory = expand_path options[:output]
168
+ Abrizer::Canvas.new(filepath, output_directory, options[:url]).create
118
169
  end
119
170
 
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
171
+ desc 'data', 'Creates a JSON file with data about the video resources.'
172
+ shared_options :input_optional, :output, :url
173
+ def data
174
+ filepath = expand_path options[:input]
175
+ output_directory = expand_path options[:output]
176
+ Abrizer::Data.new(filepath, output_directory, options[:url]).create
124
177
  end
125
178
 
126
- desc 'clean <filepath> <output_directory>', 'Clean up intermediary files'
127
- def clean(filepath, output_dir=nil)
128
- Abrizer::Cleaner.new(filepath, output_dir).clean
179
+ desc 'clean', 'Clean up intermediary files'
180
+ shared_options :output
181
+ def clean
182
+ output_dir = expand_path options[:output]
183
+ Abrizer::Cleaner.new(output_dir).clean
129
184
  end
130
185
  end
131
186
  end
data/lib/abrizer/data.rb CHANGED
@@ -7,23 +7,12 @@ module Abrizer
7
7
  include InformationHelpers
8
8
  include ReadAdaptations
9
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
10
+ def initialize(output_directory, base_url)
14
11
  @output_directory = output_directory
15
12
  @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
13
  read_adaptations
20
14
  end
21
15
 
22
- def find_adaptations
23
- finder = AdaptationFinder.new(@filename)
24
- @adaptations = finder.adaptations
25
- end
26
-
27
16
  def create
28
17
  FileUtils.mkdir_p output_directory unless File.exist? output_directory
29
18
  File.open(data_filepath, 'w') do |fh|
@@ -0,0 +1,25 @@
1
+ module Abrizer
2
+
3
+ # This error is raised if Abrizer::ReadAdaptations is unable to determine
4
+ # the adaptations that have or will be created for a given mezzanine file.
5
+ class ReadAdaptationsError < StandardError
6
+ def initialize
7
+ msg = "Unable to read adaptations. Either inlude the path to a master file or an identifier. If passing just the identifier you must have created an adaptations.json file to read in or as a final fallback have already created a VP9 derivative."
8
+ super(msg)
9
+ end
10
+ end
11
+
12
+ class FfprobeError < StandardError
13
+ def initialize
14
+ msg = "Unable to find file to run ffprobe on or unable to read in ffprobe.json file."
15
+ super(msg)
16
+ end
17
+ end
18
+
19
+ class Mp4AdaptationNotFoundError < StandardError
20
+ def initialize
21
+ msg = "The fragmented adaptation used to create the progressive MP4 access derivative was not found. You must run `process` before this."
22
+ end
23
+ end
24
+
25
+ end
@@ -5,10 +5,10 @@ module Abrizer
5
5
  include FilepathHelpers
6
6
  include DebugSettings
7
7
 
8
- def initialize(filename, output_dir=nil)
8
+ def initialize(filename, output_dir)
9
9
  @filename = filename
10
10
  @output_directory = output_dir
11
- @adaptation_finder = Abrizer::AdaptationFinder.new(@filename)
11
+ @adaptation_finder = Abrizer::AdaptationFinder.new(filepath: @filename)
12
12
  end
13
13
 
14
14
  def process
@@ -24,7 +24,7 @@ module Abrizer
24
24
  end
25
25
 
26
26
  def first_pass_adaptation
27
- adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
27
+ adaptations = Abrizer::AdaptationFinder.new(filepath: @filename).adaptations
28
28
  sorted = adaptations.sort_by do |adaptation|
29
29
  adaptation.width
30
30
  end
@@ -46,8 +46,8 @@ module Abrizer
46
46
  cmd = adaptation.ffmpeg_cmd(@filename, output_directory, 2)
47
47
  puts cmd
48
48
  `#{cmd}`
49
- `mp4fragment #{adaptation.filepath(@filename, output_directory)} #{adaptation.filepath_fragmented(@filename, output_directory)}`
50
- FileUtils.rm adaptation.filepath(@filename, output_directory)
49
+ `mp4fragment #{adaptation.filepath(output_directory)} #{adaptation.filepath_fragmented(output_directory)}`
50
+ FileUtils.rm adaptation.filepath(output_directory)
51
51
  end
52
52
  end
53
53
 
@@ -4,13 +4,14 @@ module Abrizer
4
4
  include FilepathHelpers
5
5
 
6
6
  def initialize(filename, output_directory)
7
- @informer = FfprobeInformer.new(filename)
7
+ @informer = FfprobeInformer.new(filepath: filename)
8
8
  @output_directory = output_directory
9
+ FileUtils.mkdir_p @output_directory unless File.exist? @output_directory
9
10
  end
10
11
 
11
12
  def run
12
13
  File.open(ffprobe_filepath, 'w') do |fh|
13
- fh.puts @informer.json_result
14
+ fh.puts @informer.to_json
14
15
  end
15
16
  end
16
17
  end
@@ -1,12 +1,31 @@
1
1
  module Abrizer
2
2
  class FfprobeInformer
3
+
4
+ include FilepathHelpers
5
+
3
6
  attr_reader :json_result, :info
4
- def initialize(filename)
5
- @filename = filename
7
+ def initialize(filepath: nil, output_directory: nil)
8
+ @filepath = filepath
9
+ @output_directory = output_directory
6
10
  get_info
7
11
  end
8
12
 
9
13
  def get_info
14
+ if @filepath && File.exist?(@filepath) && !File.directory?(@filepath)
15
+ get_info_with_command
16
+ elsif @output_directory && File.exist?(ffprobe_filepath)
17
+ get_info_from_file
18
+ else
19
+ raise FfprobeError
20
+ end
21
+ end
22
+
23
+ def get_info_from_file
24
+ @json_result = File.read ffprobe_filepath
25
+ @info = MultiJson.load @json_result
26
+ end
27
+
28
+ def get_info_with_command
10
29
  @json_result = `#{ffmpeg_info_cmd}`
11
30
  @info = MultiJson.load @json_result
12
31
  end
@@ -20,7 +39,11 @@ module Abrizer
20
39
  end
21
40
 
22
41
  def duration
23
- video_stream['duration'] if video_stream
42
+ if probe_format && probe_format['duration']
43
+ probe_format['duration']
44
+ elsif video_stream && video_stream['duration']
45
+ video_stream['duration']
46
+ end
24
47
  end
25
48
 
26
49
  def display_aspect_ratio #dar
@@ -54,6 +77,10 @@ module Abrizer
54
77
  end
55
78
  end
56
79
 
80
+ def probe_format
81
+ @info['format']
82
+ end
83
+
57
84
  def audio_stream
58
85
  @info['streams'].find do |stream|
59
86
  stream['codec_type'] == 'audio'
@@ -61,7 +88,7 @@ module Abrizer
61
88
  end
62
89
 
63
90
  def ffmpeg_info_cmd
64
- "ffprobe -v error -print_format json -show_format -show_streams #{@filename}"
91
+ "ffprobe -v error -print_format json -show_format -show_streams #{@filepath}"
65
92
  end
66
93
 
67
94
  def to_s
@@ -69,5 +96,13 @@ module Abrizer
69
96
  "#{width}x#{height} DAR:#{display_aspect_ratio}"
70
97
  end
71
98
 
99
+ def to_json
100
+ information = @info
101
+ info_filename = information['format']['filename']
102
+ truncated_filename = File.basename info_filename
103
+ information['format']['filename'] = truncated_filename
104
+ MultiJson.dump information
105
+ end
106
+
72
107
  end
73
108
  end
@@ -1,23 +1,30 @@
1
1
  module Abrizer
2
2
  module FilepathHelpers
3
+
4
+ def all_media_paths
5
+ [mpd_filepath, hlsts_filepath, vp9_filepath, mp4_filepath, captions_filepath, sprites_filepath]
6
+ end
7
+
3
8
  def audio_filepath
4
- File.join output_directory, "#{basename}-audio.m4a"
9
+ File.join output_directory, "adaptation-audio.m4a"
5
10
  end
6
11
 
7
12
  def audio_filepath_fragmented
8
- File.join output_directory, "#{basename}-audio-frag.m4a"
13
+ File.join output_directory, "adaptation-audio-frag.m4a"
9
14
  end
10
15
 
16
+ # TODO: webvtt_input_filepath should look multiple places in case vtt
17
+ # file(s) already copied over.
11
18
  def webvtt_input_filepath
12
- File.join filename_directory, "#{basename}.vtt"
19
+ File.join filename_directory, "#{basename}.vtt" if @filename
13
20
  end
14
21
 
15
22
  def output_directory
16
- if @output_directory
23
+ # if @output_directory
17
24
  @output_directory
18
- else
19
- File.join filename_directory, basename
20
- end
25
+ # else
26
+ # File.join filename_directory, basename
27
+ # end
21
28
  end
22
29
 
23
30
  def output_directory_basename
@@ -1,8 +1,10 @@
1
1
  module Abrizer
2
2
  module InformationHelpers
3
3
 
4
+ # TODO: Could this be more flexible to potentially use a file
5
+ # other than the mp4_filepath?
4
6
  def duration
5
- informer = Abrizer::FfprobeInformer.new(mp4_filepath)
7
+ informer = Abrizer::FfprobeInformer.new(filepath: mp4_filepath, output_directory: @output_directory)
6
8
  informer.duration.to_f
7
9
  end
8
10
 
@@ -3,10 +3,9 @@ module Abrizer
3
3
 
4
4
  include FilepathHelpers
5
5
 
6
- def initialize(filename, output_dir=nil)
7
- @filename = filename
6
+ def initialize(output_dir)
8
7
  @output_directory = output_dir
9
- @adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
8
+ @adaptations = Abrizer::AdaptationFinder.new(output_directory: @output_directory).adaptations
10
9
  end
11
10
 
12
11
  def package
@@ -17,13 +16,13 @@ module Abrizer
17
16
 
18
17
  def video_inputs
19
18
  @adaptations.map do |adaptation|
20
- adaptation.filepath_fragmented(@filename, output_directory)
19
+ adaptation.filepath_fragmented(output_directory)
21
20
  end
22
21
  end
23
22
 
24
23
  def bento_cmd
25
24
  cmd = %Q|mp4dash --output-dir=fmp4 --force --use-segment-template-number-padding --profiles=live --hls |
26
- if File.exist? webvtt_input_filepath
25
+ if webvtt_input_filepath && File.exist?(webvtt_input_filepath)
27
26
  cmd += %Q| [+format=webvtt,+language=eng]#{webvtt_input_filepath} |
28
27
  end
29
28
  cmd += %Q| #{video_inputs.join(' ')} [+language=eng]#{audio_filepath_fragmented} |
@@ -5,7 +5,7 @@ module Abrizer
5
5
 
6
6
  def initialize(filename, output_dir=nil)
7
7
  @filename = filename
8
- @adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
8
+ @adaptations = Abrizer::AdaptationFinder.new(filepath: @filename).adaptations
9
9
  end
10
10
 
11
11
  def package
@@ -3,10 +3,9 @@ module Abrizer
3
3
 
4
4
  include FilepathHelpers
5
5
 
6
- def initialize(filename, output_dir=nil)
7
- @filename = filename
6
+ def initialize(output_dir)
8
7
  @output_directory = output_dir
9
- @adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
8
+ @adaptations = Abrizer::AdaptationFinder.new(output_directory: @output_directory).adaptations
10
9
  end
11
10
 
12
11
  def package
@@ -17,13 +16,13 @@ module Abrizer
17
16
 
18
17
  def video_inputs
19
18
  @adaptations.map do |adaptation|
20
- adaptation.filepath_fragmented(@filename, output_directory)
19
+ adaptation.filepath_fragmented(output_directory)
21
20
  end
22
21
  end
23
22
 
24
23
  def bento_cmd
25
24
  cmd = %Q|mp4hls --output-dir=hls --force --output-single-file |
26
- if File.exist? webvtt_input_filepath
25
+ if webvtt_input_filepath && File.exist?(webvtt_input_filepath)
27
26
  cmd += %Q| [+format=webvtt,+language=eng]#{webvtt_input_filepath} |
28
27
  end
29
28
  cmd += %Q| #{video_inputs.join(' ')} [+language=eng]#{audio_filepath_fragmented} |
@@ -5,7 +5,7 @@ module Abrizer
5
5
 
6
6
  def initialize(filename, output_dir=nil)
7
7
  @filename = filename
8
- @adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
8
+ @adaptations = Abrizer::AdaptationFinder.new(filepath: @filename).adaptations
9
9
  end
10
10
 
11
11
  def package
@@ -1,4 +1,5 @@
1
1
  module Abrizer
2
+ # TODO: Allow MP3 to be created from the adaptation audio
2
3
  class ProgressiveMp3
3
4
 
4
5
  include FilepathHelpers
@@ -3,18 +3,21 @@ module Abrizer
3
3
 
4
4
  include FilepathHelpers
5
5
 
6
- def initialize(filename, output_dir=nil)
7
- @filename = filename
6
+ def initialize(output_dir)
8
7
  @output_directory = output_dir
9
8
  find_adaptation
10
9
  end
11
10
 
12
11
  def create
13
- `#{ffmpeg_cmd}`
12
+ if File.exist? input_video_filepath
13
+ `#{ffmpeg_cmd}`
14
+ else
15
+ raise Mp4AdaptationNotFoundError
16
+ end
14
17
  end
15
18
 
16
19
  def find_adaptation
17
- adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
20
+ adaptations = Abrizer::AdaptationFinder.new(output_directory: @output_directory).adaptations
18
21
  sorted = adaptations.sort_by do |adaptation|
19
22
  adaptation.width
20
23
  end
@@ -22,7 +25,7 @@ module Abrizer
22
25
  end
23
26
 
24
27
  def input_video_filepath
25
- @adaptation.filepath_fragmented(@filename, output_directory)
28
+ @adaptation.filepath_fragmented(@output_directory)
26
29
  end
27
30
 
28
31
  def ffmpeg_cmd
@@ -22,7 +22,7 @@ module Abrizer
22
22
  end
23
23
 
24
24
  def find_adaptation
25
- adaptations = Abrizer::AdaptationFinder.new(@filename).adaptations
25
+ adaptations = Abrizer::AdaptationFinder.new(filepath: @filename).adaptations
26
26
  sorted = adaptations.sort_by do |adaptation|
27
27
  adaptation.width
28
28
  end
@@ -1,15 +1,13 @@
1
1
  module Abrizer
2
2
  module ReadAdaptations
3
3
 
4
-
5
-
6
4
  def read_adaptations
7
5
  # Either we have a filepath to an original or we make the assumption we
8
6
  # really have an identifier instead of a filepath and we use that
9
7
  # identifier to look for an adaptations.json file. Failing finding the
10
8
  # adaptations.json file we just use the adaptations based on the
11
9
  # vp9_filepath.
12
- if File.exist?(File.expand_path(@filepath)) && !File.directory?(@filepath)
10
+ if @filepath && File.exist?(@filepath) && !File.directory?(@filepath)
13
11
  @filename = @filepath
14
12
  find_adaptations
15
13
  elsif File.exist? adaptations_filepath
@@ -27,8 +25,14 @@ module Abrizer
27
25
  @filename = vp9_filepath
28
26
  find_adaptations
29
27
  else
30
- raise "Neither original file or VP9 version exist."
28
+ raise ReadAdaptationsError
31
29
  end
32
30
  end
31
+
32
+ def find_adaptations
33
+ finder = AdaptationFinder.new(filepath: @filename)
34
+ @adaptations = finder.adaptations
35
+ end
36
+
33
37
  end
34
38
  end
@@ -1,3 +1,3 @@
1
1
  module Abrizer
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
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.4.0
4
+ version: 0.5.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-03-30 00:00:00.000000000 Z
11
+ date: 2017-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -213,6 +213,7 @@ files:
213
213
  - lib/abrizer/cli.rb
214
214
  - lib/abrizer/data.rb
215
215
  - lib/abrizer/debug_settings.rb
216
+ - lib/abrizer/errors.rb
216
217
  - lib/abrizer/ffmpeg_processor.rb
217
218
  - lib/abrizer/ffprobe_file.rb
218
219
  - lib/abrizer/ffprobe_informer.rb