tictacsync 0.82a0__tar.gz → 0.95a0__tar.gz

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.

Potentially problematic release.


This version of tictacsync might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tictacsync
3
- Version: 0.82a0
3
+ Version: 0.95a0
4
4
  Summary: command for syncing audio video recordings
5
5
  Home-page: https://tictacsync.org/
6
6
  Author: Raymond Lutz
@@ -32,7 +32,7 @@ setup(
32
32
  'multi2polywav = tictacsync.multi2polywav:main',
33
33
  ]
34
34
  },
35
- version = '0.82a',
35
+ version = '0.95a',
36
36
  description = "command for syncing audio video recordings",
37
37
  long_description_content_type='text/markdown',
38
38
  long_description = long_descr,
@@ -69,6 +69,7 @@ class Tracks:
69
69
  others: list #of all other tags: (tag, track#) tuples
70
70
  rawtrx: list # list of strings read from file
71
71
  error_msg: str # 'None' if none
72
+ lag_values: list # list of lag in ms, entry is None if not specified.
72
73
 
73
74
  @dataclass
74
75
  class Device:
@@ -109,7 +110,13 @@ def media_at_path(input_structure, p):
109
110
  if stream['codec_type']=='audio'
110
111
  ]
111
112
  if len(audio_streams) > 1:
112
- raise Exception('ffprobe gave multiple audio streams?')
113
+ print('for [gold1]%s[/gold1], ffprobe gave multiple audio streams, quitting.'%p)
114
+ quit()
115
+ # raise Exception('ffprobe gave multiple audio streams?')
116
+ if len(audio_streams) == 0:
117
+ print('ffprobe gave no audio stream for [gold1]%s[/gold1], quitting.'%p)
118
+ quit()
119
+ # raise Exception('ffprobe gave no audio stream for %s, quitting'%p)
113
120
  audio_str = audio_streams[0]
114
121
  n = audio_str['channels']
115
122
  # pprint(ffmpeg.probe(p))
@@ -146,6 +153,7 @@ def get_device_ffprobe_UID(file):
146
153
  print(e.stderr, file)
147
154
  return None, None #-----------------------------------------------------
148
155
  # fall back to folder name
156
+ logger.debug('ffprobe %s'%probe)
149
157
  streams = probe['streams']
150
158
  codecs = [stream['codec_type'] for stream in streams]
151
159
  device_type = 'CAM' if 'video' in codecs else 'REC'
@@ -155,6 +163,7 @@ def get_device_ffprobe_UID(file):
155
163
  probe_lines = [l for l in probe_string.split('\n')
156
164
  if '_time' not in l
157
165
  and 'time_' not in l
166
+ and 'location' not in l
158
167
  and 'date' not in l ]
159
168
  # this removes any metadata related to the file
160
169
  # but keeps metadata related to the device
@@ -302,12 +311,12 @@ class Scanner:
302
311
  audio_devices = [d for d in devices if d.dev_type == 'REC']
303
312
  for recorder in audio_devices:
304
313
  recorder.tracks = self._get_tracks_from_file(recorder)
314
+ if recorder.tracks:
315
+ if not all([lv == None for lv in recorder.tracks.lag_values]):
316
+ logger.debug('%s has lag_values %s'%(
317
+ recorder.name, recorder.tracks.lag_values))
305
318
  no_name_devices = [m.device for m in self.found_media_files
306
319
  if not m.device.name]
307
- # if no_name_devices:
308
- # pprint_no_name = pformat([(d, self.get_media_for_device(d)) for d in no_name_devices])
309
- # print('those are anon devices%s\n'%pprint_no_name)
310
- # logger.debug('those media have anon device%s'%no_name_devices)
311
320
  for anon_dev in no_name_devices:
312
321
  medias = self.get_media_for_device(anon_dev)
313
322
  guess_name = _try_name(medias)
@@ -321,7 +330,7 @@ class Scanner:
321
330
 
322
331
  def _get_tracks_from_file(self, device) -> Tracks:
323
332
  """
324
- Look for track names in TRACKSFN file, possibly stored inside the
333
+ Look for eventual track names in TRACKSFN file, stored inside the
325
334
  recorder folder alongside the audio files. If there, returns a Tracks
326
335
  object, if not returns None.
327
336
  """
@@ -477,14 +486,16 @@ class Scanner:
477
486
  read track names for naming separated ISOs
478
487
  from tracks_file.
479
488
 
489
+ tokens looked for: mix mixL mixR 0 ttc
490
+
480
491
  repeting prefixes signals a stereo track
481
492
  and entries will correspondingly panned into
482
493
  a stero mix named mixL.wav and mixR.wav
483
494
 
484
- mic1 L # space is optionnal and will be removed
485
- mic1 R
486
- mic2 L
487
- mic2 R
495
+ xyz L # spaces are ignored |
496
+ zyz R | stereo pair
497
+ abc L
498
+ abc R
488
499
 
489
500
  mixL
490
501
 
@@ -502,41 +513,56 @@ class Scanner:
502
513
  ch = [c for c in chaine if c != ' ']
503
514
  return ''.join(ch)
504
515
  def _WO_LR(chaine):
505
- ch = [c for c in chaine if c not in 'lr']
516
+ ch = [c for c in chaine if c not in 'LR']
506
517
  return ''.join(ch)
507
518
  def _seemsStereoMic(tag):
508
519
  # is tag likely a stereo pair tag?
509
- # should start with 'mic' and end with 'l' or 'r'
510
- return tag[:3]=='mic' and tag[-1] in 'lr'
520
+ # should start with 'mic' and end with 'L' or 'R'
521
+ return tag[:3]=='mic' and tag[-1] in 'LR'
511
522
  file=open(tracks_file,"r")
512
523
  whole_txt = file.read()
513
524
  logger.debug('all_lines:\n%s'%whole_txt)
514
- tracks_lines = [l.split('#')[0] for l in whole_txt.splitlines() if len(l) > 0 ]
515
- tracks_lines = [_WOspace(l).lower() for l in tracks_lines if len(l) > 0 ]
525
+ tracks_lines = [l.split('#')[0] for l in whole_txt.splitlines()
526
+ if len(l) > 0 ]
527
+ tracks_lines = [_WOspace(l) for l in tracks_lines if len(l) > 0 ]
516
528
  rawtrx = tracks_lines
529
+ # add index with tuples, starting at 1
530
+ logger.debug('tracks_lines whole: %s'%tracks_lines)
531
+ def _detach_lag_value(line):
532
+ # look for ";number" ending any line, returns a two-list
533
+ splt = line.split(';')
534
+ if len(splt) == 1:
535
+ splt += [None]
536
+ if len(splt) != 2:
537
+ # error
538
+ print('Text error in %s, line %s has too many ";"'%(
539
+ tracks_file, line))
540
+ return splt
541
+ tracks_lines, lag_values = zip(*[_detach_lag_value(l) for l
542
+ in tracks_lines])
543
+ logger.debug('tracks_lines WO lag: %s'%[tracks_lines])
544
+ logger.debug('lag_values: %s'%[lag_values])
517
545
  tracks_lines = [(t,ix+1) for ix,t in enumerate(tracks_lines)]
518
- # tracks_lines = [l for l in tracks_lines if l not in ['ttc', '0']]
519
- # track_names = [l.split()[0] for l in tracks_lines if l != 'ttc']
520
- logger.debug('tracks_lines: %s'%tracks_lines)
521
546
  # first check for stereo mic pairs (could be more than one pair):
522
547
  spairs = [e for e in tracks_lines if _seemsStereoMic(e[0])]
523
548
  # spairs is stereo pairs candidates
524
549
  msg = 'Confusing stereo pair tags: %s'%' '.join([e[0]
525
550
  for e in spairs])
526
- error_output_stereo = Tracks(None,[],[],[],[],[],msg)
551
+ error_output_stereo = Tracks(None,[],[],[],[],[],msg,[])
527
552
  if len(spairs)%2 == 1: # not pairs?, quit.
528
553
  return error_output_stereo
529
554
  logger.debug('_seemsStereoM: %s'%spairs)
530
- output_tracks = Tracks(None,[],[],[],[],rawtrx,None)
531
- def _LR(p):
532
- # p = (('mic1l', 1), ('mic1r', 2))
533
- # check if L then R
534
- p1, p2 = p
535
- return p1[0][-1] == 'l' and p2[0][-1] == 'r'
555
+ output_tracks = Tracks(None,[],[],[],[],rawtrx,None,[])
556
+ output_tracks.lag_values = lag_values
557
+ # def _LR(p):
558
+ # # p = (('mic1l', 1), ('mic1r', 2))
559
+ # # check if L then R
560
+ # p1, p2 = p
561
+ # return p1[0][-1] == 'l' and p2[0][-1] == 'r'
536
562
  if spairs:
537
563
  even_idxes = range(0,len(spairs),2)
538
564
  paired = [(spairs[i], spairs[i+1]) for i in even_idxes]
539
- # eg [(('mic1l', 1), ('mic1r', 2)), (('mic2l', 3), ('mic2r', 4))]
565
+ # eg [(('mic1L', 1), ('mic1R', 2)), (('mic2L', 3), ('mic2R', 4))]
540
566
  def _mic_same(p):
541
567
  # p = (('mic1l', 1), ('mic1r', 2))
542
568
  # check if mic1 == mic1
@@ -546,16 +572,22 @@ class Scanner:
546
572
  logger.debug('mic_prefix_OK: %s'%mic_prefix_OK)
547
573
  if not mic_prefix_OK:
548
574
  return error_output_stereo
549
- mic_LR_OK = all([_LR(p) for p in paired])
550
- logger.debug('mic_LR_OK %s'%mic_LR_OK)
551
- if not mic_LR_OK:
552
- return error_output_stereo
575
+ # mic_LR_OK = all([_LR(p) for p in paired])
576
+ # logger.debug('mic_LR_OK %s'%mic_LR_OK)
577
+ # if not mic_LR_OK:
578
+ # return error_output_stereo
553
579
  def _stereo_mic_pref_chan(p):
554
- # p = (('mic1l', 1), ('mic1r', 2))
580
+ # p = (('mic1R', 1), ('mic1L', 2))
555
581
  # returns ('mic1', (1,2))
556
582
  first, second = p
557
583
  mic_prefix = _WO_LR(first[0])
558
- return (mic_prefix, (first[1], second[1]) )
584
+ # check if first token last char
585
+ if p[0][0][-1] == 'L':
586
+ logger.debug('sequence %s is L+R'%[p])
587
+ return (mic_prefix, (first[1], second[1]) )
588
+ else:
589
+ logger.debug('sequence %s is R+L'%[p])
590
+ return (mic_prefix, (second[1], first[1]) )
559
591
  grouped_stereo_mic_channels = [_stereo_mic_pref_chan(p) for p
560
592
  in paired]
561
593
  logger.debug('grouped_stereo_mic_channels: %s'%
@@ -1,4 +1,4 @@
1
- # print('Loading modules...', end='')
1
+ print('Loading modules...', end='')
2
2
 
3
3
  # I know, the following is ugly, but I need those try's to
4
4
  # run the command in my dev setting AND from
@@ -16,11 +16,11 @@ except:
16
16
  import timeline
17
17
  import multi2polywav
18
18
 
19
- import argparse
19
+ import argparse, tempfile
20
20
  from loguru import logger
21
21
  from pathlib import Path
22
22
  # import os, sys
23
- import os, sys
23
+ import os, sys, sox
24
24
  from rich.progress import track
25
25
  # from pprint import pprint
26
26
  from rich.console import Console
@@ -29,6 +29,8 @@ from rich.table import Table
29
29
  from rich import print
30
30
  from pprint import pprint
31
31
 
32
+ DEL_TEMP = False
33
+
32
34
  av_file_extensions = \
33
35
  """MOV webm mkv flv flv vob ogv ogg drc gif gifv mng avi MTS M2TS TS mov qt
34
36
  wmv yuv rm rmvb viv asf amv mp4 m4p m4v mpg mp2 mpeg mpe mpv mpg mpeg m2v
@@ -40,7 +42,7 @@ logger.level("DEBUG", color="<yellow>")
40
42
 
41
43
  def process_files_with_progress_bars(medias):
42
44
  recordings = []
43
- rec_with_yaltc = []
45
+ rec_with_TTC = []
44
46
  times = []
45
47
  for m in track(medias,
46
48
  description="1/4 Initializing Recordings:"):
@@ -49,29 +51,32 @@ def process_files_with_progress_bars(medias):
49
51
  for r in track(recordings,
50
52
  description="2/4 Looking for TicTacCode:"):
51
53
  if r.seems_to_have_TicTacCode_at_beginning():
52
- rec_with_yaltc.append(r)
53
- for r in track(rec_with_yaltc,
54
+ rec_with_TTC.append(r)
55
+ for r in track(rec_with_TTC,
54
56
  description="3/4 Finding start times:"):
55
57
  times.append(r.get_start_time())
56
- return recordings, rec_with_yaltc, times
58
+ return recordings, rec_with_TTC, times
57
59
 
58
60
  def process_files(medias):
59
61
  recordings = []
60
- rec_with_yaltc = []
62
+ rec_with_TTC = []
61
63
  times = []
62
64
  for m in medias:
63
65
  recordings.append(yaltc.Recording(m))
64
66
  for r in recordings:
65
67
  # print('%s duration %.2fs'%(r.AVpath.name, r.get_duration()))
66
68
  if r.seems_to_have_TicTacCode_at_beginning():
67
- rec_with_yaltc.append(r)
68
- for r in rec_with_yaltc:
69
+ rec_with_TTC.append(r)
70
+ for r in rec_with_TTC:
69
71
  times.append(r.get_start_time())
70
- return recordings, rec_with_yaltc, times
72
+ return recordings, rec_with_TTC, times
71
73
 
72
74
  def process_single(file, args):
73
75
  # argument is a single file
74
76
  m = device_scanner.media_at_path(None, Path(file))
77
+ if args.plotting:
78
+ print('\nPlots can be zoomed and panned...')
79
+ print('Close window for next one.')
75
80
  a_rec = yaltc.Recording(m, do_plots=args.plotting)
76
81
  time = a_rec.get_start_time()
77
82
  # time = a_rec.get_start_time(plots=args.plotting)
@@ -94,43 +99,93 @@ def process_single(file, args):
94
99
  print('Start time couldnt be determined')
95
100
  sys.exit(1)
96
101
 
102
+ def process_lag_adjustement(media_object):
103
+ # trim channels that are lagging (as stated in tracks.txt)
104
+ # replace the old file, and rename the old one with .wavbk
105
+ # if .wavbk exist, process was done already, so dont process
106
+ # returns nothing
107
+ lags = media_object.device.tracks.lag_values
108
+ logger.debug('will process %s lags'%[lags])
109
+ channels = timeline._split_channels(media_object.path)
110
+ # add bk to file on filesystem, but media_object.path is unchanged (?)
111
+ backup_name = str(media_object.path) + 'bk'
112
+ if Path(backup_name).exists():
113
+ logger.debug('%s exists, so return now.'%backup_name)
114
+ return
115
+ media_object.path.replace(backup_name)
116
+ logger.debug('channels %s'%channels)
117
+ def _trim(lag, chan_file):
118
+ if lag == None:
119
+ return chan_file
120
+ else:
121
+ logger.debug('process %s for lag of %s'%(chan_file, lag))
122
+ sox_transform = sox.Transformer()
123
+ sox_transform.trim(float(lag)*1e-3)
124
+ output_fh = tempfile.NamedTemporaryFile(suffix='.wav', delete=DEL_TEMP)
125
+ out_file = timeline._pathname(output_fh)
126
+ input_file = timeline._pathname(chan_file)
127
+ logger.debug('sox in and out files: %s %s'%(input_file, out_file))
128
+ logger.debug('calling sox_transform.build()')
129
+ status = sox_transform.build(input_file, out_file, return_output=True )
130
+ logger.debug('sox.build exit code %s'%str(status))
131
+ return output_fh
132
+ new_channels = [_trim(*e) for e in zip(lags, channels)]
133
+ logger.debug('new_channels %s'%new_channels)
134
+ trimmed_multichanfile = timeline._sox_combine(new_channels)
135
+ logger.debug('trimmed_multichanfile %s'%timeline._pathname(trimmed_multichanfile))
136
+ Path(timeline._pathname(trimmed_multichanfile)).replace(media_object.path)
137
+
97
138
  def main():
98
139
  parser = argparse.ArgumentParser()
99
140
  parser.add_argument(
100
- "directory",
141
+ "path",
101
142
  type=str,
102
143
  nargs=1,
103
- help="path of media directory"
144
+ help="directory_name or media_file"
104
145
  )
105
146
  # parser.add_argument("directory", nargs="?", help="path of media directory")
106
147
  # parser.add_argument('-v', action='store_true')
107
- parser.add_argument('-v', action='store_true', default=False,
108
- dest='verbose_output',
109
- help='Set verbose ouput')
148
+ parser.add_argument('-v',
149
+ action='store_true', #ie default False
150
+ dest='verbose_output',
151
+ help='Set verbose ouput')
110
152
  parser.add_argument('-o', nargs=1,
111
- help='where to write synced clips')
112
- parser.add_argument('-p', action='store_true', default=False,
153
+ help='Where to write the SyncedMedia folder [default to "path" ]')
154
+ parser.add_argument('-t','--timelineoffset',
155
+ nargs=1,
156
+ default=['00:00:00:00'],
157
+ dest='timelineoffset',
158
+ help='When processing multicam, where to place clips on NLE timeline (HH:MM:SS:FF)')
159
+ parser.add_argument('-p',
160
+ action='store_true',
113
161
  dest='plotting',
114
- help='Make plots')
115
- parser.add_argument('--isos', action='store_true', default=False,
162
+ help='Produce plots')
163
+ parser.add_argument('--isos',
164
+ action='store_true',
116
165
  dest='write_ISOs',
117
166
  help='Write ISO sound files')
118
- parser.add_argument('--nosync', action='store_true',
167
+ parser.add_argument('--nosync',
168
+ action='store_true',
119
169
  dest='nosync',
120
- help='just scan and decode')
121
- parser.add_argument('--terse', action='store_true',
170
+ help='Just scan and decode')
171
+ parser.add_argument('--terse',
172
+ action='store_true',
122
173
  dest='terse',
123
- help='terse output')
174
+ help='Terse output')
124
175
  args = parser.parse_args()
176
+ # print(args)
177
+ if len(args.timelineoffset) != 1:
178
+ print('--timelineoffset needs one value, got %s'%args.timelineoffset)
179
+ quit()
125
180
  if args.verbose_output:
126
181
  logger.add(sys.stderr, level="DEBUG")
127
182
  # logger.add(sys.stdout, filter="__main__")
128
183
  # logger.add(sys.stdout, filter="yaltc")
129
- # logger.add(sys.stdout, filter=lambda r: r["function"] == "build_audio_and_write_video")
130
- # logger.add(sys.stdout, filter=lambda r: r["function"] == "_detect_sync_pulse_position")
131
- # logger.add(sys.stdout, filter=lambda r: r["function"] == "_get_device_mix")
132
- # logger.add(sys.stdout, filter=lambda r: r["function"] == "_sox_mix_files")
133
- top_dir = args.directory[0]
184
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "process_lag_adjustement")
185
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "_dedrift_rec")
186
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "scan_media_and_build_devices_UID")
187
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "_parse_track_values")
188
+ top_dir = args.path[0]
134
189
  if os.path.isfile(top_dir):
135
190
  file = top_dir
136
191
  process_single(file, args)
@@ -148,7 +203,13 @@ def main():
148
203
  sys.exit(1)
149
204
  multi2polywav.poly_all(top_dir)
150
205
  scanner = device_scanner.Scanner(top_dir, stay_silent=args.terse)
151
- scanner.scan_media_and_build_devices_UID()
206
+ scanner.scan_media_and_build_devices_UID()
207
+ for m in scanner.found_media_files:
208
+ if m.device.tracks:
209
+ if not all([lv == None for lv in m.device.tracks.lag_values]):
210
+ logger.debug('%s has lag_values %s'%(
211
+ m.path, m.device.tracks.lag_values))
212
+ process_lag_adjustement(m)
152
213
  if not args.terse:
153
214
  if scanner.input_structure == 'folder_is_device':
154
215
  print('\nDetected structured folders', end='')
@@ -159,10 +220,8 @@ def main():
159
220
  else:
160
221
  print('\nDetected loose structure')
161
222
  if scanner.CAM_numbers() > 1:
162
- print('\nNote: different CAMs are present, will sync audio')
163
- print('for each of them but if you want to set their')
164
- print('respective timecode for NLE timeline alignement')
165
- print('you should regroup clips by CAM under their own DIR.')
223
+ print('\nNote: different CAMs are present, will sync audio for each of them but if you want to set their')
224
+ print('respective timecode for NLE timeline alignement you should regroup clips by CAM under their own DIR.')
166
225
  print('\nFound [gold1]%i[/gold1] media files '%(
167
226
  len(scanner.found_media_files)), end='')
168
227
  print('from [gold1]%i[/gold1] devices:\n'%(
@@ -173,25 +232,18 @@ def main():
173
232
  for m in medias[:-1]:
174
233
  print('[gold1]%s[/gold1]'%m.path.name, end=', ')
175
234
  print('[gold1]%s[/gold1]'%medias[-1].path.name)
176
- # print('\nThese recordings will be analysed for timestamps:\n')
177
- # for m in (scanner.found_media_files):
178
- # print(' ', '[gold1]%s[/gold1]'%m.path.name)
179
235
  print()
180
- if args.verbose_output or args.terse: # verbose or terse, so no progress bars
181
- rez = process_files(scanner.found_media_files)
182
- else:
183
- rez = process_files_with_progress_bars(scanner.found_media_files)
184
- recordings, rec_with_yaltc, times = rez
236
+ rez = process_files(scanner.found_media_files)
237
+ recordings, rec_with_TTC, times = rez
185
238
  recordings_with_time = [
186
239
  rec
187
- for rec in rec_with_yaltc
240
+ for rec in rec_with_TTC
188
241
  if rec.get_start_time()
189
242
  ]
190
243
  if not args.terse:
191
- print('\n\n')
192
244
  table = Table(title="tictacsync results")
193
245
  table.add_column("Recording\n", justify="center", style='gold1')
194
- table.add_column("TicTacCode\nChannel", justify="center", style='gold1')
246
+ table.add_column("TTC chan\n (1st=#0)", justify="center", style='gold1')
195
247
  # table.add_column("Device\n", justify="center", style='gold1')
196
248
  table.add_column("UTC times\nstart:end", justify="center", style='gold1')
197
249
  table.add_column("Clock drift\n(ppm)", justify="right", style='gold1')
@@ -199,7 +251,7 @@ def main():
199
251
  table.add_column("Date\n", justify="center", style='gold1')
200
252
  rec_WO_time = [
201
253
  rec.AVpath.name
202
- for rec in rec_with_yaltc
254
+ for rec in rec_with_TTC
203
255
  if not rec.get_start_time()
204
256
  ]
205
257
  if rec_WO_time:
@@ -226,9 +278,6 @@ def main():
226
278
  print()
227
279
  n_devices = scanner.get_devices_number()
228
280
  OUT_struct_for_mcam = scanner.top_dir_has_multicam
229
- # if n_devices > 2:
230
- # print('\nMerging for more than 2 devices is not implemented yet, quitting...')
231
- # sys.exit(1)
232
281
  if len(recordings_with_time) < 2:
233
282
  if not args.terse:
234
283
  print('\nNothing to sync, exiting.\n')
@@ -244,32 +293,25 @@ def main():
244
293
  print('Warning, can\'t write ISOs without structured folders: [gold1]--isos[/gold1] option ignored.\n')
245
294
  asked_ISOs = False
246
295
  output_dir = args.o
247
- if args.verbose_output or args.terse: # verbose, so no progress bars
248
- for stitcher in matcher.video_mergers:
249
- stitcher.build_audio_and_write_video(top_dir, arg_out_dir,
250
- OUT_struct_for_mcam,
251
- asked_ISOs,)
252
- else:
253
- print()
254
- for stitcher in track(matcher.video_mergers,
255
- description="4/4 Merging sound to videos:"):
256
- stitcher.build_audio_and_write_video(top_dir, arg_out_dir,
257
- OUT_struct_for_mcam,
258
- asked_ISOs,)
296
+ # if args.verbose_output or args.terse: # verbose, so no progress bars
297
+ for merger in matcher.video_mergers:
298
+ merger.build_audio_and_write_video(top_dir, arg_out_dir,
299
+ OUT_struct_for_mcam,
300
+ asked_ISOs,)
259
301
  if not args.terse:
260
302
  print("\n")
261
303
  # find out where files were wrtitten
262
- a_stitcher = matcher.video_mergers[0]
304
+ a_merger = matcher.video_mergers[0]
263
305
  print('\nWrote output in folder [gold1]%s[/gold1]'%(
264
- a_stitcher.synced_clip_dir))
265
- for stitcher in matcher.video_mergers:
266
- print('[gold1]%s[/gold1]'%stitcher.videoclip.AVpath.name, end='')
267
- for audio in stitcher.get_matched_audio_recs():
306
+ a_merger.synced_clip_dir))
307
+ for merger in matcher.video_mergers:
308
+ print('[gold1]%s[/gold1]'%merger.videoclip.AVpath.name, end='')
309
+ for audio in merger.get_matched_audio_recs():
268
310
  print(' + [gold1]%s[/gold1]'%audio.AVpath.name, end='')
269
- new_file = stitcher.videoclip.final_synced_file.parts
270
- print(' became [gold1]%s[/gold1]'%stitcher.videoclip.final_synced_file.name)
311
+ new_file = merger.videoclip.final_synced_file.parts
312
+ print(' became [gold1]%s[/gold1]'%merger.videoclip.final_synced_file.name)
271
313
  # matcher._build_otio_tracks_for_cam()
272
- matcher.shrink_gaps_between_takes()
314
+ matcher.shrink_gaps_between_takes(args.timelineoffset)
273
315
  sys.exit(0)
274
316
 
275
317
  if __name__ == '__main__':
@@ -1,4 +1,4 @@
1
- import argparse, wave, subprocess
1
+ import argparse, wave, subprocess, sys
2
2
  from loguru import logger
3
3
  from pathlib import Path
4
4
  from itertools import groupby