aviglitch 0.0.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.
- data/ChangeLog +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +43 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/bin/datamosh +25 -0
- data/lib/aviglitch.rb +170 -0
- data/lib/aviglitch/frame.rb +64 -0
- data/lib/aviglitch/frames.rb +97 -0
- data/spec/aviglitch_spec.rb +109 -0
- data/spec/files/sample.avi +0 -0
- data/spec/spec_helper.rb +14 -0
- metadata +76 -0
data/ChangeLog
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 ucnv
|
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.rdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
= AviGlitch
|
2
|
+
|
3
|
+
* http://github.com/ucnv/aviglitch/tree/master
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
AviGlitch destroys your AVI files.
|
8
|
+
|
9
|
+
I can't explain why they're going to destroy their own data.
|
10
|
+
|
11
|
+
See followig urls for details;
|
12
|
+
* vimeo http://www.vimeo.com/groups/artifacts
|
13
|
+
* wikipedia http://en.wikipedia.org/wiki/Compression_artifact
|
14
|
+
|
15
|
+
== Features/Problems
|
16
|
+
|
17
|
+
* Not supports AVI2 files right now.
|
18
|
+
* Not supports files with interleave.
|
19
|
+
* Parses only container level structure, not parses codecs.
|
20
|
+
|
21
|
+
== Synopsis
|
22
|
+
|
23
|
+
require 'aviglitch'
|
24
|
+
|
25
|
+
avi = AviGlitch.new('/path/to/your.avi')
|
26
|
+
avi.glitch(:keyframe) do |data|
|
27
|
+
data.gsub(/\d/, '0')
|
28
|
+
end
|
29
|
+
avi.write('/path/to/broken.avi')
|
30
|
+
|
31
|
+
This library also includes a command tool named +datamosh+.
|
32
|
+
It creates the keyframes removed video.
|
33
|
+
|
34
|
+
$ datamosh /path/to/your.avi /path/to/broken.avi
|
35
|
+
|
36
|
+
== Installation
|
37
|
+
|
38
|
+
gem sources -a http://gems.github.com
|
39
|
+
sudo gem install ucnv-aviglitch
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2009 ucnv. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "aviglitch"
|
8
|
+
gem.summary = "A Ruby library to destroy your AVI files."
|
9
|
+
gem.email = "ucnvvv@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/ucnv/aviglitch"
|
11
|
+
gem.authors = ["ucnv"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
gem.files = %w(README.rdoc ChangeLog Rakefile VERSION) +
|
14
|
+
Dir.glob("{bin,spec,lib}/**/*")
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
27
|
+
|
28
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
if File.exist?('VERSION.yml')
|
40
|
+
config = YAML.load(File.read('VERSION.yml'))
|
41
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
42
|
+
else
|
43
|
+
version = ""
|
44
|
+
end
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "aviglitch #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
51
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/datamosh
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Generate datamoshing
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'aviglitch'
|
6
|
+
|
7
|
+
if ARGV.size < 1 || ARGV.first == '--help'
|
8
|
+
puts <<-BANNER.gsub(/^\s+/, '')
|
9
|
+
Usage: #{File.basename $0} INPUT [OUTPUT]
|
10
|
+
Generate a datamoshing video from INPUT to OUTPUT (./out.avi by default).
|
11
|
+
BANNER
|
12
|
+
exit 0
|
13
|
+
end
|
14
|
+
|
15
|
+
input, output = ARGV
|
16
|
+
|
17
|
+
a = AviGlitch.new input
|
18
|
+
a.glitch_with_index :keyframe do |frame, i|
|
19
|
+
if i == 0 # keep the first frame
|
20
|
+
frame
|
21
|
+
else
|
22
|
+
"\000" * frame.size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
a.write(output || 'out.avi')
|
data/lib/aviglitch.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'aviglitch/frame'
|
4
|
+
require 'aviglitch/frames'
|
5
|
+
|
6
|
+
# AviGlitch provides the ways to glitch AVI formatted video files.
|
7
|
+
#
|
8
|
+
# == Synopsis:
|
9
|
+
#
|
10
|
+
# You can manipulate each frame, like:
|
11
|
+
#
|
12
|
+
# avi = Aviglitch.new '/path/to/your.avi'
|
13
|
+
# avi.frames.each |frame|
|
14
|
+
# if frame.is_keyframe?
|
15
|
+
# frame.data = frame.data.gsub(/\d/, '0')
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
# avi.write '/path/to/broken.avi'
|
19
|
+
#
|
20
|
+
# Using the method glitch, it can be written like:
|
21
|
+
#
|
22
|
+
# avi = AviGlitch.new '/path/to/your.avi'
|
23
|
+
# avi.glitch(:keyframe) do |data|
|
24
|
+
# data.gsub(/\d/, '0')
|
25
|
+
# end
|
26
|
+
# avi.write '/path/to/broken.avi'
|
27
|
+
#
|
28
|
+
#--
|
29
|
+
# It does not support AVI2, interleave format.
|
30
|
+
#
|
31
|
+
class AviGlitch
|
32
|
+
|
33
|
+
VERSION = '0.0.1'
|
34
|
+
|
35
|
+
# AviGlitch::Frames object generated from the +file+.
|
36
|
+
attr_reader :frames
|
37
|
+
# The input file (copied tempfile).
|
38
|
+
attr_reader :file
|
39
|
+
|
40
|
+
##
|
41
|
+
# Create a new instance of AviGlitch, open the file and
|
42
|
+
# make it ready to manipulate.
|
43
|
+
# It requires +path+ as String or Pathname.
|
44
|
+
def initialize path
|
45
|
+
File.open(path) do |f|
|
46
|
+
# copy as tempfile
|
47
|
+
@file = Tempfile.open 'aviglitch'
|
48
|
+
f.rewind
|
49
|
+
while d = f.read(1024) do
|
50
|
+
@file.print d
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
unless AviGlitch.surely_formatted? @file
|
55
|
+
raise 'Unsupported file passed.'
|
56
|
+
end
|
57
|
+
@frames = Frames.new @file
|
58
|
+
# I believe Ruby's GC to close and remove the Tempfile..
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Output the glitched file to +path+, and close the file.
|
63
|
+
def write path
|
64
|
+
FileUtils.cp @file.path, path
|
65
|
+
close
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# An explicit file close.
|
70
|
+
def close
|
71
|
+
@file.close!
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Glitch each frame data.
|
76
|
+
# It is a convent method to iterate each frame.
|
77
|
+
#
|
78
|
+
# The argument +target+ takes symbols listed below:
|
79
|
+
# [<tt>:keyframe</tt> or <tt>:iframe</tt>] select video key frames (aka I-frame)
|
80
|
+
# [<tt>:deltaframe</tt> or <tt>:pframe</tt>] select video delta frames (difference frames)
|
81
|
+
# [<tt>:videoframe</tt>] select both of keyframe and deltaframe
|
82
|
+
# [<tt>:audioframe</tt>] select audio frames
|
83
|
+
# [<tt>:all</tt>] select all frames
|
84
|
+
#
|
85
|
+
# It also requires a block. In the block, you take the frame data
|
86
|
+
# as a String parameter.
|
87
|
+
# To modify the data, simply return a modified data.
|
88
|
+
def glitch target = :all, &block # :yield: data
|
89
|
+
frames.each do |frame|
|
90
|
+
if valid_target? target, frame
|
91
|
+
frame.data = yield frame.data
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Do glitch with index.
|
98
|
+
def glitch_with_index target = :all, &block # :yield: data, index
|
99
|
+
i = 0
|
100
|
+
frames.each do |frame|
|
101
|
+
if valid_target? target, frame
|
102
|
+
frame.data = yield(frame.data, i)
|
103
|
+
i += 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
alias :output :write
|
109
|
+
|
110
|
+
def valid_target? target, frame # :nodoc:
|
111
|
+
return true if target == :all
|
112
|
+
begin
|
113
|
+
frame.send "is_#{target.to_s}?"
|
114
|
+
rescue
|
115
|
+
false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
private_instance_methods :valid_target?
|
120
|
+
class << self
|
121
|
+
|
122
|
+
##
|
123
|
+
# Check if the +file+ is a correctly formetted AVI file.
|
124
|
+
# +file+ can be String or Pathname or IO.
|
125
|
+
def surely_formatted? file, debug = false
|
126
|
+
answer = true
|
127
|
+
is_io = file.respond_to?(:seek) # Probably IO.
|
128
|
+
file = File.open(file) unless is_io
|
129
|
+
begin
|
130
|
+
file.seek 0, IO::SEEK_END
|
131
|
+
eof = file.pos
|
132
|
+
file.rewind
|
133
|
+
unless file.read(4) == 'RIFF'
|
134
|
+
answer = false
|
135
|
+
warn 'RIFF sign is not found' if debug
|
136
|
+
end
|
137
|
+
len = file.read(4).unpack('V').first
|
138
|
+
unless len + 8 == eof
|
139
|
+
answer = false
|
140
|
+
warn 'Length info is invalid' if debug
|
141
|
+
end
|
142
|
+
unless file.read(4) == 'AVI '
|
143
|
+
answer = false
|
144
|
+
warn 'AVI sign is not found' if debug
|
145
|
+
end
|
146
|
+
while file.read(4) =~ /^(?:LIST|JUNK)$/ do
|
147
|
+
s = file.read(4).unpack('V').first
|
148
|
+
file.pos += s
|
149
|
+
end
|
150
|
+
file.pos -= 4
|
151
|
+
# we require idx1
|
152
|
+
unless file.read(4) == 'idx1'
|
153
|
+
answer = false
|
154
|
+
warn 'idx1 is not found' if debug
|
155
|
+
end
|
156
|
+
s = file.read(4).unpack('V').first
|
157
|
+
file.pos += s
|
158
|
+
rescue => err
|
159
|
+
warn err.message if debug
|
160
|
+
answer = false
|
161
|
+
ensure
|
162
|
+
file.close unless is_io
|
163
|
+
end
|
164
|
+
answer
|
165
|
+
end
|
166
|
+
|
167
|
+
alias :open :new
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class AviGlitch
|
2
|
+
|
3
|
+
# Frame is the struct of the frame data and meta-data.
|
4
|
+
# You can access this class through AviGlitch::Frames.
|
5
|
+
# To modify the binary data, operate the +data+ property.
|
6
|
+
class Frame
|
7
|
+
|
8
|
+
AVIIF_LIST = 0x00000001
|
9
|
+
AVIIF_KEYFRAME = 0x00000010
|
10
|
+
AVIIF_NO_TIME = 0x00000100
|
11
|
+
|
12
|
+
attr_accessor :data
|
13
|
+
attr_reader :id, :flag
|
14
|
+
|
15
|
+
##
|
16
|
+
# Create a new AviGlitch::Frame object.
|
17
|
+
#
|
18
|
+
# The arguments are:
|
19
|
+
# [+data+] just data, without meta-data
|
20
|
+
# [+id+] id for the stream number and content type code
|
21
|
+
# (like "00dc")
|
22
|
+
# [+flag+] flag that describes the chunk type (taken from idx1)
|
23
|
+
#
|
24
|
+
def initialize data, id, flag
|
25
|
+
@data = data
|
26
|
+
@id = id
|
27
|
+
@flag = flag
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Returns if it is a video frame and also a key frame.
|
32
|
+
def is_keyframe?
|
33
|
+
is_videoframe? && @flag & AVIIF_KEYFRAME != 0
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Alias for is_keyframe?
|
38
|
+
alias :is_iframe? :is_keyframe?
|
39
|
+
|
40
|
+
##
|
41
|
+
# Returns if it is a video frame and also not a key frame.
|
42
|
+
def is_deltaframe?
|
43
|
+
is_videoframe? && @flag & AVIIF_KEYFRAME == 0
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Alias for is_deltaframe?
|
48
|
+
alias :is_pframe? :is_deltaframe?
|
49
|
+
|
50
|
+
##
|
51
|
+
# Returns if it is a video frame.
|
52
|
+
def is_videoframe?
|
53
|
+
@id[2, 2] == 'db' || @id[2, 2] == 'dc'
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Returns if it is an audio frame.
|
58
|
+
def is_audioframe?
|
59
|
+
@id[2, 2] == 'wb'
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class AviGlitch
|
2
|
+
|
3
|
+
# Frames provides the interface to access each frame
|
4
|
+
# in the AVI file.
|
5
|
+
# It is implemented as Enumerable. You can access this object
|
6
|
+
# through AviGlitch#frames, for example:
|
7
|
+
#
|
8
|
+
# avi = AviGlitch.new '/path/to/your.avi'
|
9
|
+
# frames = avi.frames
|
10
|
+
# frames.each do |frame|
|
11
|
+
# ## frame is a reference of a AviGlitch::Frame object
|
12
|
+
# frame.data = frame.data.gsub(/\d/, '0')
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# In the block passed into iteration method, the parameter is the reference
|
16
|
+
# of AviGlitch::Frame object.
|
17
|
+
#
|
18
|
+
class Frames
|
19
|
+
include Enumerable
|
20
|
+
|
21
|
+
def initialize io
|
22
|
+
io.rewind
|
23
|
+
io.pos = 12 # /^RIFF[\s\S]{4}AVI $/
|
24
|
+
while io.read(4) =~ /^(?:LIST|JUNK)$/ do
|
25
|
+
s = io.read(4).unpack('V').first
|
26
|
+
@pos_of_movi = io.pos - 4 if io.read(4) == 'movi'
|
27
|
+
io.pos += s - 4
|
28
|
+
end
|
29
|
+
@pos_of_idx1 = io.pos - 4 # here must be idx1
|
30
|
+
s = io.read(4).unpack('V').first + io.pos
|
31
|
+
@meta = []
|
32
|
+
while chunk_id = io.read(4) do
|
33
|
+
break if io.pos >= s
|
34
|
+
@meta << {
|
35
|
+
:id => chunk_id,
|
36
|
+
:flag => io.read(4).unpack('V').first,
|
37
|
+
:offset => io.read(4).unpack('V').first,
|
38
|
+
:size => io.read(4).unpack('V').first,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
io.rewind
|
42
|
+
@io = io
|
43
|
+
end
|
44
|
+
|
45
|
+
def each
|
46
|
+
temp = Tempfile.new 'frames'
|
47
|
+
temp.print 'movi'
|
48
|
+
@meta = @meta.select do |m|
|
49
|
+
@io.pos = @pos_of_movi + m[:offset] + 8
|
50
|
+
frame = Frame.new(@io.read(m[:size]), m[:id], m[:flag])
|
51
|
+
yield frame
|
52
|
+
unless frame.data.nil? || frame.data.to_s.empty?
|
53
|
+
m[:offset] = temp.pos
|
54
|
+
m[:size] = frame.data.size
|
55
|
+
temp.print m[:id]
|
56
|
+
temp.print [frame.data.size].pack('V')
|
57
|
+
temp.print frame.data
|
58
|
+
temp.print "\000" if frame.data.size % 2 == 1
|
59
|
+
true
|
60
|
+
else
|
61
|
+
false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Overwrite the file
|
66
|
+
@io.pos = @pos_of_movi - 4
|
67
|
+
@io.print [temp.pos].pack('V')
|
68
|
+
temp.rewind
|
69
|
+
while d = temp.read(1024) do
|
70
|
+
@io.print d
|
71
|
+
end
|
72
|
+
temp.close true
|
73
|
+
@io.print 'idx1'
|
74
|
+
@io.print [@meta.size * 16].pack('V')
|
75
|
+
@meta.each do |m|
|
76
|
+
@io.print m[:id]
|
77
|
+
@io.print [m[:flag], m[:offset], m[:size]].pack('V3')
|
78
|
+
end
|
79
|
+
eof = @io.pos
|
80
|
+
@io.truncate eof
|
81
|
+
|
82
|
+
# Fix info
|
83
|
+
## file size
|
84
|
+
@io.pos = 4
|
85
|
+
@io.print [eof - 8].pack('V')
|
86
|
+
## frame count
|
87
|
+
@io.pos = 48
|
88
|
+
@io.print [@meta.size].pack('V')
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
def size
|
93
|
+
@meta.size
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe AviGlitch do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
FileUtils.mkdir OUTPUT_DIR unless File.exist? OUTPUT_DIR
|
7
|
+
@in = FILES_DIR + 'sample.avi'
|
8
|
+
@out = OUTPUT_DIR + 'out.avi'
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
FileUtils.rm Dir.glob((OUTPUT_DIR + '*').to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
FileUtils.rmdir OUTPUT_DIR
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'raise an error against unsupported files' do
|
20
|
+
lambda {
|
21
|
+
avi = AviGlitch.new __FILE__
|
22
|
+
}.should raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'saves the same file when nothing is changed' do
|
26
|
+
avi = AviGlitch.new @in
|
27
|
+
avi.frames.each do |f|
|
28
|
+
;
|
29
|
+
end
|
30
|
+
avi.write @out
|
31
|
+
FileUtils.cmp(@in, @out).should be true
|
32
|
+
|
33
|
+
avi = AviGlitch.new @in
|
34
|
+
avi.glitch do |d|
|
35
|
+
d
|
36
|
+
end
|
37
|
+
avi.write @out
|
38
|
+
FileUtils.cmp(@in, @out).should be true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'can manipulate each frame' do
|
42
|
+
avi = AviGlitch.new @in
|
43
|
+
f = avi.frames
|
44
|
+
f.should be_kind_of Enumerable
|
45
|
+
avi.frames.each do |f|
|
46
|
+
if f.is_keyframe?
|
47
|
+
f.data = f.data.gsub(/\d/, '0')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
avi.write @out
|
51
|
+
AviGlitch.surely_formatted?(@out, true).should be true
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can glitch each keyframe' do
|
55
|
+
avi = AviGlitch.new @in
|
56
|
+
n = 0
|
57
|
+
avi.glitch :keyframe do |kf|
|
58
|
+
n += 1
|
59
|
+
kf.slice(10..kf.size)
|
60
|
+
end
|
61
|
+
avi.write @out
|
62
|
+
i_size = File.stat(@in).size
|
63
|
+
o_size = File.stat(@out).size
|
64
|
+
o_size.should == i_size - (10 * n)
|
65
|
+
AviGlitch.surely_formatted?(@out, true).should be true
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'can glitch each keyframe with index' do
|
69
|
+
avi = AviGlitch.new @in
|
70
|
+
avi.glitch_with_index :keyframe do |kf, idx|
|
71
|
+
if idx < 25
|
72
|
+
kf.slice(10..kf.size)
|
73
|
+
else
|
74
|
+
kf
|
75
|
+
end
|
76
|
+
end
|
77
|
+
avi.write @out
|
78
|
+
i_size = File.stat(@in).size
|
79
|
+
o_size = File.stat(@out).size
|
80
|
+
o_size.should == i_size - (10 * 25)
|
81
|
+
AviGlitch.surely_formatted?(@out, true).should be true
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'can remove a frame with returning nil' do
|
85
|
+
avi = AviGlitch.new @in
|
86
|
+
in_frame_size = avi.frames.size
|
87
|
+
rem_count = 0
|
88
|
+
avi.glitch :keyframe do |kf|
|
89
|
+
rem_count += 1
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
avi.write @out
|
93
|
+
AviGlitch.surely_formatted?(@out, true).should be true
|
94
|
+
|
95
|
+
# frames length in the output file is correct
|
96
|
+
avi = AviGlitch.new @out
|
97
|
+
out_frame_size = avi.frames.size
|
98
|
+
out_frame_size.should == in_frame_size - rem_count
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'has some alias methods' do
|
102
|
+
lambda {
|
103
|
+
avi = AviGlitch.open @in
|
104
|
+
avi.output @out
|
105
|
+
}.should_not raise_error
|
106
|
+
AviGlitch.surely_formatted?(@out, true).should be true
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
require 'aviglitch'
|
6
|
+
require 'pathname'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
FILES_DIR = Pathname.new(File.dirname(__FILE__)).realpath + 'files'
|
10
|
+
OUTPUT_DIR = FILES_DIR + 'output'
|
11
|
+
|
12
|
+
Spec::Runner.configure do |config|
|
13
|
+
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aviglitch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- ucnv
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2009-08-02 00:00:00 +09:00
|
18
|
+
default_executable: datamosh
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: ucnvvv@gmail.com
|
23
|
+
executables:
|
24
|
+
- datamosh
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- ChangeLog
|
29
|
+
- LICENSE
|
30
|
+
- README.rdoc
|
31
|
+
files:
|
32
|
+
- ChangeLog
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- bin/datamosh
|
37
|
+
- lib/aviglitch.rb
|
38
|
+
- lib/aviglitch/frame.rb
|
39
|
+
- lib/aviglitch/frames.rb
|
40
|
+
- spec/aviglitch_spec.rb
|
41
|
+
- spec/files/sample.avi
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
- LICENSE
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/ucnv/aviglitch
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options:
|
50
|
+
- --charset=UTF-8
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.3.6
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: A Ruby library to destroy your AVI files.
|
74
|
+
test_files:
|
75
|
+
- spec/aviglitch_spec.rb
|
76
|
+
- spec/spec_helper.rb
|