yamdi 0.1.1 → 0.1.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/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
|