class Framecurve::Extractors::FCP_XML
Pulls all varispeed timeremaps from an FCP XML V4 file
Public Class Methods
new()
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 9 def initialize() @xml = Framecurve::XMLBridge.new end
Public Instance Methods
extract(io)
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 13 def extract(io) doc = @xml.document_from_io(io) # Find all of the parameterid elements with graphdict @xml.xpath_each(doc, "//parameterid") do | e | if @xml.element_text(e) == "graphdict" parameter = @xml.parent(e) effect = @xml.parent(e, 2) if @xml.xpath_first_text(effect, "name") == "Time Remap" $stderr.puts "Found a timewarp at %s" % parameter.xpath curve = pull_timewarp(parameter, File.basename(io.path)) destination = compose_filename(io.path, parameter) File.open(destination, "wb") do | f | $stderr.puts "Writing out a framecurve to %s" % destination Framecurve::Serializer.new.validate_and_serialize(f, curve) end end end end end
Private Instance Methods
compose_filename(source_path, parameter)
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 37 def compose_filename(source_path, parameter) path = @xml.xpath_of(parameter).split("/") # Path to the parameter node is something like this # /xmeml/project/children/sequence/media/video/track/clipitem[1]/filter[7]/effect/parameter[6] # From this we want to preserve: # sequence and it's name # track number # clipitem number (offset) relevant_nodenames = path.grep(/^(sequence|track|clipitem)/) # Add default indices relevant_nodenames.map! do | nodename_and_offset | if nodename_and_offset =~ /\]$/ elems = nodename_and_offset.scan(/(\w+)(\[(\d+)\])/).flatten [elems.shift, elems.pop] else [nodename_and_offset, "1"] end end mappings = {"sequence" => "SEQ", "track"=>"V", "clipitem" => "CLIP"} naming = relevant_nodenames.map do | nodename, offset | [mappings[nodename], offset].join("") end.join('-') [source_path, naming, "framecurve.txt"].join('.') end
pull_timewarp(param, source_filename)
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 63 def pull_timewarp(param, source_filename) clipitem = @xml.parent(param, 3) c = Framecurve::Curve.new $stderr.puts clipitem.xpath c.comment!("From FCP XML %s" % source_filename) c.comment!("Information from %s" % clipitem.xpath) # c.comment!("Sequence start TC is %s", timecode_from(param)) clip_item_name = @xml.xpath_first_text(clipitem, "name") # The clip in point in the edit timeline, also first frame of the TW in_point = @xml.xpath_first_text(clipitem, "in").to_i out_point = @xml.xpath_first_text(clipitem, "out").to_i c.filename = [clip_item_name, "framecurve.txt"].join('.') # Accumulate keyframes @xml.xpath_each(param, "keyframe") do | kf | write_keyframe(c, kf, in_point, out_point) end $stderr.puts("Generated a curve of #{c.length} keys") c end
timecode_from(param)
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 87 def timecode_from(param) sequence = @xml.parent_by_name(param, "sequence") tc = @xml.xpath_first_text(sequence, "timecode/string") end
write_keyframe(c, kf, in_point, out_point)
click to toggle source
# File lib/framecurve/extractors/fcp_xml.rb, line 92 def write_keyframe(c, kf, in_point, out_point) kf_when, kf_value = @xml.xpath_first_text(kf, "when").to_i, @xml.xpath_first_text(kf, "value").to_f # TODO: should be a flag at = kf_when - in_point + 1 value = kf_value + 1 # FCP starts clips at 0 c.tuple!(at, value) unless (at < 1 || value < 1 || at > out_point) end