Skip to content

Commit 2666a3e

Browse files
committed
fixing -exf logic
1 parent c9ff652 commit 2666a3e

File tree

2 files changed

+76
-23
lines changed

2 files changed

+76
-23
lines changed

auto_editor/__main__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -577,10 +577,12 @@ def newOutputName(oldFile: str, audio, final_cut_pro, data, json) -> str:
577577
del hasLoud
578578

579579
clips = []
580-
numCuts = len(chunks)
580+
numCuts = 0
581581
for chunk in chunks:
582582
if(speeds[chunk[2]] != 99999):
583583
clips.append([chunk[0], chunk[1], speeds[chunk[2]] * 100])
584+
else:
585+
numCuts += 1
584586

585587
if(fps is None and not audioFile):
586588
if(makingDataFile):

auto_editor/editor.py

+73-22
Original file line numberDiff line numberDiff line change
@@ -56,60 +56,111 @@ def fixUrl(path: str, resolve: bool) -> str:
5656
def fcpXML(myInput: str, temp: str, output, ffprobe, clips, chunks, tracks: int,
5757
sampleRate, audioFile, fps, log):
5858

59-
duration = chunks[len(chunks) - 1][1]
60-
pathurl = 'file:///' + os.path.abspath(myInput)
59+
pathurl = 'file://' + os.path.abspath(myInput)
6160
name = os.path.splitext(os.path.basename(myInput))[0]
6261

63-
def fraction(inp: float) -> str:
64-
num, dem = inp.as_integer_ratio()
65-
if(num == 0):
62+
def fraction(inp, fps) -> str:
63+
from fractions import Fraction
64+
65+
if(inp == 0):
6666
return '0s'
67-
num *= 1000
68-
dem *= 1000
67+
68+
if(isinstance(inp, float)):
69+
inp = Fraction(inp)
70+
if(isinstance(fps, float)):
71+
fps = Fraction(fps)
72+
73+
74+
frac = Fraction(inp, fps).limit_denominator()
75+
num = frac.numerator
76+
dem = frac.denominator
77+
78+
if(dem < 3000):
79+
factor = int(3000 / dem)
80+
print(3000 / dem)
81+
print(f'{num}/{dem}')
82+
num *= factor
83+
dem *= factor
84+
print(f'{num}/{dem}')
85+
6986
return f'{num}/{dem}s'
7087

7188
if(not audioFile):
7289
width, height = ffprobe.getResolution(myInput).split('x')
90+
total_dur = ffprobe.getDuration(myInput)
91+
if(total_dur == 'N/A'):
92+
total_dur = ffprobe.pipe(['-show_entries', 'format=duration', '-of',
93+
'default=noprint_wrappers=1:nokey=1', myInput]).strip()
7394
else:
7495
width, height = '1920', '1080'
96+
total_dur = ffprobe.getAudioDuration(myInput)
97+
total_dur = float(total_dur) * fps
7598

7699
with open(output, 'w', encoding='utf-8') as outfile:
100+
101+
frame_duration = fraction(1, fps)
102+
new_duration = fraction(chunks[len(chunks) - 1][1], fps)
103+
77104
outfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
78105
outfile.write('<!DOCTYPE fcpxml>\n\n')
79106
outfile.write('<fcpxml version="1.9">\n')
80107
outfile.write('\t<resources>\n')
81108
outfile.write(f'\t\t<format id="r1" name="FFVideoFormat{height}p{fps}" '\
82-
f'frameDuration="100/3000s" width="{width}" height="{height}"'\
109+
f'frameDuration="{frame_duration}" width="{width}" height="{height}"'\
83110
' colorSpace="1-1-1 (Rec. 709)"/>\n')
84111

85112
outfile.write(f'\t\t<asset id="r2" name="{name}" start="0s" '\
86-
'duration="3816000/90000s" hasVideo="1" format="r1" hasAudio="1" '\
113+
'hasVideo="1" format="r1" hasAudio="1" '\
87114
f'audioSources="1" audioChannels="2" audioRate="{sampleRate}">\n')
88115

89116
outfile.write(f'\t\t\t<media-rep kind="original-media" '\
90117
f'src="{pathurl}"></media-rep>\n')
91118
outfile.write('\t\t</asset>\n')
92119
outfile.write('\t</resources>\n')
93-
outfile.write('\t<library location="file:///Users/wyattblue/Movies/Untitled.fcpbundle/">\n')
94-
outfile.write('\t\t<event name="3-16-21">\n')
120+
outfile.write('\t<library>\n')
121+
outfile.write('\t\t<event name="auto-editor output">\n')
95122
outfile.write(f'\t\t\t<project name="{name}">\n')
96123
outfile.write(formatXML(4,
97-
f'<sequence duration="{fraction(duration)}" format="r1" tcStart="0s" tcFormat="NDF" '\
124+
f'<sequence duration="{new_duration}" format="r1" tcStart="0s" tcFormat="NDF" '\
98125
'audioLayout="stereo" audioRate="48k">',
99-
'\t<spine>'))
126+
'\t<spine>')
127+
)
128+
129+
last_dur = 0
100130

101-
total = 0
102131
for j, clip in enumerate(clips):
103-
total += (clip[1] - clip[0])
104-
off = fraction(clip[0] + total)
132+
clip_dur = (clip[1] - clip[0]) / (clip[2] / 100)
133+
dur = fraction(clip_dur, fps)
105134

106-
dur = fraction(clip[1] - clip[0])
107-
if(j == 0):
108-
outfile.write(formatXML(6, f'<asset-clip name="{name}" offset="{total}" ref="r2"'\
109-
f' duration="{dur}" audioRole="dialogue" tcFormat="NDF"/>'))
135+
close = '/' if clip[2] == 100 else ''
136+
137+
if(last_dur == 0):
138+
outfile.write(formatXML(6, f'<asset-clip name="{name}" offset="0s" ref="r2"'\
139+
f' duration="{dur}" audioRole="dialogue" tcFormat="NDF"{close}>'))
110140
else:
111-
outfile.write(formatXML(6, f'<asset-clip name="{name}" offset="{total}" ref="r2"'\
112-
f' duration="{dur}" audioRole="dialogue" tcFormat="NDF"/>'))
141+
start = fraction(clip[0], fps)
142+
off = fraction(last_dur, fps)
143+
outfile.write(formatXML(6,
144+
f'<asset-clip name="{name}" offset="{off}" ref="r2"'\
145+
f' duration="{dur}" start="{start}" audioRole="dialogue" tcFormat="NDF"{close}>',
146+
))
147+
148+
if(clip[2] != 100):
149+
# See "Time Maps" in developer.apple.com/library/archive/documentation/FinalCutProX/Reference/FinalCutProXXMLFormat/StoryElements/StoryElements.html
150+
151+
frac_total = fraction(total_dur, fps)
152+
total_dur_divided_by_speed = fraction((total_dur) / (clip[2] / 100), fps)
153+
154+
155+
outfile.write(formatXML(6,
156+
'\t<timeMap>',
157+
'\t\t<timept time="0s" value="0s" interp="smooth2"/>',
158+
f'\t\t<timept time="{total_dur_divided_by_speed}" value="{frac_total}" interp="smooth2"/>',
159+
'\t</timeMap>',
160+
'</asset-clip>'
161+
))
162+
163+
last_dur += clip_dur
113164

114165
outfile.write('\t\t\t\t\t</spine>\n')
115166
outfile.write('\t\t\t\t</sequence>\n')

0 commit comments

Comments
 (0)