GuanYixuan / GuanYixuan/pyCapCut

draft_meta_info.json `draft_materials` left empty → CapCut 9.1.0 shows imported media as inaccessible / relink

Open
#13 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
664
Forks
91
PR merge metrics
No merged PRs in 30d

Description

## Summary

Drafts generated by pycapcut leave every group in `draft_meta_info.json` → `draft_materials` **empty**, and the timeline's imported media is never registered there. On **CapCut International 9.1.0 (macOS)**, opening such a draft shows the imported video/audio/image clips as **"file inaccessible" / prompts a relink**, even though the files exist on disk and the `path` fields in `draft_content.json` are correct.

Populating `draft_materials` with the timeline media makes CapCut open the draft with all clips recognized (no relink).

## Root cause

- `DraftFolder.create_draft()` copies a **static** template into the draft folder and never updates it afterwards:
```python
# pycapcut/draft_folder.py (~line 85)
shutil.copy(assets.get_asset_path("DRAFT_META_TEMPLATE"),
os.path.join(draft_path, "draft_meta_info.json"))
```
The template (`pycapcut/assets/draft_meta_info.json`) has all `draft_materials` groups empty:
```json
"draft_materials": [
{"type": 0, "value": []},
{"type": 1, "value": []},
...
]
```
- `ScriptFile.save() → dump(save_path)` only writes `draft_content.json`. Nothing ever writes the imported materials (which the script already knows via `self.materials.videos` / `self.materials.audios`) into `draft_meta_info.json`'s `draft_materials`.

So `draft_content.json` correctly references the media, but the sibling `draft_meta_info.json` "import manifest" stays empty — and CapCut 9.1.0 appears to use that manifest to decide which media has actually been imported.

## Reproduction

```python
import pycapcut as p
df = p.DraftFolder("/path/to/CapCut/.../com.lveditor.draft")
sc = df.create_draft("demo", 1080, 1920, 30, allow_replace=True)
sc.add_segment(p.VideoSegment(p.VideoMaterial("/abs/path/clip.mp4"),
p.Timerange(0, 3_000_000)))
sc.save()
```
Open `demo` in CapCut 9.1.0 → the clip shows as inaccessible / relink prompt.
Inspecting `demo/draft_meta_info.json` → `draft_materials` groups are all `[]`.

## Workaround we currently use (post-save, for reference)

After `save()`, we read the materials back out of `draft_content.json` and write one entry per local video/audio into the `type: 0` group of `draft_meta_info.json`. The entry shape that made CapCut 9.1.0 stop asking for a relink is:

```python
{
"ai_group_type": "", "create_time": -1,
"duration": , # 0 for images
"enter_from": 0, "extra_info": , "file_Path": ,
"height": , "id": , "import_time": -1, "import_time_ms": -1,
"item_source": 1, "material_color_tag": "", "md5": "", "metetype": <"video"|"photo"|"music">,
"roughcut_time_range": {"duration": -1, "start": -1},
"sub_time_range": {"duration": -1, "start": -1},
"type": 0, "width": ,
}
```

This is reverse-engineered from a CapCut-International-9.1.0 hand-authored draft, so it is almost certainly **version-specific** — which is exactly why I'd rather ask than send a blind PR.

## Questions

1. Is populating `draft_meta_info.json` → `draft_materials` at save time meant to be the library's responsibility (i.e. is this a bug), or is it intentionally left to CapCut to backfill on import?
2. What is the correct **`type` grouping** (the template has 0/1/2/3/6/7/8) for each media kind, and the canonical per-entry schema across the CapCut vs 剪映 (JianYing) draft formats? Our workaround crudely dumps all media into `type: 0`, which works for our case but is likely not general.
3. If this is in scope, I'm happy to open a PR that populates the manifest inside `dump()` from `self.materials`. Any guidance on placement / format before I do so would help me get it right.

## Environment

- pycapcut `0.0.3` (behavior unchanged on current `main`)
- CapCut International 9.1.0, macOS

Thanks for the library!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with pycapcut/draft_folder.py and the ScriptFile.save() → dump(save_path) path, then inspect pycapcut/assets/draft_meta_info.json. Run the provided reproduction and compare draft_content.json with draft_meta_info.json, including the materials in self.materials.videos and self.materials.audios. Done requires an agreed CapCut/JianYing grouping and entry schema, with save-time output that CapCut 9.1.0 recognizes without relinking.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.