kelredd-pruview 0.1.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.

Potentially problematic release.


This version of kelredd-pruview might be problematic. Click here for more details.

data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = Pruview
2
+
3
+ == Description
4
+
5
+ A gem to ease generating image previews (thumbnails) of various files
6
+
7
+ == Installation
8
+
9
+ # install image magick with whatever build dependencies you need for image handling, etc...)
10
+ # if you want to preview movie files
11
+ # => install ffmpeg with whatever build dependencies you need for video/audio handling, etc...)
12
+ # if you want to preview postscript files (PDFs, Adobe Illustrator, etc...)
13
+ # => install any postscript handling libs or dependencies for image magick
14
+
15
+ sudo gem install kelredd-pruview --source http://gems.github.com
16
+
17
+ == Dependencies
18
+
19
+ * image magick + any special file type handling dependencies
20
+ * ffmpeg + h264 encoder + any special file type handling dependencies (for video previewing)
21
+ # something like 'sudo port install ffmpeg +gpl +lame +x264 +xvid' on Mac OSX Leopard
22
+ * gawk
23
+ * Rubygems: mini_magick
24
+
25
+ == Usage
26
+
27
+ require 'pruview'
28
+
29
+ # Preview a document (using image magick)
30
+ document = Pruview::Document.new(<document_file_path>, <pruview_output_path>)
31
+ doc_image_thumb_path = document.to_jpg(<thumb_file_name>, <thumb_pixel_width>, <thumb_pixel_height)
32
+
33
+ # Preview a video (ffmpeg to get an image from movie, then image magick to resize that image)
34
+ video_image_path = Pruview::VideoImage.to_jpg(<video_file_path>, <pruview_output_path>, <video_image_file_name>)
35
+ document = Pruview::Document.new(video_image_path, <pruview_output_path>)
36
+ video_image_thumb_path = document.to_jpg(<thumb_file_name>, <thumb_pixel_width>, <thumb_pixel_height)
37
+
38
+
39
+ == License
40
+
41
+ Copyright (c) 2007-2009 Kelly Redding
42
+
43
+ Permission is hereby granted, free of charge, to any person
44
+ obtaining a copy of this software and associated documentation
45
+ files (the "Software"), to deal in the Software without
46
+ restriction, including without limitation the rights to use,
47
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
48
+ copies of the Software, and to permit persons to whom the
49
+ Software is furnished to do so, subject to the following
50
+ conditions:
51
+
52
+ The above copyright notice and this permission notice shall be
53
+ included in all copies or substantial portions of the Software.
54
+
55
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
56
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
57
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
58
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
59
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
60
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
61
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
62
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+
5
+ require 'lib/pruview/version'
6
+
7
+ task :default => :test
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'pruview'
11
+ s.version = Pruview::Version.to_s
12
+ s.has_rdoc = true
13
+ s.extra_rdoc_files = %w(README.rdoc)
14
+ s.rdoc_options = %w(--main README.rdoc)
15
+ s.summary = "A gem to ease generating image previews (thumbnails) of various files"
16
+ s.author = 'Kelly Redding'
17
+ s.email = 'kelly@kelredd.com'
18
+ s.homepage = ''
19
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{features,lib,test}/**/*")
20
+ # s.executables = ['pruview']
21
+
22
+ s.add_dependency('mini_magick')
23
+ s.add_dependency('flvtool2')
24
+ end
25
+
26
+ Rake::GemPackageTask.new(spec) do |pkg|
27
+ pkg.gem_spec = spec
28
+ end
29
+
30
+ Rake::TestTask.new do |t|
31
+ t.libs << 'test'
32
+ t.test_files = FileList["test/**/*_test.rb"]
33
+ t.verbose = true
34
+ end
35
+
36
+ desc 'Generate the gemspec to serve this Gem from Github'
37
+ task :github do
38
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
39
+ File.open(file, 'w') {|f| f << spec.to_ruby }
40
+ puts "Created gemspec: #{file}"
41
+ end
@@ -0,0 +1,21 @@
1
+ Feature: Document
2
+ In order have file thumbnails programmatically
3
+ As a user
4
+ I want create document file thumbnails
5
+
6
+ Scenario: Basic Image thumbnail
7
+ Given I have a basic image document
8
+ When I create a jpg version
9
+ Then I should have a jpg file
10
+
11
+ Scenario: Invalid source image
12
+ Given I have an invalid image document
13
+ Then Pruview should complain about an invalid source file
14
+
15
+ Scenario: Invalid output path
16
+ Given I have an invalid output path for documents
17
+ Then Pruview should complain about an invalid output path
18
+
19
+ Scenario: Invalid source format
20
+ Given I have an invalid format document
21
+ Then Pruview should complain about an invalid source file format
@@ -0,0 +1,32 @@
1
+ When /^I create a[n]* (.+) version$/ do |format|
2
+ @output = @file.send("to_#{format}", 'file', 50, 50)
3
+ end
4
+
5
+ Then /^I should have a[n]* (.+) file$/ do |format|
6
+ assert File.exists?(@output)
7
+ assert File.extname(@output), format
8
+ end
9
+
10
+ Then /^Pruview should complain about an invalid source file$/ do
11
+ assert @complaint
12
+ assert_kind_of Pruview::Exceptions::InvalidError, @complaint
13
+ assert_match /^Invalid source file/, @complaint.message
14
+ end
15
+
16
+ Then /^Pruview should complain about an invalid output path$/ do
17
+ assert @complaint
18
+ assert_kind_of Pruview::Exceptions::InvalidError, @complaint
19
+ assert_match /^Invalid target directory/, @complaint.message
20
+ end
21
+
22
+ Then /^Pruview should complain about an invalid source file format$/ do
23
+ assert @complaint
24
+ assert_kind_of Pruview::Exceptions::InvalidError, @complaint
25
+ assert_match /not supported - file extension: .poop/, @complaint.message
26
+ end
27
+
28
+ Then /^Pruview should complain about an error$/ do
29
+ assert @complaint
30
+ assert_kind_of Pruview::Exceptions::InvalidError, @complaint
31
+ assert_match /not supported - file extension: .poop/, @complaint.message
32
+ end
@@ -0,0 +1,16 @@
1
+ Given /^I have a[n]* (.+) document$/ do |file_type|
2
+ begin
3
+ @file = Pruview::Document.new(FILES[file_type], OUTPUT_PATH)
4
+ rescue Exception => err
5
+ @complaint = err
6
+ end
7
+ end
8
+
9
+ Given /^I have an invalid output path for documents$/ do
10
+ begin
11
+ @file = Pruview::Document.new(FILES['basic image'], INVALID_OUTPUT_PATH)
12
+ rescue Exception => err
13
+ @complaint = err
14
+ end
15
+ end
16
+
@@ -0,0 +1,20 @@
1
+ require 'test/unit/assertions'
2
+ World(Test::Unit::Assertions)
3
+
4
+ require File.dirname(__FILE__) + '/../../../lib/pruview'
5
+
6
+ FILES_PATH = "./test/files"
7
+ OUTPUT_PATH = "./test_output"
8
+ INVALID_OUTPUT_PATH = "./test_output/invalid"
9
+ FILES = {
10
+ 'basic image' => "./test/files/basic.jpg",
11
+ 'invalid image' => "./test/files/invalid.jpg",
12
+ 'error image' => "./test/files/error.jpg",
13
+ 'basic video' => "./test/files/basic.mpg",
14
+ 'invalid video' => "./test/files/invalid.mov",
15
+ 'error video' => "./test/files/error.mov",
16
+ 'invalid format' => "./test/files/invalid_format.poop"
17
+ }
18
+
19
+ FileUtils.mkdir_p File.expand_path(FILES_PATH) unless File.exists? File.expand_path(FILES_PATH)
20
+ FileUtils.mkdir_p File.expand_path(OUTPUT_PATH) unless File.exists? File.expand_path(OUTPUT_PATH)
@@ -0,0 +1,5 @@
1
+ module PruviewFeature
2
+ module Helpers
3
+
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ Given /^I have a[n]* (.+) video image (.+)$/ do |file_type, format|
2
+ begin
3
+ @output = Pruview::VideoImage.send("to_#{format}", FILES[file_type], OUTPUT_PATH, 'file')
4
+ rescue Exception => err
5
+ @complaint = err
6
+ end
7
+ end
8
+
9
+ Given /^I have an invalid output path for video images$/ do
10
+ begin
11
+ @output = Pruview::VideoImage.to_jpg(FILES['basic video'], INVALID_OUTPUT_PATH, 'file')
12
+ rescue Exception => err
13
+ @complaint = err
14
+ end
15
+ end
16
+
@@ -0,0 +1,16 @@
1
+ Given /^I have a[n]* (.+) file$/ do |file_type|
2
+ begin
3
+ @file = Pruview::Video.new(FILES[file_type], OUTPUT_PATH)
4
+ rescue Exception => err
5
+ @complaint = err
6
+ end
7
+ end
8
+
9
+ Given /^I have an invalid output path for videos$/ do
10
+ begin
11
+ @file = Pruview::Video.new(FILES['basic video'], INVALID_OUTPUT_PATH)
12
+ rescue Exception => err
13
+ @complaint = err
14
+ end
15
+ end
16
+
@@ -0,0 +1,26 @@
1
+ Feature: Video
2
+ In order to use video in more universal ways
3
+ As a user
4
+ I want convert video to other formats for viewing
5
+
6
+ Scenario: Basic video to FLV
7
+ Given I have a basic video file
8
+ When I create an flv version
9
+ Then I should have an flv file
10
+
11
+ Scenario: Basic video to MOV
12
+ Given I have a basic video file
13
+ When I create an mov version
14
+ Then I should have an mov file
15
+
16
+ Scenario: Invalid source video
17
+ Given I have an invalid video file
18
+ Then Pruview should complain about an invalid source file
19
+
20
+ Scenario: Invalid output path
21
+ Given I have an invalid output path for videos
22
+ Then Pruview should complain about an invalid output path
23
+
24
+ Scenario: Invalid source format
25
+ Given I have an invalid format file
26
+ Then Pruview should complain about an invalid source file format
@@ -0,0 +1,20 @@
1
+ Feature: Video Image
2
+ In order have video image thumbnails programmatically
3
+ As a user
4
+ I want create video image file thumbnails
5
+
6
+ Scenario: Basic Image thumbnail
7
+ Given I have a basic video video image jpg
8
+ Then I should have a jpg file
9
+
10
+ Scenario: Invalid source image
11
+ Given I have an invalid video video image jpg
12
+ Then Pruview should complain about an invalid source file
13
+
14
+ Scenario: Invalid output path
15
+ Given I have an invalid output path for video images
16
+ Then Pruview should complain about an invalid output path
17
+
18
+ Scenario: Invalid source format
19
+ Given I have an invalid format video image jpg
20
+ Then Pruview should complain about an invalid source file format
data/lib/pruview.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'mini_magick'
3
+ require 'yaml'
4
+
5
+ require File.join(File.dirname(__FILE__), 'pruview', 'exceptions.rb')
6
+ require File.join(File.dirname(__FILE__), 'pruview', 'document.rb')
7
+ require File.join(File.dirname(__FILE__), 'pruview', 'video.rb')
8
+ require File.join(File.dirname(__FILE__), 'pruview', 'video_image.rb')
Binary file
@@ -0,0 +1,138 @@
1
+ module Pruview
2
+
3
+ class Document
4
+
5
+ def initialize(source, target_dir)
6
+ raise Pruview::Exceptions::InvalidError, "Invalid source file: #{source.to_s}" if !File.file?(source)
7
+ raise Pruview::Exceptions::InvalidError, "Invalid target directory: #{target_dir.to_s}" if !File.directory?(target_dir)
8
+ raise Pruview::Exceptions::InvalidError, "Document not supported - file extension: " + file_extension(source) if !format_supported?(source)
9
+ @source = source
10
+ @target_dir = target_dir
11
+ @image = process_image(get_image(source))
12
+ @tempfile = nil
13
+ end
14
+
15
+ def to_jpg(name, width, height, crop = false)
16
+ scale_img = scale_image(width, height, crop)
17
+ scale_img.combine_options do |img|
18
+ img.format 'jpg'
19
+ img.quality '90'
20
+ img.interlace 'plane'
21
+ end
22
+ target = File.join(@target_dir, name.to_s + '.jpg')
23
+ scale_img.write(target)
24
+ return target
25
+ end
26
+
27
+ protected
28
+
29
+ def format_supported?(source)
30
+ file_ext = file_extension(source)
31
+ #return true if file_ext == PSD_EXT # don't support photoshop for now
32
+ POSTSCRIPT_EXT.each { |extension| return true if file_ext == extension }
33
+ IMAGE_EXT.each { |extension| return true if file_ext == extension }
34
+ return false
35
+ end
36
+
37
+ def format_postscript?(source)
38
+ file_ext = file_extension(source)
39
+ POSTSCRIPT_EXT.each { |extension| return true if file_ext == extension }
40
+ return false
41
+ end
42
+
43
+ def file_extension(source_file)
44
+ File.extname(source_file).downcase.chomp
45
+ end
46
+
47
+ def get_image(source)
48
+ source = get_postscript_source(source) if format_postscript?(source)
49
+ begin
50
+ return MiniMagick::Image.from_file(source)
51
+ rescue Exception => err
52
+ raise "Error reading source image: #{err.message}"
53
+ end
54
+ end
55
+
56
+ def get_postscript_source(source)
57
+ begin
58
+ @tempfile = MiniMagick::ImageTempFile.new("pruview.jpg")
59
+ @tempfile.binmode
60
+ ensure
61
+ @tempfile.close
62
+ end
63
+ run_system_command("convert -format jpg \"#{source}[0]\" \"#{@tempfile.path}\"", "Error processing postscript document")
64
+ return @tempfile.path
65
+ end
66
+
67
+ def process_image(image)
68
+ image.format PROCESS_FORMAT
69
+ set_RGB_colorspace(image)
70
+ image.strip
71
+ return image
72
+ end
73
+
74
+ def set_RGB_colorspace(image)
75
+ colorspace = run_system_command("identify -format \"%r\" #{image.path}", "Error reading document colorspace")
76
+ puts "Colorspace: #{colorspace}"
77
+ if colorspace =~ /CMYK/
78
+ image.combine_options do |img|
79
+ img.profile File.join(File.dirname(__FILE__), 'USWebCoatedSWOP.icc')
80
+ img.profile File.join(File.dirname(__FILE__), 'sRGB.icm')
81
+ img.colorspace 'sRGB'
82
+ end
83
+ end
84
+ end
85
+
86
+ def scale_image(width, height, crop = false)
87
+ begin
88
+ image = MiniMagick::Image.from_file(@image.path)
89
+ crop_image(image, crop)
90
+ image.resize "#{width}x#{height}" if crop || @image[:width].to_i > width || @image[:height] > height
91
+ return image
92
+ rescue Exception => err
93
+ raise "Error scaling image: #{err.message}"
94
+ end
95
+ end
96
+
97
+ def crop_image(image, ratio)
98
+ if ratio.kind_of?(Array) && ratio.length == 2
99
+ ratio_width, ratio_height = ratio
100
+ puts "image orig size: #{image[:width].to_i}x#{image[:height].to_i}"
101
+ puts "ratio_width: #{ratio_width}, ratio_height: #{ratio_height}"
102
+ if ratio_width > ratio_height || (ratio_width == ratio_height && image[:height].to_i > image[:width].to_i)
103
+ # calc ratio height from width
104
+ rheight = (image[:width].to_i*(ratio_height.to_f / ratio_width.to_f)).round
105
+ puts "rheight: #{rheight}"
106
+ # shave off height
107
+ shave_off = ((image[:height].to_i - rheight)/2).round
108
+ puts "shave off height: #{image[:height].to_i - rheight}"
109
+ image.shave("0x#{shave_off}")
110
+ puts "image crop size: #{image[:width].to_i}x#{image[:height].to_i}"
111
+ elsif ratio_height > ratio_width || (ratio_width == ratio_height && image[:width].to_i > image[:height].to_i)
112
+ # calc ratio width from height
113
+ rwidth = (image[:height].to_i*(ratio_width.to_f / ratio_height.to_f)).round
114
+ # shave off width
115
+ shave_off = ((image[:width].to_i - rwidth).to_f / 2.to_f).round
116
+ image.shave("#{shave_off}x0")
117
+ end
118
+ end
119
+ return image
120
+ end
121
+
122
+ def run_system_command(command, error_message)
123
+ output = `#{command}`
124
+ raise "#{error_message}: error given #{$?}\n#{output}" if $? != 0
125
+ return output
126
+ end
127
+
128
+ end
129
+
130
+ # Configurations
131
+ Document::PROCESS_FORMAT = 'jpg'
132
+
133
+ Document::PSD_EXT = '.psd'
134
+ Document::POSTSCRIPT_EXT = ['.pdf', '.eps', '.ai']
135
+ Document::IMAGE_EXT = ['.bmp', '.gif', '.jpg', '.jpeg', '.png', '.tga']
136
+
137
+ end
138
+
@@ -0,0 +1,8 @@
1
+ module Pruview
2
+ module Exceptions
3
+
4
+ class InvalidError < ::StandardError
5
+ end
6
+
7
+ end
8
+ end
Binary file
@@ -0,0 +1,13 @@
1
+ module Pruview
2
+ module Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ TINY = 1
7
+
8
+ def self.to_s # :nodoc:
9
+ [MAJOR, MINOR, TINY].join('.')
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,130 @@
1
+ module Pruview
2
+
3
+ class Video
4
+
5
+ # this class assumes you have 'ffmpeg' and 'flvtool2' installed and in your path
6
+
7
+ def initialize(source, target_dir, bitrate_mult = 1)
8
+ raise Pruview::Exceptions::InvalidError, "Invalid source file:: #{source.to_s}" if !File.file?(source)
9
+ raise Pruview::Exceptions::InvalidError, "Invalid target directory: #{target_dir.to_s}" if !File.directory?(target_dir)
10
+ raise Pruview::Exceptions::InvalidError, "Video not supported - file extension: " + file_extension(source) if !format_supported?(source)
11
+ @source = source
12
+ @target_dir = target_dir
13
+ @bitrate_multiplier = bitrate_mult
14
+ end
15
+
16
+ def to_flv(name, width, height, scale_static = false)
17
+ target = to_base(name, width, height, '.flv', scale_static)
18
+ run("#{FLVTOOL} -U #{target}", "Unable to add meta-data for #{target}.")
19
+ return target
20
+ end
21
+
22
+ def to_mov(name, width, height, scale_static = false)
23
+ target = to_base(name, width, height, '.mov', scale_static)
24
+ # TODO: run qt-faststart
25
+ return target
26
+ end
27
+
28
+ protected
29
+
30
+ def to_base(name, width, height, extension, scale_static)
31
+ target = File.join(@target_dir, name.to_s + extension)
32
+ info_yml = File.join(@target_dir, name.to_s + '_info.yml')
33
+ run(build_command(@source, target, width, height, get_info(info_yml), scale_static), "Unable to convert #{@source} to #{target}.")
34
+ return target
35
+ end
36
+
37
+ def format_supported?(source)
38
+ file_ext = file_extension(source)
39
+ EXT.each { |extension| return true if file_ext == extension }
40
+ return false
41
+ end
42
+
43
+ def file_extension(source_file)
44
+ File.extname(source_file).downcase.chomp
45
+ end
46
+
47
+ def get_info(yml)
48
+ run("#{FFYML} #{@source} #{yml}", "Unable to get video info")
49
+ YAML.load_file(yml)
50
+ end
51
+
52
+ def build_command(source, target, width, height, info, scale_static)
53
+ command = "#{FFMPEG} -i #{source}"
54
+ command += get_scale_command(info['width'], info['height'], width, height, scale_static)
55
+ scale_factor = get_scale_factor(info['width'], info['height'], width, height)
56
+ if file_extension(target) != '.flv' # use h264 codec with lower bitrate scaling factor
57
+ command += " -vcodec libx264"
58
+ scale_factor /= 2.0
59
+ end
60
+ puts "scale factor: #{scale_factor.to_s}"
61
+ if !info['bitrate'].zero?
62
+ command += " -b #{(info['bitrate']*@bitrate_multiplier*scale_factor).to_s}"
63
+ else
64
+ command += " -sameq"
65
+ end
66
+ command += " -ab #{AUDIO_BITRATE}"
67
+ command += " -ar #{AUDIO_SAMPLING}"
68
+ command += " -y #{target}"
69
+ end
70
+
71
+ def get_scale_factor(source_width, source_height, scale_width, scale_height)
72
+ if source_width > source_height
73
+ return (scale_width.to_f / source_width.to_f)
74
+ else
75
+ return (scale_height.to_f / source_height.to_f)
76
+ end
77
+ end
78
+
79
+ def get_scale_command(source_width, source_height, scale_width, scale_height, static)
80
+ # this type of scaling assumes a static overall resolution with black padding added appropriately
81
+ # to keep the meaningful video area at the source aspect ratio
82
+ scale_params = get_scaling_params(source_width, source_height, scale_width, scale_height)
83
+ scale_command = " -s #{scale_params[:width].to_s}x#{scale_params[:height].to_s}"
84
+ if static == true
85
+ scale_command += " -padcolor #{PAD_COLOR}"
86
+ scale_command += " -padleft #{scale_params[:left]}" if scale_params[:left] > 0
87
+ scale_command += " -padtop #{scale_params[:top]}" if scale_params[:top] > 0
88
+ scale_command += " -padright #{scale_params[:right]}" if scale_params[:right] > 0
89
+ scale_command += " -padbottom #{scale_params[:bottom]}" if scale_params[:bottom] > 0
90
+ end
91
+ scale_command
92
+ end
93
+
94
+ def get_scaling_params(source_width, source_height, scale_width, scale_height)
95
+ params = {}
96
+ params[:left],params[:top],params[:right],params[:bottom] = 0,0,0,0
97
+ params[:width],params[:height] = scale_width, scale_height
98
+ scale_aspect = scale_width.to_f / scale_height.to_f
99
+ source_aspect = source_width.to_f / source_height.to_f
100
+ if(source_aspect > scale_aspect)
101
+ params[:height] = (scale_width.to_f / source_aspect).to_i
102
+ params[:height] += 1 if params[:height] % 2 != 0
103
+ params[:top] = params[:bottom] = ((scale_height - params[:height]).to_f / 2).to_i
104
+ params[:top] = params[:bottom] += 1 if params[:top] % 2 != 0
105
+ elsif(source_aspect < scale_aspect)
106
+ params[:width] = (scale_height.to_f * source_aspect).to_i
107
+ params[:width] += 1 if params[:width] % 2 != 0
108
+ params[:left] = params[:right] = ((scale_width - params[:width]).to_f / 2).to_i
109
+ params[:left] = params[:right] += 1 if params[:left] % 2 != 0
110
+ end
111
+ return params
112
+ end
113
+
114
+ def run(command, error_message = "Unknown error.")
115
+ raise "Ffmpeg error: " + error_message + " - command: '#{command}'" if !system(command)
116
+ end
117
+
118
+ # Configurations
119
+ Video::FFYML = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'ffyml'))
120
+ Video::FFMPEG = 'ffmpeg'
121
+ Video::FLVTOOL = 'flvtool2'
122
+ Video::PAD_COLOR = "000000"
123
+ Video::AUDIO_BITRATE = '128' # kbps
124
+ Video::AUDIO_SAMPLING = '44100'
125
+
126
+ Video::EXT = ['.avi', '.flv', '.mov', '.mpg', '.mp4']
127
+
128
+ end
129
+ end
130
+
@@ -0,0 +1,40 @@
1
+ module Pruview
2
+ class VideoImage
3
+
4
+ # this class assumes you have 'ffmpeg' installed and in your path
5
+
6
+ def self.to_jpg(source, target_dir, name)
7
+ raise Pruview::Exceptions::InvalidError, "Invalid source file:: #{source.to_s}" if !File.file?(source)
8
+ raise Pruview::Exceptions::InvalidError, "Invalid target directory: #{target_dir.to_s}" if !File.directory?(target_dir)
9
+ raise Pruview::Exceptions::InvalidError, "Video not supported - file extension: " + file_extension(source) if !format_supported?(source)
10
+ target = File.join(target_dir, name.to_s + '.jpg')
11
+ run(build_command(source, '-ss 00:00:00.2', 'mjpeg', target), "Unable to get preview image for #{target}")
12
+ # TODO: analyze image - create better
13
+ return target
14
+ end
15
+
16
+ protected
17
+
18
+ def self.format_supported?(source)
19
+ file_ext = file_extension(source)
20
+ Video::EXT.each { |extension| return true if file_ext == extension }
21
+ return false
22
+ end
23
+
24
+ def self.file_extension(source_file)
25
+ File.extname(source_file).downcase.chomp
26
+ end
27
+
28
+ def self.build_command(source, time_str, format, target)
29
+ command = "#{Video::FFMPEG} -i #{source}"
30
+ command += " #{time_str}"
31
+ command += " -f #{format}" if !format.empty?
32
+ command += " -an -y #{target}"
33
+ end
34
+
35
+ def self.run(command, error_message = "Unknown error.")
36
+ raise "Ffmpeg error: " + error_message + " - command: '#{command}'" if !system(command)
37
+ end
38
+
39
+ end
40
+ end
Binary file
Binary file
File without changes
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ # http://sneaq.net/textmate-wtf
2
+ $:.reject! { |e| e.include? 'TextMate' }
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'matchy'
7
+ require 'context'
8
+ require 'mocha'
9
+
10
+ require File.dirname(__FILE__) + '/../lib/pruview'
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class PruviewTest < Test::Unit::TestCase
4
+
5
+ describe "An instance of the Pruview class" do
6
+
7
+ it "should flunk" do
8
+ flunk "Please provide some tests"
9
+ end
10
+
11
+ end
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kelredd-pruview
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Kelly Redding
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-22 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mini_magick
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: flvtool2
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: kelly@kelredd.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - README.rdoc
45
+ - Rakefile
46
+ - features/document.feature
47
+ - features/step_definitions
48
+ - features/step_definitions/common_steps.rb
49
+ - features/step_definitions/document_steps.rb
50
+ - features/step_definitions/support
51
+ - features/step_definitions/support/env.rb
52
+ - features/step_definitions/support/helpers.rb
53
+ - features/step_definitions/video_image_steps.rb
54
+ - features/step_definitions/video_steps.rb
55
+ - features/video.feature
56
+ - features/video_image.feature
57
+ - lib/pruview
58
+ - lib/pruview/document.rb
59
+ - lib/pruview/exceptions.rb
60
+ - lib/pruview/sRGB.icm
61
+ - lib/pruview/USWebCoatedSWOP.icc
62
+ - lib/pruview/version.rb
63
+ - lib/pruview/video.rb
64
+ - lib/pruview/video_image.rb
65
+ - lib/pruview.rb
66
+ - test/files
67
+ - test/files/basic.jpg
68
+ - test/files/basic.mpg
69
+ - test/files/error.jpg
70
+ - test/files/error.mov
71
+ - test/files/invalid_format.poop
72
+ - test/test_helper.rb
73
+ - test/unit
74
+ - test/unit/pruview_test.rb
75
+ has_rdoc: true
76
+ homepage: ""
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --main
80
+ - README.rdoc
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ version:
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.2.0
99
+ signing_key:
100
+ specification_version: 2
101
+ summary: A gem to ease generating image previews (thumbnails) of various files
102
+ test_files: []
103
+