Update app.py
Browse files
app.py
CHANGED
|
@@ -82,7 +82,6 @@ ACTIVE_GEMINI_KEY = ENV_GEMINI_KEY if ENV_GEMINI_KEY else HARDCODED_GEMINI_KEY
|
|
| 82 |
def clean_json_response(text):
|
| 83 |
"""Strips markdown code fences from Gemini output to prevent JSON errors."""
|
| 84 |
try:
|
| 85 |
-
# Remove ```json ... ``` or just ``` ... ```
|
| 86 |
pattern = r"```(?:json)?\s*(.*?)```"
|
| 87 |
match = re.search(pattern, text, re.DOTALL)
|
| 88 |
if match:
|
|
@@ -130,16 +129,18 @@ def generate_cmx_edl(edl_title, segments, source_name, fps=25):
|
|
| 130 |
def generate_xml(sequence_name, segments, source_name, fps=25):
|
| 131 |
"""Constructs a Robust XML for Premiere AND Resolve."""
|
| 132 |
|
| 133 |
-
# Static UUID to ensure all cuts are seen as the same master clip
|
| 134 |
master_id = "masterfile-1"
|
| 135 |
|
| 136 |
-
# FPS Logic
|
| 137 |
timebase = int(round(fps))
|
| 138 |
is_ntsc = "TRUE" if fps % 1 != 0 else "FALSE"
|
| 139 |
|
| 140 |
-
#
|
|
|
|
|
|
|
|
|
|
| 141 |
encoded_name = quote(source_name)
|
| 142 |
-
path_url = f"file://localhost/{encoded_name}
|
| 143 |
|
| 144 |
lines = []
|
| 145 |
lines.append('<?xml version="1.0" encoding="UTF-8"?>')
|
|
@@ -175,7 +176,6 @@ def generate_xml(sequence_name, segments, source_name, fps=25):
|
|
| 175 |
tl_start = timeline_head_frames
|
| 176 |
tl_end = tl_start + duration_frames
|
| 177 |
|
| 178 |
-
# Truncate clip names for Premiere safety (max 80 chars)
|
| 179 |
raw_note = seg.get('note', 'Junior Editor Selection')
|
| 180 |
clip_note = (raw_note[:75] + '..') if len(raw_note) > 75 else raw_note
|
| 181 |
|
|
@@ -189,9 +189,7 @@ def generate_xml(sequence_name, segments, source_name, fps=25):
|
|
| 189 |
lines.append(f'\t\t\t\t\t<out>{src_out_frames}</out>')
|
| 190 |
lines.append(f'\t\t\t\t\t<masterclipid>{master_id}</masterclipid>')
|
| 191 |
|
| 192 |
-
# ---
|
| 193 |
-
# We repeat the full definition every time. It's verbose, but it's the only way
|
| 194 |
-
# to guarantee Premiere sees the metadata AND Resolve sees the path.
|
| 195 |
lines.append(f'\t\t\t\t\t<file id="{master_id}">')
|
| 196 |
lines.append(f'\t\t\t\t\t\t<name>{source_name}</name>')
|
| 197 |
lines.append(f'\t\t\t\t\t\t<pathurl>{path_url}</pathurl>')
|
|
@@ -349,7 +347,8 @@ st.divider()
|
|
| 349 |
|
| 350 |
with st.sidebar:
|
| 351 |
st.header("Project Settings")
|
| 352 |
-
|
|
|
|
| 353 |
|
| 354 |
st.header("Export Settings")
|
| 355 |
export_format = st.radio("Output Format", ["EDL", "XML (Multicam)"], index=0)
|
|
|
|
| 82 |
def clean_json_response(text):
|
| 83 |
"""Strips markdown code fences from Gemini output to prevent JSON errors."""
|
| 84 |
try:
|
|
|
|
| 85 |
pattern = r"```(?:json)?\s*(.*?)```"
|
| 86 |
match = re.search(pattern, text, re.DOTALL)
|
| 87 |
if match:
|
|
|
|
| 129 |
def generate_xml(sequence_name, segments, source_name, fps=25):
|
| 130 |
"""Constructs a Robust XML for Premiere AND Resolve."""
|
| 131 |
|
|
|
|
| 132 |
master_id = "masterfile-1"
|
| 133 |
|
| 134 |
+
# FPS Logic
|
| 135 |
timebase = int(round(fps))
|
| 136 |
is_ntsc = "TRUE" if fps % 1 != 0 else "FALSE"
|
| 137 |
|
| 138 |
+
# --- NAME & PATH LOGIC ---
|
| 139 |
+
# We DO NOT force an extension. If the user provided one (e.g. .mp4), keep it.
|
| 140 |
+
# If they didn't (e.g. "Multicam1"), keep it raw.
|
| 141 |
+
# This is critical for Premiere Multicam linking.
|
| 142 |
encoded_name = quote(source_name)
|
| 143 |
+
path_url = f"file://localhost/{encoded_name}"
|
| 144 |
|
| 145 |
lines = []
|
| 146 |
lines.append('<?xml version="1.0" encoding="UTF-8"?>')
|
|
|
|
| 176 |
tl_start = timeline_head_frames
|
| 177 |
tl_end = tl_start + duration_frames
|
| 178 |
|
|
|
|
| 179 |
raw_note = seg.get('note', 'Junior Editor Selection')
|
| 180 |
clip_note = (raw_note[:75] + '..') if len(raw_note) > 75 else raw_note
|
| 181 |
|
|
|
|
| 189 |
lines.append(f'\t\t\t\t\t<out>{src_out_frames}</out>')
|
| 190 |
lines.append(f'\t\t\t\t\t<masterclipid>{master_id}</masterclipid>')
|
| 191 |
|
| 192 |
+
# --- ROBUST FILE DEFINITION ---
|
|
|
|
|
|
|
| 193 |
lines.append(f'\t\t\t\t\t<file id="{master_id}">')
|
| 194 |
lines.append(f'\t\t\t\t\t\t<name>{source_name}</name>')
|
| 195 |
lines.append(f'\t\t\t\t\t\t<pathurl>{path_url}</pathurl>')
|
|
|
|
| 347 |
|
| 348 |
with st.sidebar:
|
| 349 |
st.header("Project Settings")
|
| 350 |
+
fps_options = [23.98, 24, 25, 29.97, 30, 50, 59.94, 60]
|
| 351 |
+
fps = st.selectbox("Timeline FPS", fps_options, index=2)
|
| 352 |
|
| 353 |
st.header("Export Settings")
|
| 354 |
export_format = st.radio("Output Format", ["EDL", "XML (Multicam)"], index=0)
|