方案概览
AccuFace 在 iClone/Character Creator 里写入的是 Reallusion 60 标准 BlendShape 曲线。要把它们导出为 ARKit 52 并写入文本文件,可采用「iClone → FBX(ARKit 52 命名) → Blender → Python 脚本 → JSON/CSV」这一条相对稳妥的管线。
关键步骤下面分拆说明,并给出可直接运行的脚本示例。
步骤 1:把 Reallusion 60 映射到 ARKit 52
-
在 iClone 8 / CC 4 选中角色,点击
Modify 面板 → Expression Editor。 -
右上角预设下拉菜单里选择 ARKit (52),软件会自动把 60 组 Slider 匹配到 Apple 的 52 组名称(JawOpen、EyeBlink_L…)1。
-
检查是否有未自动匹配的条目,手动拖拽即可补齐。保存表情配置后,AccuFace 捕捉到的曲线会直接写入这些 ARKit 名称的 Slider。
如角色最初就由 CC4 创建,ExPlus 表情库本身已含 ARKit 对应滑杆,通常无需手动映射。
步骤 2:FBX 导出(内含 52 曲线)
-
File → Export → Export FBX。
-
点击右上角齿轮图标,Profile 选择 ARKit (52 BlendShapes);同时勾选
-
Convert Skinned Expressions to Morphs
-
Mouth Open as Morph
这样所有表情都会以 Morph Target 曲线形式写进 FBX 文件1。
-
-
Bake Animation 选择 All Frames,其余默认,导出完成。
步骤 3:Blender 导入 FBX
在 Blender(≥3.0)执行
File → Import → FBX,保持默认即可。
导入后可在
Object Data Properties → Shape Keys
看到 52 个 ARKit 命名的 Shape Key;时间轴上对应 Action 已含关键帧曲线。
步骤 4:Python 脚本批量写出 JSON/CSV
切到 Scripting 选项卡,把下列脚本复制到编辑器并运行(请先选中含 Shape Key 的网格对象,修改输出路径即可):
import bpy, json, csv, os
# ========= 配置区域 =========
OUT_DIR = r"C:\temp" # 输出文件夹
CSV_NAME = "arkit52_curves.csv"
JSON_NAME = "arkit52_curves.json"
ARKIT_52 = [ # 官方顺序,可自行调整
"browDown_L","browDown_R","browInnerUp","browOuterUp_L","browOuterUp_R",
"cheekPuff","cheekSquint_L","cheekSquint_R","eyeBlink_L","eyeBlink_R",
"eyeLookDown_L","eyeLookDown_R","eyeLookIn_L","eyeLookIn_R","eyeLookOut_L",
"eyeLookOut_R","eyeLookUp_L","eyeLookUp_R","eyeSquint_L","eyeSquint_R",
"eyeWide_L","eyeWide_R","jawForward","jawLeft","jawOpen","jawRight",
"mouthClose","mouthDimple_L","mouthDimple_R","mouthFrown_L","mouthFrown_R",
"mouthFunnel","mouthLeft","mouthLowerDown_L","mouthLowerDown_R",
"mouthPress_L","mouthPress_R","mouthPucker","mouthRight",
"mouthRollLower","mouthRollUpper","mouthShrugLower","mouthShrugUpper",
"mouthSmile_L","mouthSmile_R","mouthStretch_L","mouthStretch_R",
"mouthUpperUp_L","mouthUpperUp_R","noseSneer_L","noseSneer_R",
"tongueOut"
]
# ========= 处理开始 =========
obj = bpy.context.object
action = obj.animation_data.action
csv_rows, json_dict = [], {}
for fcurve in action.fcurves:
# 仅保留 ShapeKey 动画
if not fcurve.data_path.startswith('key_blocks'):
continue
sk_name = fcurve.data_path.split('"')[1]
if sk_name not in ARKIT_52:
continue
for kp in fcurve.keyframe_points:
frame, value = int(kp.co.x), round(kp.co.y, 6)
csv_rows.append([sk_name, frame, value])
json_dict.setdefault(frame, {})[sk_name] = value
# 写 CSV
csv_path = os.path.join(OUT_DIR, CSV_NAME)
with open(csv_path, "w", newline="") as f:
csv.writer(f).writerows([["ShapeKey","Frame","Value"]] + csv_rows)
# 写 JSON(按帧聚合)
json_path = os.path.join(OUT_DIR, JSON_NAME)
with open(json_path, "w") as f:
json.dump(json_dict, f, indent=2)
print(f"已导出:\n{csv_path}\n{json_path}")
脚本要点
-
只遍历数据路径为
key_blocks["xxx"].value
的 F-Curve,即 Shape Key 曲线; -
过滤到 ARKit 52 列表里指定的名称;
-
同时生成
·arkit52_curves.csv
:三列(ShapeKey / Frame / Value)
·arkit52_curves.json
:按帧聚合,结构更贴近 iOS 原生输出23。
可选:直接用 iClone Python API 导出
如果想跳过 Blender,也可用 iClone/CC4 内置的 Python Console 把 Slider 值逐帧写到 JSON;思路与上面完全一致,只是调用 RLPy
API 读取 RAvatar.GetMorphComponent().GetValue(slider_name)
。官方并未给出现成脚本,需要自写或借助社区示例。
常见问题 & 提示
-
映射对不上? 先确认 Expression Editor 的 Profile 已切到 ARKit (52),否则会看到 Reallusion 自有命名。
-
缺少眼球/舌头权重? ARKit 将眼球视线、舌头吐出都做成 BlendShape,而 AccuFace 默认把眼球转动写成骨骼。若需要纯形变,可在 FBX 导出前勾选 Convert Skinned Expressions to Morphs,眼球、舌头动画会一起烘焙成 Shape Key1。
-
只要权重不要模型? FBX 导出后用 FBX SDK 解析
FbxAnimCurve
也可以;但相较 Blender/Python,可读性与开发成本更高23。
小结
1 ) 在 iClone/CC4 把 AccuFace 捕捉结果映射到 ARKit 52 滑杆;
2 ) 以 ARKit (52 BlendShapes) 预设导出 FBX;
3 ) Blender 导入并运行脚本,即可一键得到按帧记录的 ARKit 52 BlendShape 权重 JSON/CSV。
整个流程无需第三方付费插件,完全脱离 iOS 设备即可完成。
- CC4 and iC8 ARKit to other ARKit
- How to export arkit blendshapes weights - Audio2Face (closed) - NVIDIA Developer Forums
- https://github.com/ButzYung/SystemAnimatorOnline/issues/67
- https://github.com/elijah-atkins/ARKitBlendshapeHelper
- https://www.reddit.com/r/blender/comments/17glejw/how_to_export_a_model_from_blender_that_can_be/
- https://github.com/Gaphodil/vrm-52arkit-creation-scripts
- https://www.youtube.com/watch?v=LOIOU2v3N3w
- https://www.reddit.com/r/vtubertech/comments/v5ypbq/software_for_outputting_arkit_blendshapes_from_a/
- https://www.cgtrader.com/3d-models/character/child/cartoon-polar-bear-cub-arkit-blendshapes-rigged
- https://www.youtube.com/watch?v=U7Duzhqo_xQ
- https://www.reddit.com/r/vtubertech/comments/1973y7j/despite_creating_52_arkit_blendshape_for_iphone/
- https://www.youtube.com/watch?v=IUbqGNeq1yc
- Solving Blendshapes for ARKit – Filmic Worlds
- https://www.youtube.com/watch?v=w839CmVfL4g
- "Import USD Animation" from Claire adds prefixes to animation curves (A2F 2023.2.0) - Audio2Face (closed) - NVIDIA Developer Forums
- Saving and Loading Your Work
- https://blender.stackexchange.com/questions/224269/how-to-extract-animation-details-for-export
- https://support.rokoko.com/hc/en-us/articles/18877624744721-Rokoko-Studio-Export-options-and-file-formats
- https://stackoverflow.com/questions/45390112/model-options-for-arkit