tictacsync 0.3a2__py3-none-any.whl → 0.3a4__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.

Potentially problematic release.


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

@@ -230,21 +230,6 @@ class Scanner:
230
230
  Sets Scanner.input_structure = 'loose'|'folder_is_device'
231
231
 
232
232
  """
233
- visible = [f for f in listdir(self.top_directory) if f[0] != '.']
234
- logger.debug('visible: %s'%visible)
235
- are_dir = all([isdir(join(self.top_directory, f)) for f in visible])
236
- are_files = all([isfile(join(self.top_directory, f)) for f in visible])
237
- logger.debug('dir: %s'%[isdir(join(self.top_directory, f)) for f
238
- in visible])
239
- if are_dir:
240
- visible = [e for e in visible if e != 'SyncedMedia']
241
- print('\nAssuming those are device folders: ',end='')
242
- [print('[gold1]%s[/gold1]'%f, end=', ') for f in visible[:-1]]
243
- print('[gold1]%s[/gold1].'%visible[-1])
244
- self.input_structure = 'folder_is_device'
245
- else: # are_files
246
- self.input_structure = 'loose'
247
- self.top_dir_has_multicam = False
248
233
  files = Path(self.top_directory).rglob('*.*')
249
234
  paths = [
250
235
  p
@@ -252,17 +237,33 @@ class Scanner:
252
237
  if p.suffix[1:] in av_file_extensions
253
238
  and 'SyncedMedia' not in p.parts
254
239
  ]
240
+ logger.debug('found media files %s'%paths)
241
+ parents = [p.parent for p in paths]
242
+ logger.debug('found parents %s'%parents)
243
+ def _list_all_the_same(a_list):
244
+ return a_list.count(a_list[0]) == len(a_list)
245
+ all_parents_are_the_same = _list_all_the_same(parents)
246
+ logger.debug('all_parents_are_the_same %s'%all_parents_are_the_same)
247
+ if all_parents_are_the_same:
248
+ # all media (video + audio) are in a same folder, so this is loose
249
+ self.input_structure = 'loose'
250
+ # for now (TO DO?) 'loose' == no multi-cam
251
+ self.top_dir_has_multicam = False
252
+ else:
253
+ # check later if inside each folder, media have same device,
254
+ # for now, we'll guess structure is 'folder_is_device'
255
+ self.input_structure = 'folder_is_device'
255
256
  for p in paths:
256
257
  new_media = media_at_path(self.input_structure, p) # dev UID set here
257
258
  self.found_media_files.append(new_media)
258
259
  # files from devices without UID or name
259
- def _same(l):
260
- return all(e == l[0] for e in l)
260
+ # def _list_all_the_same(l):
261
+ # return all(e == l[0] for e in l)
261
262
  def _try_name(medias):
262
263
  # return common first strings in filename
263
264
  names = [m.path.name for m in medias]
264
265
  transposed_names = list(map(list, zip(*names)))
265
- same = list(map(_same, transposed_names))
266
+ same = list(map(_list_all_the_same, transposed_names))
266
267
  try:
267
268
  first_diff = same.index(False)
268
269
  except:
tictacsync/entry.py CHANGED
@@ -126,8 +126,8 @@ def main():
126
126
  # logger.add(sys.stdout, filter="__main__")
127
127
  # logger.add(sys.stdout, filter="device_scanner")
128
128
  # logger.add(sys.stdout, filter="yaltc") _extract_sound_to_merge
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"] == "_get_audio_devices")
129
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "scan_media_and_build_devices_UID")
130
+ # logger.add(sys.stdout, filter=lambda r: r["function"] == "_sox_multi2mono")
131
131
  # logger.add(sys.stdout, filter=lambda r: r["function"] == "_get_mix")
132
132
  # logger.add(sys.stdout, filter=lambda r: r["function"] == "_sox_mix")
133
133
  top_dir = args.directory[0]
tictacsync/timeline.py CHANGED
@@ -66,24 +66,23 @@ def _sox_keep(audio_file, kept_channels) -> tempfile.NamedTemporaryFile:
66
66
  """
67
67
  Returns a NamedTemporaryFile containing the selected kept_channels
68
68
 
69
- Building dict according to pysox.remix format.
70
- https://pysox.readthedocs.io/en/latest/api.html#sox.transform.Transformer.remix
71
- eg: 4 channels with TicTacCode_channel at #2
72
- returns {1: [1], 2: [3], 3: [4]}
73
- ie the number of channels drops by one and chan 2 is missing
74
- excluded_channels is a list of Zero Based indexing chan numbers
75
-
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
76
71
  """
72
+
73
+
74
+
75
+
77
76
  audio_file = _pathname(audio_file)
78
77
  nchan = sox.file_info.channels(audio_file)
79
78
  logger.debug('in file of %i chan, have to keep %s'%
80
79
  (nchan, kept_channels))
81
80
  all_channels = range(1, nchan + 1) # from 1 to nchan included
82
- # list of list for pysox API
83
- # eg [[1], [3], [4]]
81
+ # Building dict according to pysox.remix format.
82
+ # https://pysox.readthedocs.io/en/latest/api.html#sox.transform.Transformer.remix
83
+ # eg: {1: [3], 2: [4]} to keep channels 3 & 4
84
84
  kept_channels = [[n] for n in kept_channels]
85
85
  sox_remix_dict = dict(zip(all_channels, kept_channels))
86
- # {1: [1], 2: [3], 3: [4]} -> from 4 to 3 chan and chan 2 is dropped
87
86
  output_fh = tempfile.NamedTemporaryFile(suffix='.wav', delete=DEL_TEMP)
88
87
  out_file = _pathname(output_fh)
89
88
  logger.debug('sox in and out files: %s %s'%(audio_file, out_file))
@@ -159,6 +158,26 @@ def _sox_combine(paths) -> Path:
159
158
  (merged_duration, nchan))
160
159
  return out_file_handle
161
160
 
161
+ def _sox_multi2mono(multichan_tmpfl) -> tempfile.NamedTemporaryFile:
162
+ # return a mono mix down
163
+ n_chan_input = sox.file_info.channels(_pathname(multichan_tmpfl))
164
+ logger.debug('n chan input: %s'%n_chan_input)
165
+ if n_chan_input == 1: # nothing to mix down
166
+ return multichan_tmpfl
167
+ mono_tpfl = tempfile.NamedTemporaryFile(suffix='.wav',
168
+ delete=DEL_TEMP)
169
+ tfm = sox.Transformer()
170
+ tfm.channels(1)
171
+ status = tfm.build(_pathname(multichan_tmpfl),_pathname(mono_tpfl))
172
+ 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)
175
+ if status != True:
176
+ print('Error, sox did not normalize file in _sox_multi2mono()')
177
+ sys.exit(1)
178
+ return mono_tpfl
179
+
180
+
162
181
  def _sox_mix(paths:list) -> tempfile.NamedTemporaryFile:
163
182
  """
164
183
  mix files referred by the list of Path into a new temporary files passed on return
@@ -183,6 +202,8 @@ def _sox_mix(paths:list) -> tempfile.NamedTemporaryFile:
183
202
  cbn.set_input_format(file_type=['wav']*N)
184
203
  filenames = [_pathname(p) for p in paths]
185
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])
186
207
  mixed_tempf = tempfile.NamedTemporaryFile(suffix='.wav',delete=DEL_TEMP)
187
208
  status = cbn.build(filenames,
188
209
  _pathname(mixed_tempf),
@@ -580,35 +601,65 @@ class AudioStitcherVideoMerger:
580
601
  stereo) mix track, returns a tmpfl containing the corresponding
581
602
  tracks. If not, mix all the tracks with sox.
582
603
 
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
+
583
608
  """
584
- if device.tracks != None:
585
- mix_tracks = device.tracks.mix
586
- if len(mix_tracks) > 0:
587
- logger.debug('%s has mix %s'%(device.name, mix_tracks))
588
- logger.debug('device %s'%device)
589
- if 'ttc' in device.tracks.rawtrx:
590
- sox_TTC_chan = device.tracks.rawtrx.index('ttc')
591
- elif 'tc' in device.tracks.rawtrx:
592
- sox_TTC_chan = device.tracks.rawtrx.index('tc')
593
- else:
594
- print('Error: no tc or ttc tag in track.txt')
595
- sys.exit(1)
596
- sox_TTC_chan += 1 # sox NZBIDX
597
- logger.debug('TTC chan %i'%sox_TTC_chan)
598
- # redo indexing since tracks.txt numbers refere to complete
599
- # files and here audio file had TTC and muted channels
600
- # removed.
601
- shift = 0
602
- if mix_tracks[0] > sox_TTC_chan:
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
+ 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')
625
+ 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:
603
657
  shift += 1
604
- for unused_tr in device.tracks.unused:
605
- if mix_tracks[0] > unused_tr:
606
- shift += 1
607
- mix_tracks = [t-shift for t in mix_tracks]
608
- logger.debug('new mix_tracks: %s'%mix_tracks)
609
- return _sox_keep(multichan_tmpfl, mix_tracks)
610
- else: # no tracks declaration, mix programmatically
611
- return _sox_mix(_split_channels(multichan_tmpfl))
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
+
612
663
 
613
664
  def build_audio_and_write_video(self, top_dir, output_dir,
614
665
  write_multicam_structure,
@@ -690,8 +741,6 @@ class AudioStitcherVideoMerger:
690
741
  logger.debug('there are %i dev mixes'%len(mixes))
691
742
  logger.debug('mixes %s'%mixes)
692
743
  dev_mixes_mix = _sox_mix(mixes)
693
- # dev_mixes_mix = _sox_combine([audio for _, audio
694
- # in merged_audio_files_by_device]) # all devices
695
744
  logger.debug('will merge with %s'%(_pathname(dev_mixes_mix)))
696
745
  self.ref_recording.synced_audio = dev_mixes_mix
697
746
  logger.debug('dev_mixes_mix n chan: %i'%
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tictacsync
3
- Version: 0.3a2
3
+ Version: 0.3a4
4
4
  Summary: command for syncing audio video recordings
5
5
  Home-page: https://tictacsync.org/
6
6
  Author: Raymond Lutz
@@ -0,0 +1,15 @@
1
+ tictacsync/LTCcheck.py,sha256=IEfpB_ZajWuRTWtqji0H-B2g7GQvWmGVjfT0Icumv7o,15704
2
+ tictacsync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ tictacsync/device_scanner.py,sha256=nOUw95hXYUU797wiwoO8_XOfqoalsWWoUxijbpeLkjE,27616
4
+ tictacsync/entry.py,sha256=KeocpXt3ghxgV4cdoZW90pCZ4TAW6upocZ5T2nYiUCQ,11393
5
+ tictacsync/multi2polywav.py,sha256=Zl5EP2Yf-PKiZ8ewRSwqWsDULvKKjeWANK_-Yd5RAg4,7279
6
+ tictacsync/remergemix.py,sha256=BUtZ8YHw5Oz8VseTD-A4imNbtF7h391pw5yyl6v6OG4,4885
7
+ tictacsync/synciso.py,sha256=XmUcdUF9rl4VdCm7XW4PeYWYWM0vgAY9dC2hapoul9g,4821
8
+ tictacsync/timeline.py,sha256=oijPv8w0ROD6-cyhF3fylOSfXKnVjLNjTvSKz9EOHTs,47608
9
+ tictacsync/yaltc.py,sha256=eGCDzp5aTF4zqFN4wNfiESXRnaHEXtQB-u13gYBf8g8,76810
10
+ tictacsync-0.3a4.dist-info/LICENSE,sha256=ZAOPXLh1zlQAnhHUd7oLslKM01YZ5UiAu3STYjwIxck,1068
11
+ tictacsync-0.3a4.dist-info/METADATA,sha256=ejbuKOuHqV2f1h88K60Kw41OgPWgakRBKqdO5vZHduo,5298
12
+ tictacsync-0.3a4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
13
+ tictacsync-0.3a4.dist-info/entry_points.txt,sha256=g3tdFFrVRcrKpuyKOCLUVBMgYfV65q9kpLZUOD_XCKg,139
14
+ tictacsync-0.3a4.dist-info/top_level.txt,sha256=eaCWG-BsYTRR-gLTJbK4RfcaXajr0gjQ6wG97MkGRrg,11
15
+ tictacsync-0.3a4.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- tictacsync/LTCcheck.py,sha256=IEfpB_ZajWuRTWtqji0H-B2g7GQvWmGVjfT0Icumv7o,15704
2
- tictacsync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- tictacsync/device_scanner.py,sha256=-m2gd0XWXyJLNWfpLc_XQbMwFfNLJ4y3AmI4abz85W4,27558
4
- tictacsync/entry.py,sha256=ptE6Vf1SeAg-Bc8-O3Ni8KnZhU6LtAHYHZqCHMsPt98,11391
5
- tictacsync/multi2polywav.py,sha256=Zl5EP2Yf-PKiZ8ewRSwqWsDULvKKjeWANK_-Yd5RAg4,7279
6
- tictacsync/remergemix.py,sha256=BUtZ8YHw5Oz8VseTD-A4imNbtF7h391pw5yyl6v6OG4,4885
7
- tictacsync/synciso.py,sha256=XmUcdUF9rl4VdCm7XW4PeYWYWM0vgAY9dC2hapoul9g,4821
8
- tictacsync/timeline.py,sha256=XVFnvxzM6uZmsWjhsl6Yadjp7M7YwUqy0xcXitmx63s,45977
9
- tictacsync/yaltc.py,sha256=eGCDzp5aTF4zqFN4wNfiESXRnaHEXtQB-u13gYBf8g8,76810
10
- tictacsync-0.3a2.dist-info/LICENSE,sha256=ZAOPXLh1zlQAnhHUd7oLslKM01YZ5UiAu3STYjwIxck,1068
11
- tictacsync-0.3a2.dist-info/METADATA,sha256=NB4_AB8eD5SLW6vNcNHsu1PCHWdwIez2lcXW5KNeO4Y,5298
12
- tictacsync-0.3a2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
13
- tictacsync-0.3a2.dist-info/entry_points.txt,sha256=g3tdFFrVRcrKpuyKOCLUVBMgYfV65q9kpLZUOD_XCKg,139
14
- tictacsync-0.3a2.dist-info/top_level.txt,sha256=eaCWG-BsYTRR-gLTJbK4RfcaXajr0gjQ6wG97MkGRrg,11
15
- tictacsync-0.3a2.dist-info/RECORD,,