Summary
When loading an existing CapCut draft via Script_file.load_template(path), then calling .dump(path) to save modifications, all segments inside sticker, text, and effect tracks are silently dropped. The tracks themselves are preserved (with empty segments: []), but the actual sticker/text/effect content (along with its keyframes, materials, and positioning) is lost.
This caused a destructive data loss in my workflow — I edited an existing draft programmatically and silently deleted manually-placed user stickers/highlights.
Root cause
In pyJianYingDraft/template_mode.py line 218, function import_track():
if track_type.value.allow_modify and imported_materials:
for segment_data in json_data.get("segments", []):
# ... handle Video / Audio / other
The allow_modify flag controls whether segments are imported. Looking at track.py:
sticker = Track_meta(Sticker_segment, 14000, False) # allow_modify=False
text = Track_meta(Text_segment, 15000, False) # allow_modify=False
effect = Track_meta(Effect_segment, 16000, False) # allow_modify=False
So for these track types, segments are NEVER iterated/imported. The track is created but with segments=[]. When dump() is later called, the empty tracks export back to JSON with no segments — silently overwriting any existing segments that were on disk.
Reproduction
- Open CapCut, create a draft with at least one sticker (e.g.
Highlight EN Line overlay) with keyframes.
- Quit CapCut (so the file is settled on disk).
- Run:
from pyJianYingDraft import Script_file
s = Script_file.load_template(draft_info_json_path)
s.dump(draft_info_json_path) # no other changes
- Reopen the draft in CapCut. The sticker track is now empty.
Expected behavior
load_template + dump should be a round-trip preserving operation when no modifications are made. Even for tracks that pyJianYingDraft can't actively edit, segments should be preserved as ImportedSegment (or similar) and round-tripped through dump().
Suggested fix
The else branch already exists in import_track (line 322) for "other types" via ImportedSegment. The issue is the outer condition if track_type.value.allow_modify. Remove that condition (or invert it) so the else branch runs for sticker/text/effect tracks, preserving segments as opaque ImportedSegment objects.
# Inside import_track, after creating track:
for segment_data in json_data.get("segments", []):
# build common_keyframes (always)
common_keyframes = build_keyframes_from(segment_data)
if track_type == Track_type.video:
# existing video logic, with allow_modify gate
...
elif track_type == Track_type.audio:
# existing audio logic
...
else:
# NEW: preserve sticker/text/effect as opaque
segment = ImportedSegment(segment_data)
segment.common_keyframes = common_keyframes
track.segments.append(segment)
ImportedSegment.export_json() should already write back the original dict.
Environment
- pyJianYingDraft: current
main (commit b085f7e)
- Python 3.13 / macOS 26.1
- CapCut International 8.5.0
Workaround
Edit the draft_info.json directly with json.load / json.dump instead of using Script_file.load_template + .dump() when the existing draft contains stickers, text, or effects.
Happy to send a PR if the approach above sounds good.
Summary
When loading an existing CapCut draft via
Script_file.load_template(path), then calling.dump(path)to save modifications, all segments inside sticker, text, and effect tracks are silently dropped. The tracks themselves are preserved (with emptysegments: []), but the actual sticker/text/effect content (along with its keyframes, materials, and positioning) is lost.This caused a destructive data loss in my workflow — I edited an existing draft programmatically and silently deleted manually-placed user stickers/highlights.
Root cause
In
pyJianYingDraft/template_mode.pyline 218, functionimport_track():The
allow_modifyflag controls whether segments are imported. Looking attrack.py:So for these track types, segments are NEVER iterated/imported. The track is created but with
segments=[]. Whendump()is later called, the empty tracks export back to JSON with no segments — silently overwriting any existing segments that were on disk.Reproduction
Highlight EN Lineoverlay) with keyframes.Expected behavior
load_template+dumpshould be a round-trip preserving operation when no modifications are made. Even for tracks thatpyJianYingDraftcan't actively edit, segments should be preserved asImportedSegment(or similar) and round-tripped throughdump().Suggested fix
The
elsebranch already exists inimport_track(line 322) for "other types" viaImportedSegment. The issue is the outer conditionif track_type.value.allow_modify. Remove that condition (or invert it) so theelsebranch runs for sticker/text/effect tracks, preserving segments as opaqueImportedSegmentobjects.ImportedSegment.export_json()should already write back the original dict.Environment
main(commit b085f7e)Workaround
Edit the
draft_info.jsondirectly withjson.load/json.dumpinstead of usingScript_file.load_template+.dump()when the existing draft contains stickers, text, or effects.Happy to send a PR if the approach above sounds good.