mediakit 0.0.1 → 0.0.2
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/.travis.yml +4 -0
- data/README.md +11 -6
- data/Rakefile +16 -1
- data/lib/mediakit/drivers.rb +26 -18
- data/lib/mediakit/ffmpeg/introspection.rb +29 -0
- data/lib/mediakit/ffmpeg/options.rb +14 -26
- data/lib/mediakit/ffmpeg.rb +6 -36
- data/lib/mediakit/ffprobe.rb +1 -5
- data/lib/mediakit/utils/process_runner.rb +159 -0
- data/lib/mediakit/version.rb +1 -1
- data/mediakit.gemspec +2 -2
- data/sample/configure.rb +9 -0
- metadata +21 -18
- data/lib/mediakit/utils/popen_helper.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bce22e6bb5655d6ef5522dfb86cd95660b56119
|
4
|
+
data.tar.gz: 4ae5b7f5a0c1348aa22de26b0da11a80c47f0f05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67789568de47730bc876c7be8971d45bfa6e69179cb227abd4052a390e41aea7eb52939932b144a27bcc2752abe02c690361e88c8e8b9f5973ae3a2897d8ed54
|
7
|
+
data.tar.gz: 8db964b6558ceec920bc45833bcb7e57cccc1a5f6891c69540c40b3934a35761feb7d02f440f0abb0bbfda304bf463c02de0b20b3d21cab73f8854032dc751ef
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Mediakit
|
2
2
|
|
3
|
+
[](https://travis-ci.org/ainame/mediakit)
|
4
|
+
|
3
5
|
mediakit is the libraries for ffmpeg and sox backed media manipulation something.
|
4
6
|
I've design this library for following purpose.
|
5
7
|
|
@@ -8,7 +10,10 @@ I've design this library for following purpose.
|
|
8
10
|
|
9
11
|
## Development Plan
|
10
12
|
|
13
|
+
Currently under development.
|
14
|
+
|
11
15
|
* [x] low-level interface for ffmpeg
|
16
|
+
* [ ] low-level interface's basic feature
|
12
17
|
* [ ] high-level interface for ffmpeg
|
13
18
|
* [ ] low-level interface for sox
|
14
19
|
* [ ] high-level interface for sox
|
@@ -46,18 +51,18 @@ but can pass certain it.
|
|
46
51
|
|
47
52
|
```rb
|
48
53
|
driver = Mediakit::Drivers::FFmpeg.new
|
49
|
-
ffmpeg = Mediakit::
|
54
|
+
ffmpeg = Mediakit::FFmpeg.new(driver)
|
50
55
|
|
51
|
-
options = Mediakit::
|
52
|
-
Mediakit::
|
56
|
+
options = Mediakit::FFmpeg::Options.new(
|
57
|
+
Mediakit::FFmpeg::Options::GlobalOption.new(
|
53
58
|
't' => 100,
|
54
59
|
'y' => true,
|
55
60
|
),
|
56
|
-
Mediakit::
|
61
|
+
Mediakit::FFmpeg::Options::InputFileOption.new(
|
57
62
|
options: nil,
|
58
63
|
path: input,
|
59
64
|
),
|
60
|
-
Mediakit::
|
65
|
+
Mediakit::FFmpeg::Options::OutputFileOption.new(
|
61
66
|
options: {
|
62
67
|
'vf' => 'crop=320:320:0:0',
|
63
68
|
'ar' => '44100',
|
@@ -66,7 +71,7 @@ options = Mediakit::Runners::FFmpeg::Options.new(
|
|
66
71
|
path: output,
|
67
72
|
),
|
68
73
|
)
|
69
|
-
puts "$ ffmpeg
|
74
|
+
puts "$ #{ffmpeg.command(options)}"
|
70
75
|
puts ffmpeg.run(options)
|
71
76
|
```
|
72
77
|
|
data/Rakefile
CHANGED
@@ -1 +1,16 @@
|
|
1
|
-
require
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'yard'
|
5
|
+
require 'yard/rake/yardoc_task'
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.libs << 'test'
|
9
|
+
t.test_files = FileList['test/**/test_*.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
task(default: :test)
|
13
|
+
|
14
|
+
YARD::Rake::YardocTask.new do |t|
|
15
|
+
t.files = ['lib/**/*.rb']
|
16
|
+
end
|
data/lib/mediakit/drivers.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'shellwords'
|
2
|
-
require 'mediakit/utils/
|
2
|
+
require 'mediakit/utils/process_runner'
|
3
3
|
|
4
4
|
module Mediakit
|
5
5
|
module Drivers
|
6
6
|
class DriverError < StandardError; end
|
7
|
+
class FailError < DriverError; end
|
7
8
|
class ConfigurationError < DriverError; end
|
8
9
|
|
9
10
|
class Base
|
@@ -25,18 +26,21 @@ module Mediakit
|
|
25
26
|
# execute command and return result
|
26
27
|
#
|
27
28
|
# @overload run(args)
|
28
|
-
# @param
|
29
|
-
# @overload run(*args)
|
30
|
-
# @param
|
31
|
-
#
|
29
|
+
# @param [String] args string argument for command
|
30
|
+
# @overload run(*args, options)
|
31
|
+
# @param [Array] args arguments for command
|
32
|
+
# @option [Hash] options run options
|
33
|
+
# @return [Bool] stdout output
|
32
34
|
def run(*args)
|
35
|
+
options = (args.last && args.last.kind_of?(Hash)) ? args.pop : {}
|
33
36
|
begin
|
34
|
-
escaped_args = Mediakit::Utils::
|
35
|
-
Mediakit::Utils::
|
36
|
-
|
37
|
+
escaped_args = Mediakit::Utils::ProcessRunner.escape(*args)
|
38
|
+
runner = Mediakit::Utils::ProcessRunner.new(options)
|
39
|
+
stdout, stderr, exit_status = runner.run(bin, escaped_args)
|
40
|
+
raise(FailError, stderr) unless exit_status
|
41
|
+
stdout
|
42
|
+
rescue Mediakit::Utils::ProcessRunner::CommandNotFoundError => e
|
37
43
|
raise(ConfigurationError, "cant' find bin in #{bin}.")
|
38
|
-
rescue => e
|
39
|
-
raise(DriverError, "#{self.class} catch error with command(#{Mediakit::Utils::PopenHelper.command(bin,escaped_args)}) - #{e.message}, #{e.backtrace.join("\n")}")
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
@@ -46,9 +50,9 @@ module Mediakit
|
|
46
50
|
# @param args [String] arguments for command
|
47
51
|
# @overload run(*args)
|
48
52
|
# @param args [Array] arguments for command
|
49
|
-
# @return
|
53
|
+
# @return [String] command
|
50
54
|
def command(*args)
|
51
|
-
escaped_args = Mediakit::Utils::
|
55
|
+
escaped_args = Mediakit::Utils::ProcessRunner.escape(*args)
|
52
56
|
"#{bin} #{escaped_args}"
|
53
57
|
end
|
54
58
|
end
|
@@ -58,18 +62,19 @@ module Mediakit
|
|
58
62
|
#
|
59
63
|
# @overload run(args)
|
60
64
|
# @param args [String] arguments for command
|
61
|
-
# @overload run(*args)
|
65
|
+
# @overload run(*args, options)
|
62
66
|
# @param args [Array] arguments for command
|
63
|
-
#
|
67
|
+
# @option options [Hash] run options
|
68
|
+
# @return [Bool] stdout output
|
64
69
|
def run(args = '')
|
65
70
|
begin
|
66
71
|
# Force escape args string on here,
|
67
72
|
# because this design can't use Cocaine::CommandLine's safety solution.
|
68
|
-
escaped_args = Mediakit::Utils::
|
73
|
+
escaped_args = Mediakit::Utils::ProcessRunner.escape(args.dup)
|
69
74
|
command_line = Cocaine::CommandLine.new(bin, escaped_args, swallow_stderr: true)
|
70
75
|
command_line.run
|
71
|
-
rescue => e
|
72
|
-
raise(
|
76
|
+
rescue Cocaine::ExitStatusError => e
|
77
|
+
raise(FailError, e.message)
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
@@ -79,7 +84,7 @@ module Mediakit
|
|
79
84
|
# @param args [String] arguments for command
|
80
85
|
# @overload run(*args)
|
81
86
|
# @param args [Array] arguments for command
|
82
|
-
# @return
|
87
|
+
# @return [String] command commands to execute
|
83
88
|
def command(args = '')
|
84
89
|
Cocaine::CommandLine.new(bin, args).command
|
85
90
|
end
|
@@ -126,12 +131,15 @@ module Mediakit
|
|
126
131
|
end
|
127
132
|
end
|
128
133
|
|
134
|
+
# factory class for ffmpeg driver
|
129
135
|
class FFmpeg < AbstractFactory
|
130
136
|
end
|
131
137
|
|
138
|
+
# factory class for ffprobe driver
|
132
139
|
class FFprobe < AbstractFactory
|
133
140
|
end
|
134
141
|
|
142
|
+
# factory class for sox driver
|
135
143
|
class Sox < AbstractFactory
|
136
144
|
end
|
137
145
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mediakit
|
2
|
+
class FFmpeg
|
3
|
+
module Introspection
|
4
|
+
DELIMITER_FOR_CODECS = "\n -------\n".freeze
|
5
|
+
DELIMITER_FOR_FORMATS = "\n --\n".freeze
|
6
|
+
DELIMITER_FOR_CODER = "\n ------\n".freeze
|
7
|
+
|
8
|
+
def codecs
|
9
|
+
@codecs ||= run(global_options('codecs')).split(DELIMITER_FOR_CODECS)[1].each_line.to_a
|
10
|
+
end
|
11
|
+
|
12
|
+
def formats
|
13
|
+
@formats ||= run(global_options('formats')).split(DELIMITER_FOR_FORMATS)[1].each_line.to_a
|
14
|
+
end
|
15
|
+
|
16
|
+
def decoders
|
17
|
+
@decoders ||= run(global_options('decoders')).split(DELIMITER_FOR_CODER)[1].each_line.to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def encoders
|
21
|
+
@encoders ||= run(global_options('encoders')).split(DELIMITER_FOR_CODER)[1].each_line.to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
def global_options(flag)
|
25
|
+
Options.new(Options::GlobalOption.new(flag => true))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -9,11 +9,10 @@ module Mediakit
|
|
9
9
|
#
|
10
10
|
class Options
|
11
11
|
attr_reader(:global, :inputs, :output)
|
12
|
-
|
13
|
-
#
|
14
|
-
# @option args
|
15
|
-
# @option
|
16
|
-
# @option args [Mediakit::FFmpeg::Options::OutputFileOption]
|
12
|
+
|
13
|
+
# @option [Mediakit::FFmpeg::Options::GlobalOption] args option
|
14
|
+
# @option [Mediakit::FFmpeg::Options::InputFileOption] args Mediakit::FFmpeg::Options::InputOption
|
15
|
+
# @option [Mediakit::FFmpeg::Options::OutputFileOption] args output file option
|
17
16
|
def initialize(*args)
|
18
17
|
@global, @inputs, @output = nil, [], nil
|
19
18
|
args.each do |option|
|
@@ -61,9 +60,7 @@ module Mediakit
|
|
61
60
|
|
62
61
|
# Base class for Options
|
63
62
|
class OrderedHash < ActiveSupport::OrderedHash
|
64
|
-
#
|
65
|
-
#
|
66
|
-
# @param options [Hash] initial option values
|
63
|
+
# @param [Hash] options initial option values
|
67
64
|
def initialize(options = {})
|
68
65
|
options.each { |key, value| raise_if_invalid_arg_error(key, value) } if options
|
69
66
|
self.merge!(options) if options && options.kind_of?(Hash)
|
@@ -119,8 +116,8 @@ module Mediakit
|
|
119
116
|
end
|
120
117
|
|
121
118
|
class InputFileOption < OptionPathPair
|
122
|
-
# @param
|
123
|
-
# @param
|
119
|
+
# @param [Hash] :options input options
|
120
|
+
# @param [String] :path input file path
|
124
121
|
def initialize(options:, path:)
|
125
122
|
ordered_hash = OrderedHash.new(options)
|
126
123
|
super(options: ordered_hash, path: path)
|
@@ -132,8 +129,8 @@ module Mediakit
|
|
132
129
|
end
|
133
130
|
|
134
131
|
class OutputFileOption < OptionPathPair
|
135
|
-
# @param
|
136
|
-
# @param
|
132
|
+
# @param [Hash] :options output options
|
133
|
+
# @param [String] :path output file path
|
137
134
|
def initialize(options:, path:)
|
138
135
|
ordered_hash = OrderedHash.new(options)
|
139
136
|
super(options: ordered_hash, path: path)
|
@@ -144,23 +141,14 @@ module Mediakit
|
|
144
141
|
end
|
145
142
|
end
|
146
143
|
|
147
|
-
class
|
148
|
-
|
149
|
-
|
150
|
-
# @param *input_file_options [Mediakit::FFmpeg::InputFileOptions]
|
151
|
-
def initialize(*input_file_options)
|
152
|
-
@options = input_file_options
|
153
|
-
end
|
154
|
-
|
155
|
-
def empty?
|
156
|
-
@options.empty?
|
144
|
+
class QuoteString
|
145
|
+
def initialize(string)
|
146
|
+
@string = string
|
157
147
|
end
|
158
148
|
|
159
|
-
def
|
160
|
-
@
|
149
|
+
def to_s
|
150
|
+
"\"#{@string}\""
|
161
151
|
end
|
162
|
-
|
163
|
-
alias_method :to_s, :compose
|
164
152
|
end
|
165
153
|
|
166
154
|
# see https://www.ffmpeg.org/ffmpeg.html#Stream-specifiers-1
|
data/lib/mediakit/ffmpeg.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
require 'mediakit/ffmpeg/options'
|
2
1
|
require 'mediakit/drivers'
|
2
|
+
require 'mediakit/ffmpeg/options'
|
3
|
+
require 'mediakit/ffmpeg/introspection'
|
3
4
|
|
4
5
|
module Mediakit
|
5
6
|
class FFmpeg
|
6
|
-
|
7
|
-
end
|
7
|
+
include Introspection
|
8
|
+
class FFmpegError < StandardError; end
|
8
9
|
|
9
|
-
DELIMITER_FOR_CODECS = "\n -------\n".freeze
|
10
|
-
DELIMITER_FOR_FORMATS = "\n --\n".freeze
|
11
|
-
DELIMITER_FOR_CODER = "\n ------\n".freeze
|
12
10
|
|
13
11
|
def initialize(driver)
|
14
12
|
@driver = driver
|
@@ -16,7 +14,7 @@ module Mediakit
|
|
16
14
|
|
17
15
|
# execute runners with options object
|
18
16
|
#
|
19
|
-
# @param
|
17
|
+
# @param [Mediakit::Runners::FFmpeg::Options] options options to create CLI argument
|
20
18
|
def run(options)
|
21
19
|
args = options.compose
|
22
20
|
execute(args)
|
@@ -27,38 +25,10 @@ module Mediakit
|
|
27
25
|
@driver.command(args)
|
28
26
|
end
|
29
27
|
|
30
|
-
def codecs
|
31
|
-
@codecs ||= run(global_options('codecs')).split(DELIMITER_FOR_CODECS)[1].each_line.to_a
|
32
|
-
end
|
33
|
-
|
34
|
-
def formats
|
35
|
-
@formats ||= run(global_options('formats')).split(DELIMITER_FOR_FORMATS)[1].each_line.to_a
|
36
|
-
end
|
37
|
-
|
38
|
-
def decoders
|
39
|
-
@decoders ||= run(global_options('decoders')).split(DELIMITER_FOR_CODER)[1].each_line.to_a
|
40
|
-
end
|
41
|
-
|
42
|
-
def encoders
|
43
|
-
@encoders ||= run(global_options('encoders')).split(DELIMITER_FOR_CODER)[1].each_line.to_a
|
44
|
-
end
|
45
|
-
|
46
28
|
private
|
47
29
|
|
48
30
|
def execute(args = '')
|
49
|
-
|
50
|
-
@driver.run(args)
|
51
|
-
rescue Drivers::DriverError => e
|
52
|
-
raise(FFmpegError, "#catch driver's error - #{e.message}, #{e.backtrace.join("\n")}")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def global_options(flag)
|
57
|
-
Mediakit::FFmpeg::Options.new(
|
58
|
-
Mediakit::FFmpeg::Options::GlobalOptions.new(
|
59
|
-
flag => true,
|
60
|
-
),
|
61
|
-
)
|
31
|
+
@driver.run(args)
|
62
32
|
end
|
63
33
|
end
|
64
34
|
end
|
data/lib/mediakit/ffprobe.rb
CHANGED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'open3'
|
3
|
+
require 'thread'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
|
7
|
+
module Mediakit
|
8
|
+
module Utils
|
9
|
+
class ProcessRunner
|
10
|
+
class CommandNotFoundError < StandardError;
|
11
|
+
end
|
12
|
+
class TimeoutError < StandardError;
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(timeout: nil)
|
16
|
+
@timeout = timeout
|
17
|
+
end
|
18
|
+
|
19
|
+
# @overload run(command, *args)
|
20
|
+
# @param command [String]
|
21
|
+
# @param args [Array] args as array for safety shellescape
|
22
|
+
# @overload run(command, args)
|
23
|
+
# @param command [String] command name
|
24
|
+
# @param args [Array] args as string
|
25
|
+
# @return out [String] stdout of command
|
26
|
+
# @return err [String] stderr of command
|
27
|
+
# @return exit_status [Boolean] is succeeded
|
28
|
+
def run(bin, *args)
|
29
|
+
command = self.class.command(bin, *args)
|
30
|
+
|
31
|
+
pid, out, err, exit_status = nil
|
32
|
+
out_reader, err_reader = nil
|
33
|
+
watch = TimeoutWatch.new(@timeout)
|
34
|
+
begin
|
35
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3(command)
|
36
|
+
stdin.close
|
37
|
+
pid = wait_thr.pid
|
38
|
+
watch.start(Thread.current)
|
39
|
+
out_reader = IOReader.new(stdout) { |chunk| watch.update }
|
40
|
+
err_reader = IOReader.new(stderr) { |chunk| watch.update }
|
41
|
+
|
42
|
+
wait_thr.join
|
43
|
+
exit_status = (wait_thr.value.exitstatus == 0)
|
44
|
+
rescue Errno::ENOENT => e
|
45
|
+
raise(CommandNotFoundError, "Can't find command - #{command}, #{e.meessage}")
|
46
|
+
rescue Timeout::Error => error
|
47
|
+
Process.kill('SIGKILL', pid)
|
48
|
+
raise(error)
|
49
|
+
ensure
|
50
|
+
out_reader.finish
|
51
|
+
err_reader.finish
|
52
|
+
watch.finish
|
53
|
+
end
|
54
|
+
|
55
|
+
[out_reader.data, err_reader.data, exit_status]
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.command(bin, *args)
|
59
|
+
escaped_args = escape(*args)
|
60
|
+
"#{bin} #{escaped_args}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.escape(*args)
|
64
|
+
case args.size
|
65
|
+
when 1
|
66
|
+
escape_with_split(args[0])
|
67
|
+
else
|
68
|
+
Shellwords.join(args.map { |x| Shellwords.escape(x) })
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def self.escape_with_split(string)
|
75
|
+
splits = Shellwords.split(string)
|
76
|
+
splits = splits.map { |x| Shellwords.escape(x) }
|
77
|
+
splits.join(' ')
|
78
|
+
end
|
79
|
+
|
80
|
+
class IOReader
|
81
|
+
attr_reader(:data)
|
82
|
+
|
83
|
+
def initialize(io, &block)
|
84
|
+
raise(ArgumentError) unless block_given?
|
85
|
+
@io = io
|
86
|
+
@data = ''
|
87
|
+
@block = block
|
88
|
+
start
|
89
|
+
end
|
90
|
+
|
91
|
+
def finish
|
92
|
+
@thread.join
|
93
|
+
@thread.kill
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def start
|
98
|
+
@thread = Thread.new { read }
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def read
|
103
|
+
return if @io.closed?
|
104
|
+
begin
|
105
|
+
while chunk = @io.gets
|
106
|
+
@data << chunk
|
107
|
+
@block.call(chunk) if @block
|
108
|
+
end
|
109
|
+
rescue IOError => e
|
110
|
+
warn "[WARN] IOError #{e.message}"
|
111
|
+
ensure
|
112
|
+
@io.close unless @io.closed?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# watch process progress by io.
|
118
|
+
# when wait time exceed duration, then kill process.
|
119
|
+
class TimeoutWatch
|
120
|
+
attr_reader(:duration)
|
121
|
+
|
122
|
+
def initialize(duration)
|
123
|
+
@duration = duration
|
124
|
+
@watched_at = Time.now
|
125
|
+
@mutex = Mutex.new
|
126
|
+
end
|
127
|
+
|
128
|
+
def start(current_thread, &block)
|
129
|
+
@current_thread = current_thread
|
130
|
+
@watch_thread = Thread.new do
|
131
|
+
loop do
|
132
|
+
if timeout?
|
133
|
+
@current_thread.raise(Timeout::Error, "wait timeout error with #{duration} sec.")
|
134
|
+
end
|
135
|
+
sleep(0.1)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def finish
|
142
|
+
@watch_thread.kill
|
143
|
+
end
|
144
|
+
|
145
|
+
def update
|
146
|
+
@mutex.synchronize do
|
147
|
+
@watched_at = Time.now
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def timeout?
|
154
|
+
(Time.now - @watched_at) > duration
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/mediakit/version.rb
CHANGED
data/mediakit.gemspec
CHANGED
@@ -24,8 +24,8 @@ EOS
|
|
24
24
|
|
25
25
|
spec.add_runtime_dependency "cocaine", "~> 0.5.7"
|
26
26
|
spec.add_runtime_dependency "activesupport", "~> 4"
|
27
|
-
spec.add_development_dependency "bundler", "~> 1.9"
|
28
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
-
spec.add_development_dependency "pry",
|
28
|
+
spec.add_development_dependency "pry", '~> 0.10'
|
30
29
|
spec.add_development_dependency "ruby-debug-ide", "~> 0.4"
|
30
|
+
spec.add_development_dependency "yard", "> 0.8"
|
31
31
|
end
|
data/sample/configure.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'mediakit'
|
2
|
+
|
3
|
+
root = File.expand_path(File.join(File.dirname(__FILE__), '../'))
|
4
|
+
Mediakit::Drivers::FFmpeg.configure do |config|
|
5
|
+
config.bin_path = File.join(root, 'test/supports/ffmpeg')
|
6
|
+
end
|
7
|
+
|
8
|
+
driver = Mediakit::Drivers::FFmpeg.new
|
9
|
+
puts driver.run('-version')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mediakit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ainame
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cocaine
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bundler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.9'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.9'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rake
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +80,20 @@ dependencies:
|
|
94
80
|
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '0.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.8'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.8'
|
97
97
|
description: |
|
98
98
|
mediakit is the libraries for ffmpeg and sox backed media manipulation something.
|
99
99
|
you can create complex manipulation for media as a ruby code.
|
@@ -113,11 +113,13 @@ files:
|
|
113
113
|
- lib/mediakit.rb
|
114
114
|
- lib/mediakit/drivers.rb
|
115
115
|
- lib/mediakit/ffmpeg.rb
|
116
|
+
- lib/mediakit/ffmpeg/introspection.rb
|
116
117
|
- lib/mediakit/ffmpeg/options.rb
|
117
118
|
- lib/mediakit/ffprobe.rb
|
118
|
-
- lib/mediakit/utils/
|
119
|
+
- lib/mediakit/utils/process_runner.rb
|
119
120
|
- lib/mediakit/version.rb
|
120
121
|
- mediakit.gemspec
|
122
|
+
- sample/configure.rb
|
121
123
|
- sample/raw_crop.rb
|
122
124
|
- templates/codec.rb.erb
|
123
125
|
- templates/decoder.rb.erb
|
@@ -142,8 +144,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
144
|
version: '0'
|
143
145
|
requirements: []
|
144
146
|
rubyforge_project:
|
145
|
-
rubygems_version: 2.4.
|
147
|
+
rubygems_version: 2.4.6
|
146
148
|
signing_key:
|
147
149
|
specification_version: 4
|
148
150
|
summary: mediakit is the libraries for ffmpeg and sox backed media manipulation something.
|
149
151
|
test_files: []
|
152
|
+
has_rdoc:
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'shellwords'
|
2
|
-
require 'open3'
|
3
|
-
|
4
|
-
module Mediakit
|
5
|
-
module Utils
|
6
|
-
module PopenHelper
|
7
|
-
|
8
|
-
class CommandNotFoundError < StandardError;
|
9
|
-
end
|
10
|
-
|
11
|
-
# @overload run(command, *args)
|
12
|
-
# @param command [String]
|
13
|
-
# @param args [Array] args as array for safety shellescape
|
14
|
-
# @overload run(command, args)
|
15
|
-
# @param command [String] command name
|
16
|
-
# @param args [Array] args as string
|
17
|
-
# @return out [String] stdout of command
|
18
|
-
# @return err [String] stderr of command
|
19
|
-
# @return exit_status [Boolean] is succeeded
|
20
|
-
def run(bin, *args)
|
21
|
-
command = command(bin, *args)
|
22
|
-
|
23
|
-
out, err, exit_status = nil
|
24
|
-
begin
|
25
|
-
Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
|
26
|
-
stdin.close
|
27
|
-
out = stdout.read
|
28
|
-
err = stderr.read
|
29
|
-
exit_status = (wait_thr.value.exitstatus == 0)
|
30
|
-
end
|
31
|
-
rescue Errno::ENOENT => e
|
32
|
-
raise(CommandNotFoundError, "Can't find command - #{command}, #{e.meessage}")
|
33
|
-
end
|
34
|
-
|
35
|
-
[out, err, exit_status]
|
36
|
-
end
|
37
|
-
|
38
|
-
module_function(:run)
|
39
|
-
|
40
|
-
def command(bin, *args)
|
41
|
-
escaped_args = escape(*args)
|
42
|
-
"#{bin} #{escaped_args}"
|
43
|
-
end
|
44
|
-
|
45
|
-
module_function(:command)
|
46
|
-
|
47
|
-
def escape(*args)
|
48
|
-
case args.size
|
49
|
-
when 1
|
50
|
-
_escape_with_split(args[0])
|
51
|
-
else
|
52
|
-
Shellwords.join(args.map { |x| Shellwords.escape(x) })
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
module_function(:escape)
|
57
|
-
|
58
|
-
def _escape_with_split(string)
|
59
|
-
splits = Shellwords.split(string)
|
60
|
-
splits = splits.map { |x| Shellwords.escape(x) }
|
61
|
-
splits.join(' ')
|
62
|
-
end
|
63
|
-
|
64
|
-
module_function(:_escape_with_split)
|
65
|
-
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|