Hello,
I'm using a CC3_Base_Plus character.
I managed to get the plugin, Omnivers_Audio2Face to load. But when I attempt to load the .json blendshape animation file, there are index out of range errors. I analyzed the json structure of the file, and there are the same number of frames as are in iClone project timeline (GOOD) and there are 69 blendshape channels/json keys. (GOOD). I exported as USDA, USD from the Omniverse export from iClone so I could validate that all the blendshapes in the USDA match those in the omni_output_facial_anim.json. And all is good, 69 blendshapes defined and 69 entries in the animation dictionary-- 69 per frame.
So, I used Copilot and ChatGpt to write a python debug script to analyse the data (see below).
The script below, prints out hundreds of frames worth of the 69 blendshape keys without error-- when loading in the .json from Audio2face.
When reading the actual Audio2Face plugin python code, i noticed a few "magic numbers" for ranges etc and am a bit concerned. The plugin seems to be broken on lines 105 and 157.
In the snippet below, I could not determine why 60 is used when I see 69 blendshape names in the USD and the .json. The 51, and the index calculation, [j+8] really threw me for a loop. It would be greatly appreciated if you could push an update or email a working version for iClone 7.93 to:
lnickers@gmail.com cc:
nickarthur.night@gmail.comHere's the most mystical of the code blocks:
for i in range(bs_frame_count):#(len(bs_animation)):
for j in range(60):#(bs_pose_count):
morph[j] = bs_animation[i][j+8]
for k in range(51):
custom[k] = bs_animation[i][k+68]
bone[7] = bs_animation[i][121] * 0.6 Index out of Range Error Line 105:
custom[k] = bs_animation[i][k+68]
Above, I don't see how we arrive at k+68 being valid or the index 121, but maybe it works in iClone 8??? Also, I'm using a CC3_BASE_PLUS Character that i shipped to iClone from Character Creator-- hope that is OK.
The other code block that has an index out of range error is (line 157):
for i in range(bs_frame_count):
for j in range(60):
morph[j] = bs_anim[i][j+8] * expStren
for k in range(51):
custom[k] = bs_anim[i][k+68] * expStren
bone[7] = bs_anim[i][121] * 0.6 * openStren
time_i = RLPy.RTime.IndexedFrameTime(i+srt_frame, RLPy.RGlobal.GetFps())
face_component.AddExpressionKey( time_i, morph, bone, custom, 1 )
On This line:
custom[k] = bs_anim[i][k+68] * expStrenPlease help, fast, I've lost a few days on this. I took it as a time to learn a bit about the innards, but I have to generate some output.
import json
def open_file():
# Function to open a JSON file containing animation data and print the content for analysis
json_file_path = f"C:\\Users\\nickarthur\\Videos\\ARTIST_ANIM_VIDS\\Night_OVER_EGYPT\\AUDIO_2_FACE\\A2F_OUTPUT\\a2f_export_Nights_Over_Egypt_Facial_Animation_bsweight.json"
# Hardcoded path to the JSON file
with open(json_file_path, 'r') as animate_json_reader:
j_data = animate_json_reader.read()
json_animate = json.loads(j_data)
bs_animation = json_animate['weightMat']
bs_pose_count = json_animate['numPoses']
bs_frame_count = json_animate['numFrames']
bs_names = json_animate['facsNames']
print("bs_frame_count:", bs_frame_count)
print("bs_pose_count:", bs_pose_count)
print("bs_names:", bs_names)
try:
# Iterate over the loaded JSON data to analyze its structure
# for i in range(min(5, bs_frame_count)):
for i in range(bs_frame_count):
print(f"Frame {i}:")
for j in range(bs_pose_count):
try:
pose_name = bs_names[j] # Get the pose name
weights = bs_animation[i][j] # Get the weights for the current pose
print(f" Pose {j} ({pose_name}): Animation Data: {weights}")
except IndexError:
print(f" Error: Pose index {j} is out of range.")
except IndexError:
print(f"Error: Frame index {i} is out of range.")
# Optionally, you can print more details or analyze additional aspects of the loaded JSON data
open_file()