newbamboo-rvideo 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +70 -0
- data/ENV +100 -0
- data/ENV2 +129 -0
- data/LICENSE +20 -0
- data/Manifest +68 -0
- data/README +106 -0
- data/RULES +11 -0
- data/Rakefile +63 -0
- data/config/boot.rb +25 -0
- data/lib/rvideo.rb +46 -0
- data/lib/rvideo/errors.rb +24 -0
- data/lib/rvideo/float.rb +7 -0
- data/lib/rvideo/frame_capturer.rb +127 -0
- data/lib/rvideo/inspector.rb +482 -0
- data/lib/rvideo/reporter.rb +176 -0
- data/lib/rvideo/reporter/views/index.html.erb +27 -0
- data/lib/rvideo/reporter/views/report.css +27 -0
- data/lib/rvideo/reporter/views/report.html.erb +81 -0
- data/lib/rvideo/reporter/views/report.js +9 -0
- data/lib/rvideo/string.rb +5 -0
- data/lib/rvideo/tools/abstract_tool.rb +406 -0
- data/lib/rvideo/tools/ffmpeg.rb +356 -0
- data/lib/rvideo/tools/ffmpeg2theora.rb +42 -0
- data/lib/rvideo/tools/flvtool2.rb +50 -0
- data/lib/rvideo/tools/mencoder.rb +103 -0
- data/lib/rvideo/tools/mp4box.rb +21 -0
- data/lib/rvideo/tools/mp4creator.rb +35 -0
- data/lib/rvideo/tools/mplayer.rb +31 -0
- data/lib/rvideo/tools/qtfaststart.rb +37 -0
- data/lib/rvideo/tools/segmenter.rb +21 -0
- data/lib/rvideo/tools/yamdi.rb +44 -0
- data/lib/rvideo/transcoder.rb +139 -0
- data/lib/rvideo/version.rb +9 -0
- data/rvideo.gemspec +36 -0
- data/scripts/txt2html +67 -0
- data/setup.rb +1585 -0
- data/spec/files/boat.avi +0 -0
- data/spec/files/kites.mp4 +0 -0
- data/spec/fixtures/ffmpeg_builds.yml +28 -0
- data/spec/fixtures/ffmpeg_results.yml +608 -0
- data/spec/fixtures/files.yml +398 -0
- data/spec/fixtures/recipes.yml +58 -0
- data/spec/integrations/formats_spec.rb +315 -0
- data/spec/integrations/frame_capturer_spec.rb +26 -0
- data/spec/integrations/inspection_spec.rb +112 -0
- data/spec/integrations/recipes_spec.rb +0 -0
- data/spec/integrations/rvideo_spec.rb +17 -0
- data/spec/integrations/transcoder_integration_spec.rb +29 -0
- data/spec/integrations/transcoding_spec.rb +9 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support.rb +36 -0
- data/spec/units/abstract_tool_spec.rb +111 -0
- data/spec/units/ffmpeg_spec.rb +323 -0
- data/spec/units/flvtool2_spec.rb +324 -0
- data/spec/units/frame_capturer_spec.rb +72 -0
- data/spec/units/inspector_spec.rb +59 -0
- data/spec/units/mencoder_spec.rb +4994 -0
- data/spec/units/mp4box_spec.rb +34 -0
- data/spec/units/mp4creator_spec.rb +34 -0
- data/spec/units/mplayer_spec.rb +34 -0
- data/spec/units/qtfaststart_spec.rb +35 -0
- data/spec/units/string_spec.rb +8 -0
- data/spec/units/transcoder_spec.rb +156 -0
- data/tasks/deployment.rake +5 -0
- data/tasks/testing.rake +27 -0
- data/tasks/transcoding.rake +40 -0
- data/tasks/website.rake +8 -0
- metadata +179 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class Mp4box
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
attr_reader :raw_metadata
|
6
|
+
|
7
|
+
def tool_command
|
8
|
+
'MP4Box'
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_result(result)
|
14
|
+
#currently, no useful info returned in result to determine if successful or not
|
15
|
+
@raw_metadata = result.empty? ? "No Results" : result
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class Mp4creator
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
|
6
|
+
attr_reader :raw_metadata
|
7
|
+
|
8
|
+
def tool_command
|
9
|
+
'mp4creator'
|
10
|
+
end
|
11
|
+
|
12
|
+
def format_fps(params={})
|
13
|
+
" -rate=#{params[:fps]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_result(result)
|
17
|
+
if m = /can't open file/.match(result)
|
18
|
+
raise TranscoderError::InvalidFile, "I/O error"
|
19
|
+
end
|
20
|
+
|
21
|
+
if m = /unknown file type/.match(result)
|
22
|
+
raise TranscoderError::InvalidFile, "I/O error"
|
23
|
+
end
|
24
|
+
|
25
|
+
if @options['output_file'] && !File.exist?(@options['output_file'])
|
26
|
+
raise TranscoderError::UnexpectedResult, "An unknown error has occured with mp4creator:#{result}"
|
27
|
+
end
|
28
|
+
|
29
|
+
@raw_metadata = result.empty? ? "No Results" : result
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class Mplayer
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
|
6
|
+
attr_reader :raw_metadata
|
7
|
+
|
8
|
+
def tool_command
|
9
|
+
'mplayer'
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_result(result)
|
13
|
+
if m = /This will likely crash/.match(result)
|
14
|
+
raise TranscoderError::InvalidFile, "unknown format"
|
15
|
+
end
|
16
|
+
|
17
|
+
if m = /Failed to open/.match(result)
|
18
|
+
raise TranscoderError::InvalidFile, "I/O error"
|
19
|
+
end
|
20
|
+
|
21
|
+
if m = /File not found/.match(result)
|
22
|
+
raise TranscoderError::InvalidFile, "I/O error"
|
23
|
+
end
|
24
|
+
|
25
|
+
@raw_metadata = result.empty? ? "No Results" : result
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class QtFaststart
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
attr_reader :raw_metadata
|
6
|
+
|
7
|
+
def tool_command
|
8
|
+
'qt-faststart'
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def parse_result(result)
|
14
|
+
|
15
|
+
if m = /Usage: qt-faststart <infile.mov> <outfile.mov>/.match(result)
|
16
|
+
raise TranscoderError::InvalidCommand, "Usage: qt-faststart <infile.mov> <outfile.mov>"
|
17
|
+
end
|
18
|
+
|
19
|
+
if m = /last atom in file was not a moov atom/.match(result)
|
20
|
+
raise TranscoderError::InvalidFile, "Could not find moov atom"
|
21
|
+
end
|
22
|
+
|
23
|
+
if m = /No such file or directory/.match(result)
|
24
|
+
raise TranscoderError::InvalidFile, "No such file or directory"
|
25
|
+
end
|
26
|
+
|
27
|
+
if m = /Undefined error:/.match(result)
|
28
|
+
raise TranscoderError::UnexpectedResult, "Undefined error"
|
29
|
+
end
|
30
|
+
|
31
|
+
@raw_metadata = result.empty? ? "No Results" : result
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class Segmenter
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
|
6
|
+
attr_reader :raw_metadata
|
7
|
+
|
8
|
+
def tool_command
|
9
|
+
'segmenter'
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_result(result)
|
15
|
+
# TODO: parse segmenter results
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module RVideo
|
2
|
+
module Tools
|
3
|
+
class Yamdi
|
4
|
+
include AbstractTool::InstanceMethods
|
5
|
+
|
6
|
+
attr_reader :raw_metadata
|
7
|
+
|
8
|
+
def tool_command
|
9
|
+
'yamdi'
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_result(result)
|
15
|
+
if result.empty?
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
if m = /Couldn't stat on (.*)/.match(result)
|
20
|
+
raise TranscoderError::InputFileNotFound, m[0]
|
21
|
+
end
|
22
|
+
|
23
|
+
if m = /The input file is not a FLV./.match(result)
|
24
|
+
raise TranscoderError::InvalidFile, "input must be a valid FLV file"
|
25
|
+
end
|
26
|
+
|
27
|
+
if m = /\(c\) \d{4} Ingo Oppermann/i.match(result)
|
28
|
+
raise TranscoderError::InvalidCommand, "command printed yamdi help text (and presumably didn't execute)"
|
29
|
+
end
|
30
|
+
|
31
|
+
if m = /Please provide at least one output file/i.match(result)
|
32
|
+
raise TranscoderError::InvalidCommand, "command did not contain a valid output file. Yamdi expects a -o switch."
|
33
|
+
end
|
34
|
+
|
35
|
+
if m = /ERROR: undefined method .?timestamp.? for nil/.match(result)
|
36
|
+
raise TranscoderError::InvalidFile, "Output file was empty (presumably)"
|
37
|
+
end
|
38
|
+
|
39
|
+
raise TranscoderError::UnexpectedResult, result
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module RVideo # :nodoc:
|
2
|
+
class Transcoder
|
3
|
+
|
4
|
+
attr_reader :executed_commands, :processed, :errors, :warnings, :total_time
|
5
|
+
|
6
|
+
#
|
7
|
+
# To transcode a video, initialize a Transcoder object:
|
8
|
+
#
|
9
|
+
# transcoder = RVideo::Transcoder.new("/path/to/input.mov")
|
10
|
+
#
|
11
|
+
# Then pass a recipe and valid options to the execute method
|
12
|
+
#
|
13
|
+
# recipe = "ffmpeg -i $input_file$ -ar 22050 -ab 64 -f flv -r 29.97 -s"
|
14
|
+
# recipe += " $resolution$ -y $output_file$"
|
15
|
+
# recipe += "\nflvtool2 -U $output_file$"
|
16
|
+
# begin
|
17
|
+
# transcoder.execute(recipe, {:output_file => "/path/to/output.flv",
|
18
|
+
# :resolution => "640x360"})
|
19
|
+
# rescue TranscoderError => e
|
20
|
+
# puts "Unable to transcode file: #{e.class} - #{e.message}"
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# If the job succeeds, you can access the metadata of the input and output
|
24
|
+
# files with:
|
25
|
+
#
|
26
|
+
# transcoder.original # RVideo::Inspector object
|
27
|
+
# transcoder.processed # RVideo::Inspector object
|
28
|
+
#
|
29
|
+
# If the transcoding succeeds, the file may still have problems. RVideo
|
30
|
+
# will populate an errors array if the duration of the processed video
|
31
|
+
# differs from the duration of the original video, or if the processed
|
32
|
+
# file is unreadable.
|
33
|
+
#
|
34
|
+
|
35
|
+
def initialize(input_file = nil)
|
36
|
+
# Allow a nil input_file for backwards compatibility. (Change at 1.0?)
|
37
|
+
check_input_file(input_file)
|
38
|
+
|
39
|
+
@input_file = input_file
|
40
|
+
@executed_commands = []
|
41
|
+
@errors = []
|
42
|
+
@warnings = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def original
|
46
|
+
@original ||= Inspector.new(:file => @input_file)
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Requires a command and a hash of various interpolated options. The
|
51
|
+
# command should be one or more lines of transcoder tool commands (e.g.
|
52
|
+
# ffmpeg, flvtool2). Interpolate options by adding $option_key$ to the
|
53
|
+
# recipe, and passing :option_key => "value" in the options hash.
|
54
|
+
#
|
55
|
+
# recipe = "ffmpeg -i $input_file$ -ar 22050 -ab 64 -f flv -r 29.97
|
56
|
+
# recipe += "-s $resolution$ -y $output_file$"
|
57
|
+
# recipe += "\nflvtool2 -U $output_file$"
|
58
|
+
#
|
59
|
+
# transcoder = RVideo::Transcoder.new("/path/to/input.mov")
|
60
|
+
# begin
|
61
|
+
# transcoder.execute(recipe, {:output_file => "/path/to/output.flv", :resolution => "320x240"})
|
62
|
+
# rescue TranscoderError => e
|
63
|
+
# puts "Unable to transcode file: #{e.class} - #{e.message}"
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
|
67
|
+
def execute(task, options = {})
|
68
|
+
options[:progress_sample_rate] ||= 5
|
69
|
+
options[:progress_timeout] ||= false
|
70
|
+
|
71
|
+
t1 = Time.now
|
72
|
+
|
73
|
+
if @input_file.nil?
|
74
|
+
@input_file = options[:input_file]
|
75
|
+
end
|
76
|
+
|
77
|
+
RVideo.logger.info("\nNew transcoder job\n================\nTask: #{task}\nOptions: #{options.inspect}")
|
78
|
+
|
79
|
+
if block_given?
|
80
|
+
parse_and_execute(task, options) do |tool, progress|
|
81
|
+
yield(tool, progress)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
parse_and_execute(task, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
@processed = Inspector.new(:file => options[:output_file])
|
88
|
+
result = check_integrity
|
89
|
+
RVideo.logger.info("\nFinished task. Total errors: #{@errors.size}\n")
|
90
|
+
@total_time = Time.now - t1
|
91
|
+
result
|
92
|
+
rescue TranscoderError => e
|
93
|
+
raise e
|
94
|
+
rescue Exception => e
|
95
|
+
RVideo.logger.error "[ERROR] Unhandled RVideo exception: #{e.class} - #{e.message}"
|
96
|
+
RVideo.logger.error e.backtrace.join("\n\t")
|
97
|
+
raise TranscoderError::UnknownError, "Unexpected RVideo error: #{e.message} (#{e.class})"
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def check_input_file(input_file)
|
103
|
+
if input_file and !FileTest.exist?(input_file.gsub("\"",""))
|
104
|
+
raise TranscoderError::InputFileNotFound, "File not found (#{input_file})"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_integrity
|
109
|
+
precision = 1.1
|
110
|
+
if @processed.invalid?
|
111
|
+
@errors << "Output file invalid"
|
112
|
+
elsif (@processed.duration >= (original.duration * precision) or @processed.duration <= (original.duration / precision))
|
113
|
+
@errors << "Original file has a duration of #{original.duration}, but processed file has a duration of #{@processed.duration}"
|
114
|
+
end
|
115
|
+
return @errors.size == 0
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse_and_execute(task, options = {})
|
119
|
+
raise TranscoderError::ParameterError, "Expected a recipe class (as a string), but got a #{task.class.to_s} (#{task})" unless task.is_a? String
|
120
|
+
options = options.merge(:input_file => @input_file)
|
121
|
+
|
122
|
+
commands = task.split("\n").compact
|
123
|
+
commands.each do |c|
|
124
|
+
tool = Tools::AbstractTool.assign(c, options)
|
125
|
+
tool.original = original
|
126
|
+
|
127
|
+
if block_given?
|
128
|
+
tool.execute do |progress|
|
129
|
+
yield(tool, progress)
|
130
|
+
end
|
131
|
+
else
|
132
|
+
tool.execute
|
133
|
+
end
|
134
|
+
|
135
|
+
executed_commands << tool
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/rvideo.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{newbamboo-rvideo}
|
5
|
+
s.version = "0.9.6"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Peter Boling, Jonathan Dahl (Slantwise Design), Seth Thomas Rasmussen"]
|
9
|
+
s.date = %q{2010-01-29}
|
10
|
+
s.description = %q{Inspect and transcode video and audio files.}
|
11
|
+
s.email = %q{sethrasmussen@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/rvideo/errors.rb", "lib/rvideo/float.rb", "lib/rvideo/frame_capturer.rb", "lib/rvideo/inspector.rb", "lib/rvideo/reporter/views/index.html.erb", "lib/rvideo/reporter/views/report.css", "lib/rvideo/reporter/views/report.html.erb", "lib/rvideo/reporter/views/report.js", "lib/rvideo/reporter.rb", "lib/rvideo/string.rb", "lib/rvideo/tools/abstract_tool.rb", "lib/rvideo/tools/ffmpeg.rb", "lib/rvideo/tools/ffmpeg2theora.rb", "lib/rvideo/tools/flvtool2.rb", "lib/rvideo/tools/mencoder.rb", "lib/rvideo/tools/mp4box.rb", "lib/rvideo/tools/mp4creator.rb", "lib/rvideo/tools/mplayer.rb", "lib/rvideo/tools/qtfaststart.rb", "lib/rvideo/tools/yamdi.rb", "lib/rvideo/tools/segmenter.rb", "lib/rvideo/transcoder.rb", "lib/rvideo/version.rb", "lib/rvideo.rb", "LICENSE", "README", "tasks/deployment.rake", "tasks/testing.rake", "tasks/transcoding.rake", "tasks/website.rake"]
|
13
|
+
s.files = ["CHANGELOG", "config/boot.rb", "ENV", "ENV2", "lib/rvideo/errors.rb", "lib/rvideo/float.rb", "lib/rvideo/frame_capturer.rb", "lib/rvideo/inspector.rb", "lib/rvideo/reporter/views/index.html.erb", "lib/rvideo/reporter/views/report.css", "lib/rvideo/reporter/views/report.html.erb", "lib/rvideo/reporter/views/report.js", "lib/rvideo/reporter.rb", "lib/rvideo/string.rb", "lib/rvideo/tools/abstract_tool.rb", "lib/rvideo/tools/ffmpeg.rb", "lib/rvideo/tools/ffmpeg2theora.rb", "lib/rvideo/tools/flvtool2.rb", "lib/rvideo/tools/mencoder.rb", "lib/rvideo/tools/mp4box.rb", "lib/rvideo/tools/mp4creator.rb", "lib/rvideo/tools/mplayer.rb", "lib/rvideo/tools/qtfaststart.rb", "lib/rvideo/tools/yamdi.rb", "lib/rvideo/tools/segmenter.rb", "lib/rvideo/transcoder.rb", "lib/rvideo/version.rb", "lib/rvideo.rb", "LICENSE", "Manifest", "Rakefile", "README", "RULES", "rvideo.gemspec", "scripts/txt2html", "setup.rb", "spec/files/boat.avi", "spec/files/kites.mp4", "spec/fixtures/ffmpeg_builds.yml", "spec/fixtures/ffmpeg_results.yml", "spec/fixtures/files.yml", "spec/fixtures/recipes.yml", "spec/integrations/formats_spec.rb", "spec/integrations/frame_capturer_spec.rb", "spec/integrations/inspection_spec.rb", "spec/integrations/recipes_spec.rb", "spec/integrations/rvideo_spec.rb", "spec/integrations/transcoder_integration_spec.rb", "spec/integrations/transcoding_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/support.rb", "spec/units/abstract_tool_spec.rb", "spec/units/ffmpeg_spec.rb", "spec/units/flvtool2_spec.rb", "spec/units/frame_capturer_spec.rb", "spec/units/inspector_spec.rb", "spec/units/mencoder_spec.rb", "spec/units/mp4box_spec.rb", "spec/units/mp4creator_spec.rb", "spec/units/mplayer_spec.rb", "spec/units/qtfaststart_spec.rb", "spec/units/string_spec.rb", "spec/units/transcoder_spec.rb", "tasks/deployment.rake", "tasks/testing.rake", "tasks/transcoding.rake", "tasks/website.rake"]
|
14
|
+
s.homepage = %q{http://github.com/newbamboo/rvideo}
|
15
|
+
s.rdoc_options = ["--quiet", "--title", "rvideo documentation", "--opname", "index.html", "--line-numbers", "--main", "README", "--inline-source"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{newbamboo-rvideo}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Inspect and transcode video and audio files.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
27
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
30
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
34
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
35
|
+
end
|
36
|
+
end
|
data/scripts/txt2html
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'redcloth'
|
5
|
+
require 'syntax/convertors/html'
|
6
|
+
require 'erb'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/rvideo/version.rb'
|
8
|
+
|
9
|
+
version = Rvideo::VERSION::STRING
|
10
|
+
download = 'http://rubyforge.org/projects/rvideo'
|
11
|
+
|
12
|
+
class Fixnum
|
13
|
+
def ordinal
|
14
|
+
# teens
|
15
|
+
return 'th' if (10..19).include?(self % 100)
|
16
|
+
# others
|
17
|
+
case self % 10
|
18
|
+
when 1: return 'st'
|
19
|
+
when 2: return 'nd'
|
20
|
+
when 3: return 'rd'
|
21
|
+
else return 'th'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Time
|
27
|
+
def pretty
|
28
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def convert_syntax(syntax, source)
|
33
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
34
|
+
end
|
35
|
+
|
36
|
+
if ARGV.length >= 1
|
37
|
+
src, template = ARGV
|
38
|
+
template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
|
39
|
+
|
40
|
+
else
|
41
|
+
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
42
|
+
exit!
|
43
|
+
end
|
44
|
+
|
45
|
+
template = ERB.new(File.open(template).read)
|
46
|
+
|
47
|
+
title = nil
|
48
|
+
body = nil
|
49
|
+
File.open(src) do |fsrc|
|
50
|
+
title_text = fsrc.readline
|
51
|
+
body_text = fsrc.read
|
52
|
+
syntax_items = []
|
53
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</>!m){
|
54
|
+
ident = syntax_items.length
|
55
|
+
element, syntax, source = $1, $2, $3
|
56
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
57
|
+
"syntax-temp-#{ident}"
|
58
|
+
}
|
59
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
60
|
+
body = RedCloth.new(body_text).to_html
|
61
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
62
|
+
end
|
63
|
+
stat = File.stat(src)
|
64
|
+
created = stat.ctime
|
65
|
+
modified = stat.mtime
|
66
|
+
|
67
|
+
$stdout << template.result(binding)
|