tictacsync 0.3a4__py3-none-any.whl → 0.5a0__py3-none-any.whl

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.
tictacsync/timeline.py CHANGED
@@ -9,14 +9,16 @@ from rich import print
9
9
  from itertools import groupby
10
10
  # import opentimelineio as otio
11
11
  from datetime import timedelta
12
- import pprint, shutil, os
12
+ import pprint, shutil, os, sys
13
13
  from subprocess import Popen, PIPE
14
14
 
15
15
  from inspect import currentframe, getframeinfo
16
16
  try:
17
17
  from . import yaltc
18
+ from . import device_scanner
18
19
  except:
19
20
  import yaltc
21
+ import device_scanner
20
22
 
21
23
  CLUSTER_GAP = 0.5 # secs between multicam clusters
22
24
  DEL_TEMP = False
@@ -26,13 +28,13 @@ OUT_DIR_DEFAULT = 'SyncedMedia'
26
28
  # utility for accessing pathnames
27
29
  def _pathname(tempfile_or_path) -> str:
28
30
  if isinstance(tempfile_or_path, str):
29
- return tempfile_or_path
31
+ return tempfile_or_path ################################################
30
32
  if isinstance(tempfile_or_path, yaltc.Recording):
31
- return str(tempfile_or_path.AVpath)
33
+ return str(tempfile_or_path.AVpath) ####################################
32
34
  if isinstance(tempfile_or_path, Path):
33
- return str(tempfile_or_path)
35
+ return str(tempfile_or_path) ###########################################
34
36
  if isinstance(tempfile_or_path, tempfile._TemporaryFileWrapper):
35
- return tempfile_or_path.name
37
+ return tempfile_or_path.name ###########################################
36
38
  else:
37
39
  raise Exception('%s should be Path or tempfile...'%tempfile_or_path)
38
40
 
@@ -62,17 +64,12 @@ def _extr_channel(source, dest, channel):
62
64
  status = sox_transform.build(str(source), str(dest))
63
65
  logger.debug('sox status %s'%status)
64
66
 
65
- def _sox_keep(audio_file, kept_channels) -> tempfile.NamedTemporaryFile:
67
+ def _sox_keep(audio_file, kept_channels: list) -> tempfile.NamedTemporaryFile:
66
68
  """
67
69
  Returns a NamedTemporaryFile containing the selected kept_channels
68
70
 
69
- if len(kept_channels) == 1 then it's a mono mix on the specified track
70
- if len(kept_channels) == 2 then it's a stereo mix on the specified tracks
71
+ Channels numbers in kept_channels are not ZBIDXed as per SOX format
71
72
  """
72
-
73
-
74
-
75
-
76
73
  audio_file = _pathname(audio_file)
77
74
  nchan = sox.file_info.channels(audio_file)
78
75
  logger.debug('in file of %i chan, have to keep %s'%
@@ -83,8 +80,8 @@ def _sox_keep(audio_file, kept_channels) -> tempfile.NamedTemporaryFile:
83
80
  # eg: {1: [3], 2: [4]} to keep channels 3 & 4
84
81
  kept_channels = [[n] for n in kept_channels]
85
82
  sox_remix_dict = dict(zip(all_channels, kept_channels))
86
- output_fh = tempfile.NamedTemporaryFile(suffix='.wav', delete=DEL_TEMP)
87
- out_file = _pathname(output_fh)
83
+ output_tempfile = tempfile.NamedTemporaryFile(suffix='.wav', delete=DEL_TEMP)
84
+ out_file = _pathname(output_tempfile)
88
85
  logger.debug('sox in and out files: %s %s'%(audio_file, out_file))
89
86
  # sox_transform.set_output_format(channels=1)
90
87
  sox_transform = sox.Transformer()
@@ -103,8 +100,7 @@ def _sox_keep(audio_file, kept_channels) -> tempfile.NamedTemporaryFile:
103
100
  stdout, stderr = p.communicate()
104
101
  logger.debug('remixed out_file ffprobe:\n%s'%(stdout +
105
102
  stderr).decode('utf-8'))
106
- return output_fh
107
-
103
+ return output_tempfile
108
104
 
109
105
  def _split_channels(multi_chan_audio:Path) -> list:
110
106
  nchan = sox.file_info.channels(_pathname(multi_chan_audio))
@@ -132,7 +128,7 @@ def _sox_combine(paths) -> Path:
132
128
  """
133
129
  if len(paths) == 1: # one device only, nothing to stack
134
130
  logger.debug('one device only, nothing to stack')
135
- return paths[0]
131
+ return paths[0] ########################################################
136
132
  out_file_handle = tempfile.NamedTemporaryFile(suffix='.wav',
137
133
  delete=DEL_TEMP)
138
134
  filenames = [_pathname(p) for p in paths]
@@ -158,29 +154,95 @@ def _sox_combine(paths) -> Path:
158
154
  (merged_duration, nchan))
159
155
  return out_file_handle
160
156
 
161
- def _sox_multi2mono(multichan_tmpfl) -> tempfile.NamedTemporaryFile:
162
- # return a mono mix down
157
+ def _sox_multi2stereo(multichan_tmpfl, stereo_trxs) -> tempfile.NamedTemporaryFile:
158
+
159
+ """
160
+ This mixes down all the tracks in multichan_tmpfl to a stereo wav file. Any
161
+ mono tracks are panned 50-50 (mono tracks are those not present in argument
162
+ stereo_trxs)
163
+
164
+ Args:
165
+ multichan_tmpfl : tempfile.NamedTemporaryFile
166
+ contains the edited and synced audio, almost ready to be merged
167
+ with the concurrent video file
168
+ stereo_trxs : list of pairs of integers
169
+ each pairs identifies a left-right tracks, 1st track in
170
+ multichan_tmpfl is index 1 (sox is not ZBIDX)
171
+ Returns:
172
+ the tempfile.NamedTemporaryFile of a stereo wav file
173
+ containing the audio to be merged with the video
174
+ """
163
175
  n_chan_input = sox.file_info.channels(_pathname(multichan_tmpfl))
164
176
  logger.debug('n chan input: %s'%n_chan_input)
165
177
  if n_chan_input == 1: # nothing to mix down
166
- return multichan_tmpfl
167
- mono_tpfl = tempfile.NamedTemporaryFile(suffix='.wav',
178
+ return multichan_tmpfl #################################################
179
+ stereo_tempfile = tempfile.NamedTemporaryFile(suffix='.wav',
168
180
  delete=DEL_TEMP)
169
181
  tfm = sox.Transformer()
170
182
  tfm.channels(1)
171
- status = tfm.build(_pathname(multichan_tmpfl),_pathname(mono_tpfl))
183
+ status = tfm.build(_pathname(multichan_tmpfl),_pathname(stereo_tempfile))
184
+ logger.debug('n chan ouput: %s'%
185
+ sox.file_info.channels(_pathname(stereo_tempfile)))
186
+ logger.debug('sox.build status for _sox_multi2stereo(): %s'%status)
187
+ if status != True:
188
+ print('Error, sox did not normalize file in _sox_multi2stereo()')
189
+ sys.exit(1)
190
+ return stereo_tempfile
191
+
192
+ def _sox_mix_channels(multichan_tmpfl, stereo_pairs=[]) -> tempfile.NamedTemporaryFile:
193
+ """
194
+ Returns a mix down of the multichannel wav file. If stereo_pairs list is
195
+ empty, a mono mix is done with all the channel present in multichan_tmpfl.
196
+ If stereo_pairs contains one or more elements, a stereo mix is returned with
197
+ the specified Left-Right pairs and all other mono tracks (panned 50-50)
198
+
199
+ Note: stereo_pairs numbers are not ZBIDXed
200
+ """
201
+ n_chan_input = sox.file_info.channels(_pathname(multichan_tmpfl))
202
+ logger.debug('n chan input: %s'%n_chan_input)
203
+ if n_chan_input == 1: # nothing to mix down
204
+ return multichan_tmpfl #################################################
205
+ if stereo_pairs == []:
206
+ # all mono
207
+ mono_tpfl = tempfile.NamedTemporaryFile(suffix='.wav',
208
+ delete=DEL_TEMP)
209
+ tfm = sox.Transformer()
210
+ tfm.channels(1)
211
+ status = tfm.build(_pathname(multichan_tmpfl),_pathname(mono_tpfl))
212
+ logger.debug('number of chan in ouput: %s'%
213
+ sox.file_info.channels(_pathname(mono_tpfl)))
214
+ logger.debug('sox.build status for _sox_mix_channels(): %s'%status)
215
+ if status != True:
216
+ print('Error, sox did not normalize file in _sox_mix_channels()')
217
+ sys.exit(1)
218
+ return mono_tpfl
219
+ else:
220
+ # stereo tracks present, so stereo output
221
+ logger.debug('stereo tracks present %s, so stereo output'%stereo_pairs)
222
+ stereo_files = [_sox_keep(pair) for pair in stereo_pairs]
223
+ return
224
+
225
+ def _sox_mono2stereo(temp_file) -> tempfile.NamedTemporaryFile:
226
+ # upgrade a mono file to stereo panning 50-50
227
+ stereo_tempfile = tempfile.NamedTemporaryFile(suffix='.wav',
228
+ delete=DEL_TEMP)
229
+ tfm = sox.Transformer()
230
+ tfm.channels(2)
231
+ status = tfm.build(_pathname(temp_file),_pathname(stereo_tempfile))
172
232
  logger.debug('n chan ouput: %s'%
173
- sox.file_info.channels(_pathname(mono_tpfl)))
174
- logger.debug('sox.build status for _sox_multi2mono(): %s'%status)
233
+ sox.file_info.channels(_pathname(stereo_tempfile)))
234
+ logger.debug('sox.build status for _sox_mono2stereo(): %s'%status)
175
235
  if status != True:
176
- print('Error, sox did not normalize file in _sox_multi2mono()')
236
+ print('Error, sox did not normalize file in _sox_mono2stereo()')
177
237
  sys.exit(1)
178
- return mono_tpfl
238
+ return stereo_tempfile
179
239
 
180
240
 
181
- def _sox_mix(paths:list) -> tempfile.NamedTemporaryFile:
241
+ def _sox_mix_files(temp_files_to_mix:list) -> tempfile.NamedTemporaryFile:
182
242
  """
183
- mix files referred by the list of Path into a new temporary files passed on return
243
+ Mix files referred by the list of Path into a new temporary files passed on
244
+ return. If one of the files is stereo, upgrade each mono file to a panned
245
+ 50-50 stereo file before mixing.
184
246
  """
185
247
  def _sox_norm(tempf):
186
248
  normed_tempfile = tempfile.NamedTemporaryFile(suffix='.wav',
@@ -190,28 +252,42 @@ def _sox_mix(paths:list) -> tempfile.NamedTemporaryFile:
190
252
  status = tfm.build(_pathname(tempf),_pathname(normed_tempfile))
191
253
  logger.debug('sox.build status for norm(): %s'%status)
192
254
  if status != True:
193
- print('Error, sox did not normalize file in _sox_mix()')
255
+ print('Error, sox did not normalize file in _sox_mix_files()')
194
256
  sys.exit(1)
195
257
  return normed_tempfile
196
- paths = [_sox_norm(p) for p in paths]
197
- cbn = sox.Combiner()
198
- N = len(paths)
258
+ N = len(temp_files_to_mix)
199
259
  if N == 1: # nothing to mix
200
260
  logger.debug('one file: nothing to mix')
201
- return paths[0]
261
+ return temp_files_to_mix[0] ########################################################
262
+ cbn = sox.Combiner()
202
263
  cbn.set_input_format(file_type=['wav']*N)
203
- filenames = [_pathname(p) for p in paths]
204
- logger.debug('%i files to mix %s'%(N, filenames))
205
- logger.debug('nchan for each file %s'%[sox.file_info.channels(f) for
206
- f in filenames])
264
+ # check if stereo files are present
265
+ max_n_chan = max([sox.file_info.channels(f) for f
266
+ in [_pathname(p) for p in temp_files_to_mix]])
267
+ logger.debug('max_n_chan %s'%max_n_chan)
268
+ if max_n_chan == 2:
269
+ # upgrade all mono to stereo
270
+ stereo_tempfiles = [p for p in temp_files_to_mix
271
+ if sox.file_info.channels(_pathname(p)) == 2 ]
272
+ mono_tempfiles = [p for p in temp_files_to_mix
273
+ if sox.file_info.channels(_pathname(p)) == 1 ]
274
+ logger.debug('there are %i mono files and %i stereo files'%
275
+ (len(stereo_tempfiles), len(mono_tempfiles)))
276
+ new_stereo = [_sox_mono2stereo(tmpfl) for tmpfl
277
+ in mono_tempfiles]
278
+ stereo_tempfiles += new_stereo
279
+ files_to_mix = [_pathname(tempfl) for tempfl in stereo_tempfiles]
280
+ else:
281
+ # all mono
282
+ files_to_mix = [_pathname(tempfl) for tempfl in temp_files_to_mix]
207
283
  mixed_tempf = tempfile.NamedTemporaryFile(suffix='.wav',delete=DEL_TEMP)
208
- status = cbn.build(filenames,
284
+ status = cbn.build(files_to_mix,
209
285
  _pathname(mixed_tempf),
210
286
  combine_type='mix',
211
287
  input_volumes=[1/N]*N)
212
288
  logger.debug('sox.build status for mix: %s'%status)
213
289
  if status != True:
214
- print('Error, sox did not mix files in _sox_mix()')
290
+ print('Error, sox did not mix files in _sox_mix_files()')
215
291
  sys.exit(1)
216
292
  normed_tempfile = tempfile.NamedTemporaryFile(suffix='.wav',delete=DEL_TEMP)
217
293
  tfm = sox.Transformer()
@@ -219,16 +295,15 @@ def _sox_mix(paths:list) -> tempfile.NamedTemporaryFile:
219
295
  status = tfm.build(_pathname(mixed_tempf),_pathname(normed_tempfile))
220
296
  logger.debug('sox.build status for norm(): %s'%status)
221
297
  if status != True:
222
- print('Error, sox did not normalize file in _sox_mix()')
298
+ print('Error, sox did not normalize file in _sox_mix_files()')
223
299
  sys.exit(1)
224
300
  return normed_tempfile
225
301
 
226
-
227
302
  class AudioStitcherVideoMerger:
228
303
  """
229
304
  Typically each found video is associated with an AudioStitcherVideoMerger
230
305
  instance. AudioStitcherVideoMerger does the actual audio-video file
231
- processing of merging self.ref_recording (gen. a video) with all audio
306
+ processing of merging self.videoclip (gen. a video) with all audio
232
307
  files in self.edited_audio as determined by the Matcher
233
308
  object (it instanciates and manages AudioStitcherVideoMerger objects).
234
309
 
@@ -237,15 +312,15 @@ class AudioStitcherVideoMerger:
237
312
  devices to match the precise clock value of the ref recording (to a few
238
313
  ppm), using sox tempo transform.
239
314
 
240
- N.B.: A audio_stitch doesn't extend beyond the corresponding ref_recording
315
+ N.B.: A audio_stitch doesn't extend beyond the corresponding videoclip
241
316
  video start and end times: it is not a audio montage for the whole movie
242
317
  project.
243
318
 
244
319
 
245
320
  Attributes:
246
321
 
247
- ref_recording : a Recording instance
248
- The video (or designated main sound) audio files are synced to
322
+ videoclip : a Recording instance
323
+ The video to which audio files are synced
249
324
 
250
325
  edited_audio : dict as {Recording : path}
251
326
  keys are elements of matched_audio_recordings of class Recording
@@ -259,19 +334,19 @@ class AudioStitcherVideoMerger:
259
334
 
260
335
  """
261
336
 
262
- def __init__(self, reference_recording):
263
- self.ref_recording = reference_recording
337
+ def __init__(self, video_clip):
338
+ self.videoclip = video_clip
264
339
  # self.matched_audio_recordings = []
265
340
  self.edited_audio = {}
266
341
  logger.debug('instantiating AudioStitcherVideoMerger for %s'%
267
- reference_recording)
342
+ video_clip)
268
343
 
269
344
  def add_matched_audio(self, audio_rec):
270
345
  """
271
346
  Populates self.edited_audio, a dict as {Recording : path}
272
347
 
273
348
  AudioStitcherVideoMerger.add_matched_audio() is called
274
- within Matcher.scan_audio_for_each_ref_rec()
349
+ within Matcher.scan_audio_for_each_videoclip()
275
350
 
276
351
  Returns nothing, fills self.edited_audio dict with
277
352
  matched audio.
@@ -290,7 +365,7 @@ class AudioStitcherVideoMerger:
290
365
 
291
366
  def get_matched_audio_recs(self):
292
367
  """
293
- Returns audio recordings that overlap self.ref_recording.
368
+ Returns audio recordings that overlap self.videoclip.
294
369
  Simply keys of self.edited_audio dict
295
370
  """
296
371
  return list(self.edited_audio.keys())
@@ -315,14 +390,14 @@ class AudioStitcherVideoMerger:
315
390
  sox_transform = sox.Transformer()
316
391
  # tempo_scale_factor = rec.device_relative_speed
317
392
  tempo_scale_factor = rec.device_relative_speed
318
- reC_dev = rec.device.name
319
- reF_dev = self.ref_recording.device.name
393
+ audio_dev = rec.device.name
394
+ video_dev = self.videoclip.device.name
320
395
  if tempo_scale_factor > 1:
321
396
  print('[gold1]%s[/gold1] clock too fast relative to [gold1]%s[/gold1] so file is too long by a %f factor\n'%
322
- (reC_dev, reF_dev, tempo_scale_factor))
397
+ (audio_dev, video_dev, tempo_scale_factor))
323
398
  else:
324
399
  print('[gold1]%s[/gold1] clock too slow relative to [gold1]%s[/gold1] so file is too short by a %f factor\n'%
325
- (reC_dev, reF_dev, tempo_scale_factor))
400
+ (audio_dev, video_dev, tempo_scale_factor))
326
401
  sox_transform.tempo(tempo_scale_factor)
327
402
  # scaled_file = self._get_soxed_file(rec, sox_transform)
328
403
  logger.debug('sox_transform %s'%sox_transform.effects)
@@ -347,11 +422,11 @@ class AudioStitcherVideoMerger:
347
422
  # ones. List the files and warn the user there is a risk of error if
348
423
  # they're not from the same device.
349
424
 
350
- logger.debug('%i audio files for reference rec %s:'%(len(recordings),
351
- self.ref_recording))
425
+ logger.debug('%i audio files for videoclip %s:'%(len(recordings),
426
+ self.videoclip))
352
427
  for r in recordings:
353
428
  logger.debug(' %s'%r)
354
- speeds = numpy.array([rec.get_speed_ratio(self.ref_recording)
429
+ speeds = numpy.array([rec.get_speed_ratio(self.videoclip)
355
430
  for rec in recordings])
356
431
  mean_speed = numpy.mean(speeds)
357
432
  for r in recordings:
@@ -359,9 +434,9 @@ class AudioStitcherVideoMerger:
359
434
  # r.device_relative_speed = 0.9
360
435
  logger.debug('set device_relative_speed for %s'%r)
361
436
  logger.debug(' value: %f'%r.device_relative_speed)
362
- r.set_time_position_to(self.ref_recording)
437
+ r.set_time_position_to(self.videoclip)
363
438
  logger.debug('time_position for %s: %fs relative to %s'%(r,
364
- r.time_position, self.ref_recording))
439
+ r.time_position, self.videoclip))
365
440
  # st_dev_speeds just to check for anomalous situation
366
441
  st_dev_speeds = numpy.std(speeds)
367
442
  logger.debug('mean speed for %s: %.6f std dev: %.0e'%(device,
@@ -427,7 +502,7 @@ class AudioStitcherVideoMerger:
427
502
  end_time = sox.file_info.duration(growing_file.name)
428
503
  logger.debug('total edited audio duration %.2f s'%end_time)
429
504
  logger.debug('video duration %.2f s'%
430
- self.ref_recording.get_duration())
505
+ self.videoclip.get_duration())
431
506
  return growing_file
432
507
 
433
508
  def _pad_or_trim_first_audio(self, first_rec):
@@ -436,17 +511,17 @@ class AudioStitcherVideoMerger:
436
511
  NO: will change tempo after trimming/padding
437
512
 
438
513
  Store (into Recording.edited_audio dict) the handle of the sox processed
439
- first recording, padded or chopped according to AudioStitcherVideoMerger.ref_recording
514
+ first recording, padded or chopped according to AudioStitcherVideoMerger.videoclip
440
515
  starting time. Length of the written file can differ from length of the
441
516
  submitted Recording object if drift is corrected with sox tempo
442
517
  transform, so check it with sox.file_info.duration()
443
518
  """
444
519
  logger.debug(' editing %s'%first_rec)
445
520
  audio_start = first_rec.get_start_time()
446
- ref_start = self.ref_recording.get_start_time()
447
- if ref_start < audio_start: # padding
521
+ video_start = self.videoclip.get_start_time()
522
+ if video_start < audio_start: # padding
448
523
  logger.debug('padding')
449
- pad_duration = (audio_start-ref_start).total_seconds()
524
+ pad_duration = (audio_start-video_start).total_seconds()
450
525
  """padding first_file:
451
526
  ┏━━━━━━━━━━━━━━━┓
452
527
  ┗━━━━━━━━━━━━━━━┛ref
@@ -456,7 +531,7 @@ class AudioStitcherVideoMerger:
456
531
  self._pad_file(first_rec, pad_duration)
457
532
  else:
458
533
  logger.debug('trimming')
459
- length = (ref_start-audio_start).total_seconds()
534
+ length = (video_start-audio_start).total_seconds()
460
535
  """chopping first_file:
461
536
  ┏━━━━━━━━━━━━━━━┓
462
537
  ┗━━━━━━━━━━━━━━━┛ref
@@ -505,7 +580,7 @@ class AudioStitcherVideoMerger:
505
580
  logger.debug('transform: %s'%sox_transform.effects)
506
581
  recording_fh = self.edited_audio[audio_rec]
507
582
  logger.debug('for recording %s, matching %s'%(audio_rec,
508
- self.ref_recording))
583
+ self.videoclip))
509
584
  input_file = _pathname(recording_fh)
510
585
  logger.debug('AudioStitcherVideoMerger.edited_audio[audio_rec]: %s'%
511
586
  input_file)
@@ -551,7 +626,7 @@ class AudioStitcherVideoMerger:
551
626
  """
552
627
  sox_transform = sox.Transformer()
553
628
  audio_length = sox.file_info.duration(_pathname(audio_tempfile))
554
- video_length = self.ref_recording.get_duration()
629
+ video_length = self.videoclip.get_duration()
555
630
  if audio_length > video_length:
556
631
  # trim audio
557
632
  sox_transform.trim(0, video_length)
@@ -570,9 +645,9 @@ class AudioStitcherVideoMerger:
570
645
  logger.debug('audio duration %.2f s'%
571
646
  sox.file_info.duration(_pathname(out_tf)))
572
647
  logger.debug('video duration %.2f s'%
573
- self.ref_recording.get_duration())
648
+ self.videoclip.get_duration())
574
649
  return out_tf
575
- synced_clip_file = self.ref_recording.final_synced_file
650
+ synced_clip_file = self.videoclip.final_synced_file
576
651
  synced_clip_dir = synced_clip_file.parent
577
652
  # build ISOs subfolders structure, see comment string below
578
653
  video_stem_WO_suffix = synced_clip_file.stem
@@ -591,75 +666,148 @@ class AudioStitcherVideoMerger:
591
666
  mono_tmpfl_trimpad = _fit_length(mono_tmpfl)
592
667
  shutil.copy(_pathname(mono_tmpfl_trimpad), destination)
593
668
  logger.debug('destination:%s'%destination)
594
- # # mixNnormed = _sox_mix(tempfiles)
669
+ # # mixNnormed = _sox_mix_files(tempfiles)
595
670
  # # print('516', _pathname(mixNnormed))
596
671
  # os.remove(ISO_multi_chan)
597
672
 
598
- def _get_mix(self, device, multichan_tmpfl) -> tempfile.NamedTemporaryFile:
599
- """
600
- If device has an associated Tracks description that declares a (mono or
601
- stereo) mix track, returns a tmpfl containing the corresponding
602
- tracks. If not, mix all the tracks with sox.
673
+ def _get_device_mix(self, device, multichan_tmpfl) -> tempfile.NamedTemporaryFile:
674
+ """
675
+ Build or get a mix from edited and joined audio for a given device
676
+
677
+ Returns a mix for merging with video clip. The way the mix is obtained
678
+ (or created) depends if a tracks.txt for the device was submitted and
679
+ depends on its content. There are 4 cases (explained later):
680
+
681
+ #1 no mix (or no tracks.txt), all mono
682
+ #2 no mix, one or more stereo mics
683
+ #3 mono mix declared
684
+ #4 stereo mix declared
685
+
686
+ In details:
687
+
688
+ If no device tracks.txt file declared a mix track (or if tracks.txt is
689
+ absent), a mix is done programmatically. Two possibilities:
690
+
691
+ #1- no stereo pairs were declared: a global mono mix is returned.
692
+ #2- one or more stereo pair mics were used and declared (micL, micR):
693
+ a global stereo mix is returned with mono tracks panned 50-50
694
+
695
+ If device has an associated Tracks description AND it declares a(mono or
696
+ stereo) mix track, this fct returns a tempfile containing the
697
+ corresponding tracks, simpley extarcting them from multichan_tmpfl
698
+ (thos covers cases #3 and #4)
699
+
700
+ Args:
701
+ device : device_scanner.Device dataclass
702
+ the device that recorded the audio found in multichan_tmpfl
703
+ multichan_tmpfl : tempfile.NamedTemporaryFile
704
+ contains the edited and synced audio, almost ready to be merged
705
+ with the concurrent video file (after mix down)
706
+
707
+ Returns:
708
+ the tempfile.NamedTemporaryFile of a stereo or mono wav file
709
+ containing the audio to be merged with the video in
710
+ self.videoclip
603
711
 
604
- If no L-R tracks are declared in tracks.txt, a mono mix is returned;
605
- If some
606
- micL micR or mixL mixR
607
712
 
608
713
  """
609
- if device.tracks is None:
610
- logger.debug('no tracks.txt, mixing all')
611
- return _sox_multi2mono(multichan_tmpfl)
612
- mix_tracks = device.tracks.mix
613
- if mix_tracks == []:
614
- logger.debug('tracks.txt present but no mix trx, mixing all')
615
- return _sox_multi2mono(multichan_tmpfl)
616
- # if here, mix exists
617
- logger.debug('%s has mix %s'%(device.name, mix_tracks))
618
714
  logger.debug('device %s'%device)
619
- if 'ttc' in device.tracks.rawtrx:
620
- sox_TTC_chan = device.tracks.rawtrx.index('ttc')
621
- elif 'tc' in device.tracks.rawtrx:
622
- sox_TTC_chan = device.tracks.rawtrx.index('tc')
623
- else:
624
- print('Error: no tc or ttc tag in track.txt')
715
+ if device.n_chan == 2:
716
+ # tracks.txt or not,
717
+ # it's stereo, ie audio + TTC, so remove TTC and return
718
+ kept_channel = (device.ttc + 1)%2 # 1 -> 0 and 0 -> 1
719
+ logger.debug('no tracks.txt, keeping one chan %i'%kept_channel)
720
+ return _sox_keep(multichan_tmpfl, [kept_channel + 1]) #-------------
721
+ logger.debug('device.n_chan != 2, so multitrack')
722
+ # it's multitrack (more than 2 channels)
723
+ if device.tracks is None:
724
+ # multitrack but no mix done on location, so do mono mix with all
725
+ all_channels = list(range(device.n_chan))
726
+ logger.debug('multitrack but no tracks.txt, mixing %s except TTC at %i'%
727
+ (all_channels, device.ttc))
728
+ all_channels.remove(device.ttc)
729
+ sox_kept_channels = [i + 1 for i in all_channels] # sox indexing
730
+ logger.debug('mixing channels: %s (sox #)'%sox_kept_channels)
731
+ kept_audio = _sox_keep(multichan_tmpfl, sox_kept_channels)
732
+ return _sox_mix_channels(kept_audio) #------------------------------
733
+ logger.debug('there IS a device.tracks')
734
+ # user wrote a tracks.txt metadata file, check it to get the mix(or do
735
+ # it). But first a check is done if the ttc tracks concur: the track
736
+ # detected by the Decoder class, stored in device.ttc VS the track
737
+ # declared by the user, device.tracks.ttc (see device_scanner.py). If
738
+ # not, warn the user and exit.
739
+ logger.debug('ttc channel declared for the device: %i, ttc detected: %i, non zero base indexing'%
740
+ (device.ttc, device.tracks.ttc))
741
+ if device.ttc + 1 != device.tracks.ttc: # warn and quit
742
+ print('Error: TicTacCode channel detected is [gold1]%i[/gold1]'%
743
+ device.ttc + 1, end=' ')
744
+ print('and the file [gold1]%s[/gold1] specifies channel [gold1]%i[/gold1],'%
745
+ (device_scanner.TRACKSFN, device.tracks.ttc))
746
+ print('Please correct the discrepancy and rerun. Quitting.')
747
+ sys.exit(1)
748
+ if device.tracks.mix == [] and device.tracks.stereomics == []:
749
+ # it's multitrac and no mix done on location, so do a mono mix with
750
+ # all, but here remove '0' and TTC tracks from mix
751
+ all_channels = list(range(1, device.n_chan + 1)) # sox not ZBIDX
752
+ to_remove = device.tracks.unused + [device.ttc+1]# unused is sox idx
753
+ logger.debug('multitrack but no tracks.txt, mixing %s except # %s (sox #)'%
754
+ (all_channels, to_remove))
755
+ sox_kept_channels = [i for i in all_channels
756
+ if i not in to_remove]
757
+ logger.debug('mixing channels: %s (sox #)'%sox_kept_channels)
758
+ kept_audio = _sox_keep(multichan_tmpfl, sox_kept_channels)
759
+ return _sox_mix_channels(kept_audio) #------------------------------
760
+ logger.debug('device.tracks.mix != [] or device.tracks.stereomics != []')
761
+ if device.tracks.mix != []:
762
+ # Mix were done on location, no and we only have to extracted it
763
+ # from the recording. If mono mix, device.tracks.mix has one element;
764
+ # if stereo mix, device.tracks.mix is a pair of number:
765
+ logger.debug('%s has mix %s'%(device.name, device.tracks.mix))
766
+ logger.debug('device %s'%device)
767
+ # just checking coherency
768
+ if 'ttc' in device.tracks.rawtrx:
769
+ trx_TTC_chan = device.tracks.rawtrx.index('ttc')
770
+ elif 'tc' in device.tracks.rawtrx:
771
+ trx_TTC_chan = device.tracks.rawtrx.index('tc')
772
+ else:
773
+ print('Error: no tc or ttc tag in track.txt')
774
+ sys.exit(1)
775
+ logger.debug('TTC chan %i, dev ttc %i'%(trx_TTC_chan, device.ttc))
776
+ if trx_TTC_chan != device.ttc:
777
+ print('Error: ttc channel # incoherency in track.txt')
778
+ sys.exit(1)
779
+ # coherency check done, extract mix track (or tracks if stereo)
780
+ mix_kind = 'mono' if len(device.tracks.mix) == 1 else 'stereo'
781
+ logger.debug('%s mix declared on channel %s (sox #)'%
782
+ (mix_kind, device.tracks.mix))
783
+ return _sox_keep(multichan_tmpfl, device.tracks.mix) #--------------
784
+ logger.debug('device.tracks.mix == []')
785
+ # if here, all cases have been covered, all is remaining is this case:
786
+ # tracks.txt exists AND there is no mix AND stereo mic(s) so first a
787
+ # coherency check, and then proceed
788
+ if device.tracks.stereomics == []:
789
+ print('Error, no stereo mic?, check tracks.txt. Quitting')
625
790
  sys.exit(1)
626
- sox_TTC_chan += 1 # sox Not ZBIDX
627
- logger.debug('TTC chan %i'%sox_TTC_chan)
628
- # redo indexing since tracks.txt numbers refere to complete
629
- # files and here audio file had TTC and muted channels
630
- # removed:
631
- if len(mix_tracks) == 2: # two tracks to shift
632
- mixL_chan, mixR_chan = mix_tracks
633
- # shifting left chan if necessary
634
- shift = 0
635
- if mixL_chan > sox_TTC_chan:
636
- shift += 1
637
- for unused_tr in device.tracks.unused:
638
- if mixL_chan > unused_tr:
639
- shift += 1
640
- mixL_chan -= shift
641
- # shifting right chan if necessary
642
- shift = 0
643
- if mixR_chan > sox_TTC_chan:
644
- shift += 1
645
- for unused_tr in device.tracks.unused:
646
- if mixR_chan > unused_tr:
647
- shift += 1
648
- mixR_chan -= shift
649
- mix_tracks = [mixL_chan, mixR_chan]
650
- else: # mono, one track to shift
651
- monomix_chan = mix_tracks[0]
652
- shift = 0
653
- if monomix_chan > sox_TTC_chan:
654
- shift += 1
655
- for unused_tr in device.tracks.unused:
656
- if monomix_chan > unused_tr:
657
- shift += 1
658
- monomix_chan -= shift
659
- mix_tracks = [monomix_chan]
660
- logger.debug('new mix_tracks: %s'%mix_tracks)
661
- return _sox_keep(multichan_tmpfl, mix_tracks)
662
-
791
+ logger.debug('processing stereo pair(s) %s'%device.tracks.stereomics)
792
+ stereo_mic_idx_pairs = [pair for name, pair in device.tracks.stereomics]
793
+ logger.debug('stereo pairs idxs %s'%stereo_mic_idx_pairs)
794
+ mic_stereo_files = [_sox_keep(multichan_tmpfl, pair) for pair
795
+ in stereo_mic_idx_pairs]
796
+ # flatten list of tuples of channels being stereo mics
797
+ stereo_mic_idx_flat = [item for sublist in stereo_mic_idx_pairs
798
+ for item in sublist]
799
+ logger.debug('stereo_mic_idx_flat %s'%stereo_mic_idx_flat)
800
+ mono_tracks = [i for i in range(1, device.n_chan + 1)
801
+ if i not in stereo_mic_idx_flat]
802
+ logger.debug('mono_tracks: %s'%mono_tracks)
803
+ # remove TTC track number
804
+ mono_tracks.remove(device.ttc + 1)
805
+ logger.debug('mono_tracks %s'%mono_tracks)
806
+ mono_files = [_sox_keep(multichan_tmpfl, [chan]) for chan
807
+ in mono_tracks]
808
+ new_stereo_files = [_sox_mono2stereo(f) for f in mono_files]
809
+ stereo_files = mic_stereo_files + new_stereo_files
810
+ return _sox_mix_files(stereo_files)
663
811
 
664
812
  def build_audio_and_write_video(self, top_dir, output_dir,
665
813
  write_multicam_structure,
@@ -674,7 +822,7 @@ class AudioStitcherVideoMerger:
674
822
 
675
823
  asked_ISOs: bool flag specified as CLI argument
676
824
 
677
- For each audio devices found overlapping self.ref_recording: pad, trim
825
+ For each audio devices found overlapping self.videoclip: pad, trim
678
826
  or stretch audio files by calling _get_concatenated_audiofile_for(), and
679
827
  put them in merged_audio_files_by_device. More than one audio recorder
680
828
  can be used for a shot: that's why merged_audio_files_by_device is a
@@ -686,8 +834,8 @@ class AudioStitcherVideoMerger:
686
834
  """
687
835
  logger.debug(' fct args: top_dir: %s; output_dir: %s; write_multicam_structure: %s; asked_ISOs: %s;'%
688
836
  (top_dir, output_dir, write_multicam_structure, asked_ISOs))
689
- logger.debug('device for rec %s: %s'%(self.ref_recording,
690
- self.ref_recording.device))
837
+ logger.debug('device for rec %s: %s'%(self.videoclip,
838
+ self.videoclip.device))
691
839
  # suppose the user called tictacsync with 'mondayPM' as top folder to
692
840
  # scan for dailies (and 'somefolder' for output):
693
841
  if output_dir == None:
@@ -695,56 +843,72 @@ class AudioStitcherVideoMerger:
695
843
  else:
696
844
  synced_clip_dir = Path(output_dir)/Path(top_dir).name # = somefolder/mondayPM
697
845
  if write_multicam_structure:
698
- device_name = self.ref_recording.device.name
846
+ device_name = self.videoclip.device.name
699
847
  synced_clip_dir = synced_clip_dir/device_name # = synced_clip_dir/ZOOM
700
848
  self.synced_clip_dir = synced_clip_dir
701
849
  os.makedirs(synced_clip_dir, exist_ok=True)
702
850
  logger.debug('synced_clip_dir is: %s'%synced_clip_dir)
703
851
  synced_clip_file = synced_clip_dir/\
704
- Path(self.ref_recording.new_rec_name).name
852
+ Path(self.videoclip.new_rec_name).name
705
853
  logger.debug('editing files for %s'%synced_clip_file)
706
- self.ref_recording.final_synced_file = synced_clip_file # relative
707
- # collecting edited audio by device, in (Device, tempfile) pairs:
854
+ self.videoclip.final_synced_file = synced_clip_file # relative path
855
+ # Collecting edited audio by device, in (Device, tempfile) pairs:
856
+ # for a given self.videoclip, each audio device will have a sequence
857
+ # of matched, synced and joined audio files present in a single
858
+ # edited audio file, returned by _get_concatenated_audiofile_for
708
859
  merged_audio_files_by_device = [
709
860
  (d, self._get_concatenated_audiofile_for(d))
710
861
  for d in self._get_audio_devices()]
711
862
  if len(merged_audio_files_by_device) == 0:
712
863
  # no audio file overlaps for this clip
713
- return
864
+ return #############################################################
714
865
  if len(merged_audio_files_by_device) == 1:
715
866
  # only one audio recorder was used, pick singleton in list
716
867
  dev, concatenate_audio_file = merged_audio_files_by_device[0]
717
868
  logger.debug('one audio device only: %s'%dev)
718
869
  # check if this sole recorder is stereo
719
870
  if dev.n_chan == 2:
720
- # stereo minus TTC chan = mono, check consistency:
871
+ # consistency check
721
872
  nchan_sox = sox.file_info.channels(
722
873
  _pathname(concatenate_audio_file))
723
- logger.debug('nchan_sox: %i mono?'%nchan_sox)
724
- if not nchan_sox == 1:
874
+ logger.debug('Two chan only, nchan_sox: %i dev.n_chan %i'%
875
+ (nchan_sox, dev.n_chan))
876
+ if not nchan_sox == 2:
725
877
  raise Exception('Error in channel processing')
726
878
  # all OK, merge and return
727
- logger.debug('simply mono to merge')
728
- self.ref_recording.synced_audio = concatenate_audio_file
879
+ logger.debug('simply mono to merge, TTC on chan %i'%
880
+ dev.ttc)
881
+ # only 2 channels so keep the channel OTHER than TTC
882
+ if dev.ttc == 1:
883
+ # keep channel 0, but + 1 because of sox indexing
884
+ sox_kept_channel = 1
885
+ else:
886
+ # dev.ttc == 0 so keep ch 1, but + 1 (sox indexing)
887
+ sox_kept_channel = 2
888
+ self.videoclip.synced_audio = \
889
+ _sox_keep(concatenate_audio_file, [sox_kept_channel])
729
890
  self._merge_audio_and_video()
730
- return
731
- # if still here, either multitracks and/or multi recorders so check if a
732
- # mix has been done on location and identified as is in atracks.txt
733
- # file. Split audio channels in mono wav tempfiles at the same time
891
+ return #########################################################
892
+ #
893
+ # if not returned yet from fct, either multitracks and/or multi
894
+ # recorders so check if a mix has been done on location and identified
895
+ # as is in atracks.txt file. Split audio channels in mono wav tempfiles
896
+ # at the same time
734
897
  #
735
898
  multiple_recorders = len(merged_audio_files_by_device) > 1
736
899
  logger.debug('multiple_recorder: %s'%multiple_recorders)
737
- # dev_mixes_mix contains all audio recorders if many
738
- mixes = [self._get_mix(device, multi_chan_audio)
900
+ # the device_mixes list contains all audio recorders if many. If only
901
+ # one audiorecorder was used (most of the cases) len(device_mixes) is 1
902
+ device_mixes = [self._get_device_mix(device, multi_chan_audio)
739
903
  for device, multi_chan_audio
740
904
  in merged_audio_files_by_device]
741
- logger.debug('there are %i dev mixes'%len(mixes))
742
- logger.debug('mixes %s'%mixes)
743
- dev_mixes_mix = _sox_mix(mixes)
744
- logger.debug('will merge with %s'%(_pathname(dev_mixes_mix)))
745
- self.ref_recording.synced_audio = dev_mixes_mix
746
- logger.debug('dev_mixes_mix n chan: %i'%
747
- sox.file_info.channels(_pathname(dev_mixes_mix)))
905
+ logger.debug('there are %i dev device_mixes'%len(device_mixes))
906
+ logger.debug('device_mixes %s'%device_mixes)
907
+ mix_of_device_mixes = _sox_mix_files(device_mixes)
908
+ logger.debug('will merge with %s'%(_pathname(mix_of_device_mixes)))
909
+ self.videoclip.synced_audio = mix_of_device_mixes
910
+ logger.debug('mix_of_device_mixes n chan: %i'%
911
+ sox.file_info.channels(_pathname(mix_of_device_mixes)))
748
912
  self._merge_audio_and_video()
749
913
  # devices_and_monofiles is list of (device, [monofiles])
750
914
  # [(dev1, multichan1), (dev2, multichan2)] in
@@ -757,24 +921,28 @@ class AudioStitcherVideoMerger:
757
921
  in merged_audio_files_by_device]
758
922
  logger.debug('devices_and_monofiles: %s'%
759
923
  pprint.pformat(devices_and_monofiles))
760
- def _trnm(dev, idx): # used in the list comprehension just below
924
+ def _trnm(dev, idx): # used in the loop just below
761
925
  # generates track name for later if asked_ISOs
762
926
  # idx is from 0 to nchan-1 for this device
763
927
  if dev.tracks == None:
764
928
  tag = 'chan%s'%str(idx+1).zfill(2)
765
929
  else:
766
- audio_tags = [tag for tag in dev.tracks.rawtrx
767
- if tag not in ['ttc','0','tc']]
768
- tag = audio_tags[idx]
930
+ # audio_tags = [tag for tag in dev.tracks.rawtrx
931
+ # if tag not in ['ttc','0','tc']]
932
+ tag = dev.tracks.rawtrx[idx]
769
933
  if multiple_recorders:
770
934
  tag += '_' + dev.name
771
- return tag
935
+ logger.debug('tag %s'%tag)
936
+ return tag #####################################################
772
937
  # replace device, idx pair with track name (+ device name if many)
773
938
  # loop over devices than loop over tracks
774
939
  names_audio_tempfiles = []
775
940
  for dev, mono_tmpfiles_list in devices_and_monofiles:
776
941
  for idx, monotf in enumerate(mono_tmpfiles_list):
777
- names_audio_tempfiles.append((_trnm(dev, idx), monotf))
942
+ track_name = _trnm(dev, idx)
943
+ if track_name[0] == '0': # muted, skip
944
+ continue
945
+ names_audio_tempfiles.append((track_name, monotf))
778
946
  logger.debug('names_audio_tempfiles %s'%names_audio_tempfiles)
779
947
  self._write_ISOs(names_audio_tempfiles)
780
948
  logger.debug('merged_audio_files_by_device %s'%
@@ -804,25 +972,24 @@ class AudioStitcherVideoMerger:
804
972
  out1 = in1.output(file_handle.name, map='0:v', vcodec='copy')
805
973
  ffmpeg.run([out1.global_args(*silenced_opts)], overwrite_output=True)
806
974
  return file_handle
807
- # os.path.split audio channels if more than one
808
975
 
809
976
  def _merge_audio_and_video(self):
810
977
  """
811
- Calls ffmpeg to join video in self.ref_recording.AVpath to
812
- audio in self.ref_recording.synced_audio
978
+ Calls ffmpeg to join video in self.videoclip.AVpath to
979
+ audio in self.videoclip.synced_audio
813
980
 
814
- On entry, ref_recording.final_synced_file is a Path to an non existing
815
- file (contrarily to ref_recording.synced_audio).
816
- On exit, self.ref_recording.final_synced_file points to the final synced
981
+ On entry, videoclip.final_synced_file is a Path to an non existing
982
+ file (contrarily to videoclip.synced_audio).
983
+ On exit, self.videoclip.final_synced_file points to the final synced
817
984
  video file.
818
985
 
819
986
  Returns nothing.
820
987
  """
821
- synced_clip_file = self.ref_recording.final_synced_file
822
- video_path = self.ref_recording.AVpath
823
- timecode = self.ref_recording.get_timecode()
824
- # self.ref_recording.synced_audio = audio_path
825
- audio_path = self.ref_recording.synced_audio
988
+ synced_clip_file = self.videoclip.final_synced_file
989
+ video_path = self.videoclip.AVpath
990
+ timecode = self.videoclip.get_timecode()
991
+ # self.videoclip.synced_audio = audio_path
992
+ audio_path = self.videoclip.synced_audio
826
993
  vid_only_handle = self._keep_VIDEO_only(video_path)
827
994
  a_n = _pathname(audio_path)
828
995
  v_n = str(vid_only_handle.name)
@@ -876,20 +1043,10 @@ class Matcher:
876
1043
  AudioStitcherVideoMerger objects that do the actual file manipulations. Each video
877
1044
  (and main sound) will have its AudioStitcherVideoMerger instance.
878
1045
 
879
- All videos are de facto reference recording and matching audio files are
880
- looked up for each one of them.
881
-
882
1046
  The Matcher doesn't keep neither set any editing information in itself: the
883
1047
  in and out time values (UTC times) used are those kept inside each Recording
884
1048
  instances.
885
1049
 
886
- [NOT YET IMPLEMENTED]: When shooting is done with multiple audio recorders,
887
- ONE audio device can be designated as 'main sound' and used as reference
888
- recording; then all audio tracks are synced together against this main
889
- sound audio file, keeping the TicTacCode track alongside for syncing against
890
- their video counterpart(in a second pass and after a mixdown editing).
891
- [/NOT YET IMPLEMENTED]
892
-
893
1050
  Attributes:
894
1051
 
895
1052
  recordings : list of Recording instances
@@ -897,7 +1054,7 @@ class Matcher:
897
1054
 
898
1055
  video_mergers : list
899
1056
  of AudioStitcherVideoMerger Class instances, built by
900
- scan_audio_for_each_ref_rec(); each video has a corresponding
1057
+ scan_audio_for_each_videoclip(); each video has a corresponding
901
1058
  AudioStitcherVideoMerger object. An audio_stitch doesn't extend
902
1059
  beyond the corresponding video start and end times.
903
1060
 
@@ -929,7 +1086,7 @@ class Matcher:
929
1086
  _pathname(rec.AVpath),
930
1087
  _pathname(rec.new_rec_name)))
931
1088
 
932
- def scan_audio_for_each_ref_rec(self):
1089
+ def scan_audio_for_each_videoclip(self):
933
1090
  """
934
1091
  For each video (and for the Main Sound) in self.recordings, this finds
935
1092
  any audio that has overlapping times and instantiates a
@@ -940,21 +1097,21 @@ class Matcher:
940
1097
  V3 checked against ...
941
1098
  Main Sound checked against A1, A2, A3, A4
942
1099
  """
943
- refeference_recordings = [r for r in self.recordings if r.is_video()
1100
+ video_recordings = [r for r in self.recordings if r.is_video()
944
1101
  or r.is_reference]
945
1102
  audio_recs = [r for r in self.recordings if r.is_audio()
946
1103
  and not r.is_reference]
947
1104
  if not audio_recs:
948
1105
  print('\nNo audio recording found, syncing of videos only not implemented yet, exiting...\n')
949
1106
  sys.exit(1)
950
- for ref_rec in refeference_recordings:
951
- reference_tag = 'video' if ref_rec.is_video() else 'audio'
1107
+ for videoclip in video_recordings:
1108
+ reference_tag = 'video' if videoclip.is_video() else 'audio'
952
1109
  logger.debug('Looking for overlaps with %s %s'%(
953
1110
  reference_tag,
954
- ref_rec))
955
- audio_stitch = AudioStitcherVideoMerger(ref_rec)
1111
+ videoclip))
1112
+ audio_stitch = AudioStitcherVideoMerger(videoclip)
956
1113
  for audio in audio_recs:
957
- if self._does_overlap(ref_rec, audio):
1114
+ if self._does_overlap(videoclip, audio):
958
1115
  audio_stitch.add_matched_audio(audio)
959
1116
  logger.debug('recording %s overlaps,'%(audio))
960
1117
  # print(' recording [gold1]%s[/gold1] overlaps,'%(audio))
@@ -962,13 +1119,13 @@ class Matcher:
962
1119
  self.video_mergers.append(audio_stitch)
963
1120
  else:
964
1121
  logger.debug('\n nothing\n')
965
- print('No overlap found for %s'%ref_rec.AVpath.name)
1122
+ print('No overlap found for %s'%videoclip.AVpath.name)
966
1123
  del audio_stitch
967
1124
  logger.debug('%i video_mergers created'%len(self.video_mergers))
968
1125
 
969
- def _does_overlap(self, ref_rec, audio_rec):
1126
+ def _does_overlap(self, videoclip, audio_rec):
970
1127
  A1, A2 = audio_rec.get_start_time(), audio_rec.get_end_time()
971
- R1, R2 = ref_rec.get_start_time(), ref_rec.get_end_time()
1128
+ R1, R2 = videoclip.get_start_time(), videoclip.get_end_time()
972
1129
  no_overlap = (A2 < R1) or (A1 > R2)
973
1130
  return not no_overlap
974
1131
 
@@ -990,11 +1147,11 @@ class Matcher:
990
1147
  Returns nothing, changes are done in the video files metadata
991
1148
  (each referenced by Recording.final_synced_file)
992
1149
  """
993
- vids = [m.ref_recording for m in self.video_mergers]
1150
+ vids = [m.videoclip for m in self.video_mergers]
994
1151
  logger.debug('vids %s'%vids)
995
1152
  if len(vids) == 1:
996
1153
  logger.debug('just one take, no gap to shrink')
997
- return
1154
+ return #############################################################
998
1155
  # INs_and_OUTs contains (time, direction, video) for each video,
999
1156
  # where direction is 'in|out' and video an instance of Recording
1000
1157
  INs_and_OUTs = [(vid.get_start_time(), 'in', vid) for vid in vids]