(an issue suggested by Claude :-)
Bug
PoseBody.fps is documented and typed as float in pose_body.py, but several locations in the codebase cast it to int, silently losing precision for non-integer framerates like 29.97 fps (NTSC standard).
Affected locations
1. utils/openpose.py — load_openpose()
# load_openpose() accepts fps as float, but casts to int
body = NumPyPoseBody(fps=int(fps), data=masked_data, confidence=confidence)
The fps parameter is typed as float, but explicitly cast to int before constructing the body. A video at 29.97 fps becomes 29 fps.
2. tensorflow/pose_body.py — TFRecord serialization
# Record description defines fps as int64
'fps': tf.io.FixedLenFeature([], tf.int64, default_value=0),
# Serialization stores fps as int64
'fps': tf.train.Feature(int64_list=tf.train.Int64List(value=[self.fps])),
FPS is stored as int64 in TFRecords. On deserialization it's cast back to float32, but the fractional part is already lost.
3. utils/generic.py — fake_pose()
# Function signature types fps as int
def fake_pose(num_frames: int, fps: int=25, ...):
body = NumPyPoseBody(fps=int(fps), ...)
Minor (test utility), but reinforces the pattern.
Impact
Any video with a non-integer framerate (29.97, 23.976, 59.94 fps — all common standards) will have its framerate silently truncated. This causes audio/video sync drift and incorrect timing when the .pose file is used downstream.
Suggested fix
- Remove the
int() casts in load_openpose() and fake_pose(), pass fps through as-is
- Change the TFRecord field from
tf.int64 to tf.float32 (or serialize as bytes)
- Update
fake_pose() signature to fps: float = 25.0
(an issue suggested by Claude :-)
Bug
PoseBody.fpsis documented and typed asfloatinpose_body.py, but several locations in the codebase cast it toint, silently losing precision for non-integer framerates like 29.97 fps (NTSC standard).Affected locations
1.
utils/openpose.py—load_openpose()The
fpsparameter is typed asfloat, but explicitly cast tointbefore constructing the body. A video at 29.97 fps becomes 29 fps.2.
tensorflow/pose_body.py— TFRecord serializationFPS is stored as
int64in TFRecords. On deserialization it's cast back tofloat32, but the fractional part is already lost.3.
utils/generic.py—fake_pose()Minor (test utility), but reinforces the pattern.
Impact
Any video with a non-integer framerate (29.97, 23.976, 59.94 fps — all common standards) will have its framerate silently truncated. This causes audio/video sync drift and incorrect timing when the
.posefile is used downstream.Suggested fix
int()casts inload_openpose()andfake_pose(), passfpsthrough as-istf.int64totf.float32(or serialize as bytes)fake_pose()signature tofps: float = 25.0