koyachi-scissor-video 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2009-07-05
2
+
3
+ * initial release
4
+
data/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+
2
+ = scissor-video
3
+
4
+ utility to chop video files
5
+
6
+ == Description
7
+
8
+
9
+ == Installation
10
+
11
+ === Requirements
12
+
13
+ * {scissor}[http://github.com/youpy/scissor/tree/master]
14
+ * {FFmpeg}[http://ffmpeg.mplayerhq.hu/]
15
+ * {Mencoder}[http://en.wikipedia.org/wiki/MEncoder]
16
+
17
+ === Archive Installation
18
+
19
+ rake install
20
+
21
+ === Gem Installation
22
+
23
+ gem install scissor-video
24
+
25
+
26
+ == Features/Problems
27
+
28
+
29
+ == Synopsis
30
+
31
+ == Original
32
+
33
+ http://github.com/youpy/scissor/tree/master
34
+
35
+ == Copyright
36
+
37
+ Author:: koyachi <rtk2106@gmail.com>
38
+ Copyright:: Copyright (c) 2009 koyachi
39
+ License:: MIT
data/Rakefile ADDED
@@ -0,0 +1,106 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'spec/rake/spectask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+ include FileUtils
12
+
13
+ NAME = "scissor-video"
14
+ AUTHOR = "koyachi"
15
+ EMAIL = "rtk2106@gmail.com"
16
+ DESCRIPTION = "utility to chop video files"
17
+ RUBYFORGE_PROJECT = "scissorvideo"
18
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
19
+ BIN_FILES = %w( )
20
+ VERS = "0.0.1"
21
+
22
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
23
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
24
+ RDOC_OPTS = [
25
+ '--title', "#{NAME} documentation",
26
+ "--charset", "utf-8",
27
+ "--opname", "index.html",
28
+ "--line-numbers",
29
+ "--main", "README.rdoc",
30
+ "--inline-source",
31
+ ]
32
+
33
+ task :default => [:spec]
34
+ task :package => [:clean]
35
+
36
+ Spec::Rake::SpecTask.new do |t|
37
+ t.spec_opts = ['--options', "spec/spec.opts"]
38
+ t.spec_files = FileList['spec/*_spec.rb']
39
+ t.rcov = true
40
+ end
41
+
42
+ spec = Gem::Specification.new do |s|
43
+ s.name = NAME
44
+ s.version = VERS
45
+ s.platform = Gem::Platform::RUBY
46
+ s.has_rdoc = true
47
+ s.extra_rdoc_files = ["README.rdoc", "ChangeLog"]
48
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
49
+ s.summary = DESCRIPTION
50
+ s.description = DESCRIPTION
51
+ s.author = AUTHOR
52
+ s.email = EMAIL
53
+ s.homepage = HOMEPATH
54
+ s.executables = BIN_FILES
55
+ s.rubyforge_project = RUBYFORGE_PROJECT
56
+ s.bindir = "bin"
57
+ s.require_path = "lib"
58
+ s.autorequire = ""
59
+ s.test_files = Dir["test/*_test.rb"]
60
+
61
+ s.add_dependency('youpy-scissor')
62
+ s.add_dependency('open4')
63
+
64
+ s.files = %w(README.rdoc ChangeLog Rakefile) +
65
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
66
+ Dir.glob("ext/**/*.{h,c,rb}") +
67
+ Dir.glob("examples/**/*.rb") +
68
+ Dir.glob("tools/*.rb")
69
+
70
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
71
+ end
72
+
73
+ Rake::GemPackageTask.new(spec) do |p|
74
+ p.need_tar = true
75
+ p.gem_spec = spec
76
+ end
77
+
78
+ task :install do
79
+ name = "#{NAME}-#{VERS}.gem"
80
+ sh %{rake package}
81
+ sh %{sudo gem install pkg/#{name}}
82
+ end
83
+
84
+ task :uninstall => [:clean] do
85
+ sh %{sudo gem uninstall #{NAME}}
86
+ end
87
+
88
+
89
+ Rake::RDocTask.new do |rdoc|
90
+ rdoc.rdoc_dir = 'html'
91
+ rdoc.options += RDOC_OPTS
92
+ rdoc.template = "resh"
93
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
94
+ if ENV['DOC_FILES']
95
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
96
+ else
97
+ rdoc.rdoc_files.include('README.rdoc', 'ChangeLog')
98
+ rdoc.rdoc_files.include('lib/**/*.rb')
99
+ rdoc.rdoc_files.include('ext/**/*.c')
100
+ end
101
+ end
102
+
103
+ desc 'Show information about the gem.'
104
+ task :debug_gem do
105
+ puts spec.to_ruby
106
+ end
@@ -0,0 +1,51 @@
1
+ require 'scissor'
2
+ require 'scissor-video/float'
3
+ require 'scissor-video/command'
4
+ require 'scissor-video/command/ffmpeg.rb'
5
+ require 'scissor-video/command/mencoder.rb'
6
+ require 'scissor-video/chunk'
7
+ require 'scissor-video/video_file'
8
+
9
+ def ScissorVideo(*args)
10
+ Scissor::VideoChunk.new(*args)
11
+ end
12
+
13
+ def Scissor(*args)
14
+ # Scissor::Chunk.new(*args)
15
+ if args.length == 0
16
+ Scissor::Chunk.new(*args)
17
+ else
18
+ filename = args[0]
19
+ f = Pathname.new(filename)
20
+ ext = f.extname.sub(/^\./, '').downcase
21
+ if Scissor::SoundFile::SUPPORTED_FORMATS.include?(ext)
22
+ Scissor::Chunk.new(filename)
23
+ else
24
+ ScissorVideo(filename)
25
+ end
26
+ end
27
+ end
28
+
29
+ module Scissor
30
+ @logger = Logger.new(STDOUT)
31
+ @logger.level = Logger::INFO
32
+
33
+ class << self
34
+ attr_accessor :logger
35
+ end
36
+
37
+ def logger
38
+ self.class.logger
39
+ end
40
+
41
+ class << self
42
+ def ffmpeg(*args)
43
+ FFmpeg.new(*args)
44
+ end
45
+
46
+ def mencoder(*args)
47
+ Mencoder.new(*args)
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'digest/md5'
3
+
4
+ module Scissor
5
+ # video対応
6
+ class Chunk
7
+ def +(other)
8
+ new_instance = self.class.new
9
+ new_instance.add_fragments(@fragments + other.fragments)
10
+ new_instance
11
+ end
12
+ end
13
+
14
+ class VideoChunk < Chunk
15
+ def initialize(filename = nil)
16
+ @fragments = []
17
+
18
+ if filename
19
+ @fragments << Fragment.new(
20
+ filename,
21
+ 0,
22
+ VideoFile.new(filename).length)
23
+ end
24
+ end
25
+
26
+ def to_file(filename, options = {})
27
+ filename = Pathname.new(filename)
28
+
29
+ if @fragments.empty?
30
+ raise EmptyFragment
31
+ end
32
+
33
+ options = {
34
+ :overwrite => false,
35
+ :save_workfiles => false
36
+ }.merge(options)
37
+
38
+ filename = Pathname.new(filename)
39
+
40
+ if filename.exist?
41
+ if options[:overwrite]
42
+ filename.unlink
43
+ else
44
+ raise FileExists
45
+ end
46
+ end
47
+
48
+ concat_files = []
49
+ ffmpeg = Scissor.ffmpeg
50
+
51
+ position = 0.0
52
+ tmpdir = ffmpeg.work_dir
53
+ tmpfile = tmpdir + 'tmp.avi'
54
+
55
+ begin
56
+ @fragments.each_with_index do |fragment, index|
57
+ fragment_filename = fragment.filename
58
+ fragment_duration = fragment.duration
59
+
60
+ fragment_tmpfile = tmpdir + (Digest::MD5.hexdigest(fragment_filename) + "_#{index}.avi")
61
+
62
+ unless fragment_tmpfile.exist?
63
+ ffmpeg.cut({
64
+ :input_video => fragment_filename,
65
+ :output_video => fragment_tmpfile,
66
+ :start => fragment.start,
67
+ :duration => fragment_duration
68
+ })
69
+ concat_files.push fragment_tmpfile
70
+ end
71
+
72
+ position += fragment_duration
73
+ end
74
+
75
+ Scissor.mencoder.concat({
76
+ :input_videos => concat_files,
77
+ :output_video => tmpfile
78
+ })
79
+
80
+ ffmpeg.encode({
81
+ :input_video => tmpfile,
82
+ :output_video => filename
83
+ })
84
+ ensure
85
+ ffmpeg.cleanup unless options[:save_workfiles]
86
+ end
87
+
88
+ self.class.new(filename)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'open4'
3
+ require 'logger'
4
+
5
+ module Scissor
6
+ class Command
7
+ attr_accessor :work_dir, :command
8
+
9
+ def initialize(args)
10
+ @command = args[:command]
11
+ @work_dir = args[:work_dir] || Dir.tmpdir + "/scissor-video-work-" + $$.to_s
12
+ @work_dir = Pathname.new(@work_dir)
13
+ @work_dir.mkpath
14
+ end
15
+
16
+ def run_command(cmd, force = false)
17
+ Scissor.logger.debug("run_command: #{cmd}")
18
+
19
+ result = ''
20
+ status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
21
+ err = stderr.read
22
+ Scissor.logger.debug(err)
23
+ result = stdout.read
24
+ if force && err
25
+ result = err
26
+ end
27
+ end
28
+
29
+ if status.exitstatus != 0 && !force
30
+ raise CommandFailed.new(cmd)
31
+ end
32
+
33
+ return result
34
+ end
35
+
36
+ def _run(option, force = false)
37
+ cmd = [@command, option.keys.map {|k| "#{k} #{option[k]}"}].flatten.join(' ')
38
+ run_command(cmd, force)
39
+ end
40
+
41
+ # パラメタ指定順番意識するものもあるので
42
+ def run(option_str, force = false)
43
+ run_command([@command, option_str].join(' '), force)
44
+ end
45
+
46
+ def which(command)
47
+ run_command("which #{command}").chomp
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ class Float
2
+ def to_msec
3
+ (self * 1000).to_i
4
+ end
5
+
6
+ # for Scissor::FFmpeg#cut
7
+ def to_ffmpegtime
8
+ min = 60
9
+ hour = 60 * min
10
+
11
+ h = self.to_i / hour
12
+ m = (self.to_i - h * hour) / min
13
+ sec = self.to_i - h * hour - m * min
14
+ msec = (self * 1000 % 1000).to_i
15
+ sprintf "%02d:%02d:%02d.%03d", h, m, sec, msec
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Scissor
3
+ class VideoFile
4
+ SUPPORTED_FORMATS = %w/avi flv/
5
+
6
+ class Error < StandardError; end
7
+ class UnknownFormat < Error; end
8
+
9
+ def initialize(filename)
10
+ @filename = Pathname.new(filename)
11
+ @ext = @filename.extname.sub(/^\./, '').downcase
12
+
13
+ unless SUPPORTED_FORMATS.include?(@ext)
14
+ raise UnknownFormat
15
+ end
16
+ end
17
+
18
+ def length
19
+ # FFmpeg.new.get_duration(@filename)
20
+ # FFmpeg.get_duration(@filename)
21
+ # ffmpeg.get_duration(@filename)
22
+ Scissor.ffmpeg.get_duration(@filename)
23
+ end
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: koyachi-scissor-video
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - koyachi
8
+ autorequire: ""
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-05 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: youpy-scissor
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: open4
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: utility to chop video files
36
+ email: rtk2106@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ - ChangeLog
44
+ files:
45
+ - README.rdoc
46
+ - ChangeLog
47
+ - Rakefile
48
+ - lib/scissor-video
49
+ - lib/scissor-video/chunk.rb
50
+ - lib/scissor-video/command.rb
51
+ - lib/scissor-video/video_file.rb
52
+ - lib/scissor-video/float.rb
53
+ - lib/scissor-video.rb
54
+ has_rdoc: true
55
+ homepage: http://scissorvideo.rubyforge.org
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --title
59
+ - scissor-video documentation
60
+ - --charset
61
+ - utf-8
62
+ - --opname
63
+ - index.html
64
+ - --line-numbers
65
+ - --main
66
+ - README.rdoc
67
+ - --inline-source
68
+ - --exclude
69
+ - ^(examples|extras)/
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project: scissorvideo
87
+ rubygems_version: 1.2.0
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: utility to chop video files
91
+ test_files: []
92
+