Add export_markers.py
This commit is contained in:
103
export_markers.py
Normal file
103
export_markers.py
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
# --- ARCH LINUX PATH FIX ---
|
||||
module_path = "/opt/resolve/Developer/Scripting/Modules/"
|
||||
if module_path not in sys.path:
|
||||
sys.path.append(module_path)
|
||||
|
||||
try:
|
||||
import DaVinciResolveScript as dvr_script
|
||||
except ImportError:
|
||||
print(f"❌ Critical Error: Could not find 'DaVinciResolveScript.py'.")
|
||||
sys.exit(1)
|
||||
# ---------------------------
|
||||
|
||||
def export_clip_markers_final():
|
||||
try:
|
||||
resolve = dvr_script.scriptapp("Resolve")
|
||||
project = resolve.GetProjectManager().GetCurrentProject()
|
||||
timeline = project.GetCurrentTimeline()
|
||||
except:
|
||||
return
|
||||
|
||||
if not timeline:
|
||||
print("❌ Error: No active timeline found.")
|
||||
return
|
||||
|
||||
# Base Path
|
||||
base_output_path = os.path.expanduser("~/Videos/Resolve_Exports")
|
||||
timeline_name = timeline.GetName()
|
||||
safe_timeline_name = re.sub(r'[\\/*?:"<>|]', "", timeline_name).replace(" ", "_")
|
||||
timeline_dir = os.path.join(base_output_path, safe_timeline_name)
|
||||
|
||||
# Get Clips from Video Track 1
|
||||
clips = timeline.GetItemListInTrack("video", 1)
|
||||
if not clips:
|
||||
print("No clips found.")
|
||||
return
|
||||
|
||||
job_count = 0
|
||||
print(f"Scanning {len(clips)} clips...")
|
||||
|
||||
for clip in clips:
|
||||
markers = clip.GetMarkers()
|
||||
if not markers: continue
|
||||
|
||||
# 1. Prepare Folder Name (Clip Name)
|
||||
clip_name_raw = clip.GetName()
|
||||
safe_clip_folder = re.sub(r'[\\/*?:"<>|]', "", clip_name_raw)
|
||||
safe_clip_folder = safe_clip_folder.replace(".mov", "").replace(".mp4", "").replace(".mxf", "").strip()
|
||||
|
||||
clip_target_dir = os.path.join(timeline_dir, safe_clip_folder)
|
||||
|
||||
# Create folder if missing
|
||||
if not os.path.exists(clip_target_dir):
|
||||
try:
|
||||
os.makedirs(clip_target_dir)
|
||||
except OSError: continue
|
||||
|
||||
# 2. Timing Calculations
|
||||
clip_start_timeline = clip.GetStart()
|
||||
clip_left_offset = clip.GetLeftOffset()
|
||||
|
||||
for marker_frame, marker_data in markers.items():
|
||||
timeline_frame_pos = (marker_frame - clip_left_offset) + clip_start_timeline
|
||||
|
||||
# 3. Prepare File Name (Marker Name)
|
||||
raw_name = marker_data['name'] if marker_data['name'] else marker_data['note']
|
||||
|
||||
if not raw_name:
|
||||
base_name = f"Frame_{marker_frame}"
|
||||
else:
|
||||
base_name = re.sub(r'[\\/*?:"<>|]', "", raw_name).strip()
|
||||
|
||||
# --- THE FIX: Force correct naming ---
|
||||
# We set UniqueFilenameStyle to 1 (Suffix) but we manually control the name.
|
||||
# Unfortunately, API limitation: Resolve ALWAYS appends frame number on image sequences.
|
||||
# The cleanest "trick" is to use the name as is, and accept that Resolve
|
||||
# adds the frame digits. The previous "underscore" trick is the safest bet.
|
||||
|
||||
final_filename = base_name + "_"
|
||||
|
||||
# 4. Add to Render Queue
|
||||
project.SetRenderSettings({
|
||||
"SelectAllFrames": False,
|
||||
"MarkIn": timeline_frame_pos,
|
||||
"MarkOut": timeline_frame_pos,
|
||||
"TargetDir": clip_target_dir,
|
||||
"CustomName": final_filename,
|
||||
"UniqueFilenameStyle": 0
|
||||
})
|
||||
|
||||
project.AddRenderJob()
|
||||
job_count += 1
|
||||
print(f"✅ Queued: {safe_clip_folder}/{final_filename}[####].ext")
|
||||
|
||||
print("-" * 30)
|
||||
print(f"🎉 Queued {job_count} stills.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
export_clip_markers_final()
|
||||
Reference in New Issue
Block a user