kastner-kompress 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.
- data/kompress.gemspec +18 -0
- data/lib/kompress.rb +5 -0
- data/lib/kompress/config.rb +5 -7
- data/lib/kompress/job.rb +152 -0
- data/test/config_test.rb +3 -2
- data/test/job-freeze +11 -0
- data/test/job-status +24 -0
- data/test/job_test.rb +115 -0
- data/test/test_helper.rb +2 -0
- metadata +10 -4
data/kompress.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "kompress"
|
3
|
+
s.version = "0.0.2"
|
4
|
+
s.date = "2008-09-14"
|
5
|
+
s.summary = "Kompress - kompress videos and see progress"
|
6
|
+
s.email = "kastner@gmail.com"
|
7
|
+
s.homepage = "http://github.com/kastner/kompress.git"
|
8
|
+
s.description = "Kompress - kompress videos and see progress"
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.require_path = '.'
|
11
|
+
s.authors = ["Erik Kastner"]
|
12
|
+
s.files = ["kompress.gemspec", "lib/kompress", "lib/kompress/compress.rb",
|
13
|
+
"lib/kompress/config.rb", "lib/kompress/exceptions.rb", "lib/kompress/job.rb",
|
14
|
+
"lib/kompress.rb", "README.mkdn", "test/config_test.rb", "test/job-freeze",
|
15
|
+
"test/job-status", "test/job_test.rb", "test/test_helper.rb"]
|
16
|
+
|
17
|
+
s.rdoc_options = ["--main", "README.mkdn"]
|
18
|
+
end
|
data/lib/kompress.rb
CHANGED
data/lib/kompress/config.rb
CHANGED
@@ -29,8 +29,12 @@ module Kompress
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def reset
|
33
|
+
@commands = @settings = nil
|
34
|
+
end
|
35
|
+
|
32
36
|
class Preset
|
33
|
-
attr_reader :name
|
37
|
+
attr_reader :name, :command
|
34
38
|
attr_accessor :options
|
35
39
|
|
36
40
|
def initialize(name, options = {})
|
@@ -39,12 +43,6 @@ module Kompress
|
|
39
43
|
@options = options
|
40
44
|
end
|
41
45
|
|
42
|
-
def command
|
43
|
-
kc = Kompress::Config
|
44
|
-
replacements = kc.settings.merge(kc.commands.merge(@options))
|
45
|
-
@command.gsub(/:\w+/) {|s| replacements[s.gsub(/^:/,'').intern] || s }
|
46
|
-
end
|
47
|
-
|
48
46
|
def description
|
49
47
|
@options[:description] || @name
|
50
48
|
end
|
data/lib/kompress/job.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
module Kompress
|
2
|
+
class Job
|
3
|
+
attr_accessor :options, :job_id, :input_file, :container_type
|
4
|
+
attr_accessor :state
|
5
|
+
|
6
|
+
def self.from_file(file)
|
7
|
+
rpls = YAML.load(open(file).read)
|
8
|
+
job = new
|
9
|
+
job.instance_eval do
|
10
|
+
@state = :running
|
11
|
+
@job_id = rpls[:job_id]
|
12
|
+
@container_type = rpls[:container_type]
|
13
|
+
@input_file = rpls[:input_file]
|
14
|
+
@options = rpls
|
15
|
+
def replacements; @options; end
|
16
|
+
end
|
17
|
+
job
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_preset(preset, input_file, container_type = "mp4")
|
21
|
+
config_preset = Kompress::Config.presets[preset]
|
22
|
+
raise Kompress::NoConfigurationError unless config_preset
|
23
|
+
|
24
|
+
job = new
|
25
|
+
job.fill(preset, config_preset.command, input_file, container_type, config_preset.options)
|
26
|
+
job
|
27
|
+
end
|
28
|
+
|
29
|
+
def fill(name, command, input_file, container_type, options)
|
30
|
+
@state = :pending
|
31
|
+
@options, @input_file, @command = options, input_file, command
|
32
|
+
@container_type = container_type
|
33
|
+
@job_id = Time.now.to_i.to_s + "-" + name.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def kc_replacements
|
37
|
+
kc = Kompress::Config
|
38
|
+
(kc.settings || {}).merge((kc.commands || {}).merge(@options))
|
39
|
+
end
|
40
|
+
|
41
|
+
def replacements
|
42
|
+
rpl = {}
|
43
|
+
rpl[:job_id] = @job_id
|
44
|
+
rpl[:container_type] = @container_type
|
45
|
+
rpl[:input_file] = @input_file
|
46
|
+
rpl.merge(kc_replacements)
|
47
|
+
end
|
48
|
+
|
49
|
+
def command
|
50
|
+
substitute(@command, replacements)
|
51
|
+
end
|
52
|
+
|
53
|
+
def post_command
|
54
|
+
substitute(options[:post_command], replacements)
|
55
|
+
end
|
56
|
+
|
57
|
+
def temp_file
|
58
|
+
input_file.gsub(/\.(mov|avi|mp4|flv|wmv)$/, ".tmp.#{container_type}")
|
59
|
+
end
|
60
|
+
|
61
|
+
def output_file
|
62
|
+
input_file.gsub(/\.(mov|avi|mp4|flv|wmv)$/, ".#{container_type}")
|
63
|
+
end
|
64
|
+
|
65
|
+
def substitute(string, subs)
|
66
|
+
string.gsub(/:\w+/) do |s|
|
67
|
+
s.gsub!(/^:/, '')
|
68
|
+
if respond_to?(s)
|
69
|
+
send(s)
|
70
|
+
else
|
71
|
+
subs[s.gsub(/^:/,'').intern] || s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def status_file
|
77
|
+
kc_replacements[:directory] + "/kompress-#{@job_id}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def state_file
|
81
|
+
kc_replacements[:directory] + "/kompress-#{@job_id}.state"
|
82
|
+
end
|
83
|
+
|
84
|
+
def done_file
|
85
|
+
kc_replacements[:directory] + "/kompress-#{@job_id}.done"
|
86
|
+
end
|
87
|
+
|
88
|
+
def status_contents
|
89
|
+
open(status_file).read
|
90
|
+
end
|
91
|
+
|
92
|
+
def frame_rate
|
93
|
+
@frame_rate ||= status_contents[@options[:frame_rate_regexp], 1].to_f
|
94
|
+
end
|
95
|
+
|
96
|
+
def duration
|
97
|
+
@duration ||= begin
|
98
|
+
d = status_contents[@options[:duration_regexp], 1]
|
99
|
+
if (d.match(/:/))
|
100
|
+
p = d.split(/:/)
|
101
|
+
p[-1].to_f + p[-2].to_f * 60 + p[-3].to_f * 60 * 60
|
102
|
+
else
|
103
|
+
d.to_f
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def total_frames
|
109
|
+
duration * frame_rate
|
110
|
+
end
|
111
|
+
|
112
|
+
def current_frame
|
113
|
+
return 0 unless @state == :running
|
114
|
+
matches = status_contents.scan(@options[:current_frame_regexp])
|
115
|
+
|
116
|
+
if (File.exists?(done_file))
|
117
|
+
@state = :done
|
118
|
+
finalize
|
119
|
+
end
|
120
|
+
|
121
|
+
matches.last[0].to_i
|
122
|
+
end
|
123
|
+
|
124
|
+
def finalize
|
125
|
+
system(post_command) if post_command
|
126
|
+
cleanup
|
127
|
+
end
|
128
|
+
|
129
|
+
def cleanup
|
130
|
+
File.unlink(state_file)
|
131
|
+
File.unlink(status_file)
|
132
|
+
File.unlink(done_file)
|
133
|
+
File.unlink(temp_file)
|
134
|
+
end
|
135
|
+
|
136
|
+
def write_state_to_disk
|
137
|
+
File.open(state_file, "w") do |f|
|
138
|
+
f.puts replacements.to_yaml
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def go
|
143
|
+
@state = :running
|
144
|
+
write_state_to_disk
|
145
|
+
Thread.new do
|
146
|
+
system command
|
147
|
+
end
|
148
|
+
|
149
|
+
while (!File.exists?(status_file)); sleep 0.2; end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
data/test/config_test.rb
CHANGED
@@ -26,8 +26,9 @@ describe "Kompress::Config" do
|
|
26
26
|
Kompress::Config.settings[:directory].should == "/t"
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should
|
30
|
-
Kompress::Config.
|
29
|
+
it "should be emptyable" do
|
30
|
+
Kompress::Config.reset
|
31
|
+
Kompress::Config.settings.should == nil
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
data/test/job-freeze
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
---
|
2
|
+
:frame_rate_regexp: !ruby/regexp /0.0,,,,,Video,.*q=.*,([\d\.]+)$/
|
3
|
+
:job_id: 1221549341-rad
|
4
|
+
:post_command: ":qt_faststart :temp_file :output_file"
|
5
|
+
:qt_faststart: /usr/bin/qt-faststart
|
6
|
+
:current_frame_regexp: !ruby/regexp /frame=\s*(\d+)/
|
7
|
+
:input_file: ~/Development/Ruby/test.mov
|
8
|
+
:container_type: mp4
|
9
|
+
:duration_regexp: !ruby/regexp /Duration-(\d+)/
|
10
|
+
:ffmpeg: /Library/Application\ Support/Techspansion/vh131ffmpeg
|
11
|
+
:directory: /tmp
|
data/test/job-status
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
FFmpeg version SVN-r9226, Copyright (c) 2000-2007 Fabrice Bellard, et al.
|
2
|
+
libavutil: 49.4.0 libavcodec: 51.40.4 libavformat: 51.12.1
|
3
|
+
built: Feb 12 2008 19:58:15, gcc: 4.0.1 (Apple Computer, Inc. build 5367), i386
|
4
|
+
|
5
|
+
Seems stream 0 codec frame rate differs from container frame rate: 1000.00 (1000/1) -> 44.92 (539/12)
|
6
|
+
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/kastner/Development/Ruby/test.mov':
|
7
|
+
Duration-06
|
8
|
+
start-0.000000
|
9
|
+
bitrate-1585
|
10
|
+
|
11
|
+
0.0,,,(eng),,Video,mpeg4,yuv420p,640,480,44.92
|
12
|
+
0.1,,,(eng),,Audio,mpeg4aac,44100,2
|
13
|
+
Output #0, mp4, to '/Users/kastner/Development/Ruby/test.tmp.mp4':
|
14
|
+
0.0,,,,,Video,mpeg4,yuv420p,640,480, q=1-31,44.92
|
15
|
+
0.1,,,,,Audio,libfaac,44100,2,64
|
16
|
+
Stream mapping:
|
17
|
+
Stream #0.0 -> #0.0
|
18
|
+
Stream #0.1 -> #0.1
|
19
|
+
Press [q] to stop encoding
|
20
|
+
frame= 54 fps= 0 q=4.2 size= 183kB time=1.2 bitrate=1244.3kbits/s
|
21
|
+
frame= 114 fps=113 q=8.9 size= 269kB time=2.5 bitrate= 895.3kbits/s
|
22
|
+
frame= 157 fps=115 q=9.4 Lsize= 330kB time=3.4 bitrate= 796.3kbits/s
|
23
|
+
video:12kB audio:19kB global headers:0kB muxing overhead 935.696529%
|
24
|
+
Received signal 2: terminating.
|
data/test/job_test.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
describe "Kompress::Job" do
|
4
|
+
setup do
|
5
|
+
Kompress::Config.write do |k|
|
6
|
+
k.command :ffmpeg => "/usr/bin/ffmpeg"
|
7
|
+
k.setting :directory => "/t"
|
8
|
+
|
9
|
+
k.preset :test => {
|
10
|
+
:command => ":ffmpeg go > :directory/:job_id"
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
@job = Kompress::Job.from_preset(:test, "")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should substitue placeholders" do
|
18
|
+
@job.command.should.match /\/ffmpeg/
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should substitue job_id placeholder" do
|
22
|
+
@job.command.should == "/usr/bin/ffmpeg go > /t/#{@job.job_id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set a status file" do
|
26
|
+
@job.status_file.should == "/t/kompress-#{@job.job_id}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "A fake job" do
|
31
|
+
setup do
|
32
|
+
Kompress::Config.write do |k|
|
33
|
+
k.preset :t => { :duration_regexp => /Duration: ([\d:]+)/ }
|
34
|
+
end
|
35
|
+
|
36
|
+
@job = Kompress::Job.from_preset(:t, "")
|
37
|
+
@job.stubs(:status_contents).returns("Duration: 00:01:26.95, start: 0.0000")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should calculate seconds" do
|
41
|
+
@job.duration.should == 86.0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "A real job" do
|
46
|
+
setup do
|
47
|
+
Kompress::Config.write do |k|
|
48
|
+
k.command :ffmpeg => "/Library/Application\\ Support/Techspansion/vh131ffmpeg"
|
49
|
+
k.setting :directory => "/tmp"
|
50
|
+
k.setting :qt_faststart => "/usr/bin/qt-faststart"
|
51
|
+
|
52
|
+
k.preset :rad => {
|
53
|
+
:command => %Q{:ffmpeg -y -i :input_file :temp_file 2>> :status_file ; echo done > :done_file},
|
54
|
+
:post_command => %Q{:qt_faststart :temp_file :output_file},
|
55
|
+
:frame_rate_regexp => /0.0,,,,,Video,.*q=.*,([\d\.]+)$/,
|
56
|
+
:duration_regexp => /Duration-(\d+)/,
|
57
|
+
:current_frame_regexp => /frame=\s*(\d+)/
|
58
|
+
}
|
59
|
+
|
60
|
+
@job = Kompress::Job.from_preset(:rad, "~/Development/Ruby/test.mov")
|
61
|
+
@job.state = :running
|
62
|
+
end
|
63
|
+
|
64
|
+
@job.stubs(:status_contents).returns(open(File.dirname(__FILE__) + '/job-status').read)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should know it's post_command" do
|
68
|
+
@job.post_command.should == "/usr/bin/qt-faststart ~/Development/Ruby/test.tmp.mp4 ~/Development/Ruby/test.mp4"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should know frame rate" do
|
72
|
+
@job.frame_rate.should == 44.92
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should know duration" do
|
76
|
+
@job.duration.should == 6.0
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should know total frames" do
|
80
|
+
@job.total_frames.should == 269.52
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should know it's current frame #" do
|
84
|
+
@job.current_frame.should == 157
|
85
|
+
# puts @job.replacements.to_yaml
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "A frozen job" do
|
90
|
+
setup do
|
91
|
+
Kompress::Config.reset
|
92
|
+
@job = Kompress::Job.from_file(File.dirname(__FILE__) + "/job-freeze")
|
93
|
+
@job.stubs(:status_contents).returns(open(File.dirname(__FILE__) + '/job-status').read)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should have the right job id" do
|
97
|
+
@job.job_id.should == "1221549341-rad"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should be able to fetch the duration" do
|
101
|
+
@job.duration.should == 6.0
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have the right post_command" do
|
105
|
+
@job.post_command.should == "/usr/bin/qt-faststart ~/Development/Ruby/test.tmp.mp4 ~/Development/Ruby/test.mp4"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should have a lame kc_replacements method" do
|
109
|
+
@job.kc_replacements.should == @job.options
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should be considered active" do
|
113
|
+
@job.state.should == :running
|
114
|
+
end
|
115
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kastner-kompress
|
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
|
- Erik Kastner
|
@@ -22,13 +22,19 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
-
|
26
|
-
-
|
25
|
+
- kompress.gemspec
|
26
|
+
- lib/kompress
|
27
27
|
- lib/kompress/compress.rb
|
28
28
|
- lib/kompress/config.rb
|
29
29
|
- lib/kompress/exceptions.rb
|
30
|
-
-
|
30
|
+
- lib/kompress/job.rb
|
31
|
+
- lib/kompress.rb
|
32
|
+
- README.mkdn
|
31
33
|
- test/config_test.rb
|
34
|
+
- test/job-freeze
|
35
|
+
- test/job-status
|
36
|
+
- test/job_test.rb
|
37
|
+
- test/test_helper.rb
|
32
38
|
has_rdoc: false
|
33
39
|
homepage: http://github.com/kastner/kompress.git
|
34
40
|
post_install_message:
|