av 0.0.6 → 0.1.1
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 +4 -4
- data/lib/av.rb +4 -19
- data/lib/av/cli.rb +17 -8
- data/lib/av/commands/avconv.rb +19 -6
- data/lib/av/commands/base.rb +73 -25
- data/lib/av/commands/ffmpeg.rb +18 -4
- data/lib/av/exceptions.rb +2 -0
- data/lib/av/param_hash.rb +12 -0
- data/lib/av/version.rb +1 -1
- data/spec/av/avconv_spec.rb +2 -2
- data/spec/av/base_spec.rb +40 -0
- data/spec/av/ffmpeg_spec.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c457580a1a913b757c7451679a5ee05779b1e180
|
4
|
+
data.tar.gz: 789e34475f417dbf0371f7bc2bc6e7ec2ac655fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80d293f42ba494f35559df9f09a914cd59d60036be5e95ce83e2c906d07eafeacd3c78e17bb814797931984a58ecc78e3538923fd7dbb46b8f58e96bca90aebc
|
7
|
+
data.tar.gz: 2e5e1d55dbd04928f20a282115a8afe217e1cfb93175c610b1c585393f6cbefa8e9a6db412bbf976753da0053952b11e9ef213ff97abdd0a899a72462f019391
|
data/lib/av.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "av/version"
|
2
2
|
require "av/exceptions"
|
3
3
|
require "av/cli"
|
4
|
+
require "av/param_hash"
|
4
5
|
require "av/commands/ffmpeg"
|
5
6
|
require "av/commands/avconv"
|
6
7
|
require "cocaine"
|
@@ -8,17 +9,12 @@ require "cocaine"
|
|
8
9
|
module Av
|
9
10
|
extend self
|
10
11
|
|
11
|
-
def cli
|
12
|
-
::Av::Cli.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def quiet
|
16
|
-
return @quiet if @quiet
|
17
|
-
true
|
12
|
+
def cli(options = {})
|
13
|
+
::Av::Cli.new(options)
|
18
14
|
end
|
19
15
|
|
20
16
|
def run line, codes = [0]
|
21
|
-
Av.log("Running command: #{line}")
|
17
|
+
::Av.log("Running command: #{line}")
|
22
18
|
begin
|
23
19
|
Cocaine::CommandLine.new(line, "", expected_outcodes: codes).run
|
24
20
|
rescue Cocaine::ExitStatusError => e
|
@@ -29,15 +25,4 @@ module Av
|
|
29
25
|
def log message
|
30
26
|
puts "[AV] #{message}"
|
31
27
|
end
|
32
|
-
|
33
|
-
def detect_command(command)
|
34
|
-
command = "if command -v #{command} 2>/dev/null; then echo \"true\"; else echo \"false\"; fi"
|
35
|
-
result = Av.run(command)
|
36
|
-
case result
|
37
|
-
when /true/
|
38
|
-
return true
|
39
|
-
when /false/
|
40
|
-
return false
|
41
|
-
end
|
42
|
-
end
|
43
28
|
end
|
data/lib/av/cli.rb
CHANGED
@@ -2,23 +2,32 @@ module Av
|
|
2
2
|
class Cli
|
3
3
|
attr_accessor :command
|
4
4
|
|
5
|
-
def initialize
|
5
|
+
def initialize(options)
|
6
6
|
found = []
|
7
|
-
found << 'ffmpeg' if
|
8
|
-
found << 'avconv' if
|
9
|
-
::Av.log("Found: #{found.inspect}")
|
7
|
+
found << 'ffmpeg' if self.detect_command('ffmpeg')
|
8
|
+
found << 'avconv' if self.detect_command('avprobe')
|
10
9
|
if found.empty?
|
11
10
|
raise Av::UnableToDetect, "Unable to detect any supported library"
|
12
11
|
else
|
13
|
-
found.
|
14
|
-
@command = Object.const_get('Av').const_get('Commands').const_get(library.capitalize).new
|
15
|
-
end
|
12
|
+
@command = Object.const_get('Av').const_get('Commands').const_get(found.first.capitalize).new(options)
|
16
13
|
end
|
14
|
+
::Av.log("Found #{found.inspect}, using: #{found.first.capitalize}")
|
17
15
|
end
|
18
|
-
|
16
|
+
|
19
17
|
protected
|
20
18
|
def method_missing name, *args, &block
|
21
19
|
@command.send(name, *args, &block)
|
22
20
|
end
|
21
|
+
|
22
|
+
def detect_command(command)
|
23
|
+
command = "if command -v #{command} 2>/dev/null; then echo \"true\"; else echo \"false\"; fi"
|
24
|
+
result = ::Av.run(command)
|
25
|
+
case result
|
26
|
+
when /true/
|
27
|
+
return true
|
28
|
+
when /false/
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
24
33
|
end
|
data/lib/av/commands/avconv.rb
CHANGED
@@ -4,21 +4,34 @@ module Av
|
|
4
4
|
module Commands
|
5
5
|
class Avconv < Base
|
6
6
|
|
7
|
-
def initialize
|
8
|
-
super
|
9
|
-
@command_name =
|
10
|
-
@default_params =
|
7
|
+
def initialize(options = {})
|
8
|
+
super(options)
|
9
|
+
@command_name = 'avconv'
|
10
|
+
@default_params['loglevel'] = 'quiet' unless options[:quite] == false
|
11
11
|
end
|
12
12
|
|
13
13
|
def filter_concat list
|
14
|
-
|
14
|
+
add_input_param i: "concat:#{list.join('\|')} -c copy"
|
15
15
|
self
|
16
16
|
end
|
17
17
|
|
18
18
|
def filter_volume vol
|
19
|
-
|
19
|
+
add_input_param af: "volume=volume=#{vol}"
|
20
20
|
self
|
21
21
|
end
|
22
|
+
|
23
|
+
def filter_rotate degrees
|
24
|
+
raise ::Av::InvalidFilterParameter unless degrees % 90 == 0
|
25
|
+
case degrees
|
26
|
+
when 90
|
27
|
+
add_input_param vf: 'clock'
|
28
|
+
when 180
|
29
|
+
add_input_param vf: 'vflip,hflip'
|
30
|
+
when 270
|
31
|
+
add_input_param vf: 'cclock'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
22
35
|
end
|
23
36
|
end
|
24
37
|
end
|
data/lib/av/commands/base.rb
CHANGED
@@ -4,18 +4,22 @@ module Av
|
|
4
4
|
module Commands
|
5
5
|
# Common features across commands
|
6
6
|
class Base
|
7
|
+
attr_accessor :options
|
7
8
|
attr_accessor :command_name
|
8
9
|
attr_accessor :input_params
|
9
10
|
attr_accessor :output_params
|
11
|
+
attr_accessor :audio_filters
|
12
|
+
attr_accessor :video_filters
|
10
13
|
attr_accessor :default_params
|
11
14
|
|
12
15
|
attr_accessor :source
|
13
16
|
attr_accessor :destination
|
14
17
|
|
15
|
-
def initialize
|
18
|
+
def initialize(options = {})
|
16
19
|
reset_input_filters
|
17
20
|
reset_output_filters
|
18
21
|
reset_default_filters
|
22
|
+
@options = options
|
19
23
|
end
|
20
24
|
|
21
25
|
def add_source src
|
@@ -27,60 +31,65 @@ module Av
|
|
27
31
|
end
|
28
32
|
|
29
33
|
def reset_input_filters
|
30
|
-
@input_params =
|
34
|
+
@input_params = ParamHash.new
|
35
|
+
@audio_filters = ParamHash.new
|
36
|
+
@video_filters = ParamHash.new
|
31
37
|
end
|
32
38
|
|
33
39
|
def reset_output_filters
|
34
|
-
@output_params =
|
40
|
+
@output_params = ParamHash.new
|
35
41
|
end
|
36
42
|
|
37
43
|
def reset_default_filters
|
38
|
-
@
|
44
|
+
@default_params = ParamHash.new
|
39
45
|
end
|
40
46
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
47
|
+
def add_input_param *param
|
48
|
+
p = parse_param(param)
|
49
|
+
::Av.log "Adding input parameter #{p}"
|
50
|
+
@input_params[p[0]] = [] unless @input_params.has_key?(p[0])
|
51
|
+
@input_params[p[0]] << p[1]
|
45
52
|
self
|
46
53
|
end
|
47
54
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
def set_input_params hash
|
56
|
+
@input_params = hash
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_output_param *param
|
60
|
+
p = parse_param(param)
|
61
|
+
::Av.log "Adding output parameter #{p}"
|
62
|
+
@output_params[p[0]] = [] unless @output_params.has_key?(p[0])
|
63
|
+
@output_params[p[0]] << p[1]
|
52
64
|
self
|
53
65
|
end
|
54
66
|
|
55
|
-
def
|
67
|
+
def set_output_params hash
|
68
|
+
@output_params = hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def run
|
56
72
|
raise Av::CommandError if (@source.nil? && @destination.nil?) || @command_name.nil?
|
57
73
|
|
58
74
|
parameters = []
|
59
75
|
parameters << @command_name
|
60
76
|
parameters << @default_params if @default_params
|
61
77
|
if @input_params
|
62
|
-
parameters << @input_params.
|
78
|
+
parameters << @input_params.to_s
|
63
79
|
end
|
64
80
|
parameters << %Q(-i "#{@source}") if @source
|
65
81
|
if @output_params
|
66
|
-
parameters << @output_params.
|
82
|
+
parameters << @output_params.to_s
|
67
83
|
end
|
68
84
|
parameters << %Q(-y "#{@destination}") if @destination
|
69
|
-
parameters.flatten.compact.join(" ").strip.squeeze(" ")
|
70
|
-
|
71
|
-
|
72
|
-
def run
|
73
|
-
Av.run(command_line)
|
85
|
+
command_line = parameters.flatten.compact.join(" ").strip.squeeze(" ")
|
86
|
+
::Av.run(command_line)
|
74
87
|
end
|
75
88
|
|
76
89
|
def identify path
|
77
90
|
meta = {}
|
78
91
|
command = %Q(#{@command_name} -i "#{File.expand_path(path)}" 2>&1)
|
79
|
-
out = Av.run(command, [0,1])
|
80
|
-
# rescue Av::CommandError
|
81
|
-
# # Do nothing, we know ffmpeg/avconv will complain with:
|
82
|
-
# # "At least one output file must be specified"
|
83
|
-
# end
|
92
|
+
out = ::Av.run(command, [0,1])
|
84
93
|
out.split("\n").each do |line|
|
85
94
|
if line =~ /(([\d\.]*)\s.?)fps,/
|
86
95
|
meta[:fps] = $1.to_i
|
@@ -103,6 +112,45 @@ module Av
|
|
103
112
|
end
|
104
113
|
meta
|
105
114
|
end
|
115
|
+
|
116
|
+
def output_format format
|
117
|
+
case format
|
118
|
+
when 'jpg', 'jpeg', 'png', 'gif' # Images
|
119
|
+
add_output_param 'f', 'image2'
|
120
|
+
add_output_param 'vframes', '1'
|
121
|
+
when 'webm' # WebM
|
122
|
+
add_output_param 'f', 'webm'
|
123
|
+
add_output_param 'acodec', 'libvorbis'
|
124
|
+
add_output_param 'vcodec', 'libvpx'
|
125
|
+
when 'ogv' # Ogg Theora
|
126
|
+
add_output_param 'f', 'ogg'
|
127
|
+
add_output_param 'acodec', 'libvorbis'
|
128
|
+
add_output_param 'vcodec', 'libtheora'
|
129
|
+
when 'mp4'
|
130
|
+
add_output_param 'acodec', 'aac'
|
131
|
+
add_output_param 'strict', 'experimental'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Children should override the following methods
|
136
|
+
def filter_rotate degrees
|
137
|
+
raise ::Av::FilterNotImplemented, 'rotate'
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_param param
|
141
|
+
list = []
|
142
|
+
if param.count == 2
|
143
|
+
list = param
|
144
|
+
elsif param.count == 1
|
145
|
+
case param[0].class.to_s
|
146
|
+
when 'Hash'
|
147
|
+
list[0], list[1] = param[0].to_a.flatten!
|
148
|
+
when 'Array'
|
149
|
+
list = param[0]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
list
|
153
|
+
end
|
106
154
|
end
|
107
155
|
end
|
108
156
|
end
|
data/lib/av/commands/ffmpeg.rb
CHANGED
@@ -5,9 +5,10 @@ module Av
|
|
5
5
|
module Commands
|
6
6
|
class Ffmpeg < Base
|
7
7
|
|
8
|
-
def initialize
|
9
|
-
super
|
8
|
+
def initialize(options = {})
|
9
|
+
super(options)
|
10
10
|
@command_name = "ffmpeg"
|
11
|
+
# TODO handle quite for ffmpeg
|
11
12
|
end
|
12
13
|
|
13
14
|
def filter_concat list
|
@@ -17,12 +18,25 @@ module Av
|
|
17
18
|
file.write("file '#{item}'\n")
|
18
19
|
end
|
19
20
|
end
|
20
|
-
|
21
|
+
add_input_param concat: "-i #{index_file.path}"
|
21
22
|
self
|
22
23
|
end
|
23
24
|
|
24
25
|
def filter_volume vol
|
25
|
-
|
26
|
+
add_input_param af: "volume=#{vol}"
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter_rotate degrees
|
31
|
+
raise ::Av::InvalidFilterParameter unless degrees % 90 == 0
|
32
|
+
case degrees
|
33
|
+
when 90
|
34
|
+
add_input_param vf: 'transpose=1'
|
35
|
+
when 180
|
36
|
+
add_input_param vf: 'vflip,hflip'
|
37
|
+
when 270
|
38
|
+
add_input_param vf: 'transpose=2'
|
39
|
+
end
|
26
40
|
self
|
27
41
|
end
|
28
42
|
end
|
data/lib/av/exceptions.rb
CHANGED
data/lib/av/version.rb
CHANGED
data/spec/av/avconv_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Av::Commands::Avconv do
|
|
9
9
|
subject.filter_concat(list)
|
10
10
|
end
|
11
11
|
|
12
|
-
it { expect(subject.input_params.
|
12
|
+
it { expect(subject.input_params.to_s).to include %Q(concat:one\\|two) }
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '.filter_volume' do
|
@@ -17,7 +17,7 @@ describe Av::Commands::Avconv do
|
|
17
17
|
subject.filter_volume('0.5')
|
18
18
|
end
|
19
19
|
|
20
|
-
it { expect(subject.input_params.
|
20
|
+
it { expect(subject.input_params.to_s).to eq "-af volume=volume=0.5" }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
data/spec/av/base_spec.rb
CHANGED
@@ -10,5 +10,45 @@ describe Av::Commands::Base do
|
|
10
10
|
it { expect(meta).to be_a Hash }
|
11
11
|
it { expect(meta.keys).to include :size, :fps, :length, :aspect }
|
12
12
|
end
|
13
|
+
|
14
|
+
describe '.add_input_param' do
|
15
|
+
before do
|
16
|
+
subject.add_input_param({k: 'value'})
|
17
|
+
end
|
18
|
+
it { expect(subject.input_params.to_s).to eq '-k value' }
|
19
|
+
context 'multiple calls' do
|
20
|
+
before do
|
21
|
+
subject.add_input_param({k: 'value1'})
|
22
|
+
subject.add_input_param(:k, 'value2')
|
23
|
+
subject.add_input_param([:x, 'y'])
|
24
|
+
end
|
25
|
+
it { expect(subject.input_params.to_s).to eq '-k value value1 value2 -x y' }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.add_output_param' do
|
30
|
+
before do
|
31
|
+
subject.add_output_param({k: 'value'})
|
32
|
+
end
|
33
|
+
it { expect(subject.output_params.to_s).to eq '-k value' }
|
34
|
+
context 'multiple calls' do
|
35
|
+
before do
|
36
|
+
subject.add_output_param({k: 'value1'})
|
37
|
+
subject.add_output_param(:k, 'value2')
|
38
|
+
subject.add_output_param([:x, 'y'])
|
39
|
+
end
|
40
|
+
it { expect(subject.output_params.to_s).to eq '-k value value1 value2 -x y' }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.run' do
|
45
|
+
before do
|
46
|
+
subject.add_output_param(ar: 44100)
|
47
|
+
subject.add_source(source)
|
48
|
+
subject.add_destination(Tempfile.new(['one', '.ogv']).path)
|
49
|
+
end
|
50
|
+
it { expect { subject.run }.not_to raise_exception }
|
51
|
+
|
52
|
+
end
|
13
53
|
end
|
14
54
|
|
data/spec/av/ffmpeg_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Av::Commands::Ffmpeg do
|
|
9
9
|
subject.filter_concat(list)
|
10
10
|
end
|
11
11
|
|
12
|
-
it { expect(subject.input_params.
|
12
|
+
it { expect(subject.input_params.to_s).to include %Q(concat -i) }
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '.filter_volume' do
|
@@ -17,6 +17,6 @@ describe Av::Commands::Ffmpeg do
|
|
17
17
|
subject.filter_volume('0.5')
|
18
18
|
end
|
19
19
|
|
20
|
-
it { expect(subject.input_params.
|
20
|
+
it { expect(subject.input_params.to_s).to eq "-af volume=0.5" }
|
21
21
|
end
|
22
22
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: av
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Omar Abdel-Wahab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/av/commands/base.rb
|
87
87
|
- lib/av/commands/ffmpeg.rb
|
88
88
|
- lib/av/exceptions.rb
|
89
|
+
- lib/av/param_hash.rb
|
89
90
|
- lib/av/version.rb
|
90
91
|
- spec/av/av_spec.rb
|
91
92
|
- spec/av/avconv_spec.rb
|