yamdi 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.mdown +5 -0
- data/README.rdoc +16 -0
- data/VERSION +1 -1
- data/lib/key_frame.rb +41 -0
- data/lib/paperclip_processors/metadata_extractor.rb +13 -0
- data/lib/tasks/metadata_refresh.rake +34 -0
- data/lib/yamdi.rb +5 -20
- data/spec/key_frame_spec.rb +41 -0
- data/spec/yamdi_spec.rb +4 -21
- data/yamdi.gemspec +6 -2
- metadata +8 -4
data/Changelog.mdown
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
== 0.1.2 (January 28, 2011)
|
2
|
+
|
3
|
+
* Move key frames into a class of their own. [Bob Burbach]
|
4
|
+
* Update documentation and provide example rake task for refreshing metadata. [Bob Burbach]
|
5
|
+
|
1
6
|
== 0.1.1 (January 25, 2011)
|
2
7
|
|
3
8
|
* Fix errant require that caused gem to fail but tests to pass. [Bob Burbach]
|
data/README.rdoc
CHANGED
@@ -6,6 +6,8 @@ The Yamdi command line tool expects to receive a path to an flv file and will re
|
|
6
6
|
|
7
7
|
The current gem version only supports the reading of metadata. The command line tool also supports the writing of the metadata into a new .flv file but this is not yet supported in this gem.
|
8
8
|
|
9
|
+
Tested under ruby 1.8.7 and 1.9.2
|
10
|
+
|
9
11
|
|
10
12
|
== Usage
|
11
13
|
|
@@ -24,6 +26,20 @@ You can also use Yamdi in a Paperclip processor. I've provided a simple example
|
|
24
26
|
|
25
27
|
This is useful for adding things like video duration to your db when a user uploads a video.
|
26
28
|
|
29
|
+
class Video
|
30
|
+
has_attached_file :video,
|
31
|
+
:styles => {:orginal => {}},
|
32
|
+
:processors => [:metadata_extractor]
|
33
|
+
end
|
34
|
+
|
35
|
+
Be sure you add the styles hash even if it is empty as above or your paperclip processors won't run.
|
36
|
+
|
37
|
+
=== Refreshing Exisitng Videos
|
38
|
+
|
39
|
+
Perhaps you're adding yamdi to your current set up, want to refresh the data in your models or add a new column to present to your users.
|
40
|
+
|
41
|
+
This is easily accomplished of you are using Paperclip. I've added an example rake task in lib/tasks/metadata_refresh.rake
|
42
|
+
|
27
43
|
== Supported methods
|
28
44
|
|
29
45
|
duration :: float, in seconds
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/key_frame.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
class KeyFrame
|
4
|
+
|
5
|
+
attr_accessor :time, :file_position
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@time = options[:time]
|
9
|
+
@file_position = options[:file_position]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all_from_xml(keyframe_xml)
|
13
|
+
times = get_times(keyframe_xml.xpath("//times/value"))
|
14
|
+
file_positions = get_file_positions(keyframe_xml.xpath("//filepositions/value"))
|
15
|
+
|
16
|
+
count = 0
|
17
|
+
key_frames = []
|
18
|
+
while count < times.size do
|
19
|
+
key_frames << KeyFrame.new(:time => times[count], :file_position => file_positions[count])
|
20
|
+
count = count + 1
|
21
|
+
end
|
22
|
+
|
23
|
+
key_frames
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.get_times(times_data_xml)
|
27
|
+
times = []
|
28
|
+
times_data_xml.children.each do |el|
|
29
|
+
times << el.inner_text.to_f
|
30
|
+
end
|
31
|
+
times
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get_file_positions(file_positions_xml)
|
35
|
+
file_positions = []
|
36
|
+
file_positions_xml.children.each do |el|
|
37
|
+
file_positions << el.inner_text.to_i
|
38
|
+
end
|
39
|
+
file_positions
|
40
|
+
end
|
41
|
+
end
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# This assumes that you are using paperclip.
|
2
|
+
# For example you may Video model with an attachment of video.
|
3
|
+
# truncated example:
|
4
|
+
# class Video
|
5
|
+
# has_attached_file :video,
|
6
|
+
# :styles => {:orginal => {}},
|
7
|
+
# :processors => [:metadata_extractor]
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# Remember for processors to work you must define styles on
|
11
|
+
# has_attached_file. Even if they are just blank as the example
|
12
|
+
# above. Without them processors won't be triggered.
|
13
|
+
|
1
14
|
module Paperclip
|
2
15
|
class MetadataExtractor < Paperclip::Processor
|
3
16
|
def make
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Example rake task to refresh your flv metadata using yamdi
|
2
|
+
# This assumes that you are using paperclip and have a Video
|
3
|
+
# model with an attachment of video.
|
4
|
+
# truncated example:
|
5
|
+
# class Video
|
6
|
+
# has_attached_file :video,
|
7
|
+
# :styles => {:orginal => {}},
|
8
|
+
# :processors => [:metadata_extractor]
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# The rake task below even works when using Amazon s3 for storage
|
12
|
+
# thanks to Paperclip.
|
13
|
+
|
14
|
+
|
15
|
+
namespace :video do
|
16
|
+
namespace :refresh do
|
17
|
+
|
18
|
+
desc "Regenerates metadata for uploaded flv videos."
|
19
|
+
task :metadata => :environment do
|
20
|
+
errors = []
|
21
|
+
# conditions assume default value of duration column has been set to 0
|
22
|
+
Video.find(:all, :conditions => ['duration = 0']).each do |video|
|
23
|
+
#ensure we are dealing with flv's
|
24
|
+
next unless video.video_file_name && video.video_file_name.include?('.flv')
|
25
|
+
|
26
|
+
result = video.video.reprocess!
|
27
|
+
errors << [video.id, video.errors] unless video.errors.blank?
|
28
|
+
result
|
29
|
+
end
|
30
|
+
errors.each{|e| puts "#{e.first}: #{e.last.full_messages.inspect}" }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/yamdi.rb
CHANGED
@@ -2,8 +2,12 @@ require 'tempfile'
|
|
2
2
|
require 'ostruct'
|
3
3
|
require 'nokogiri'
|
4
4
|
|
5
|
+
require 'key_frame'
|
6
|
+
|
5
7
|
class Yamdi
|
6
8
|
|
9
|
+
attr_accessor :metadata
|
10
|
+
|
7
11
|
def initialize(flv_path)
|
8
12
|
@metadata = Nokogiri.parse( parse(flv_path) )
|
9
13
|
end
|
@@ -121,26 +125,7 @@ class Yamdi
|
|
121
125
|
end
|
122
126
|
|
123
127
|
def key_frames
|
124
|
-
|
125
|
-
times = []
|
126
|
-
times_data_xml.children.each do |el|
|
127
|
-
times << el.inner_text.to_f
|
128
|
-
end
|
129
|
-
|
130
|
-
file_positions_xml = @metadata.xpath("//keyframes/filepositions/value")
|
131
|
-
file_positions = []
|
132
|
-
file_positions_xml.children.each do |el|
|
133
|
-
file_positions << el.inner_text.to_i
|
134
|
-
end
|
135
|
-
|
136
|
-
count = 0
|
137
|
-
key_frames = []
|
138
|
-
while count < times.size do
|
139
|
-
key_frames << OpenStruct.new(:time => times[count], :file_position => file_positions[count])
|
140
|
-
count = count + 1
|
141
|
-
end
|
142
|
-
|
143
|
-
key_frames
|
128
|
+
KeyFrame.all_from_xml(@metadata.xpath("//keyframes"))
|
144
129
|
end
|
145
130
|
|
146
131
|
private
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "KeyFrame" do
|
4
|
+
let(:flv_path) { File.join(File.dirname(__FILE__), 'files', 'sample.flv') }
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
@metadata_xml = Yamdi.new(flv_path).metadata
|
8
|
+
end
|
9
|
+
|
10
|
+
context "internal class methods" do
|
11
|
+
it "#self.get_times returns an array of times" do
|
12
|
+
times = KeyFrame.get_times(@metadata_xml.xpath("//keyframes/times/value"))
|
13
|
+
times.first.should eq(0.04)
|
14
|
+
times.last.should eq(6.04)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "#self.get_file_positions returns an array of file positions" do
|
18
|
+
file_positions = KeyFrame.get_file_positions(@metadata_xml.xpath("//keyframes/filepositions/value"))
|
19
|
+
file_positions.first.should eq(1327)
|
20
|
+
file_positions.last.should eq(83017)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "#self.all_from_xml returns an array of Key Frame objects" do
|
25
|
+
KeyFrame.all_from_xml(@metadata_xml.xpath("//keyframes")).class.should eq(Array)
|
26
|
+
end
|
27
|
+
|
28
|
+
before(:all) do
|
29
|
+
@key_frames = KeyFrame.all_from_xml(@metadata_xml.xpath("//keyframes"))
|
30
|
+
end
|
31
|
+
|
32
|
+
it "#time returns the proper time value" do
|
33
|
+
@key_frames.first.time.should eq(0.04)
|
34
|
+
@key_frames.last.time.should eq(6.04)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "#file_position returns the proper file position value" do
|
38
|
+
@key_frames.first.file_position.should eq(1327)
|
39
|
+
@key_frames.last.file_position.should eq(83017)
|
40
|
+
end
|
41
|
+
end
|
data/spec/yamdi_spec.rb
CHANGED
@@ -116,26 +116,9 @@ describe "Yamdi" do
|
|
116
116
|
@yamdi.last_key_frame_location.should eq(83017)
|
117
117
|
end
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
it "returns an array of key frame open structs" do
|
126
|
-
@yamdi.key_frames.class.should eq(Array)
|
127
|
-
@yamdi.key_frames.first.class.should eq(OpenStruct)
|
128
|
-
@yamdi.key_frames.last.class.should eq(OpenStruct)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "returns the proper time values" do
|
132
|
-
@key_frame_1.time.should eq(0.04)
|
133
|
-
@key_frame_2.time.should eq(6.04)
|
134
|
-
end
|
135
|
-
|
136
|
-
it "returns the proper file position values" do
|
137
|
-
@key_frame_1.file_position.should eq(1327)
|
138
|
-
@key_frame_2.file_position.should eq(83017)
|
139
|
-
end
|
119
|
+
it "returns an array of key frames" do
|
120
|
+
@yamdi.key_frames.class.should eq(Array)
|
121
|
+
@yamdi.key_frames.first.class.should eq(KeyFrame)
|
122
|
+
@yamdi.key_frames.last.class.should eq(KeyFrame)
|
140
123
|
end
|
141
124
|
end
|
data/yamdi.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{yamdi}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Bob Burbach"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-28}
|
13
13
|
s.description = %q{Yamdi is a ruby wrapper around the command line tool yamdi (github.com/ioppermann/yamdi). You'll need yamdi installed in order for the gem to be of any use. If you are on OSX I recommend using homebrew (brew install yamdi).}
|
14
14
|
s.email = %q{bob.burbach@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,9 +26,12 @@ Gem::Specification.new do |s|
|
|
26
26
|
"README.rdoc",
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
|
+
"lib/key_frame.rb",
|
29
30
|
"lib/paperclip_processors/metadata_extractor.rb",
|
31
|
+
"lib/tasks/metadata_refresh.rake",
|
30
32
|
"lib/yamdi.rb",
|
31
33
|
"spec/files/sample.flv",
|
34
|
+
"spec/key_frame_spec.rb",
|
32
35
|
"spec/spec_helper.rb",
|
33
36
|
"spec/yamdi_spec.rb",
|
34
37
|
"yamdi.gemspec"
|
@@ -39,6 +42,7 @@ Gem::Specification.new do |s|
|
|
39
42
|
s.rubygems_version = %q{1.3.7}
|
40
43
|
s.summary = %q{Yamdi is a ruby wrapper around the command line tool yamdi (github.com/ioppermann/yamdi).}
|
41
44
|
s.test_files = [
|
45
|
+
"spec/key_frame_spec.rb",
|
42
46
|
"spec/spec_helper.rb",
|
43
47
|
"spec/yamdi_spec.rb"
|
44
48
|
]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yamdi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bob Burbach
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-28 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -131,9 +131,12 @@ files:
|
|
131
131
|
- README.rdoc
|
132
132
|
- Rakefile
|
133
133
|
- VERSION
|
134
|
+
- lib/key_frame.rb
|
134
135
|
- lib/paperclip_processors/metadata_extractor.rb
|
136
|
+
- lib/tasks/metadata_refresh.rake
|
135
137
|
- lib/yamdi.rb
|
136
138
|
- spec/files/sample.flv
|
139
|
+
- spec/key_frame_spec.rb
|
137
140
|
- spec/spec_helper.rb
|
138
141
|
- spec/yamdi_spec.rb
|
139
142
|
- yamdi.gemspec
|
@@ -172,5 +175,6 @@ signing_key:
|
|
172
175
|
specification_version: 3
|
173
176
|
summary: Yamdi is a ruby wrapper around the command line tool yamdi (github.com/ioppermann/yamdi).
|
174
177
|
test_files:
|
178
|
+
- spec/key_frame_spec.rb
|
175
179
|
- spec/spec_helper.rb
|
176
180
|
- spec/yamdi_spec.rb
|