web_video 1.0.0

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Brainberry
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,107 @@
1
+ =WebVideo
2
+
3
+ WebVideo allows you to inspect and process video files.
4
+
5
+ ==Installation
6
+ You need install 'ffmpeg' liblary ant it's dependent's...
7
+
8
+ ===Mac OS
9
+ sudo port install ffmpeg +lame +libogg +vorbis +faac +faad +xvid +x264 +a52
10
+
11
+ ===Linux (Ubuntu)
12
+ sudo apt-get install ffmpeg
13
+ sudo apt-get install libfaac-dev libxvidcore4-dev liba52-0.7.4 liba52-0.7.4-dev libx264-dev
14
+ sudo apt-get install libavutil49 libavutil-dev libavcodec-dev
15
+ sudo apt-get install libavcodec-unstripped-52
16
+
17
+ ===Install "WebVideo" via plugin
18
+ rails plugin install http://github.com/galetahub/web_video.git
19
+
20
+ ===Install "WebVideo" via gem
21
+ Directly from repository:
22
+ sudo gem install web_video
23
+ Or in your application "Gemfile":
24
+ gem "web_video"
25
+
26
+ ==Logger
27
+ You can put it in "config/initializers/web_video.rb".
28
+
29
+ logfile = File.open(Rails.root.join('log', 'video.log'), 'w')
30
+ logfile.sync = true
31
+
32
+ WebVideo.logger = Logger.new(logfile)
33
+
34
+ ==Example
35
+
36
+ Read video information
37
+ video = WebVideo::Adapters::FfmpegAdapter.new('demo.avi')
38
+
39
+ video.filename # => "demo.avi"
40
+
41
+ video.duration # => "00:03:39.90"
42
+
43
+ video.bitrate # => "2624 kb/s"
44
+
45
+ video.duration_in_seconds # => 219
46
+
47
+ video.streams # => Array of streams
48
+ # [ #<WebVideo::Stream @codec="mpeg4", @type="Video", @details="yuv420p, 640x480 [PAR 1:1 DAR 4:3], 30 tbr, 30 tbn, 30 tbc">,
49
+ # #<WebVideo::Stream @codec="mp3", @type="Audio", @details="44100 Hz, stereo, s16, 128 kb/s">]
50
+
51
+ Video Convertation
52
+ transcoder = WebVideo::Transcoder.new("demo.avi")
53
+ or
54
+ transcoder = WebVideo::Transcoder.new(video)
55
+
56
+ Transcoder attributes
57
+ transcoder.adapter # => :ffmpeg
58
+
59
+ transcoder.source # => return WebVideo::Adapters::FfmpegAdapter instance (video)
60
+
61
+ Generate flv file. Next example will generate "demo.flv" from "demo.avi".
62
+
63
+ options = {:resolution => "480x360"}
64
+
65
+ begin
66
+ transcoder.convert("demo.flv", options) do |command|
67
+ command << "-ar 22050"
68
+ command << "-ab 128k"
69
+ command << "-acodec libmp3lame"
70
+ command << "-vcodec flv"
71
+ command << "-r 25"
72
+ command << "-y"
73
+ end
74
+ rescue WebVideo::CommandLineError => e
75
+ WebVideo.logger.error("Unable to transcode video: #{e.class} - #{e.message}")
76
+ end
77
+
78
+
79
+ Generate images from video
80
+ By default screenshot starts at '00:00:01', to change it pass option :at => '00:05:00' (at five minutes)
81
+
82
+ transcoder.screenshot("demo.jpg", :resolution => "480x360")
83
+
84
+ Next code will generate five images: demo_01.jpg, demo_02.jpg, demo_03.jpg ...
85
+
86
+ image_files = 'demo_%2d.jpg'
87
+ options = {:resolution => "480x360", :count => 5 }
88
+
89
+ begin
90
+ transcoder.screenshot(image_files, options) do |command|
91
+ command << "-vcodec mjpeg"
92
+ # The duration for which image extraction will take place
93
+ #command << "-t 4"
94
+ command << "-y"
95
+ end
96
+ rescue WebVideo::CommandLineError => e
97
+ WebVideo.logger.error("Unable to transcode video: #{e.class} - #{e.message}")
98
+ end
99
+
100
+ ==TODO
101
+ 1. Add adapter for support 'mencoder' tool
102
+ 2. More information about video file (class Stream must parse details)
103
+ 3. Add support for 'flvtool2'
104
+ 4. Write more documentation
105
+ 5. Write tests
106
+
107
+ Copyright (c) 2010 Brainberry, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the web_video plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the web_video plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'WebVideo'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "web_video"
29
+ gemspec.version = '1.0.0'
30
+ gemspec.summary = "WebVideo allows you to inspect and process video files"
31
+ gemspec.description = "WebVideo allows you to inspect, convert and take screenshots from video files"
32
+ gemspec.email = "galeta.igor@gmail.com"
33
+ gemspec.homepage = "http://github.com/galetahub/web_video"
34
+ gemspec.authors = ["Igor Galeta"]
35
+ gemspec.files = FileList["[A-Z]*", "{lib}/**/*"]
36
+ gemspec.rubyforge_project = "web_video"
37
+ end
38
+
39
+ Jeweler::GemcutterTasks.new
40
+ rescue LoadError
41
+ puts "Jeweler not available. Install it with: gem install jeweler"
42
+ end
@@ -0,0 +1,62 @@
1
+ module WebVideo
2
+ module Adapters
3
+ class AbstractAdapter
4
+ attr_accessor :filepath, :filename, :path
5
+
6
+ def initialize(filepath, options = {})
7
+ @filepath = filepath
8
+
9
+ @filename = File.basename(@filepath)
10
+ @path = File.dirname(@filepath)
11
+
12
+ @options = options.symbolize_keys
13
+ @metadata = parse
14
+ end
15
+
16
+ def file_exists?
17
+ File.exist?(@filepath)
18
+ end
19
+
20
+ def size
21
+ File.size(@filepath)
22
+ end
23
+
24
+ def duration
25
+ @metadata[:duration]
26
+ end
27
+
28
+ def bitrate
29
+ @metadata[:bitrate]
30
+ end
31
+
32
+ def streams
33
+ @metadata[:streams]
34
+ end
35
+
36
+ def command_name
37
+ ''
38
+ end
39
+
40
+ def convert_command
41
+ []
42
+ end
43
+
44
+ def screenshot_command
45
+ []
46
+ end
47
+
48
+ def installed?
49
+ !WebVideo::Tools.run("which", command_name).blank?
50
+ end
51
+
52
+ def run(command, options = {})
53
+ WebVideo::Tools.run_with_option(command_name, command, options)
54
+ end
55
+
56
+ private
57
+ def parse
58
+ return {}
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,71 @@
1
+ module WebVideo
2
+ module Adapters
3
+ class FfmpegAdapter < AbstractAdapter
4
+
5
+ # 00:21:41.18
6
+ def duration_in_seconds
7
+ if @metadata[:duration] =~ /([0-9][0-9])\:([0-9][0-9])\:([0-9][0-9])\.([0-9][0-9])/
8
+ ( $1.to_i * 60 * 60 ) + ( $2.to_i * 60 ) + ( $3.to_i ) + ( ($4.to_i/100) * 60 )
9
+ end
10
+ end
11
+
12
+ def command_name
13
+ 'ffmpeg'
14
+ end
15
+
16
+ def convert_command
17
+ command = []
18
+ command << "-i $input_file$"
19
+ command << "-s $resolution$"
20
+
21
+ command.dup
22
+ end
23
+
24
+ def screenshot_command
25
+ command = []
26
+ command << "-i $input_file$"
27
+
28
+ # Specifies the frame size of the output (Default is the size of the original video.)
29
+ command << "-s $resolution$"
30
+
31
+ # Frame rate of video. i.e. no. of frames to be extracted into images per second
32
+ # The default value is 25
33
+ command << "-r 1"
34
+
35
+ # Disable audio recording.
36
+ command << "-an"
37
+
38
+ # Number of video frames to record
39
+ command << "-vframes $count$"
40
+
41
+ # Force format (image2|rawvideo)
42
+ command << "-f $format$"
43
+
44
+ # Start the extraction from particular point
45
+ command << "-ss $at$"
46
+
47
+ command.dup
48
+ end
49
+
50
+ private
51
+ def parse
52
+ if installed?
53
+ metadata = {}
54
+
55
+ ffmpeg_output = WebVideo::Tools.run(command_name, "-i #{@filepath}", [0,1])
56
+
57
+ metadata[:duration] = $1 if ffmpeg_output =~ /Duration\: ([0-9][0-9]\:[0-9][0-9]\:[0-9][0-9]\.[0-9][0-9])\,/
58
+ metadata[:bitrate] = $1 if ffmpeg_output =~ /\, bitrate\: (.*)$/
59
+
60
+ metadata[:streams] = []
61
+
62
+ ffmpeg_output.scan(/stream #0.([0-9])(\[.+\])?:\s(.*):\s([^,]*),\s(.*)/i).each do |match|
63
+ metadata[:streams] << WebVideo::Stream.new(:type => match[2], :codec => match[3], :details => match[4])
64
+ end
65
+
66
+ return metadata
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,26 @@
1
+ module WebVideo
2
+ class Stream
3
+ attr_accessor :type, :codec, :details
4
+
5
+ #
6
+ # stream = Stream.new :type => 'Video', :codec => 'mpeg4', :details => 'yuv420p, 640x480 [PAR 1:1 DAR 4:3], 30 tbr, 30 tbn, 30 tbc'
7
+ # stream.video? # => true
8
+ # stream.audio? # => false
9
+ #
10
+ def initialize(options = {})
11
+ options.symbolize_keys!
12
+
13
+ @type = options[:type].to_s.downcase
14
+ @codec = options[:codec]
15
+ @details = options[:details]
16
+ end
17
+
18
+ def video?
19
+ @type == 'video'
20
+ end
21
+
22
+ def audio?
23
+ @type == 'audio'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ module WebVideo
2
+ module Tools
3
+
4
+ def self.run_with_option(command_name, params, options = {})
5
+ run(command_name, apply_options(params, options))
6
+ end
7
+
8
+ #
9
+ # Execute command with params and return output if exit status equal expected_outcodes
10
+ #
11
+ def self.run(cmd, params = "", expected_outcodes = 0)
12
+ command = %Q[#{cmd} #{params}].gsub(/\s+/, " ")
13
+ command = "#{command} 2>&1"
14
+
15
+ WebVideo.logger.info(command)
16
+
17
+ output = `#{command}`
18
+
19
+ WebVideo.logger.info(output)
20
+
21
+ unless [expected_outcodes].flatten.include?($?.exitstatus)
22
+ raise WebVideo::CommandLineError, "Error while running #{cmd}"
23
+ end
24
+
25
+ output
26
+ end
27
+
28
+ def self.apply_options(command, options)
29
+ str = command.dup
30
+
31
+ options.each do |key, value|
32
+ param = value.is_a?(String) ? value.inspect : value
33
+ str.gsub!("$#{key}$", param.to_s)
34
+ end
35
+
36
+ str
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,112 @@
1
+ module WebVideo
2
+ class Transcoder
3
+ attr_accessor :source
4
+ attr_reader :adapter
5
+
6
+ # Video Convertation
7
+ #
8
+ # transcoder = WebVideo::Transcoder.new("demo.avi")
9
+ # transcoder.source # WebVideo::Adapters::AbstractAdapter instance
10
+ #
11
+ # Or
12
+ #
13
+ # video = WebVideo::Adapters::FfmpegAdapter.new('demo.avi')
14
+ # transcoder = WebVideo::Transcoder.new(video)
15
+ # transcoder.source # WebVideo::Adapters::FfmpegAdapter instance (video)
16
+ #
17
+ def initialize(filepath, options = {}, adapter = :ffmpeg)
18
+ @adapter = adapter
19
+
20
+ if filepath.is_a?(WebVideo::Adapters::AbstractAdapter)
21
+ @source = filepath
22
+ else
23
+ args = [filepath, options]
24
+
25
+ @source = case @adapter
26
+ when String, Symbol then
27
+ load_adapter(@adapter.to_s).new(*args)
28
+ when Class then
29
+ @adapter.new(*args)
30
+ else
31
+ @adapter
32
+ end
33
+ end
34
+ end
35
+
36
+ # Create screenshots
37
+ #
38
+ # transcoder = WebVideo::Transcoder.new("demo.avi")
39
+ # transcoder.screenshot("demo.jpg", :resolution => "480x360")
40
+ #
41
+ # options:
42
+ # :count - count images to generate
43
+ # :format - image decoder
44
+ # :at - time to start make screenshots from
45
+ # :resolution - image resolution
46
+ def screenshot(destination, options = {}, &block)
47
+ options.symbolize_keys!
48
+
49
+ options[:count] ||= 1
50
+ options[:format] ||= "image2"
51
+ options[:at] ||= "00:00:01"
52
+
53
+ process(destination, @source.screenshot_command, options, &block)
54
+ end
55
+
56
+ # Generate new video file
57
+ #
58
+ # transcoder = WebVideo::Transcoder.new("demo.avi")
59
+ #
60
+ # begin
61
+ # transcoder.convert("demo.flv", :resolution => "480x360") do |command|
62
+ # command << "-ar 22050"
63
+ # command << "-ab 128k"
64
+ # command << "-acodec libmp3lame"
65
+ # command << "-vcodec flv"
66
+ # command << "-r 25"
67
+ # command << "-y"
68
+ # end
69
+ # rescue WebVideo::CommandLineError => e
70
+ # WebVideo.logger.error("Unable to transcode video: #{e.class} - #{e.message}")
71
+ # end
72
+ #
73
+ # options:
74
+ # :resolution - video resolution
75
+ #
76
+ def convert(destination, options = {}, &block)
77
+ options.symbolize_keys!
78
+
79
+ process(destination, @source.convert_command, options, &block)
80
+ end
81
+
82
+ # Execute command
83
+ #
84
+ def execute(command, options = {})
85
+ @source.run(command, options)
86
+ end
87
+
88
+ private
89
+
90
+ def load_adapter(adapter_name)
91
+ class_name = "#{adapter_name}_adapter".classify
92
+ "WebVideo::Adapters::#{class_name}".constantize
93
+ end
94
+
95
+ def process(destination, command, options = {}, &block)
96
+ options[:input_file] = @source.filepath
97
+ options[:output_file] = destination
98
+
99
+ if block_given?
100
+ begin
101
+ yield command
102
+ rescue Exception => e
103
+ raise WebVideo::Error, "Error take screenshot #{destination}: #{e.class} => #{e.message}"
104
+ end
105
+ end
106
+
107
+ command << "$output_file$"
108
+
109
+ execute(command.join(' '), options)
110
+ end
111
+ end
112
+ end
data/lib/web_video.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'logger'
2
+
3
+ module WebVideo
4
+ autoload :Tools, 'web_video/tools'
5
+ autoload :Stream, 'web_video/stream'
6
+ autoload :Transcoder, 'web_video/transcoder'
7
+
8
+ module Adapters
9
+ autoload :AbstractAdapter, 'web_video/adapters/abstract_adapter'
10
+ autoload :FfmpegAdapter, 'web_video/adapters/ffmpeg_adapter'
11
+ end
12
+
13
+ #
14
+ # WebVideo.logger.info 'Demo convert'
15
+ #
16
+ def self.logger
17
+ @logger ||= Logger.new('/dev/null')
18
+ @logger
19
+ end
20
+
21
+ #
22
+ # Configure logging. Pass a valid Ruby logger object.
23
+ #
24
+ # logger = Logger.new(STDOUT)
25
+ # WebVideo.logger = logger
26
+ #
27
+ def self.logger=(value)
28
+ @logger = value
29
+ end
30
+
31
+ class Error < StandardError #:nodoc:
32
+ end
33
+
34
+ class CommandLineError < StandardError #:nodoc:
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class WebVideoTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: web_video
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Igor Galeta
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-07 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: WebVideo allows you to inspect, convert and take screenshots from video files
22
+ email: galeta.igor@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - MIT-LICENSE
31
+ - README.rdoc
32
+ - Rakefile
33
+ - lib/web_video.rb
34
+ - lib/web_video/adapters/abstract_adapter.rb
35
+ - lib/web_video/adapters/ffmpeg_adapter.rb
36
+ - lib/web_video/stream.rb
37
+ - lib/web_video/tools.rb
38
+ - lib/web_video/transcoder.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/galetahub/web_video
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project: web_video
65
+ rubygems_version: 1.3.6
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: WebVideo allows you to inspect and process video files
69
+ test_files:
70
+ - test/web_video_test.rb
71
+ - test/test_helper.rb