Class: Castaway::Production

Inherits:
Object
  • Object
show all
Extended by:
ClassMethods
Includes:
Audio, Scenes
Defined in:
lib/castaway/production.rb,
lib/castaway/production/audio.rb,
lib/castaway/production/scenes.rb,
lib/castaway/production/class_methods.rb

Defined Under Namespace

Modules: Audio, ClassMethods, Scenes

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ClassMethods

finish, from_script, output, output_path, pointer, pointers, resource, resource_path, resource_paths, scene, soundclip, soundclips, soundtrack, time

Methods included from Times

#_parse_numeric_time, #_parse_time, #_parse_timespec_time

Methods included from Scenes

#_build_scenes, #duration, #pointers, #resource, #scene

Methods included from Audio

#_build_intro, #_build_last, #_build_middle, #_build_overlay, #_duck, #_produce_soundtrack, #duck, #soundclip

Constructor Details

#initialize(options = {}) ⇒ Production

Returns a new instance of Production.



21
22
23
24
25
26
27
28
# File 'lib/castaway/production.rb', line 21

def initialize(options = {})
  @options = options
  @resolution = _translate_resolution(options[:resolution] || '480p')
  @deliverable = options[:deliverable]
  @fps = options[:fps] || 30

  _build_scenes
end

Instance Attribute Details

#current_sceneObject (readonly)

Returns the value of attribute current_scene.



18
19
20
# File 'lib/castaway/production.rb', line 18

def current_scene
  @current_scene
end

#fpsObject (readonly)

Returns the value of attribute fps.



19
20
21
# File 'lib/castaway/production.rb', line 19

def fps
  @fps
end

#optionsObject (readonly)

Returns the value of attribute options.



17
18
19
# File 'lib/castaway/production.rb', line 17

def options
  @options
end

#resolutionObject (readonly)

Returns the value of attribute resolution.



19
20
21
# File 'lib/castaway/production.rb', line 19

def resolution
  @resolution
end

#scenesObject (readonly)

Returns the value of attribute scenes.



18
19
20
# File 'lib/castaway/production.rb', line 18

def scenes
  @scenes
end

Instance Method Details

#_construct_scene(scene, definition) ⇒ Object



93
94
95
96
97
# File 'lib/castaway/production.rb', line 93

def _construct_scene(scene, definition)
  instance_exec(scene, &definition)
ensure
  @current_scene = nil
end

#_construct_timelineObject



52
53
54
55
56
# File 'lib/castaway/production.rb', line 52

def _construct_timeline
  Castaway::Timeline.new(resolution, fps).tap do |timeline|
    @scenes.each { |scene| scene.construct(timeline) }
  end
end

#_hd_resolution(rows) ⇒ Object



112
113
114
115
116
# File 'lib/castaway/production.rb', line 112

def _hd_resolution(rows)
  rows = rows.to_i
  cols = rows * 16 / 9.0
  Castaway::Size.new(cols.ceil, rows)
end

#_next_filename(ext = nil) ⇒ Object



118
119
120
121
122
# File 'lib/castaway/production.rb', line 118

def _next_filename(ext = nil)
  @next_filename ||= 0
  File.join(self.class.output_path,
            format('__%04d%s', @next_filename += 1, ext))
end

#_produce_frames(timeline, range) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/castaway/production.rb', line 62

def _produce_frames(timeline, range)
  template = _template

  start_frame = range.start_frame
  end_frame   = range.end_frame

  progress_end = end_frame - start_frame + 1
  progress = ProgressBar.create(starting_at: 0, total: progress_end)

  start_frame.upto(end_frame) do |f|
    timeline.render_frame(f, name: format(template, f - start_frame))
    progress.increment
  end
end

#_produce_movie(soundtrack) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/castaway/production.rb', line 77

def _produce_movie(soundtrack)
  FileUtils.rm_f(deliverable)

  ffmpeg = Chaussettes::Tool.new('ffmpeg')
  ffmpeg << '-thread_queue_size' << 8192
  ffmpeg << '-r' << fps << '-s' << resolution.to_resolution
  ffmpeg << '-i' << _template('.png') << '-i' << soundtrack
  ffmpeg << '-vcodec' << 'libx264'
  ffmpeg << '-preset' << 'veryslow' << '-tune' << 'stillimage'
  ffmpeg << '-crf' << 23 << '-pix_fmt' << 'yuv420p' << '-acodec' << 'aac'
  ffmpeg << deliverable

  puts ffmpeg.to_s
  system(ffmpeg.to_s)
end

#_template(ext = nil) ⇒ Object



58
59
60
# File 'lib/castaway/production.rb', line 58

def _template(ext = nil)
  File.join(self.class.output_path, format('frame-%s%s', '%05d', ext))
end

#_translate_resolution(res) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/castaway/production.rb', line 99

def _translate_resolution(res)
  case res
  when Castaway::Size then res
  when Array then Castaway::Size.new(res.first.to_i, res.last.to_i)
  when /^(\d+)p$/ then _hd_resolution(Regexp.last_match(1))
  when Integer then _hd_resolution(res)
  when /^(\d+)x(\d+)$/ then
    Castaway::Size.new(Regexp.last_match(1).to_i, Regexp.last_match(2).to_i)
  else raise ArgumentError,
             "don't know how to turn #{res.inspect} into resolution"
  end
end

#deliverableObject



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/castaway/production.rb', line 39

def deliverable
  @deliverable ||= begin
    if self.class.name
      self.class.name.split(/::/).last.
        gsub(/([^A-Z]+)([A-Z]+)/) { "#{$1}-#{$2.downcase}" }.
        gsub(/([^0-9]+)([0-9]+)/) { "#{$1}-#{$2}" }.
        downcase + '.mp4'
    else
      'production.mp4'
    end
  end
end

#produce(range = Castaway::Range.new(self)) ⇒ Object



30
31
32
33
34
35
36
37
# File 'lib/castaway/production.rb', line 30

def produce(range = Castaway::Range.new(self))
  FileUtils.mkdir_p(self.class.output_path)

  timeline = _construct_timeline
  _produce_frames(timeline, range)
  soundtrack = _produce_soundtrack(range)
  _produce_movie(soundtrack)
end