edl 0.1.5 → 0.1.6

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.
@@ -1,34 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
4
  # Can chop an offline edit into events according to the EDL
3
5
  class Cutter #:nodoc:
4
6
  def initialize(source_path)
5
7
  @source_path = source_path
6
8
  end
7
-
9
+
8
10
  def cut(edl)
9
- source_for_cutting = edl.from_zero #.without_transitions.without_generators
11
+ source_for_cutting = edl.from_zero # .without_transitions.without_generators
10
12
  # We need to use the original length in record
11
- source_for_cutting.events.each do | evt |
13
+ source_for_cutting.events.each do |evt|
12
14
  cut_segment(evt, evt.rec_start_tc, evt.rec_start_tc + evt.length)
13
15
  end
14
16
  end
15
-
17
+
16
18
  def cut_segment(evt, start_at, end_at)
17
19
  STDERR.puts "Cutting #{@source_path} from #{start_at} to #{end_at} - #{evt.num}"
18
20
  end
19
21
  end
20
-
22
+
21
23
  class FFMpegCutter < Cutter #:nodoc:
22
24
  def cut_segment(evt, start_at, end_at)
23
- source_dir, source_file = File.dirname(@source_path), File.basename(@source_path)
25
+ source_dir = File.dirname(@source_path)
26
+ source_file = File.basename(@source_path)
24
27
  dest_segment = File.join(source_dir, ('%s_%s' % [evt.num, source_file]))
25
- # dest_segment.gsub!(/\.mov$/i, '.mp4')
26
-
28
+ # dest_segment.gsub!(/\.mov$/i, '.mp4')
29
+
27
30
  offset = end_at - start_at
28
-
31
+
29
32
  cmd = "/opt/local/bin/ffmpeg -i #{@source_path} -ss #{start_at} -vframes #{offset.total} -vcodec photojpeg -acodec copy #{dest_segment}"
30
- #puts cmd
31
- `#{cmd}`
33
+ # puts cmd
34
+ `#{cmd}`
32
35
  end
33
36
  end
34
- end
37
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
4
  # Represents an edit event (or, more specifically, an EDL line denoting a clip being part of an EDL event)
3
5
  class Event
@@ -6,7 +8,7 @@ module EDL
6
8
 
7
9
  # Reel name as in the EDL
8
10
  attr_accessor :reel
9
-
11
+
10
12
  # Event tracks as in the EDL
11
13
  attr_accessor :track
12
14
 
@@ -19,7 +21,7 @@ module EDL
19
21
  attr_accessor :src_end_tc
20
22
 
21
23
  # Record start timecode of the event in the master as in the EDL
22
- attr_accessor :rec_start_tc
24
+ attr_accessor :rec_start_tc
23
25
 
24
26
  # Record end timecode of the event in the master as in the EDL,
25
27
  # outgoing transition is not included
@@ -36,76 +38,76 @@ module EDL
36
38
 
37
39
  # Incoming transition metadata (EDL::Transition), or nil if no transition is used
38
40
  attr_accessor :transition
39
-
41
+
40
42
  # How long is the incoming transition on the next event
41
43
  attr_accessor :outgoing_transition_duration
42
-
44
+
43
45
  # Where is this event located in the original file
44
46
  attr_accessor :line_number
45
-
47
+
46
48
  def initialize(opts = {})
47
- opts.each_pair{|k,v| send("#{k}=", v) }
49
+ opts.each_pair { |k, v| send("#{k}=", v) }
48
50
  yield(self) if block_given?
49
51
  end
50
-
52
+
51
53
  # Output a textual description (will not work as an EDL line!)
52
54
  def to_s
53
- %w( num reel track src_start_tc src_end_tc rec_start_tc rec_end_tc).map{|a| self.send(a).to_s}.join(" ")
55
+ %w[num reel track src_start_tc src_end_tc rec_start_tc rec_end_tc].map { |a| send(a).to_s }.join(' ')
54
56
  end
55
-
57
+
56
58
  def inspect
57
59
  to_s
58
60
  end
59
-
61
+
60
62
  def comments #:nodoc:
61
63
  @comments ||= []
62
64
  @comments
63
65
  end
64
-
66
+
65
67
  def outgoing_transition_duration #:nodoc:
66
68
  @outgoing_transition_duration ||= 0
67
69
  end
68
-
70
+
69
71
  # Is the clip reversed in the edit?
70
72
  def reverse?
71
73
  (timewarp && timewarp.reverse?)
72
74
  end
73
- alias_method :reversed?, :reverse?
74
-
75
+ alias reversed? reverse?
76
+
75
77
  def copy_properties_to(evt)
76
- %w( num reel track src_start_tc src_end_tc rec_start_tc rec_end_tc).each do | k |
78
+ %w[num reel track src_start_tc src_end_tc rec_start_tc rec_end_tc].each do |k|
77
79
  evt.send("#{k}=", send(k)) if evt.respond_to?(k)
78
80
  end
79
81
  evt
80
82
  end
81
-
83
+
82
84
  # Returns true if the clip starts with a transiton (not a jump cut)
83
85
  def has_transition?
84
86
  !!@transition
85
87
  end
86
- alias_method :starts_with_transition?, :has_transition?
87
-
88
+ alias starts_with_transition? has_transition?
89
+
88
90
  # The duration of the incoming transition, or 0 if no transition is used
89
91
  def incoming_transition_duration
90
92
  @transition ? @transition.duration : 0
91
93
  end
92
-
94
+
93
95
  # Returns true if the clip ends with a transition (if the next clip starts with a transition)
94
96
  def ends_with_transition?
95
97
  outgoing_transition_duration > 0
96
98
  end
97
-
99
+
98
100
  # Returns true if the clip has a timewarp (speed ramp, motion memory, you name it)
99
101
  def has_timewarp?
100
102
  !timewarp.nil?
101
103
  end
102
-
104
+
103
105
  # Is this a black slug?
104
106
  def black?
105
107
  reel == 'BL'
106
108
  end
107
- alias_method :slug?, :black?
108
-
109
+ alias slug? black?
110
+
109
111
  # Get the record length of the event (how long it occupies in the EDL without an eventual outgoing transition)
110
112
  def rec_length
111
113
  (rec_end_tc.to_i - rec_start_tc.to_i).to_i
@@ -115,37 +117,45 @@ module EDL
115
117
  def rec_length_with_transition
116
118
  rec_length + outgoing_transition_duration.to_i
117
119
  end
118
-
120
+
119
121
  # How long does the capture need to be to complete this event including timewarps and transitions
120
122
  def src_length
121
123
  @timewarp ? @timewarp.actual_length_of_source : rec_length_with_transition
122
124
  end
123
-
124
- alias_method :capture_length, :src_length
125
+
126
+ alias capture_length src_length
125
127
 
126
128
  # Capture from (and including!) this timecode to complete this event including timewarps and transitions
127
129
  def capture_from_tc
128
130
  @timewarp ? @timewarp.source_used_from : src_start_tc
129
131
  end
130
-
132
+
131
133
  # Capture up to AND INCLUDING this timecode to complete this event including timewarps and transitions
132
134
  def capture_to_and_including_tc
133
135
  capture_to_tc - 1
134
136
  end
135
-
137
+
136
138
  # Capture up to BUT NOT INCLUDING this timecode to complete this event including timewarps and transitions
137
139
  def capture_to_tc
138
140
  @timewarp ? @timewarp.source_used_upto : (src_end_tc + outgoing_transition_duration)
139
141
  end
140
-
142
+
141
143
  # Speed of this clip in percent relative to the source speed. 100 for non-timewarped events
142
144
  def speed
143
145
  @timewarp ? @timewarp.speed : 100.0
144
146
  end
145
-
147
+
148
+ # Sets the reel name and outputs a warning if it contains dots or spaces
149
+ def reel=(new_reel_name)
150
+ if new_reel_name =~ /[\s\.]/
151
+ $stderr.puts "Reel name #{new_reel_name.inspect} contains dots or spaces, beware."
152
+ end
153
+ @reel = new_reel_name
154
+ end
155
+
146
156
  # Returns true if this event is a generator
147
157
  def generator?
148
- black? || (%(AX GEN).include?(reel))
158
+ black? || %(AX GEN).include?(reel)
149
159
  end
150
160
  end
151
- end
161
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
4
  # When initialized with a file and passed an EDL, will generate thumbnail images
3
5
  # of the first frame of every event. It is assumed that the movie file starts at the same
@@ -7,23 +9,23 @@ module EDL
7
9
  def initialize(with_file)
8
10
  @source_path = with_file
9
11
  end
10
-
12
+
11
13
  def ffmpeg_bin
12
14
  @ffmpeg_bin || 'ffmpeg'
13
15
  end
14
-
16
+
15
17
  def grab(edl)
16
- edl.from_zero.events.each do | evt |
17
- grab_frame_tc = evt.rec_start_tc + (offset || 0 )
18
-
18
+ edl.from_zero.events.each do |evt|
19
+ grab_frame_tc = evt.rec_start_tc + (offset || 0)
20
+
19
21
  to_file = File.dirname(@source_path) + '/' + evt.num + '_' + File.basename(@source_path).gsub(/\.(\w+)$/, '')
20
22
  generate_grab(evt.num, grab_frame_tc, to_file)
21
23
  end
22
24
  end
23
-
24
- def generate_grab(evt, at, to_file)
25
+
26
+ def generate_grab(_evt, at, to_file)
25
27
  cmd = "#{ffmpeg_bin} -i #{@source_path} -an -ss #{at.with_frames_as_fraction} -vframes 1 -y #{to_file}%d.jpg"
26
28
  `#{cmd}`
27
29
  end
28
30
  end
29
- end
31
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # EDLs sometimes come with \r line breaks, and this is something that fails
2
4
  # with Ruby standard line separator detection. We need something to help us
3
5
  # with that. In this case we can just do a bulk replace because EDLs will be relatively
@@ -8,4 +10,4 @@ class EDL::LinebreakMagician < StringIO
8
10
  blob = with_io.read
9
11
  super(blob.gsub(LOOSE_CR, "\n"))
10
12
  end
11
- end
13
+ end
@@ -1,48 +1,53 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
-
3
4
  # Is used to parse an EDL
5
+ # Parsing errors are collected in +errors+
4
6
  class Parser
5
-
6
7
  attr_reader :fps
7
-
8
- # Initialize an EDL parser. Pass the FPS to it, as the usual EDL does not contain any kind of reference
8
+ attr_accessor :errors
9
+
10
+ # Initialize an EDL parser. Pass the FPS to it, as the usual EDL does not contain any kind of reference
9
11
  # to it's framerate
10
12
  def initialize(with_fps = DEFAULT_FPS)
11
13
  @fps = with_fps
12
14
  end
13
-
15
+
14
16
  def get_matchers #:nodoc:
15
- [ EventMatcher.new(@fps), EffectMatcher.new, NameMatcher.new, TimewarpMatcher.new(@fps), CommentMatcher.new ]
17
+ [EventMatcher.new(@fps), EffectMatcher.new, NameMatcher.new, TimewarpMatcher.new(@fps), CommentMatcher.new]
16
18
  end
17
-
19
+
18
20
  # Parse a passed File or IO object line by line, or the whole string
19
21
  def parse(input_string_or_io)
20
22
  return parse(StringIO.new(input_string_or_io)) unless input_string_or_io.respond_to?(:read)
21
-
22
- magic = ::EDL::LinebreakMagician.new(input_string_or_io)
23
-
23
+ self.errors = []
24
+
25
+ magic = EDL::LinebreakMagician.new(input_string_or_io)
26
+
24
27
  # Normalize line breaks
25
- stack, matchers = List.new, get_matchers
26
-
28
+ stack = List.new
29
+ matchers = get_matchers
30
+
27
31
  while current_line = magic.gets
28
-
29
- m = matchers.find{|m| m.matches?(current_line) }
30
-
32
+ m = matchers.find { |m| m.matches?(current_line) }
33
+
31
34
  next unless m
32
35
  begin
33
36
  m.apply(stack, current_line)
34
37
  stack[-1].line_number = magic.lineno if m.is_a?(EventMatcher)
35
38
  rescue Matcher::ApplyError => e
36
- STDERR.puts "Cannot parse #{current_line} - #{e}"
39
+ error = "Cannot parse #{current_line} - #{e}"
40
+ errors << error
41
+ STDERR.puts error
37
42
  end
38
43
  end
39
44
  stack
40
45
  end
41
-
46
+
42
47
  # Init a Timecode object from the passed elements with the passed framerate
43
48
  def self.timecode_from_line_elements(elements, fps) #:nodoc:
44
- args = (0..3).map{|_| elements.shift.to_i} + [fps.to_f]
49
+ args = (0..3).map { |_| elements.shift.to_i } + [fps.to_f]
45
50
  Timecode.at(*args)
46
51
  end
47
52
  end
48
- end
53
+ end
@@ -1,24 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
4
  # Represents a timewarp. Will be placed in EDL::Event#timewarp
3
5
  # For a reversed clip, the source start we get from the EDL in the src start
4
- # is the LAST used frame. For a pos rate clip, the source start is the bona fide source start. Nice eh?
6
+ # is the LAST used frame. For a pos rate clip, the source start is the bona fide source start. Nice eh?
5
7
  class Timewarp
6
-
7
8
  # What is the actual framerate of the clip (float)
8
9
  attr_accessor :actual_framerate
9
10
  attr_accessor :clip #:nodoc:
10
-
11
+
11
12
  # Does this timewarp reverse the clip?
12
13
  def reverse?
13
14
  @actual_framerate < 0
14
15
  end
15
-
16
+
16
17
  # Get the speed in percent
17
18
  def speed_in_percent
18
19
  (@actual_framerate / @clip.rec_start_tc.fps) * 100
19
20
  end
20
- alias_method :speed, :speed_in_percent
21
-
21
+ alias speed speed_in_percent
22
+
22
23
  # Compute the length of the clip we need to capture. The length is computed in frames and
23
24
  # is always rounded up (better one frame more than one frame less!)
24
25
  def actual_length_of_source
@@ -28,7 +29,7 @@ module EDL
28
29
  factor = @actual_framerate / @clip.rec_start_tc.fps
29
30
  (target_len * factor).ceil.abs
30
31
  end
31
-
32
+
32
33
  # What is the starting frame for the captured clip? If we are a reverse, then the src start of the
33
34
  # clip is our LAST frame, otherwise it's the first
34
35
  def source_used_from
@@ -36,10 +37,10 @@ module EDL
36
37
  compensation = 2
37
38
  reverse? ? (@clip.src_start_tc - actual_length_of_source + compensation) : @clip.src_start_tc
38
39
  end
39
-
40
+
40
41
  # Where to end the capture? This is also dependent on whether we are a reverse or not
41
42
  def source_used_upto
42
43
  source_used_from + actual_length_of_source
43
44
  end
44
45
  end
45
- end
46
+ end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module EDL
2
4
  # Represents a transition. We currently only support dissolves and SMPTE wipes
3
5
  # Will be avilable as EDL::Clip#transition
4
6
  class Transition
5
-
6
7
  # Length of the transition in frames
7
8
  attr_accessor :duration
8
-
9
+
9
10
  # Which effect is used (like CROSS DISSOLVE)
10
11
  attr_accessor :effect
11
12
  end
@@ -16,11 +17,10 @@ module EDL
16
17
 
17
18
  # Represents an SMPTE wipe
18
19
  class Wipe < Transition
19
-
20
20
  # Which SMPTE wipe is needed
21
21
  attr_accessor :smpte_wipe_index
22
22
  end
23
-
23
+
24
24
  class Key < Transition
25
25
  end
26
- end
26
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EDL
4
+ VERSION = '0.1.6'
5
+ end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2014-03-24 00:00:00.000000000 Z
12
12
  dependencies:
@@ -14,86 +14,44 @@ dependencies:
14
14
  name: timecode
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: shoulda-context
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: test-unit
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: jeweler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - '>='
24
+ - - ">="
67
25
  - !ruby/object:Gem::Version
68
26
  version: '0'
69
27
  - !ruby/object:Gem::Dependency
70
28
  name: rake
71
29
  requirement: !ruby/object:Gem::Requirement
72
30
  requirements:
73
- - - '>='
31
+ - - ">="
74
32
  - !ruby/object:Gem::Version
75
33
  version: '0'
76
34
  type: :development
77
35
  prerelease: false
78
36
  version_requirements: !ruby/object:Gem::Requirement
79
37
  requirements:
80
- - - '>='
38
+ - - ">="
81
39
  - !ruby/object:Gem::Version
82
40
  version: '0'
83
41
  - !ruby/object:Gem::Dependency
84
- name: flexmock
42
+ name: rspec
85
43
  requirement: !ruby/object:Gem::Requirement
86
44
  requirements:
87
- - - ~>
45
+ - - "~>"
88
46
  - !ruby/object:Gem::Version
89
- version: 1.3.2
47
+ version: '3.5'
90
48
  type: :development
91
49
  prerelease: false
92
50
  version_requirements: !ruby/object:Gem::Requirement
93
51
  requirements:
94
- - - ~>
52
+ - - "~>"
95
53
  - !ruby/object:Gem::Version
96
- version: 1.3.2
54
+ version: '3.5'
97
55
  description:
98
56
  email: me@julik.nl
99
57
  executables: []
@@ -101,6 +59,11 @@ extensions: []
101
59
  extra_rdoc_files:
102
60
  - README.rdoc
103
61
  files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".ruby-gemset"
65
+ - ".ruby-version"
66
+ - ".travis.yml"
104
67
  - Gemfile
105
68
  - History.txt
106
69
  - README.rdoc
@@ -115,21 +78,7 @@ files:
115
78
  - lib/edl/parser.rb
116
79
  - lib/edl/timewarp.rb
117
80
  - lib/edl/transition.rb
118
- - test/samples/45S_SAMPLE.EDL
119
- - test/samples/FCP_REVERSE.EDL
120
- - test/samples/KEY_TRANSITION.EDL
121
- - test/samples/PLATES.EDL
122
- - test/samples/REEL_IS_CLIP.txt
123
- - test/samples/REVERSE.EDL
124
- - test/samples/SIMPLE_DISSOLVE.EDL
125
- - test/samples/SPEEDUP_AND_FADEOUT.EDL
126
- - test/samples/SPEEDUP_REVERSE_AND_FADEOUT.EDL
127
- - test/samples/SPLICEME.EDL
128
- - test/samples/TIMEWARP.EDL
129
- - test/samples/TIMEWARP_HALF.EDL
130
- - test/samples/TRAILER_EDL.edl
131
- - test/samples/edl_mixed_line_endings.edl
132
- - test/test_edl.rb
81
+ - lib/edl/version.rb
133
82
  homepage: http://guerilla-di.org/edl
134
83
  licenses: []
135
84
  metadata: {}
@@ -139,17 +88,17 @@ require_paths:
139
88
  - lib
140
89
  required_ruby_version: !ruby/object:Gem::Requirement
141
90
  requirements:
142
- - - '>='
91
+ - - ">="
143
92
  - !ruby/object:Gem::Version
144
93
  version: '0'
145
94
  required_rubygems_version: !ruby/object:Gem::Requirement
146
95
  requirements:
147
- - - '>='
96
+ - - ">="
148
97
  - !ruby/object:Gem::Version
149
98
  version: '0'
150
99
  requirements: []
151
100
  rubyforge_project:
152
- rubygems_version: 2.0.3
101
+ rubygems_version: 2.6.11
153
102
  signing_key:
154
103
  specification_version: 4
155
104
  summary: Parser for EDL (Edit Decision List) files