def checkForContinuousVideo(videoDir, matchedFileList, dumpSegments): previousFileInfo = {} videoSegments = [] currentVideoSegment = makeNewVideoSegment(videoDir, matchedFileList[0]) videoSegments.append(currentVideoSegment) for f in matchedFileList: xmlMetafilePath = "%s/%s.xml" % (videoDir, f) docroot = ET.parse(xmlMetafilePath).getroot() endTimecode = Timecode(CINEDEK_FRAME_RATE, docroot.find("endTimecode").text) startTimecode = Timecode(CINEDEK_FRAME_RATE, docroot.find("startTimecode").text) if previousFileInfo: prevEndFrameCount = previousFileInfo["endTimecode"].frames currentStartFrameCount = startTimecode.frames if (currentStartFrameCount - prevEndFrameCount) != 1: if currentStartFrameCount < prevEndFrameCount: print "Overlapping video detected!" print " %s overlaps %s" % (previousFileInfo["filename"], f) else: print "Gap detected (%d frames)!" % (currentStartFrameCount - prevEndFrameCount) print " Start new segment for:", f currentVideoSegment = makeNewVideoSegment(videoDir, f) videoSegments.append(currentVideoSegment) currentVideoSegment.fileList.append("%s.%s" % (f, VIDEO_FILE_EXTENSION)) currentVideoSegment.updateEndtimeFromMetadata(docroot) previousFileInfo["endTimecode"] = endTimecode previousFileInfo["filename"] = f if dumpSegments: return videoSegments else: return None
def make_edl_segment(n, time_in, time_out, rec_in, rec_out, full_name, filename, fps=25): reel = full_name if len(full_name) > 7: reel = full_name[0:7] template = '{} {} AA/V C {} {} {} {}\n* FROM CLIP NAME: {}\n* COMMENT: \n FINAL CUT PRO REEL: {} REPLACED BY: {}\n\n' # print time_in, time_out, rec_in, rec_out # print Timecode(fps, start_seconds=time_in), Timecode(fps, start_seconds=time_out), Timecode(fps, start_seconds=rec_in), Timecode(fps, start_seconds=rec_out) # # print '' out = template.format(n, full_name, Timecode(fps, start_seconds=time_in), Timecode(fps, start_seconds=time_out), Timecode(fps, start_seconds=rec_in), Timecode(fps, start_seconds=rec_out), filename, full_name, reel) return out
def plot_multi_vmaf_timegraph(output_path, frame_nums, baseline_frame_scores, variant_list, target_bitrate, source_duration, fps, test_item='bitrate'): timecode = Timecode(fps, '00:00:00:00') title = " Effect of Bitrate Changes on VMAF over Asset Duration" plt.suptitle(title, fontsize=14, color='blue') plt.title("Blue line is VMAF/time of existing VOD transcode (4sec GOPs). Gray lines are quality/time for 2sec GOPs at various bitrates", fontsize=7, color='black') upper = max(baseline_frame_scores) lower = min(baseline_frame_scores) higher_bitrate_scores = [variant['vmaf_frame_scores'] for variant in variant_list if variant[test_item] > target_bitrate] lower_bitrate_scores = [variant['vmaf_frame_scores'] for variant in variant_list if variant[test_item] < target_bitrate] # generate lighter lineshades higher_lineshades = np.linspace(0.7, 0.9, len(higher_bitrate_scores)) for idx, frame_scores in enumerate(higher_bitrate_scores): upper = max(upper, max(frame_scores)) lower = min(lower, min(frame_scores)) plt.plot(frame_nums, frame_scores, str(higher_lineshades[idx])) lower_lineshades = np.linspace(0.9, 0.7, len(lower_bitrate_scores)) for idx, frame_scores in enumerate(lower_bitrate_scores): upper = max(upper, max(frame_scores)) lower = min(lower, min(frame_scores)) # plt.plot(frame_nums, frame_scores, str(1 - (0.1 * (1 + idx)))) plt.plot(frame_nums, frame_scores, str(lower_lineshades[idx])) plt.plot(frame_nums, baseline_frame_scores) # generate major tics based on evenly divided time chosen_frames = np.linspace(0, len(frame_nums) - 1, 20) ticframes = [frame_nums[int(i)] for i in chosen_frames] ticlabels = [timecode.tc_to_string( *timecode.frames_to_tc(ticframe)) for ticframe in ticframes] plt.xticks(ticframes, ticlabels, rotation='vertical') ax = plt.axes() # style = dict(size=10, color='gray') # # label the valleys # for idx, lowval in enumerate(lowest_values): # ax.text(lowval, frame_scores[lowval] - 5, str(idx + 1), **style) ax.set_xticks(ticframes, minor=True) ax.grid() plt.ylabel('vmaf score') plt.ylim(lower, upper) plt.xlabel('time') plt.subplots_adjust(bottom=0.3) plt.gcf().set_size_inches(15, 5) plt.savefig(output_path) plt.clf()
def from_plist(data, framerate_string='29.97'): timecode = Timecode(framerate_string) timecode.drop_frame = False events = [] for e in data.values(): if 'Timecode' in e: # convert iCoder-style timecode to frame number timecode.set_timecode('{}:{}:{}:{}'.format( e['Timecode']['Hour'], e['Timecode']['Minute'], e['Timecode']['Second'], e['Timecode']['Frame']) ) e['Frame'] = timecode.frames - 1 has_offset = True # by assumption; we don't know if the timecode of the first frame is 00:00:00:00 else: has_offset = False events.append( Event(trial=e['Trial'], status=e['Trial Status'] in ('on', True), response=e['Type'], frame=e['Frame'], has_offset=has_offset) ) return Events(events)
def plot_vmaf_graph(output_path, frame_nums, frame_scores, source_duration, lowest_values, fps, title=""): timecode = Timecode(fps, '00:00:00:00') plt.title(title) # generate major tics based on evenly divided time chosen_frames = np.linspace(0, len(frame_nums) - 1, 20) ticframes = [frame_nums[int(i)] for i in chosen_frames] ticlabels = [timecode.tc_to_string( *timecode.frames_to_tc(ticframe)) for ticframe in ticframes] plt.xticks(ticframes, ticlabels, rotation='vertical') plt.plot(frame_nums, frame_scores) ax = plt.axes() if lowest_values != None: style = dict(size=10, color='gray') # label the valleys for idx, lowval in enumerate(lowest_values): ax.text(lowval, frame_scores[lowval] - 5, str(idx + 1), **style) ax.set_xticks(ticframes, minor=True) ax.grid() plt.ylabel('vmaf score') plt.ylim(0, 100) plt.xlabel('time') plt.subplots_adjust(bottom=0.3) plt.gcf().set_size_inches(9, 5) plt.savefig(output_path) plt.clf()
def make_subtitle(comps, name, padding): '''writes out a subtitle file for the supercut''' fpses = {} out = '' rec_in = 0 print("[+] Creating subtitle file.") for index, comp in enumerate(comps): if comp['file'] not in fpses: fpses[comp['file']] = get_fps(comp['file']) fps = fpses[comp['file']] time_in = comp['start'] time_out = comp['end'] duration = time_out - time_in rec_out = rec_in + duration #timestamp['duration'] filename = os.path.basename(comp['file']) rec_in_timecode = str(Timecode(fps, start_seconds=rec_in + padding)) rec_out_timecode = str(Timecode(fps, start_seconds=rec_out)) rec_in_srt_format = rec_in_timecode[:8] + ',' + rec_in_timecode[9:] rec_out_srt_format = rec_out_timecode[:8] + ',' + rec_out_timecode[9:] out += '{}\n{} --> {}\n<i>{}</i>\n{}\n\n'.format( index + 1, rec_in_srt_format, rec_out_srt_format, filename, comp['line']) rec_in = rec_out with open(os.path.splitext(name)[0] + '.srt', 'w') as outfile: outfile.write(out)
def show_metadata(header, cine_file): record_rate = header["setup"].FrameRate playback_rate = header["setup"].fPbRate timecode_rate = header["setup"].fTcRate tc = header["setup"].TrigTC tc = f"{tc.hoursT}{tc.hoursU}:{tc.minutesT}{tc.minutesU}:{tc.secondsT}{tc.secondsU}:{tc.framesT}{tc.framesU}" tc_first_frame = Timecode(str(timecode_rate), tc) tc_first_frame.add_frames(header["cinefileheader"].FirstImageNo) temp = header["setup"].fWBTemp cc = header["setup"].fWBCc tone_label = header["setup"].ToneLabel.decode("ascii") tone_points = list(header["setup"].fTone)[:header["setup"].TonePoints * 2] try: created_by = header["setup"].CreatedBy.decode("ascii") except ValueError: created_by = "" out = dedent(f""" Clip: {cine_file} Created by: {created_by} Record FPS: {record_rate} Playback FPS: {playback_rate:.5g} Timecode FPS: {timecode_rate:.5g} Trigger frame time code: {tc} First frame time code: {tc_first_frame} First frame number: {header["cinefileheader"].FirstImageNo} Temp: {temp} CC: {cc} CalibrationInfo: {header['setup'].CalibrationInfo} OpticalFilter: {header['setup'].OpticalFilter} cmCalib: {list(header['setup'].cmCalib)} Tone points: {tone_label} {' '.join([str(p) for p in tone_points])} """).strip() click.echo(out + "\n")
def grab(target: str, tc: str): """ :param target: Path to search for media files :param tc: Desired timecode of stills """ clips, camera = get_clips_from_path(Path(target)) looking_for = Timecode(FPS, tc) print(looking_for) for clip in clips: if clip.suffix.lower() == '.mov': # Quick way to control for only Alexa quicktimes stats = get_media_info(clip) start_tc_frame = Timecode(FPS, stats['Start TC']) duration_frames = Timecode(FPS, start_timecode=None, frames=stats['Duration-Frames']) print('Start frame is: ' + str(start_tc_frame)) print('Duration frames are: ' + str(duration_frames)) end_frame = start_tc_frame + duration_frames print('End frame is: ' + str(end_frame.frames)) print('Looking for frame: ' + str(looking_for.frames)) if looking_for.frames in range(start_tc_frame.frames, end_frame.frames): abs_time = looking_for - start_tc_frame abs_time.set_fractional(True) print('Asking ffmpeg for frame: ' + str(abs_time)) make_thumb(clip, TEST_OUTPUT, abs_time, stats) else: print('Cannot find requested timecode in: ' + clip.name) elif clip.suffix.lower() == '.mp4': # Deal with A7s shit here elif clip.suffix.lower() == '.mxf':
def make_caption_data(video_element_name, caption_path, timecodes, duration, fps, punct, mode, segmenter): start, end = Timecode(fps, timecodes[0]), Timecode(fps, timecodes[1]) captions = webvtt.read(caption_path) captions[1].start = captions[0].start captions = captions[1:] caption_dict_list, joined_sentence = make_caption_dict_list( captions, fps, start, end, mode) sentences = segement_sentences(joined_sentence, segmenter, punct) if len(caption_dict_list) > 0: timestamps = make_timestamps(caption_dict_list, sentences, mode) try: assert len(timestamps) == len( sentences ), f'timestamps:{len(timestamps)} sentences:{len(sentences)}' except AssertionError as err: print('AssertionError:', err) annotation = { video_element_name: { 'duration': duration, 'timestamps': timestamps, 'sentences': sentences } } return annotation else: return {}
def get_comment_duration(tc1_in, tc2_in, fps): tc1 = Timecode(fps, tc1_in) tc2 = Timecode(fps, tc2_in) tc1a = tc1 + Timecode(fps, "00:00:00:00") tc2a = tc2 + Timecode(fps, "00:00:00:00") duration_frames = str((tc2 - tc1).frames) durations = {"tc1": str(tc1), "tc2": str(tc2), "tc1a": str(tc1a), "tc2a": str(tc2a), "duration_frames": duration_frames} return durations
def test_24_hour_limit_in_24fps(self): """testing if the timecode will loop back to 00:00:00:00 after 24 hours in 24 fps """ tc = Timecode('24', '00:00:00:21') tc2 = Timecode('24', '23:59:59:23') self.assertEqual('00:00:00:21', (tc + tc2).__str__()) self.assertEqual('02:00:00:00', (tc2 + 159840001).__str__())
def tc_to_f(timecode_str: str, df=False) -> int: if timecode_str.startswith('--:--:--'): return 0 if df: return Timecode.df_to_f(timecode_str) else: return Timecode.ndf_to_f(timecode_str)
def test_setting_frame_rate_to_2997_forces_drop_frame(self): """testing if setting the frame rate to 29.97 forces the dropframe to True """ tc = Timecode('29.97') self.assertTrue(tc.drop_frame) tc = Timecode('29.97') self.assertTrue(tc.drop_frame)
def test_setting_frame_rate_to_5994_forces_drop_frame(self): """testing if setting the frame rate to 59.94 forces the dropframe to True """ tc = Timecode('59.94') self.assertTrue(tc.drop_frame) tc = Timecode('59.94') self.assertTrue(tc.drop_frame)
def __init__(self, start, end, line, fps): self.start = Timecode(fps, start) self.end = Timecode(fps, end) self.delta: Timecode = self.end - self.start self.num_frames = self.delta.frames if line == '': self.line = [line] else: self.line = re.split(r'\\n|\\N', line)
def test_le_overload(self): tc1 = Timecode(24, '00:00:00:00') tc2 = Timecode(24, '00:00:00:00') tc3 = Timecode(24, '00:00:00:01') self.assertTrue(tc1 == tc2) self.assertTrue(tc1 <= tc2) self.assertTrue(tc2 <= tc3) self.assertFalse(tc2 >= tc3)
def test_setting_frame_rate_to_ms_or_1000_forces_drop_frame(self): """testing if setting the frame rate to 59.94 forces the dropframe to True """ tc = Timecode('ms') self.assertTrue(tc.ms_frame) tc = Timecode('1000') self.assertTrue(tc.ms_frame)
def test_add_with_two_different_frame_rates(self): """testing if the resultant object will have the left sides frame rate when two timecodes with different frame rates are added together """ tc1 = Timecode('29.97', '00:00:00;00') tc2 = Timecode('24', '00:00:00:10') tc3 = tc1 + tc2 self.assertEqual('29.97', tc3.framerate) self.assertEqual(12, tc3.frames) self.assertEqual('00:00:00;11', tc3)
def to_edl(self): """Returns an edl.List instance equivalent of this Sequence instance """ from edl import List, Event from timecode import Timecode l = List(self.timebase) l.title = self.name # convert clips to events if not self.media: raise RuntimeError( 'Can not run %(class)s.to_edl() without a Media instance, ' 'please add a Media instance to this %(class)s instance.' % {'class': self.__class__.__name__}) video = self.media.video if video is not None: i = 0 for track in video.tracks: for clip in track.clips: i += 1 e = Event({}) e.num = '%06i' % i e.clip_name = clip.id e.reel = clip.name e.track = 'V' if clip.type == 'Video' else 'A' e.tr_code = 'C' # TODO: for now use C (Cut) later on # expand it to add other transition codes src_start_tc = Timecode(self.timebase, frames=clip.in_ + 1) # 1 frame after last frame shown src_end_tc = Timecode(self.timebase, frames=clip.out + 1) e.src_start_tc = str(src_start_tc) e.src_end_tc = str(src_end_tc) rec_start_tc = Timecode(self.timebase, frames=clip.start + 1) # 1 frame after last frame shown rec_end_tc = Timecode(self.timebase, frames=clip.end + 1) e.rec_start_tc = str(rec_start_tc) e.rec_end_tc = str(rec_end_tc) source_file = clip.file.pathurl.replace('file://', '') e.source_file = source_file e.comments.extend([ '* FROM CLIP NAME: %s' % clip.name, '* SOURCE FILE: %s' % source_file ]) l.append(e) return l
def test_tc_to_frame_test_in_2997(self): """testing if timecode to frame conversion is ok in 2997 """ tc = Timecode('29.97', '00:00:00:00') self.assertEqual(tc.frames, 1) tc = Timecode('29.97', '00:00:00:21') self.assertEqual(tc.frames, 22) tc = Timecode('29.97', '00:00:00:29') self.assertEqual(tc.frames, 30) tc = Timecode('29.97', '00:00:00:60') self.assertEqual(tc.frames, 61) tc = Timecode('29.97', '00:00:01:00') self.assertEqual(tc.frames, 31) tc = Timecode('29.97', '00:00:10:00') self.assertEqual(tc.frames, 301) # test with non existing timecodes tc = Timecode('29.97', '00:01:00:00') self.assertEqual(1799, tc.frames) self.assertEqual('00:00:59:28', tc.__str__()) # test the limit tc = Timecode('29.97', '23:59:59:29') self.assertEqual(2589408, tc.frames)
def test_gt_overload(self): tc1 = Timecode(24, '00:00:00:00') tc2 = Timecode(24, '00:00:00:00') tc3 = Timecode(24, '00:00:00:01') tc4 = Timecode(24, '00:00:01.100') tc5 = Timecode(24, '00:00:01.200') self.assertFalse(tc1 > tc2) self.assertFalse(tc2 > tc2) self.assertTrue(tc3 > tc2) self.assertTrue(tc5 > tc4)
def test_framerate_can_be_changed(self): """testing if the timecode value will be automaticall updated when the framerate attribute is changed """ tc1 = Timecode('25', frames=100) self.assertEqual('00:00:03:24', tc1.__str__()) self.assertEqual(100, tc1.frames) tc1.framerate = '12' self.assertEqual('00:00:08:03', tc1.__str__()) self.assertEqual(100, tc1.frames)
def Convert_toTC(TC, FPS): global status_text if str(TC) == str(neg_error) or TC == "": print() else: tc3 = Timecode(FPS, start_timecode=None, frames=int(TC)) + Timecode( FPS, "00:00:00:00") # tc3 = tc1.frame_number itm['Result']({"Text": tc3}) status_text = str(tc3)
def test_ge_overload(self): tc1 = Timecode(24, '00:00:00:00') tc2 = Timecode(24, '00:00:00:00') tc3 = Timecode(24, '00:00:00:01') tc4 = Timecode(24, '00:00:01.100') tc5 = Timecode(24, '00:00:01.200') self.assertTrue(tc1 == tc2) self.assertTrue(tc1 >= tc2) self.assertTrue(tc3 >= tc2) self.assertFalse(tc2 >= tc3) self.assertTrue(tc4 <= tc5)
def test_fps_compatibility(self): a = Timecode('12:34:56:12', fps=25) b = Timecode('12:34:56:12', fps=50) def add(a1, a2): return a1 + a2 def sub(a1, a2): return a1 - a2 self.assertRaises(Timecode.FPSMismatch, add, a, b) self.assertRaises(Timecode.FPSMismatch, sub, a, b)
def test_math(self): a = Timecode('12:34:56:12', fps=25) b = Timecode('00:00:01:10', fps=25) c = a + b self.assertEqual(c, Timecode('12:34:57:22', fps=25)) d = a - b self.assertEqual(d, Timecode('12:34:55:02', fps=25))
def test_toggle_fractional_frame(self): tc = Timecode(24, 421729315) self.assertEqual(tc.__repr__(), '19:23:14:23') tc.set_fractional(True) self.assertEqual(tc.__repr__(), '19:23:14.958') tc.set_fractional(False) self.assertEqual(tc.__repr__(), '19:23:14:23')
def test_rational_frame_delimiter(self): tc = Timecode('24000/1000', frames=1) self.assertFalse(';' in tc.__repr__()) tc = Timecode('24000/1001', frames=1) self.assertFalse(';' in tc.__repr__()) tc = Timecode('30000/1001', frames=1) self.assertTrue(';' in tc.__repr__())
def test_ms_vs_fraction_frames(self): tc1 = Timecode('ms', '00:00:00.040') self.assertTrue(tc1.ms_frame) self.assertFalse(tc1.fraction_frame) tc2 = Timecode(24, '00:00:00.042') self.assertTrue(tc2.fraction_frame) self.assertFalse(tc2.ms_frame) self.assertNotEqual(tc1, tc2) self.assertEqual(tc1.frame_number, 40) self.assertEqual(tc2.frame_number, 1)
def __init__(self, edit: pycmx.Edit, timecode_rate: int = 24): self.source_file = edit.source_file self.source_name = edit.source self.frame_rate = int(timecode_rate) self.source_in = Timecode(framerate=timecode_rate, start_timecode=edit.source_in).frames self.source_out = Timecode(framerate=timecode_rate, start_timecode=edit.source_out).frames self.record_in = Timecode(framerate=timecode_rate, start_timecode=edit.record_in).frames self.record_out = Timecode(framerate=timecode_rate, start_timecode=edit.record_out).frames self.channels = edit.channels self.clip_name = edit.clip_name
def sixIndexSplitter(splitLine): splitLine = re.split(r'\s{2,}', splitter) dstIn = splitTimes[2] dstOut = splitTimes[3] dstOutSplit = dstOut.split("'") # Separates timecode from '] at end dstOut = dstOutSplit[0] # isolates timecode into dstOut variable dstIn = Timecode('25', dstIn) dstOut = Timecode('25', dstOut) srcDur = dstOut - dstIn del splitLine[0] splitLine.insert(0, num) del splitLine[-1] splitLine.append(str(srcDur)) finalFileWriter.writerow(splitLine)
def test_24_hour_limit_in_2997fps(self): """testing if the timecode will loop back to 00:00:00:00 after 24 hours in 29.97 fps """ tc = Timecode('29.97', '00:00:00:21') self.assertTrue(tc.drop_frame) self.assertEqual(22, tc.frames) tc2 = Timecode('29.97', '23:59:59:29') self.assertTrue(tc2.drop_frame) self.assertEqual(2589408, tc2.frames) self.assertEqual( '00:00:00:21', tc.__repr__() ) self.assertEqual( '23:59:59:29', tc2.__repr__() ) self.assertEqual( '00:00:00:21', (tc + tc2).__str__() ) self.assertEqual( '02:00:00:00', (tc2 + 215785).__str__() ) self.assertEqual( '02:00:00:00', (tc2 + 215785 + 2589408).__str__() ) self.assertEqual( '02:00:00:00', (tc2 + 215785 + 2589408 + 2589408).__str__() )
def test_frame_to_tc(self): def assertFrameToTC(tc_, hrs, mins, secs, frs): self.assertEqual(hrs, tc_.hrs) self.assertEqual(mins, tc_.mins) self.assertEqual(secs, tc_.secs) self.assertEqual(frs, tc_.frs) tc = Timecode('29.97', '00:00:00:01') assertFrameToTC(tc, 0, 0, 0, 1) self.assertEqual('00:00:00:01', tc.__str__()) test_code = '03:36:09:23' framerates = ['23.98', '24', '25', '29.97', '30', '59.94', '60'] for fr in framerates: tc = Timecode(fr, test_code) assertFrameToTC(tc, 3, 36, 9, 23) tc = Timecode('ms', '03:36:09:230') assertFrameToTC(tc, 3, 36, 9, 230) tc = Timecode('24', frames=12000) assertFrameToTC(tc, 0, 8, 19, 23) self.assertEqual('00:08:19:23', tc.__str__())
def test_drop_frame(self): tc = Timecode('29.97', '13:36:59:29') timecode = tc.next() self.assertEqual("13:37:00:02", timecode.__str__()) tc = Timecode('59.94', '13:36:59:59') self.assertEqual("13:36:59:59", tc.__str__()) timecode = tc.next() self.assertEqual("13:37:00:04", timecode.__str__()) tc = Timecode('59.94', '13:39:59:59') timecode = tc.next() self.assertEqual("13:40:00:00", timecode.__str__()) tc = Timecode('29.97', '13:39:59:29') timecode = tc.next() self.assertEqual("13:40:00:00", timecode.__str__())
def test_repr_overload(self): timeobj = Timecode('24', '01:00:00:00') self.assertEqual('01:00:00:00', timeobj.__repr__()) timeobj = Timecode('23.98', '20:00:00:00') self.assertEqual('20:00:00:00', timeobj.__repr__()) timeobj = Timecode('29.97', '00:09:00:00') self.assertEqual('00:08:59:28', timeobj.__repr__()) timeobj = Timecode('30', '00:10:00:00') self.assertEqual('00:10:00:00', timeobj.__repr__()) timeobj = Timecode('60', '00:00:09:00') self.assertEqual('00:00:09:00', timeobj.__repr__()) timeobj = Timecode('59.94', '00:00:20:00') self.assertEqual('00:00:20:00', timeobj.__repr__()) timeobj = Timecode('ms', '00:00:00:900') self.assertEqual('00:00:00:900', timeobj.__repr__()) timeobj = Timecode('24', frames=49) self.assertEqual('00:00:02:00', timeobj.__repr__())
def frameToTC(frame, base=TC_BASE): tc = Timecode(base, '00:00:00:00') tc.frames = frame return tc
def test_24_hour_limit(self): """testing if the timecode will loop back to 00:00:00:00 after 24 hours in 29.97 fps """ tc0 = Timecode('59.94', '23:59:59:29') self.assertEqual(5178786, tc0.frames) tc0 = Timecode('29.97', '23:59:59:29') self.assertEqual(2589408, tc0.frames) tc1 = Timecode('29.97', frames=2589408) self.assertEqual('23:59:59:29', tc1.__str__()) tc2 = Timecode('29.97', '23:59:59:29') tc3 = tc2 + 1 self.assertEqual('00:00:00:00', tc3.__str__()) tc2 = Timecode('29.97', '23:59:59:29') tc3 = tc2 + 21 self.assertEqual('00:00:00:20', tc3.__str__()) tc = Timecode('29.97', '00:00:00:21') tc2 = Timecode('29.97', '23:59:59:29') tc3 = (tc + tc2) self.assertEqual('00:00:00:21', tc3.__str__()) tc = Timecode('29.97', '04:20:13:21') tca = Timecode('29.97', frames=467944) self.assertEqual(467944, tca.frames) self.assertEqual(467944, tc.frames) self.assertEqual('04:20:13:21', tca.__str__()) self.assertEqual('04:20:13:21', tc.__str__()) tc2 = Timecode('29.97', '23:59:59:29') self.assertEqual(2589408, tc2.frames) self.assertEqual('23:59:59:29', tc2.__str__()) tc2a = Timecode('29.97', frames=2589408) self.assertEqual(2589408, tc2a.frames) self.assertEqual('23:59:59:29', tc2a.__str__()) tc3 = (tc + tc2) self.assertEqual('04:20:13:21', tc3.__str__()) tc = Timecode('59.94', '04:20:13:21') self.assertEqual('04:20:13:21', tc.__str__()) tca = Timecode('59.94', frames=935866) self.assertEqual('04:20:13:21', tc.__str__()) tc2 = Timecode('59.94', '23:59:59:59') tc3 = (tc + tc2) self.assertEqual('04:20:13:21', tc3.__str__())
def xml_paser(self): with open(self.xmlFile, 'rt') as f: tree = ElementTree.parse(f) root = tree.getroot() #complete event list with tansition events, clip events and several tracks event_list = [] for sequence_item in root.findall("./sequence"): sec_name = sequence_item.find('name').text.split(" (")[0] sec_framerate = int(sequence_item.find('./timecode/rate/timebase').text) sec_cut_in = int(sequence_item.find('./timecode/frame').text) sec_tc_in = Timecode(sec_framerate, sequence_item.find('./timecode/string').text) sec_tc_duration = Timecode(sec_framerate,) sec_tc_duration.frames = int(sequence_item.find('./duration').text) sec_tc_out = sec_tc_in + sec_tc_duration self.sequence_info = {"sec_name":sec_name,"sec_framerate":sec_framerate,\ "sec_cut_duration":sec_tc_duration.frames,"sec_tc_in":sec_tc_in,"sec_tc_out":sec_tc_out,\ "sec_cut_in":sec_cut_in,"sec_cut_out":sec_tc_out.frame_number} #print sequence_info video_tree = root.find('sequence/media/video') for child in video_tree.iter(): if child.tag == 'clipitem': #print "------------------------" #print child.tag clip_occurence = child.attrib['id'].split()[-1] #print "id: ", clip_occurence clip_item = {"type":child.tag} for element in child: if element.tag in ('name', 'duration', 'start', 'end', 'in', 'out'): clip_item.update({element.tag:element.text}) if element.tag == "file": if clip_occurence == "0": #print "SOURCE CLIP NUEVO" for field in element.iter(): if field.tag == 'pathurl': #unquote translate symbols to url chars file_path = unquote(field.text.split("//")[1]) clip_item.update({field.tag:file_path}) elif field.tag == 'timecode': for subfield in field.iter(): if subfield.tag == "string": clip_item.update({"clip_tc_in":subfield.text}) else: #print "SOURCE CLIP EXISTENTE" for event_list_item in event_list: if clip_item['name'] in event_list_item.values(): clip_item.update({"pathurl":event_list_item["pathurl"]}) clip_item.update({"clip_tc_in":event_list_item["clip_tc_in"]}) clip_in = Timecode(sec_framerate,) clip_in.frames = int(clip_item['in']) shot_tc_source_in = Timecode(sec_framerate,clip_item['clip_tc_in']) + clip_in clip_out = Timecode(sec_framerate,) clip_out.frames = int(clip_item['out']) shot_tc_source_out = Timecode(sec_framerate,clip_item['clip_tc_in']) + clip_out clip_item.update({"shot_tc_source_in": str(shot_tc_source_in)}) clip_item.update({"shot_tc_source_out": str(shot_tc_source_out)}) ###zero based frame numbers clip_item.update({"shot_cut_source_in": str(shot_tc_source_in.frame_number)}) clip_item.update({"shot_cut_source_out": str(shot_tc_source_out.frame_number)}) clip_item.update({"cut_duration": int(clip_item['out'])-int(clip_item['in'])}) #print clip_item event_list.append(clip_item) elif child.tag == 'transitionitem': #print "------------------------" #print child.tag clip_item = {"type":child.tag} for element in child.iter(): if element.tag in ("start", "end", "name"): clip_item.update({element.tag:element.text}) event_list.append(clip_item) ###seek for transitioned start or end clips and update record tc for event_list_item in event_list: if event_list_item['type'] == 'clipitem': if event_list_item['start'] == "-1": clip_item_index = event_list.index(event_list_item) transition_data = event_list[clip_item_index-1] event_list_item['start']=transition_data['start'] tc_start=Timecode(sec_framerate,) tc_start.frames=int(event_list_item['start']) event_list_item.update({'record_tc_in':self.sequence_info['sec_tc_in']+tc_start}) if event_list_item['end'] == "-1": clip_item_index = event_list.index(event_list_item) transition_data = event_list[clip_item_index+1] event_list_item['end']=transition_data['end'] tc_end=Timecode(sec_framerate,) tc_end.frames=int(event_list_item['end']) event_list_item.update({'record_tc_out':self.sequence_info['sec_tc_in']+tc_end}) self.shot_list.append(event_list_item) #order shot list by start frame on record (record cut in) self.shot_list = sorted(self.shot_list, key=lambda k: int(k['start'])) for idx, shot_list_item in enumerate(self.shot_list): #cut order is index with 3d padding begining in 1 multiple of 10 for interpolate new posible shots manually shot_list_item.update({"cut_order": "{0:03d}".format((idx+1)*10)}) shot_list_item.update({"shot_code": "PL_" + str(shot_list_item["cut_order"]) + "_" + self.sequence_info['sec_name']})
def test_frame_to_tc(self): tc = Timecode('29.97', '00:00:00:01') self.assertEqual(0, tc.hrs) self.assertEqual(0, tc.mins) self.assertEqual(0, tc.secs) self.assertEqual(1, tc.frs) self.assertEqual('00:00:00:01', tc.__str__()) tc = Timecode('29.97', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('29.97', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('30', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('25', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('59.94', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('60', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('59.94', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('23.98', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('24', '03:36:09:23') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(23, tc.frs) tc = Timecode('ms', '03:36:09:230') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(230, tc.frs) tc = Timecode('24', frames=12000) self.assertEqual('00:08:19:23', tc.__str__()) self.assertEqual(0, tc.hrs) self.assertEqual(8, tc.mins) self.assertEqual(19, tc.secs) self.assertEqual(23, tc.frs)
def test_timecode_init(self): """testing several timecode initialization """ tc = Timecode('29.97') self.assertEqual('00:00:00:00', tc.__str__()) self.assertEqual(1, tc.frames) tc = Timecode('29.97', '00:00:00:01') self.assertEqual(2, tc.frames) tc = Timecode('29.97', '03:36:09:23') self.assertEqual(388704, tc.frames) tc = Timecode('29.97', '03:36:09:23') self.assertEqual(388704, tc.frames) tc = Timecode('30', '03:36:09:23') self.assertEqual(389094, tc.frames) tc = Timecode('25', '03:36:09:23') self.assertEqual(324249, tc.frames) tc = Timecode('59.94', '03:36:09:23') self.assertEqual(777384, tc.frames) tc = Timecode('60', '03:36:09:23') self.assertEqual(778164, tc.frames) tc = Timecode('59.94', '03:36:09:23') self.assertEqual(777384, tc.frames) tc = Timecode('23.98', '03:36:09:23') self.assertEqual(311280, tc.frames) tc = Timecode('24', '03:36:09:23') self.assertEqual(311280, tc.frames) tc = Timecode('ms', '03:36:09:230') self.assertEqual(3, tc.hrs) self.assertEqual(36, tc.mins) self.assertEqual(9, tc.secs) self.assertEqual(230, tc.frs) tc = Timecode('24', frames=12000) self.assertEqual('00:08:19:23', tc.__str__()) tc = Timecode('29.97', frames=2589408) self.assertEqual('23:59:59:29', tc.__str__()) tc = Timecode('29.97', frames=2589409) self.assertEqual('00:00:00:00', tc.__str__()) tc = Timecode('59.94', frames=5178816) self.assertEqual('23:59:59:59', tc.__str__()) tc = Timecode('59.94', frames=5178817) self.assertEqual('00:00:00:00', tc.__str__())
def test_iteration(self): tc = Timecode('29.97', '03:36:09:23') self.assertEqual("03:36:09:23", tc) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(388764, tc.frames) tc = Timecode('29.97', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(388764, tc.frames) tc = Timecode('30', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:11:23", t) self.assertEqual(389154, tc.frames) tc = Timecode('25', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:08", t) self.assertEqual(324309, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(777444, tc.frames) tc = Timecode('60', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(778224, tc.frames) tc = Timecode('59.94', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:10:23", t) self.assertEqual(777444, tc.frames) tc = Timecode('23.98', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('24', '03:36:09:23') for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("03:36:12:11", t) self.assertEqual(311340, tc.frames) tc = Timecode('ms', '03:36:09:230') for x in range(60): t = tc.next() self.assertIsNotNone(t) self.assertEqual('03:36:09:290', t) self.assertEqual(12969291, tc.frames) tc = Timecode('24', frames=12000) for x in range(60): t = tc.next() self.assertTrue(t) self.assertEqual("00:08:22:11", t) self.assertEqual(12060, tc.frames)