media 0.0.3 → 0.0.4

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.
data/README.md CHANGED
@@ -4,6 +4,10 @@ An `ffmpeg` or `avconv` wrapper
4
4
 
5
5
  ## Installation
6
6
 
7
+ Install ffmpeg:
8
+
9
+ brew install ffmpeg
10
+
7
11
  Add this line to your application's Gemfile:
8
12
 
9
13
  gem 'media'
@@ -18,56 +22,39 @@ Or install it yourself as:
18
22
 
19
23
  ## Usage
20
24
 
21
- Media.convert do
22
- option 'v', 'warning'
25
+ conversion = Media.convert do
26
+ options y: true
23
27
 
24
- input 'in1.mov'
25
-
26
- input 'in2.mov' do
27
- option 'foo', 'bar'
28
+ input 'http://www.google.com/images/srpr/logo3w.png' do
29
+ options loop: 1, f: 'image2'
28
30
  end
29
31
 
30
- output 'out.mov' do
32
+ output '/path/to/test2.webm' do
33
+ options vcodec: 'libvpx', acodec: 'libvorbis', t: 4
34
+ maps label('video'), label('audio')
31
35
  graph do
32
36
  chain do
33
- filter 'split' do
34
- input 'in'
35
- output 'T1'
36
- end
37
- filter 'fifo'
38
- filter 'overlay' do
39
- input 'T2'
40
- arg '0'
41
- arg 'H/2'
42
- output 'out'
37
+ filter 'negate'
38
+ filter 'hflip' do
39
+ outputs 'video'
43
40
  end
44
41
  end
45
42
  chain do
46
- filter 'fifo' do
47
- input 'T1'
48
- end
49
- filter 'crop' do
50
- arg 'iw'
51
- arg 'ih/2'
52
- arg '0'
53
- arg 'ih/2'
54
- end
55
- filter 'vflip' do
56
- output 'T2'
43
+ filter 'aevalsrc' do
44
+ arguments 'sin(440*2*PI*t)' => true
45
+ outputs 'audio'
57
46
  end
58
47
  end
59
48
  end
60
-
61
- map 'out'
62
-
63
- option 'f', 'prores'
64
49
  end
65
50
  end
66
-
67
- Outputs:
68
51
 
69
- ffmpeg -v warning -i in1.mov -foo bar -i in2.mov -filter_complex "[in] split [T1], fifo, [T2] overlay=0:H/2 [out]; [T1] fifo, crop=iw:ih/2:0:ih/2, vflip [T2]" -map out -f prores out.mov
52
+ conversion.call {|progress| p progress}
70
53
 
54
+ Outputs:
55
+
56
+ ffmpeg -v info -y -loop 1 -f image2 -i http://www.google.com/images/srpr/logo3w.png -vcodec libvpx -acodec libvorbis -t 4 -map [video] -map [audio] -filter_complex negate, hflip [video]; aevalsrc=sin(440*2*PI*t) [audio] /path/to/test2.webm
57
+
71
58
  ## Contributing
72
59
 
73
60
  1. Fork it
data/lib/media.rb CHANGED
@@ -4,17 +4,22 @@ require_relative 'media/command'
4
4
  require_relative 'media/container'
5
5
  require_relative 'media/filter'
6
6
  require_relative 'media/input'
7
- require_relative 'media/label'
8
7
  require_relative 'media/option'
9
8
  require_relative 'media/output'
10
- require_relative 'media/size'
11
-
12
- require_relative 'media/builder/command/converter'
9
+ require_relative 'media/helper'
13
10
 
14
11
  module Media
15
12
  extend self
16
13
 
17
- def convert(&blk)
18
- Command::Converter.extend(Builder::Command::Converter).build(&blk)
14
+ def convert(&block)
15
+ Media::Command::Converter.new(&block)
16
+ end
17
+
18
+ def size(args)
19
+ Media::Helper::Size.new(args)
20
+ end
21
+
22
+ def label(name)
23
+ Media::Helper::Label.new(name: name)
19
24
  end
20
25
  end
@@ -1,4 +1,6 @@
1
1
  require_relative 'subshell'
2
+ require_relative 'progress'
3
+ require_relative '../option'
2
4
 
3
5
  module Media
4
6
  module Command
@@ -6,21 +8,65 @@ module Media
6
8
 
7
9
  attr_accessor :options, :inputs, :outputs
8
10
 
9
- def initialize(args={})
11
+ def initialize(args={}, &block)
10
12
  @options = Array args.fetch(:options, [])
11
13
  @inputs = Array args.fetch(:inputs, [])
12
14
  @outputs = Array args.fetch(:outputs, [])
13
15
 
14
16
  @cmd = args.fetch(:cmd, 'ffmpeg')
15
17
  @subshell = args.fetch(:subshell, Subshell)
18
+ @progress = args.fetch(:progress, Progress)
19
+
20
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
21
+ end
22
+
23
+ def call(&blk)
24
+ progress = @progress.new
25
+
26
+ process = @subshell.new(cmd: to_a).call do |line|
27
+ progress.update(line, &blk)
28
+ end
29
+ progress.complete(&blk) if process.success?
30
+
31
+ process
16
32
  end
17
33
 
18
- def call
19
- @subshell.new(cmd: to_s).call
34
+ def to_a
35
+ [
36
+ @cmd,
37
+ (required_options + options).map(&:to_a),
38
+ inputs.map(&:to_a),
39
+ outputs.map(&:to_a)
40
+ ].flatten
20
41
  end
21
42
 
22
43
  def to_s
23
- [@cmd, options, inputs, outputs].reject(&:empty?).join(' ')
44
+ to_a.join(' ')
45
+ end
46
+
47
+ def options(value=nil)
48
+ return @options unless value
49
+
50
+ @options = value.map {|k,v| Option.new(key: k, value: v)}
51
+ end
52
+ alias_method :options=, :options
53
+
54
+ def add_input(url, &block)
55
+ @inputs << Input.new(url: url, &block)
56
+ end
57
+ alias_method :input, :add_input
58
+
59
+ def add_output(url, &block)
60
+ @outputs << Output.new(url: url, &block)
61
+ end
62
+ alias_method :output, :add_output
63
+
64
+ private
65
+
66
+ def required_options
67
+ [
68
+ Option.new(key: 'v', value: 'info')
69
+ ]
24
70
  end
25
71
  end
26
72
  end
@@ -13,11 +13,15 @@ module Media
13
13
  end
14
14
 
15
15
  def call
16
- @subshell.new(cmd: to_s).call
16
+ @subshell.new(cmd: to_a).call
17
17
  end
18
18
 
19
- def to_s
20
- [@cmd, @options, @input].reject(&:empty?).join(' ')
19
+ def to_a
20
+ [
21
+ @cmd,
22
+ @options.map(&:to_a),
23
+ @input
24
+ ].flatten
21
25
  end
22
26
  end
23
27
  end
@@ -0,0 +1,36 @@
1
+ module Media
2
+ module Command
3
+ class Progress
4
+
5
+ DURATION = /Duration: (\d+):(\d+):(\d+.\d+), start: (\d+.\d+)/
6
+ TIME = /time=(\d+):(\d+):(\d+.\d+)/
7
+
8
+ attr_reader :duration, :time
9
+
10
+ def initialize(args={})
11
+ @duration = args.fetch(:duration, 0.0)
12
+ @time = args.fetch(:time, 0.0)
13
+ end
14
+
15
+ def update(line)
16
+ case line
17
+ when DURATION
18
+ @duration = ($1.to_i * 3600) + ($2.to_i * 60) + $3.to_f + $4.to_f
19
+ yield self if block_given?
20
+ when TIME
21
+ @time = ($1.to_i * 3600) + ($2.to_i * 60) + $3.to_f
22
+ yield self if block_given?
23
+ end
24
+ end
25
+
26
+ def complete
27
+ @time = @duration
28
+ yield self if block_given?
29
+ end
30
+
31
+ def to_f
32
+ time / duration rescue ZeroDivisionError 0.0
33
+ end
34
+ end
35
+ end
36
+ end
@@ -10,11 +10,30 @@ module Media
10
10
  attr_reader :out, :error, :status
11
11
 
12
12
  def initialize(args)
13
- @cmd = args.fetch(:cmd)
13
+ @cmd = Array(args.fetch(:cmd))
14
14
  end
15
15
 
16
16
  def call
17
- @out, @error, @status = Open3.capture3(@cmd)
17
+ @out, @error, @status = Open3.popen3(*@cmd) {|stdin,stdout,stderr,thread|
18
+
19
+ out = Thread.new do
20
+ stdout.each_with_object([]) do |line, memo|
21
+ memo << line
22
+ yield line.strip if block_given?
23
+ end.join
24
+ end
25
+
26
+ err = Thread.new do
27
+ stderr.each_with_object([]) do |line, memo|
28
+ memo << line
29
+ yield line.strip if block_given?
30
+ end.join
31
+ end
32
+
33
+ stdin.close
34
+
35
+ [out.value, err.value, thread.value]
36
+ }
18
37
  self
19
38
  end
20
39
 
@@ -6,9 +6,13 @@ require_relative 'option'
6
6
 
7
7
  module Media
8
8
  class Container
9
+
10
+ attr_reader :url, :options
11
+
9
12
  def initialize(args)
10
- @input = args.fetch(:input)
11
- @probe = args.fetch(:probe, Command::Probe)
13
+ @url = args.fetch(:url)
14
+ @probe = args.fetch(:probe, Command::Probe)
15
+ @options = args.fetch(:options, []) + required_options
12
16
  end
13
17
 
14
18
  def format
@@ -29,10 +33,10 @@ module Media
29
33
  end
30
34
 
31
35
  def probe
32
- @probe.new(input: @input, options: options).call
36
+ @probe.new(input: @url, options: options).call
33
37
  end
34
38
 
35
- def options
39
+ def required_options
36
40
  [
37
41
  Option.new(key: 'print_format', value: 'json'),
38
42
  Option.new(key: 'show_format'),
data/lib/media/filter.rb CHANGED
@@ -1,25 +1,46 @@
1
- require 'shellwords'
2
-
3
1
  require_relative 'filter/argument'
4
2
  require_relative 'filter/chain'
5
3
  require_relative 'filter/graph'
6
- require_relative 'label'
4
+ require_relative 'helper/label'
7
5
 
8
6
  module Media
9
7
  class Filter
10
- attr_reader :name, :arguments, :inputs, :outputs
8
+ attr_reader :name
11
9
 
12
- def initialize(args)
10
+ def initialize(args, &block)
13
11
  @name = args.fetch(:name)
14
12
  @arguments = Array args.fetch(:arguments, [])
15
13
  @inputs = Array args.fetch(:inputs, [])
16
14
  @outputs = Array args.fetch(:outputs, [])
15
+
16
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
17
17
  end
18
18
 
19
19
  def to_s
20
20
  [inputs, filter, outputs].reject(&:empty?).join(' ')
21
21
  end
22
22
 
23
+ def inputs(*value)
24
+ return @inputs if value.empty?
25
+
26
+ @inputs = value.map {|name| Helper::Label.new(name: name)}
27
+ end
28
+ alias_method :inputs=, :inputs
29
+
30
+ def outputs(*value)
31
+ return @outputs if value.empty?
32
+
33
+ @outputs = value.map {|name| Helper::Label.new(name: name)}
34
+ end
35
+ alias_method :outputs=, :outputs
36
+
37
+ def arguments(value=nil)
38
+ return @arguments unless value
39
+
40
+ @arguments = value.map {|k,v| Argument.new(key: k, value: v)}
41
+ end
42
+ alias_method :arguments=, :arguments
43
+
23
44
  private
24
45
 
25
46
  def filter
@@ -3,12 +3,12 @@ module Media
3
3
  class Argument
4
4
  def initialize(args)
5
5
  @key = args.fetch(:key)
6
- @value = args.fetch(:value, true)
6
+ @value = args.fetch(:value, true)
7
7
  end
8
8
 
9
9
  def to_s
10
10
  case @value
11
- when TrueClass, FalseClass then @key
11
+ when TrueClass, FalseClass then @key.to_s
12
12
  else "#{@key}=#{value}"
13
13
  end
14
14
  end
@@ -16,7 +16,7 @@ module Media
16
16
  private
17
17
 
18
18
  def value
19
- @value.gsub(/([\[\]=;,])/, "\\\\\\1")
19
+ @value.to_s.gsub(/([\[\]=;,])/, "\\\\\\1")
20
20
  end
21
21
  end
22
22
  end
@@ -3,13 +3,20 @@ module Media
3
3
  class Chain
4
4
  attr_reader :filters
5
5
 
6
- def initialize(args={}, &blk)
6
+ def initialize(args={}, &block)
7
7
  @filters = args.fetch(:filters, [])
8
+
9
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
8
10
  end
9
11
 
10
12
  def to_s
11
13
  filters.join(', ')
12
14
  end
15
+
16
+ def add_filter(name, &block)
17
+ @filters << Filter.new(name: name, &block)
18
+ end
19
+ alias_method :filter, :add_filter
13
20
  end
14
21
  end
15
22
  end
@@ -5,13 +5,20 @@ module Media
5
5
  class Graph
6
6
  attr_reader :chains
7
7
 
8
- def initialize(args={}, &blk)
8
+ def initialize(args={}, &block)
9
9
  @chains = args.fetch(:chains, [])
10
+
11
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
10
12
  end
11
13
 
12
14
  def to_s
13
- "\"#{chains.join('; ')}\""
15
+ chains.join('; ')
14
16
  end
17
+
18
+ def add_chain(&block)
19
+ @chains << Filter::Chain.new(&block)
20
+ end
21
+ alias_method :chain, :add_chain
15
22
  end
16
23
  end
17
24
  end
@@ -0,0 +1,2 @@
1
+ require_relative 'helper/size'
2
+ require_relative 'helper/label'
@@ -0,0 +1,13 @@
1
+ module Media
2
+ module Helper
3
+ class Label
4
+ def initialize(args)
5
+ @name = args.fetch(:name, [])
6
+ end
7
+
8
+ def to_s
9
+ "[#{@name}]"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Media
2
+ module Helper
3
+ class Size
4
+ def initialize(args)
5
+ @width = args.fetch(:width)
6
+ @height = args.fetch(:height)
7
+ end
8
+
9
+ def to_s
10
+ [@width, @height].join('x')
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/media/input.rb CHANGED
@@ -3,21 +3,36 @@ require_relative 'filter/graph'
3
3
 
4
4
  module Media
5
5
  class Input
6
- attr_reader :options
7
6
 
8
- def initialize(args)
9
- @url = args.fetch(:url)
7
+ def initialize(args, &block)
8
+ @url = args.fetch(:url) { raise ':url required'}
10
9
  @options = Array args.fetch(:options, [])
10
+
11
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
11
12
  end
12
13
 
13
- def to_s
14
- [options, url].reject(&:empty?).join(' ')
14
+ def to_a
15
+ (options << graph << url).compact.map(&:to_a)
15
16
  end
16
17
 
18
+ def options(value=nil)
19
+ return @options unless value
20
+
21
+ @options = value.map {|k,v| Option.new(key: k, value: v)}
22
+ end
23
+ alias_method :options=, :options
24
+
25
+ def graph(&block)
26
+ return @graph unless block_given?
27
+
28
+ @graph = Option.new(key: 'filter_complex', value: Filter::Graph.new(&block))
29
+ end
30
+ alias_method :graph=, :graph
31
+
17
32
  private
18
33
 
19
34
  def url
20
- Option.new(key: 'i', value: @url).to_s
35
+ Option.new(key: 'i', value: @url)
21
36
  end
22
37
  end
23
38
  end
data/lib/media/option.rb CHANGED
@@ -5,11 +5,11 @@ module Media
5
5
  @value = args.fetch(:value, true)
6
6
  end
7
7
 
8
- def to_s
8
+ def to_a
9
9
  case @value
10
- when TrueClass then "-#{@key}"
11
- when FalseClass then "-no#{@key}"
12
- else "-#{@key} #{@value}"
10
+ when TrueClass then ["-#{@key}"]
11
+ when FalseClass then ["-no#{@key}"]
12
+ else ["-#{@key}", @value.to_s]
13
13
  end
14
14
  end
15
15
  end
data/lib/media/output.rb CHANGED
@@ -3,15 +3,43 @@ require_relative 'option'
3
3
  module Media
4
4
  class Output
5
5
 
6
- attr_reader :options
6
+ attr_reader :options, :maps
7
7
 
8
- def initialize(args, &blk)
9
- @url = args.fetch(:url)
8
+ def initialize(args, &block)
9
+ @url = args.fetch(:url) { raise ':url required'}
10
10
  @options = Array args.fetch(:options, [])
11
+ @maps = Array args.fetch(:maps, [])
12
+
13
+ block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
11
14
  end
12
15
 
13
- def to_s
14
- [options, @url].join(' ')
16
+ def to_a
17
+ (options + maps << graph).compact.map(&:to_a) + [@url]
15
18
  end
19
+
20
+ def options(value=nil)
21
+ return @options unless value
22
+
23
+ @options = value.map {|k,v| Option.new(key: k, value: v)}
24
+ end
25
+ alias_method :options=, :options
26
+
27
+ def maps(*value)
28
+ return @maps if value.empty?
29
+
30
+ @maps = value.map {|v| Option.new(key: 'map', value: v)}
31
+ end
32
+ alias_method :maps=, :maps
33
+
34
+ def label(name)
35
+ Media.label(name)
36
+ end
37
+
38
+ def graph(&block)
39
+ return @graph unless block_given?
40
+
41
+ @graph = Option.new(key: 'filter_complex', value: Filter::Graph.new(&block))
42
+ end
43
+ alias_method :graph=, :graph
16
44
  end
17
45
  end
data/lib/media/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Media
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -18,27 +18,31 @@ module Media
18
18
  end
19
19
 
20
20
  def test_empty_call
21
- subshell.expect(:new, subshell, [cmd: 'ffmpeg'])
22
- subshell.expect(:call, true)
21
+ stub = Class.new do
22
+ def success?; true; end
23
+ end
24
+
25
+ subshell.expect(:new, subshell, [cmd: ['ffmpeg', '-v', 'info']])
26
+ subshell.expect(:call, stub.new)
23
27
 
24
28
  subject.call
25
29
  end
26
30
 
27
31
  def test_with_options
28
- assert_equal 'ffmpeg options', subject(options: ['options']).to_s
32
+ assert_equal ['ffmpeg', '-v', 'info', 'option'], subject(options: [['option']]).to_a
29
33
  end
30
34
 
31
35
  def test_call_with_inputs
32
- assert_equal 'ffmpeg inputs', subject(inputs: ['inputs']).to_s
36
+ assert_equal ['ffmpeg', '-v', 'info', 'input'], subject(inputs: [['input']]).to_a
33
37
  end
34
38
 
35
39
  def test_call_with_outputs
36
- assert_equal 'ffmpeg outputs', subject(outputs: ['outputs']).to_s
40
+ assert_equal ['ffmpeg', '-v', 'info', 'output'], subject(outputs: [['output']]).to_a
37
41
  end
38
42
 
39
43
  def test_call_with_all
40
- assert_equal 'ffmpeg options inputs outputs',
41
- subject(options: ['options'], inputs: ['inputs'], outputs: ['outputs']).to_s
44
+ assert_equal ['ffmpeg', '-v', 'info', 'option', 'input', 'output'],
45
+ subject(options: [['option']], inputs: [['input']], outputs: [['output']]).to_a
42
46
  end
43
47
  end
44
48
  end
@@ -18,19 +18,19 @@ module Media
18
18
  end
19
19
 
20
20
  def test_call
21
- subshell.expect(:new, subshell, [cmd: 'ffprobe input'])
21
+ subshell.expect(:new, subshell, [cmd: ['ffprobe', 'input']])
22
22
  subshell.expect(:call, true)
23
23
 
24
24
  subject(input: ['input']).call
25
25
  end
26
26
 
27
27
  def test_call_with_input
28
- assert_equal 'ffprobe input', subject(input: ['input']).to_s
28
+ assert_equal ['ffprobe', 'input'], subject(input: ['input']).to_a
29
29
  end
30
30
 
31
31
  def test_call_with_all
32
- assert_equal 'ffprobe options input',
33
- subject(options: ['options'], input: ['input']).to_s
32
+ assert_equal ['ffprobe', 'option', 'input'],
33
+ subject(options: [['option']], input: ['input']).to_a
34
34
  end
35
35
  end
36
36
  end
@@ -10,15 +10,15 @@ module Media
10
10
  end
11
11
 
12
12
  def test_stdout
13
- shell = subject.new(cmd: 'echo hello')
13
+ shell = subject.new(cmd: ['echo', 'hello'])
14
14
 
15
15
  assert_equal("hello\n", shell.call.out)
16
16
  end
17
17
 
18
18
  def test_stderr
19
- shell = subject.new(cmd: 'echo hello 1>&2')
20
-
21
- assert_equal("hello\n", shell.call.error)
19
+ shell = subject.new(cmd: ['ffprobe'])
20
+
21
+ assert_match(/^ffprobe/, shell.call.error)
22
22
  end
23
23
 
24
24
  def test_success
@@ -32,6 +32,15 @@ module Media
32
32
 
33
33
  refute(shell.call.success?)
34
34
  end
35
+
36
+ def test_streaming
37
+ shell = subject.new(cmd: ['echo', "hello\n", 'there'])
38
+
39
+ out = []
40
+ shell.call {|line| out << line}
41
+
42
+ assert_equal(['hello', 'there'], out)
43
+ end
35
44
  end
36
45
  end
37
46
  end
@@ -6,7 +6,7 @@ module Media
6
6
  class TestGraph < MiniTest::Unit::TestCase
7
7
 
8
8
  def test_to_s
9
- assert_equal('"a; b; c"', Graph.new(chains: %w(a b c)).to_s)
9
+ assert_equal('a; b; c', Graph.new(chains: %w(a b c)).to_s)
10
10
  end
11
11
  end
12
12
  end
@@ -1,11 +1,11 @@
1
1
  require 'helper'
2
- require 'media/label'
2
+ require 'media/helper/label'
3
3
 
4
4
  module Media
5
5
  class TestLabel < MiniTest::Unit::TestCase
6
6
 
7
7
  def test_to_s
8
- assert_equal '[foo]', Label.new(name: 'foo').to_s
8
+ assert_equal '[foo]', Helper::Label.new(name: 'foo').to_s
9
9
  end
10
10
  end
11
11
  end
@@ -5,9 +5,9 @@ module Media
5
5
  class TestInput < MiniTest::Unit::TestCase
6
6
 
7
7
  def test_to_s
8
- input = Input.new(url: 'url', options: 'options')
8
+ input = Input.new(url: 'url', options: [['option']])
9
9
 
10
- assert_equal('options -i url', input.to_s)
10
+ assert_equal([['option'], ['-i', 'url']], input.to_a)
11
11
  end
12
12
  end
13
13
  end
@@ -9,15 +9,15 @@ module Media
9
9
  end
10
10
 
11
11
  def test_option
12
- assert_equal '-foo bar', subject.new(key: 'foo', value: 'bar').to_s
12
+ assert_equal ['-foo', 'bar'], subject.new(key: 'foo', value: 'bar').to_a
13
13
  end
14
14
 
15
15
  def test_true_flag
16
- assert_equal '-foo', subject.new(key: 'foo').to_s
16
+ assert_equal ['-foo'], subject.new(key: 'foo').to_a
17
17
  end
18
18
 
19
19
  def test_false_flag
20
- assert_equal '-nofoo', subject.new(key: 'foo', value: false).to_s
20
+ assert_equal ['-nofoo'], subject.new(key: 'foo', value: false).to_a
21
21
  end
22
22
  end
23
23
  end
@@ -5,9 +5,9 @@ module Media
5
5
  class TestOutput < MiniTest::Unit::TestCase
6
6
 
7
7
  def test_to_s
8
- output = Output.new(url: 'url', options: 'options')
8
+ output = Output.new(url: 'url', options: [['option']])
9
9
 
10
- assert_equal('options url', output.to_s)
10
+ assert_equal([['option'], 'url'], output.to_a)
11
11
  end
12
12
  end
13
13
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: media
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.3
5
+ version: 0.0.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jamie Hodge
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-13 00:00:00.000000000 Z
12
+ date: 2013-02-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  prerelease: false
@@ -62,24 +62,14 @@ files:
62
62
  UmFrZWZpbGU=
63
63
  - !binary |-
64
64
  bGliL21lZGlhLnJi
65
- - !binary |-
66
- bGliL21lZGlhL2J1aWxkZXIvY29tbWFuZC9jb252ZXJ0ZXIucmI=
67
- - !binary |-
68
- bGliL21lZGlhL2J1aWxkZXIvZmlsdGVyLnJi
69
- - !binary |-
70
- bGliL21lZGlhL2J1aWxkZXIvZmlsdGVyL2NoYWluLnJi
71
- - !binary |-
72
- bGliL21lZGlhL2J1aWxkZXIvZmlsdGVyL2dyYXBoLnJi
73
- - !binary |-
74
- bGliL21lZGlhL2J1aWxkZXIvaW5wdXQucmI=
75
- - !binary |-
76
- bGliL21lZGlhL2J1aWxkZXIvb3V0cHV0LnJi
77
65
  - !binary |-
78
66
  bGliL21lZGlhL2NvbW1hbmQucmI=
79
67
  - !binary |-
80
68
  bGliL21lZGlhL2NvbW1hbmQvY29udmVydGVyLnJi
81
69
  - !binary |-
82
70
  bGliL21lZGlhL2NvbW1hbmQvcHJvYmUucmI=
71
+ - !binary |-
72
+ bGliL21lZGlhL2NvbW1hbmQvcHJvZ3Jlc3MucmI=
83
73
  - !binary |-
84
74
  bGliL21lZGlhL2NvbW1hbmQvc3Vic2hlbGwucmI=
85
75
  - !binary |-
@@ -93,15 +83,17 @@ files:
93
83
  - !binary |-
94
84
  bGliL21lZGlhL2ZpbHRlci9ncmFwaC5yYg==
95
85
  - !binary |-
96
- bGliL21lZGlhL2lucHV0LnJi
86
+ bGliL21lZGlhL2hlbHBlci5yYg==
97
87
  - !binary |-
98
- bGliL21lZGlhL2xhYmVsLnJi
88
+ bGliL21lZGlhL2hlbHBlci9sYWJlbC5yYg==
89
+ - !binary |-
90
+ bGliL21lZGlhL2hlbHBlci9zaXplLnJi
91
+ - !binary |-
92
+ bGliL21lZGlhL2lucHV0LnJi
99
93
  - !binary |-
100
94
  bGliL21lZGlhL29wdGlvbi5yYg==
101
95
  - !binary |-
102
96
  bGliL21lZGlhL291dHB1dC5yYg==
103
- - !binary |-
104
- bGliL21lZGlhL3NpemUucmI=
105
97
  - !binary |-
106
98
  bGliL21lZGlhL3ZlcnNpb24ucmI=
107
99
  - !binary |-
@@ -120,12 +112,12 @@ files:
120
112
  dGVzdC9tZWRpYS9maWx0ZXIvdGVzdF9jaGFpbi5yYg==
121
113
  - !binary |-
122
114
  dGVzdC9tZWRpYS9maWx0ZXIvdGVzdF9ncmFwaC5yYg==
115
+ - !binary |-
116
+ dGVzdC9tZWRpYS9oZWxwZXIvdGVzdF9sYWJlbC5yYg==
123
117
  - !binary |-
124
118
  dGVzdC9tZWRpYS90ZXN0X2ZpbHRlci5yYg==
125
119
  - !binary |-
126
120
  dGVzdC9tZWRpYS90ZXN0X2lucHV0LnJi
127
- - !binary |-
128
- dGVzdC9tZWRpYS90ZXN0X2xhYmVsLnJi
129
121
  - !binary |-
130
122
  dGVzdC9tZWRpYS90ZXN0X29wdGlvbi5yYg==
131
123
  - !binary |-
@@ -175,12 +167,12 @@ test_files:
175
167
  dGVzdC9tZWRpYS9maWx0ZXIvdGVzdF9jaGFpbi5yYg==
176
168
  - !binary |-
177
169
  dGVzdC9tZWRpYS9maWx0ZXIvdGVzdF9ncmFwaC5yYg==
170
+ - !binary |-
171
+ dGVzdC9tZWRpYS9oZWxwZXIvdGVzdF9sYWJlbC5yYg==
178
172
  - !binary |-
179
173
  dGVzdC9tZWRpYS90ZXN0X2ZpbHRlci5yYg==
180
174
  - !binary |-
181
175
  dGVzdC9tZWRpYS90ZXN0X2lucHV0LnJi
182
- - !binary |-
183
- dGVzdC9tZWRpYS90ZXN0X2xhYmVsLnJi
184
176
  - !binary |-
185
177
  dGVzdC9tZWRpYS90ZXN0X29wdGlvbi5yYg==
186
178
  - !binary |-
@@ -1,55 +0,0 @@
1
- require_relative '../../option'
2
- require_relative '../../input'
3
- require_relative '../../output'
4
-
5
- require_relative '../../builder/input'
6
- require_relative '../../builder/output'
7
-
8
- module Media
9
- module Builder
10
- module Command
11
- module Converter
12
-
13
- module ClassMethods
14
-
15
- def build(&blk)
16
- converter = new
17
-
18
- if block_given?
19
- context = eval('self', blk.binding)
20
- converter.instance_variable_set(:@context, context)
21
-
22
- converter.instance_eval(&blk)
23
- end
24
- converter
25
- end
26
- end
27
-
28
- module InstanceMethods
29
-
30
- def option(key, value)
31
- options << Media::Option.new(key: key, value: value)
32
- end
33
-
34
- def input(url, &blk)
35
- inputs << Media::Input.extend(Builder::Input).build(url, &blk)
36
- end
37
-
38
- def output(url, &blk)
39
- outputs << Media::Output.extend(Builder::Output).build(url, &blk)
40
- end
41
-
42
- def method_missing(method, *args, &blk)
43
- @context && @context.send(method, *args, &blk)
44
- end
45
- end
46
-
47
- def self.extended(receiver)
48
- receiver.extend(ClassMethods)
49
- receiver.send(:include, InstanceMethods)
50
- end
51
- end
52
- end
53
- end
54
- end
55
-
@@ -1,48 +0,0 @@
1
- require_relative '../filter/argument'
2
-
3
- module Media
4
- module Builder
5
- module Filter
6
-
7
- module ClassMethods
8
-
9
- def build(name, &blk)
10
- filter = new(name: name)
11
-
12
- if block_given?
13
- context = eval('self', blk.binding)
14
- filter.instance_variable_set(:@context, context)
15
-
16
- filter.instance_eval(&blk)
17
- end
18
- filter
19
- end
20
- end
21
-
22
- module InstanceMethods
23
-
24
- def input(name)
25
- inputs << Media::Label.new(name: name)
26
- end
27
-
28
- def output(name)
29
- outputs << Media::Label.new(name: name)
30
- end
31
-
32
- def argument(key, value=true)
33
- arguments << Media::Filter::Argument.new(key: key, value: value)
34
- end
35
- alias :arg :argument
36
-
37
- def method_missing(method, *args, &blk)
38
- @context && @context.send(method, *args, &blk)
39
- end
40
- end
41
-
42
- def self.extended(receiver)
43
- receiver.extend(ClassMethods)
44
- receiver.send(:include, InstanceMethods)
45
- end
46
- end
47
- end
48
- end
@@ -1,41 +0,0 @@
1
- require_relative '../filter'
2
-
3
- module Media
4
- module Builder
5
- module Filter
6
- module Chain
7
-
8
- module ClassMethods
9
-
10
- def build(&blk)
11
- chain = new
12
-
13
- if block_given?
14
- context = eval('self', blk.binding)
15
- chain.instance_variable_set(:@context, context)
16
-
17
- chain.instance_eval(&blk)
18
- end
19
- chain
20
- end
21
- end
22
-
23
- module InstanceMethods
24
-
25
- def filter(name, &blk)
26
- filters << Media::Filter.extend(Filter).build(name, &blk)
27
- end
28
-
29
- def method_missing(method, *args, &blk)
30
- @context && @context.send(method, *args, &blk)
31
- end
32
- end
33
-
34
- def self.extended(receiver)
35
- receiver.extend(ClassMethods)
36
- receiver.send(:include, InstanceMethods)
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,43 +0,0 @@
1
- require_relative '../../filter/chain'
2
-
3
- require_relative 'chain'
4
-
5
- module Media
6
- module Builder
7
- module Filter
8
- module Graph
9
-
10
- module ClassMethods
11
-
12
- def build(&blk)
13
- graph = new
14
-
15
- if block_given?
16
- context = eval('self', blk.binding)
17
- graph.instance_variable_set(:@context, context)
18
-
19
- graph.instance_eval(&blk)
20
- end
21
- graph
22
- end
23
- end
24
-
25
- module InstanceMethods
26
-
27
- def chain(&blk)
28
- chains << Media::Filter::Chain.extend(Chain).build(&blk)
29
- end
30
-
31
- def method_missing(method, *args, &blk)
32
- @context && @context.send(method, *args, &blk)
33
- end
34
- end
35
-
36
- def self.extended(receiver)
37
- receiver.extend(ClassMethods)
38
- receiver.send(:include, InstanceMethods)
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,46 +0,0 @@
1
- require_relative 'filter/graph'
2
-
3
- module Media
4
- module Builder
5
- module Input
6
-
7
- module ClassMethods
8
-
9
- def build(url, &blk)
10
- input = new(url: url)
11
-
12
- if block_given?
13
- context = eval('self', blk.binding)
14
- input.instance_variable_set(:@context, context)
15
-
16
- input.instance_eval(&blk)
17
- end
18
- input
19
- end
20
- end
21
-
22
- module InstanceMethods
23
-
24
- def option(key, value=true)
25
- @options << Media::Option.new(key: key, value: value).to_s
26
- end
27
-
28
- def graph(&blk)
29
- @options << Option.new(
30
- key: 'filter_complex',
31
- value: Media::Filter::Graph.extend(Filter::Graph).build(&blk)
32
- )
33
- end
34
-
35
- def method_missing(method, *args, &blk)
36
- @context && @context.send(method, *args, &blk)
37
- end
38
- end
39
-
40
- def self.extended(receiver)
41
- receiver.extend(ClassMethods)
42
- receiver.send(:include, InstanceMethods)
43
- end
44
- end
45
- end
46
- end
@@ -1,51 +0,0 @@
1
- require_relative '../option'
2
- require_relative '../filter/graph'
3
-
4
- require_relative 'filter/graph'
5
-
6
- module Media
7
- module Builder
8
- module Output
9
-
10
- module ClassMethods
11
-
12
- def build(url, &blk)
13
- output = new(url: url)
14
-
15
- if block_given?
16
- context = eval('self', blk.binding)
17
- output.instance_variable_set(:@context, context)
18
-
19
- output.instance_eval(&blk)
20
- end
21
- output
22
- end
23
- end
24
-
25
- module InstanceMethods
26
-
27
- def option(key, value=true)
28
- @options << Media::Option.new(key: key, value: value)
29
- end
30
-
31
- def map(value)
32
- @options << Media::Option.new(key: 'map', value: value)
33
- end
34
-
35
- def graph(&blk)
36
- @options << Media::Option.new(key: 'filter_complex',
37
- value: Media::Filter::Graph.extend(Filter::Graph).build(&blk))
38
- end
39
-
40
- def method_missing(method, *args, &blk)
41
- @context && @context.send(method, *args, &blk)
42
- end
43
- end
44
-
45
- def self.extended(receiver)
46
- receiver.extend(ClassMethods)
47
- receiver.send(:include, InstanceMethods)
48
- end
49
- end
50
- end
51
- end
data/lib/media/label.rb DELETED
@@ -1,11 +0,0 @@
1
- module Media
2
- class Label
3
- def initialize(args)
4
- @name = args.fetch(:name, [])
5
- end
6
-
7
- def to_s
8
- "[#{@name}]"
9
- end
10
- end
11
- end
data/lib/media/size.rb DELETED
@@ -1,12 +0,0 @@
1
- module Media
2
- class Size
3
- def initialize(args)
4
- @width = args.fetch(:width)
5
- @height = args.fetch(:height)
6
- end
7
-
8
- def to_s
9
- [@width, @height].join('x')
10
- end
11
- end
12
- end