Спецификации связи iFacialMocap


iFacialMocap позволяет разработчикам сторонних инструментов получать данные лица по UDP или TCP/IP без использования ПК-программы.

Получение данных через UDP

Если отправить строку "iFacialMocap_sahuasouryya9218sauhuiayeta91555dy3719" с ПК на порт 49983 со стороны iOS, iFacialMocap вернет ответ по UDP на порт 49983 с частотой 60 FPS.

・ Пример на Python

from socket import *
DstIP = "192.168.1.7"
DstPort = 49983
DstAddr = (DstIP,DstPort)
udpClntSock = socket(AF_INET, SOCK_DGRAM)
data = "iFacialMocap_sahuasouryya9218sauhuiayeta91555dy3719"
data = data.encode('utf-8')
udpClntSock.sendto(data,DstAddr)

server = socket(AF_INET, SOCK_DGRAM)
server.bind(("", 49983))
server.settimeout(0.05)

while True:
    try:
        messages, address = server.recvfrom(8192)
        print(messages.decode('utf-8'))
    except:
        pass

・ Строка, отправляемая за один кадр, выглядит следующим образом.

mouthSmile_R-0(eyeLookOut_L-0)mouthUpperUp_L-11(eyeWide_R-0)mouthClose-8|mouthPucker-4|mouthRollLower-9|eyeBlink_R-7|eyeLookDown_L-1|?cheekSquint_R-11|eyeBlink_L-7|tongueOut-0|jawRight-0|eyeLookIn_R-9|cheekSquint_L-11|mouthDimple_L-10|mouthPress_L-4|eyeSquint_L-11|mouthRight-0|mouthShrugLower-0|eyeLookUp_R-0|eyeLookOut_R-0|mouthPress_R-5|cheekPuff-2|jawForward-1|1|mouthLowerDown_L-9|mouthFrown_L-6|mouthShrugUpper-26|browOuterUp_L-4|browInnerUp-20|mouthDimple_R-10|browDown_R-0|mouthUpperUp_R-10|mouthRollUpper-8|mouthFunnel-12|mouthStretch_R-21|mouthFrown_R-13|eyeLookDown_R-17|jawOpen-12|jawLeft-0|browDown_L-0|mouthSmile_L-0|noseSneer_R-18|mouthLowerDown_R-8|noseSneer_L-21|eyeWide_L-0|mouthStretch_L-21|browOuterUp_R-4|eyeLookIn_L-4|eyeSquint_R-11|eyeLookUp_L-0|mouthLeft-0|=head#-21.488958,-6.038993,-6.6019735,-0.030653415,-0.10287084,-0.6584072|rightEye#6.0297494,2.4403017,0.25649446|leftEye#6.034903,-1.6660284,-0.17520553|34903,-1.6660284,-0.17520553|

・ Строки, отправляемые за один кадр, выглядят следующим образом.

BlendShape Name-Parameter (0 ~ 100) | … | BlendShape Name-Parameter (0 ~ 100) | … | = head # Euler angles X (degree), Euler angles Y, Euler angles Z, Position values X, Position values Y, Position values Z | rightEye # Euler angles X, Euler angles Y, Euler angles Z | leftEye # Euler angles X, Euler angles Y, Euler angles Z |

Данные углов отправляются в градусах, а не в радианах.

Начиная с iOS ver. 1.1.8 добавлена внешняя команда для совместимости с Facemotion 3d.
Если добавить строку "|sendDataVersion=v2" как показано ниже, значения отправляемого параметра BlendShape будут разделяться символом "&".
iFacialMocap_sahuasouryya9218sauhuiayeta91555dy3719|sendDataVersion=v2

[Пример]
Обычный формат
mouthSmile_R-0
sendDataVersion = v2
mouthSmile_R & 0

Причина в том, что Facemotion 3d может отправлять отрицательное значение для blendShape.
Это сделано потому, что при использовании "-" как разделителя могла возникнуть коллизия.

Получение данных через TCP/IP

При UDP кадры могут теряться, поэтому существует также способ приёма через TCP/IP.
Если по UDP отправить строку "iFacialMocap_UDPTCP_sahuasouryya9218sauhuiayeta91555dy3719" на порт 49983 со стороны iOS, данные будут отправлены на порт 49986 со стороны ПК.

Отправляемая строка — это просто строка "___iFacialMocap" добавленная к строке, отправляемой при UDP.

- пример
BlendShape Name-Parameter (0 ~ 100) | BlendShape Name-Parameter (0 ~ 100) | … | = head # Euler angles X, Euler angles Y, Euler angles Z, moving values X, moving values Y, moving values Z | rightEye # Euler angles X, Euler angles Y, Euler angles Z | leftEye # Euler angles X, Euler angles Y, Euler angles Z | ___iFacialMocap

При получении с iOS на ПК по TCP/IP может приходить строка с разделенными кадрами, поэтому используйте "___iFacialMocap" в конце как разделитель.

Чтобы остановить отправку TCP/IP, отправьте строку "iFacialMocap_UDPTCPSTOP_sahuasouryya9218sauhuiayeta91555dy3719" на порт 49983.

・ Пример использования Python для приёма через TCP/IP

from socket import socket, AF_INET, SOCK_DGRAM, SOCK_STREAM

#UDP send
HOST = ''
PORT = 49983
ADDRESS = "192.168.1.7" #iOS address

s = socket(AF_INET, SOCK_DGRAM)
msg = "iFacialMocap_UDPTCP_sahuasouryya9218sauhuiayeta91555dy3719"
s.sendto(msg.encode(), (ADDRESS, PORT))

s.close()

#create tcp server
with socket(AF_INET, SOCK_STREAM) as tcp_server:
    tcp_server.bind(("192.168.1.5", 49986)) #192.168.1.5 is pc address
    tcp_server.listen(1)

    while True:
        conn, addr = tcp_server.accept()
        with conn:
            while True:
                data = conn.recv(10000)
                print(data.decode('utf-8'))

Начиная с iOS ver. 1.1.8 добавлена внешняя команда для совместимости с Facemotion 3d.
Если добавить строку "|sendDataVersion=v2" как показано ниже, значения отправляемого параметра BlendShape будут разделяться символом "&".
iFacialMocap_UDPTCP_sahuasouryya9218sauhuiayeta91555dy3719|sendDataVersion=v2

[Пример]
Обычный формат
mouthSmile_R-0
sendDataVersion = v2
mouthSmile_R & 0

Причина в том, что Facemotion 3d может отправлять отрицательное значение blend shape; использование "-" как разделителя могло вызвать коллизии.

Получение данных через Bluetooth

Если сетевое подключение по Wi‑Fi, например UDP или TCP/IP, не работает, можно использовать Bluetooth как альтернативу. См. следующий код на GitHub.

https://github.com/emoto-yasushi/iFacialMocap_Facemotion3d_Bluetooth

Получение записанных данных в iOS

Если отправить строку "iFacialMocap_bakeRecordedAnimation_start" на порт 49983 со стороны iOS по UDP, записанные данные будут отправлены на порт 49987 со стороны ПК по TCP/IP.

Отправляемая строка имеет формат [".....", ".....", "....."] ___iFacialMocap.
Часть [".....", ".....", "....."] имеет формат JSON и хранит те же строки, которые используются в UDP и TCP/IP.

Данные, записанные с 60 FPS, всегда сохраняются. (Даже если обработка в iOS падает до 30 FPS, запись выполняется с 60 FPS.)

Это не было первоначальным назначением iFacialMocap, но сторонние разработчики могут свободно использовать эту функцию. В будущем разработка постепенно сместится к приложению-преемнику, однако сам iFacialMocap не будет закрыт. Если вы используете эту функцию, учитывайте, что в будущем приложении-преемнике ее обработка может измениться.

Выполнение кнопки lookForward

Отправьте строку "iFacialMocap_lookForward" на порт iOS 49983.

Прямой стриминг в Unity

Следующие скрипты можно использовать, прикрепив их к игровым объектам.
Он может выполнять стриминг как с iFacialMocap, так и с Facemotion3d.
https://drive.google.com/file/d/10cnZRlglrHmZIv-ECT66eqNZNsiWhMtf/view?usp=sharing

Работает при указании имени объекта, как показано на следующем изображении.

Unity Inspector for the iFacialMocap streaming script

Этот скрипт предназначен для файлов FBX, а не VRM.
Если вы хотите использовать это с VRM, создайте свою версию или напишите мне по электронной почте.