cutcut 1.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 75111491536a777f1518aa51a025c2bb87356ef9
4
+ data.tar.gz: 70b2fc148ed07dd389e27c39e68f0d8d1e0fedab
5
+ SHA512:
6
+ metadata.gz: 4ac1b04f0962ae62ddca62be5cce326a5c8de92500cc842244ae7c760ade07494aae97dcb582202ec76eb5422b72a834dd68b91cbe43d2449e5fcc29162dc037
7
+ data.tar.gz: 539a48f89ff804c4372005a62e41b9e2e2a5eb5d6752f508415d51cf8bd66a1887005eb0736f272a8f578b8aade8cf97f4b8dd950bbabbbd537297b460531307
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *~
2
+ coverage/*
3
+ *.sqlite3
4
+ .bundle
5
+ rdoc/*
6
+ pkg
7
+ log
8
+ test/tmp/*
9
+ spec/tmp/*
10
+ spec/fixtures/*.MP4
11
+ spec/fixtures/*.jpg
12
+ spec/fixtures/*.png
13
+ dummy
14
+ *.gem
15
+ Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Metrics/LineLength:
2
+ Max: 500
data/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ Changelog
2
+ =========
3
+
4
+ Version 1.1.0 (March 17, 2016)
5
+ -----------------------------
6
+
7
+ * Add Timelapse support
8
+ * Add --copy-metadata option
9
+ * Add --scale option
10
+ * Add --timelapse-fps option
11
+
12
+ Version 1.0.0 (February 11, 2016)
13
+ -----------------------------
14
+
15
+ * Use hash options on initialize
16
+ * Add `speec` to convert method
17
+
18
+ Version 0.0.2 (February 8, 2016)
19
+ -----------------------------
20
+
21
+ * Remove Gemfile.lock
22
+ * Add basename and fps to extract_screenshots
23
+ * Add `media.cut`
24
+
25
+ Version 0.0.1 (February 5, 2016)
26
+ -----------------------------
27
+
28
+ * Add Media model
29
+ * Add convert media action
30
+ * Add extract_screenshot action
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,17 @@
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ require 'guard/rspec/dsl'
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ rspec = dsl.rspec
6
+ watch(rspec.spec_helper) { rspec.spec_dir }
7
+ watch(rspec.spec_support) { rspec.spec_dir }
8
+ watch(rspec.spec_files)
9
+
10
+ ruby = dsl.ruby
11
+ dsl.watch_spec_files_for(ruby.lib_files)
12
+ end
13
+
14
+ guard :rubocop do
15
+ watch(/.+\.rb$/)
16
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
17
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Jhimy Fernandes Villar.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # cutcut
2
+
3
+ Trim/Cut/Screenshot videos
4
+
5
+ # Usage
6
+
7
+ ```
8
+ gem install cutcut git: git@github.com:stjhimy/cutcut.git
9
+ ```
10
+
11
+ ```ruby
12
+ media = CutCut::Media.new(input: 'path_to_file.mp4')
13
+ media.convert(scale: '1280:720')
14
+ media.convert(scale: '1280:720', copy_metadata: true)
15
+ media.extract_screenshots
16
+ media.cut(start: '00:00', time: 10)
17
+
18
+ timelapse = CutCut::Timelapse.new(input: 'path_to_folder')
19
+ media.convert(scale: '1280:720')
20
+ media.convert(scale: '1280:720', fps: 60)
21
+ ```
22
+
23
+ ```
24
+ cutcut --help
25
+ Usage: cutcut [options]
26
+ --convert Convert all videos in a folder
27
+ --copy-metadata Copy original video metadata
28
+ --scale SCALE_RESOLUTION
29
+ --timelapse-fps FPS Timelapse FPS
30
+ --extract-screenshots NUMBER Screenshots per second
31
+ ```
32
+
33
+ ## License
34
+
35
+ MIT License. Copyright 2016 Jhimy Fernandes Villar.
data/bin/cutcut ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cutcut'
4
+ require 'optparse'
5
+ require 'ruby-progressbar'
6
+
7
+ options = {}
8
+ OptionParser.new do |opt|
9
+ opt.on('--convert', 'Convert all videos in a folder') { options[:convert] = true }
10
+ opt.on('--copy-metadata', 'Copy original video metadata') { options[:copy_metadata] = true }
11
+ opt.on('--scale', 'SCALE_RESOLUTION') { |e| options[:scale] = e }
12
+ opt.on('--timelapse-fps FPS', 'Timelapse FPS') { |e| options[:timelapse_fps] = e }
13
+ opt.on('--extract-screenshots NUMBER', 'Screenshots per second') { |e| options[:extract_screenshots] = e }
14
+ end.parse!
15
+
16
+ pwd = ENV['PWD']
17
+ options[:input_dir] ||= pwd
18
+ options[:copy_metadata] ||= false
19
+
20
+ files = Dir[File.join(options[:input_dir], '/*.mp4')]
21
+ folders = Dir.glob(File.join(options[:input_dir], '/*')).select { |e| File.directory?(e) }
22
+ progressbar = ProgressBar.create(title: 'Converting', starting_at: 0, total: files.count + folders.count)
23
+
24
+ puts "#{files.count + folders.count} files found"
25
+
26
+ files.each do |file|
27
+ media = CutCut::Media.new(input: file)
28
+ scale = options[:scale] || '1920:1080'
29
+ media.convert(copy_metadata: options[:copy_metadata], scale: scale)
30
+ media.extract_screenshots(fps: options[:extract_screenshots], copy_metadata: true) if options[:extract_screenshots]
31
+ progressbar.increment
32
+ end
33
+
34
+ folders.each do |folder|
35
+ timelapse = CutCut::Timelapse.new(input: folder, output: File.join(options[:input_dir], File.basename(folder) + '.mp4'))
36
+ scale = options[:scale] || '1920:1080'
37
+ timelapse.convert(fps: options[:timelapse_fps] || 30, scale: scale)
38
+ progressbar.increment
39
+ end
40
+
41
+ puts "\n Finished!"
data/cutcut.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'cutcut'
3
+ s.authors = ['Jhimy Fernandes Villar']
4
+ s.email = ['stjhimy@gmail.com']
5
+ s.homepage = 'http://github.com/stjhimy/cutcut'
6
+ s.license = 'MIT'
7
+ s.summary = 'Trim/Cut/Screenshot videos'
8
+ s.description = 'CLI for working with videos'
9
+ s.version = '1.1.0'
10
+
11
+ s.executables = ['cutcut']
12
+ s.files = `git ls-files`.split("\n")
13
+ s.require_paths = ['lib']
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+
16
+ s.add_dependency 'activesupport', '~> 4.2'
17
+ s.add_dependency 'mini_exiftool', '~> 2.5'
18
+ s.add_dependency 'ruby-progressbar', '~> 1.7'
19
+
20
+ s.add_development_dependency 'guard', '~> 2.13'
21
+ s.add_development_dependency 'guard-rspec', '~> 4.6'
22
+ s.add_development_dependency 'guard-rubocop', '~> 1.2'
23
+ s.add_development_dependency 'rspec', '~> 3.4'
24
+ end
@@ -0,0 +1,26 @@
1
+ module CutCut
2
+ # Base
3
+ class Base
4
+ attr_reader :input, :output
5
+
6
+ def initialize(options = {})
7
+ @input = options.delete(:input)
8
+ @output = options.delete(:output)
9
+ end
10
+
11
+ def original_date_time
12
+ exif = MiniExiftool.new(@input)
13
+ exif.date_time_original || exif.create_date || exif.modify_date
14
+ end
15
+
16
+ private
17
+
18
+ def execute_ffmpeg_command(options = {})
19
+ system("ffmpeg #{options[:raw_options].try(:[], :input)} \
20
+ -i #{options.delete(:input) || @input} \
21
+ #{options[:raw_options].try(:[], :output)} \
22
+ #{options.delete(:output) || @output} \
23
+ -y > /dev/null 2>&1")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ module CutCut
2
+ # Helpers
3
+ class Helpers
4
+ def self.longest_common_substring(*strings)
5
+ short = strings.min_by(&:length)
6
+ max = short.length
7
+ max.downto(0) do |len|
8
+ 0.upto(max - len) do |start|
9
+ substr = short[start, len]
10
+ return substr if strings.all? { |str| str.include? substr }
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.copy_metadata(origin, target)
16
+ exif = MiniExiftool.new(target)
17
+ exif.copy_tags_from(origin, '*')
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,64 @@
1
+ module CutCut
2
+ # Media
3
+ class Media < Base
4
+ attr_reader :output_path
5
+
6
+ def initialize(options = {})
7
+ @input = options.delete(:input)
8
+ @output = options.delete(:output)
9
+ @output_path = options.delete(:output_path) || File.dirname(@input)
10
+ end
11
+
12
+ def convert(options = {})
13
+ scale = options[:scale]
14
+ speed = "-filter:v \"setpts=#{options[:speed]}*PTS\"" if options[:speed]
15
+ copy_metadata = options[:copy_metadata] || false
16
+
17
+ output = options[:output] || @output || File.join(@output_path, '__' + File.basename(@input))
18
+ raw_options = "-movflags +faststart -vf scale=#{scale} -c:v libx264 -crf 20 -preset ultrafast #{speed}"
19
+ execute_ffmpeg_command(input: @input, output: output, raw_options: { output: raw_options })
20
+
21
+ Helpers.copy_metadata(@input, output) if copy_metadata
22
+ output
23
+ end
24
+
25
+ def extract_screenshots(options = {})
26
+ fps = options[:fps] || 1
27
+ basename = options[:basename] || File.basename(@input, '.MP4') + '_screenshot'
28
+ copy_metadata = options[:copy_metadata]
29
+
30
+ execute_ffmpeg_command(
31
+ input: @input,
32
+ output: "#{output_path}/#{basename}%d.jpg",
33
+ raw_options: { output: "-vf fps=#{fps}" }
34
+ )
35
+
36
+ copy_metadata_to_screenshots(basename, fps) if copy_metadata
37
+ end
38
+
39
+ def cut(options = {})
40
+ starts_at = options[:start] || '00:00'
41
+ time = options[:time] || 1
42
+ output = options[:output] || "#{File.basename(@input, '.MP4')}_#{starts_at}.mp4"
43
+
44
+ execute_ffmpeg_command(
45
+ input: @input,
46
+ output: "#{output_path}/#{output}",
47
+ raw_options: { output: "-ss #{starts_at} -t #{time}" }
48
+ )
49
+ end
50
+
51
+ def copy_metadata_to_screenshots(basename, fps)
52
+ Dir.glob("#{output_path}/#{basename}*.jpg").sort.each do |file|
53
+ seconds = screenshot_basename_time(basename, file, fps)
54
+ exif = MiniExiftool.new(file)
55
+ exif.create_date = original_date_time + seconds.seconds
56
+ exif.save
57
+ end
58
+ end
59
+
60
+ def screenshot_basename_time(basename, file, fps)
61
+ (1.0 / fps.to_f) * File.basename(file, '.jpg').gsub(basename, '').to_i - (1.0 / fps.to_f)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ module CutCut
2
+ # Media
3
+ class Timelapse < Base
4
+ def files
5
+ Dir.glob(File.join(input, '*.JPG'))
6
+ end
7
+
8
+ def basenames
9
+ files.map { |e| File.basename(e, '.JPG').to_s }
10
+ end
11
+
12
+ def common_substring
13
+ Helpers.longest_common_substring(*basenames)
14
+ end
15
+
16
+ def start_number
17
+ basenames.first.gsub(common_substring, '')
18
+ end
19
+
20
+ def input_basename
21
+ common_substring + "%#{start_number.chars.count}d.JPG"
22
+ end
23
+
24
+ def original_date_time
25
+ exif = MiniExiftool.new(files.first)
26
+ exif.date_time_original || exif.create_date || exif.modify_date
27
+ end
28
+
29
+ def convert(options = {})
30
+ fps = options[:fps] || 30
31
+ execute_ffmpeg_command(input: File.join(@input, input_basename), output: @output,
32
+ raw_options: {
33
+ input: "-f image2 -start_number #{start_number} -framerate #{fps}",
34
+ output: '-c:v libx264 -r 30 -vf scale=-1:1080 -crf 23 -preset ultrafast -pix_fmt yuv420p'
35
+ }
36
+ )
37
+
38
+ Helpers.copy_metadata(files.first, @output)
39
+ @output
40
+ end
41
+ end
42
+ end
data/lib/cutcut.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'active_support/all'
2
+ require 'cutcut/base'
3
+ require 'cutcut/helpers'
4
+ require 'cutcut/timelapse'
5
+ require 'cutcut/media'
6
+ require 'mini_exiftool'
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe CutCut::Base do
4
+ before(:all) do
5
+ system("rm -rf #{File.join(File.dirname(__FILE__), '../fixtures/*.MP4')}")
6
+ system("rm -rf #{File.join(File.dirname(__FILE__), '../fixtures/*.mp4')}")
7
+ system("cp #{File.join(File.dirname(__FILE__), '../fixtures/example')} #{File.join(File.dirname(__FILE__), '../fixtures/example.MP4')}")
8
+ end
9
+
10
+ it 'has input and output' do
11
+ base = CutCut::Base.new(input: 'input', output: 'output')
12
+ expect(base.input).to eq('input')
13
+ expect(base.output).to eq('output')
14
+ end
15
+
16
+ it 'has original_date_time' do
17
+ base = CutCut::Base.new(input: File.join(File.dirname(__FILE__), '../fixtures/example.MP4'), output: 'output')
18
+ expect(base.original_date_time).to eq('2016-01-25 20:15:35 -0200')
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe CutCut::Helpers do
4
+ it 'return longest comon string' do
5
+ expect(CutCut::Helpers.longest_common_substring('foobar', 'foo')).to eq('foo')
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe CutCut::Media do
4
+ let(:media) do
5
+ CutCut::Media.new(input: File.join(File.dirname(__FILE__), '../fixtures/example.MP4'))
6
+ end
7
+
8
+ describe 'initialize' do
9
+ it 'initialize accessors' do
10
+ expect(media.input).to_not eq(nil)
11
+ expect(media.output).to eq(nil)
12
+ expect(media.output_path).to_not eq(nil)
13
+ end
14
+
15
+ it 'return create_date tag' do
16
+ expect(media.original_date_time).to eq('2016-01-25 20:15:35 -0200')
17
+ end
18
+ end
19
+
20
+ describe 'convert' do
21
+ it 'convert media' do
22
+ expect(File.exist?(media.convert(scale: '1920:1080'))).to eq true
23
+ end
24
+
25
+ it 'copy metadata' do
26
+ source = MiniExiftool.new(media.input)
27
+ target = MiniExiftool.new(media.convert(scale: '1920:1080', copy_metadata: true))
28
+ expect(source.create_date).to eq(target.create_date)
29
+ end
30
+ end
31
+
32
+ describe 'cut' do
33
+ it 'cut the video' do
34
+ media.cut(starts_at: '00:00', time: '0.5')
35
+ expect(File.exist?(File.join(File.dirname(__FILE__), '../fixtures/example_00:00.mp4'))).to eq(true)
36
+ end
37
+ end
38
+
39
+ describe 'extract_screenshots' do
40
+ it 'default file to _screenshot' do
41
+ expect(Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/*_screenshot*.jpg')).count).to eq(0)
42
+ media.extract_screenshots(copy_metadata: false)
43
+ expect(Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/*_screenshot*.jpg')).count).to eq(2)
44
+ end
45
+
46
+ it 'allow to save screenshots with a basename' do
47
+ expect(Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/out*.jpg')).count).to eq(0)
48
+ media.extract_screenshots(basename: 'out', copy_metadata: false)
49
+ expect(Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/out*.jpg')).count).to eq(2)
50
+ end
51
+
52
+ it 'extract screenshots based on fps' do
53
+ media.extract_screenshots(fps: 3, copy_metadata: false)
54
+ files = Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/*_screenshot*.jpg'))
55
+ expect(files.count).to eq(4)
56
+ end
57
+
58
+ it 'copy_metadata' do
59
+ media.extract_screenshots(copy_metadata: true)
60
+ files = Dir.glob(File.join(File.dirname(__FILE__), '../fixtures/*_screenshot*.jpg'))
61
+ files.each do |file|
62
+ expect(MiniExiftool.new(file).create_date).to be >= media.original_date_time
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe CutCut::Timelapse do
4
+ let(:timelapse) do
5
+ CutCut::Timelapse.new(
6
+ input: File.join(File.dirname(__FILE__), '../fixtures/timelapse/'),
7
+ output: File.join(File.dirname(__FILE__), '../fixtures/timelapse.mp4')
8
+ )
9
+ end
10
+
11
+ it 'has input and output' do
12
+ expect(timelapse.input).to_not eq(nil)
13
+ expect(timelapse.output).to_not eq(nil)
14
+ end
15
+
16
+ it 'return list of files' do
17
+ expect(timelapse.files.count).to eq(2)
18
+ timelapse.start_number
19
+ end
20
+
21
+ it 'return list of file basenames' do
22
+ expect(timelapse.basenames.count).to eq(2)
23
+ expect(timelapse.basenames.first).to eq('G0023026')
24
+ end
25
+
26
+ it 'return start_number based on first file name' do
27
+ expect(timelapse.start_number).to eq('6')
28
+ end
29
+
30
+ it 'return input_basename based on common string and start_number' do
31
+ expect(timelapse.input_basename).to eq('G002302%1d.JPG')
32
+ end
33
+
34
+ it 'should convert and create timelapse' do
35
+ expect(File.exist?(timelapse.output)).to eq false
36
+ expect(File.exist?(timelapse.convert(fps: '1'))).to eq true
37
+ expect(MiniExiftool.new(timelapse.output).duration).to eq('1.03 s')
38
+ end
39
+
40
+ it 'has original_date_time and copy from first file' do
41
+ expect(timelapse.original_date_time).to eq(MiniExiftool.new(timelapse.output).date_time_original)
42
+ end
43
+ end
Binary file
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'cutcut'
5
+
6
+ RSpec.configure do |config|
7
+ config.raise_errors_for_deprecations!
8
+
9
+ config.before(:all) do
10
+ system("rm -rf #{File.join(File.dirname(__FILE__), '/fixtures/*.MP4')}")
11
+ system("rm -rf #{File.join(File.dirname(__FILE__), '/fixtures/*.mp4')}")
12
+ system("cp #{File.join(File.dirname(__FILE__), '/fixtures/example')} #{File.join(File.dirname(__FILE__), '/fixtures/example.MP4')}")
13
+ end
14
+
15
+ config.before(:each) do
16
+ %w(jpg JPG png PNG).each do |extension|
17
+ system("rm -rf #{File.join(File.dirname(__FILE__), '/fixtures/*.' + extension)}")
18
+ end
19
+ end
20
+
21
+ config.after(:all) do
22
+ %w(jpg JPG png PNG mp4 MP4).each do |extension|
23
+ system("rm -rf #{File.join(File.dirname(__FILE__), '/fixtures/*.' + extension)}")
24
+ end
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cutcut
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jhimy Fernandes Villar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_exiftool
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ruby-progressbar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.4'
111
+ description: CLI for working with videos
112
+ email:
113
+ - stjhimy@gmail.com
114
+ executables:
115
+ - cutcut
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rubocop.yml"
121
+ - CHANGELOG.md
122
+ - Gemfile
123
+ - Guardfile
124
+ - LICENSE
125
+ - README.md
126
+ - bin/cutcut
127
+ - cutcut.gemspec
128
+ - lib/cutcut.rb
129
+ - lib/cutcut/base.rb
130
+ - lib/cutcut/helpers.rb
131
+ - lib/cutcut/media.rb
132
+ - lib/cutcut/timelapse.rb
133
+ - spec/cutcut/base_spec.rb
134
+ - spec/cutcut/helpers_spec.rb
135
+ - spec/cutcut/media_spec.rb
136
+ - spec/cutcut/timelapse_spec.rb
137
+ - spec/fixtures/example
138
+ - spec/fixtures/timelapse/G0023026.JPG
139
+ - spec/fixtures/timelapse/G0023027.JPG
140
+ - spec/spec_helper.rb
141
+ homepage: http://github.com/stjhimy/cutcut
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.4.5.1
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: Trim/Cut/Screenshot videos
165
+ test_files:
166
+ - spec/cutcut/base_spec.rb
167
+ - spec/cutcut/helpers_spec.rb
168
+ - spec/cutcut/media_spec.rb
169
+ - spec/cutcut/timelapse_spec.rb
170
+ - spec/fixtures/example
171
+ - spec/fixtures/timelapse/G0023026.JPG
172
+ - spec/fixtures/timelapse/G0023027.JPG
173
+ - spec/spec_helper.rb