Handkit 是做什么的?
手部动画本质是 JSON:一个姿态由关节角度和位置组成;一个片段是随时间变化的关键帧序列;核心引擎将这些转化为自然的运动(弹簧、手指级联、跟随动作、空闲动画),并由渲染引擎绘制。一切都是确定的:相同的片段产生完全相同的帧序列。
下方 HANDKIT 指 Handkit 文件夹(仓库根目录)。在它所在目录下执行命令。
**首次使用:**如果 Handkit 文件夹还不存在,请先设置(需要安装 git、Rust 和 FFmpeg;首次构建需要几分钟,建议在后台运行):
HANDKIT=${HANDKIT:-$HOME/.handkit}
[ -d "$HANDKIT" ] || git clone --depth 1 https://github.com/Ayushmaniar/3d-accurate-hands "$HANDKIT"
cd "$HANDKIT" && cargo build --release -p handkit-cli
(cd starters/fframes-clip && cargo build --release) # 仅当你需用 fframes 渲染视频时才需要
H=$HANDKIT/target/release/handkit # CLI(只需运行一次 cargo build --release)
P=$HANDKIT/starters/fframes-clip/target/release/fframes-clip # 视频播放器
A=$HANDKIT/assets # hand_R.glb, hand_L.glb(handkit mesh 写入后生成)
工作循环(请按顺序执行)
- 从库开始。
$H gestures列出约 50 个命名手势及其描述(如 fist、point、ok、thumbs_up、peace、spread_palm、pinch、heart_hands、camera_frame、handshake...)。在手上使用"from": "ok"可快速获取该手势的形状,这几乎是零成本的。只需为你需要的不同之处编写关节角度。 - 编写一个片段(最小化示例,30 fps):
每个关键帧默认继承前一个关键帧的状态:只写你需要改变的部分。{ "version": 1, "fps": 30, "camera": { "position": [0, 0.12, 0.6], "target": [0, 0.1, 0], "fov": 30 }, "look": { "style": "realistic", "skin": "medium" }, "keys": [ { "t": 0, "hands": { "right": { "from": "fist", "place": { "wrist": [0, 0, 0], "palm_facing": [0, 0, 1], "fingers_toward": [0, 1, 0] } } } }, { "t": 0.8, "hands": { "right": { "from": "spread_palm" } } }, { "t": 1.6, "ease": "snappy", "hands": { "right": { "from": "point" } } } ] }t表示姿态到达的时间;move表示移动持续的时间(0.12 表示快速动作);"pass": true使动作流经该关键帧而不停留。使用以下方式在画面中放置手部位置:"place": {"screen": [x, y], "depth": 0.5, "palm_facing": .., "fingers_toward": ..}(x, y 是画面比例,0,0 为左上角),并通过"elbow_screen": [1.1, 0.9]让手臂从画面边缘伸入。 - 检查:在渲染前运行
$H check clip.json(检查接触保持、手指交叉、速度、抖动、构图、肘部是否在画面内)。根据输出信息修复问题;它明确指出了存在问题的关键帧编号。 - 预览(小且快速):
$P --clip clip.json --assets $A strip -n 12生成 strip.png(查看它)。frame 2.5s生成一帧完整图像。 - 渲染:
$P --clip clip.json --assets $A render -o out.mp4(1920x1080,实际时长秒)。竖屏 1080x1920:使用相同的命令,但将 fframes-clip 替换为$HANDKIT/starters/fframes-clip/target-portrait/release/fframes-clip。背景:--background "#1d1f24",聚光灯:--spotlight 0.5,0.45,0.35,#3a3f48。
你还能做什么
- 接触求解:
"goals": [{"touch": ["right.thumb.tip", "right.index.tip"]}],然后运行$H solve pose.json将精确满足接触条件(若无法满足则退出码为 2)。瞄准:{"aim": "right.index", "at": [x,y,z]}。 - 视觉风格:顶层
"look"支持样式realistic | toon | spiderverse | arcane | clay,肤色light | medium | tan | brown | dark | #rrggbb,以及outline、motion_blur(子帧)。也可在播放器上指定:--look spiderverse,skin=brown。 - 前臂末端:骨骼止于肘部。当肘部可能露出时,使用
"look": {"arm": "fade"}或{"arm": {"sleeve": "#1e2a4a", "length": 0.08}}(卷起的袖子)。 - 将 UI 与手部同步:
$H track clip.json --site right.index.tip打印每帧中指定点在屏幕上的位置(帧比例坐标),例如用于让按钮响应点击。 - 多人:手部名称如
ana.right、ben.left(可使用任意名称);"people": {"ana": {"look": {"skin": "dark"}, "scale": 1}}(scale 0.75 表示儿童手部)。手部之间会相互推开而非穿透(设置"collide": false允许重叠)。 - 握手:接触目标
{"grip": ["ana.right", "ben.right"], "style": "handshake"};支持风格:handshake、interlaced、cupped、high_five、fist_bump、pinky。在连续关键帧中使用相同的 grip 会使双手一起移动,跟随手会延迟几帧跟随。 - 单人的双手:可通过
touch目标实现合掌、拍手或摆出取景框手势。
复现一个参考视频
首先研究它:ffmpeg -i ref.mp4 -vf fps=4,scale=480:-1 f%03d.png 并查看每一帧。为每个可见的事件设置一个关键帧;使用 screen 放置手部,用 elbow_screen 瞄准前臂;根据参考帧的时间调整关键帧时间。对比:运行 python $HANDKIT/tools/motion/compare.py ref.mp4 out.mp4 cmp(生成一个包含两者同时刻帧的对比图,以及一个并排的 MP4 视频)。
需要更多信息时
运行 $H explain(约定)、$H explain clips、$H explain looks、$H explain <参数>(例如 thumb.cmc_rot),或查看 $HANDKIT/docs/POSE_SPEC.md。只阅读你需要的部分。原始关节范围:手指 mcp_flex -30..95,pip_flex -5..110,dip_flex -10..85,mcp_abd 约 -15..25;手腕 wrist_flex -80..85,wrist_dev -35..35。
经验法则:先从库中选手势;关键帧要少、时间要准(真实手部移动约 0.2-0.6 秒并保持);渲染前先检查;看缩略图 strip 而非整个视频;保持文件小型化。