From da65028595c1d1c8cf9cf052c4a1ea04d3e13abc Mon Sep 17 00:00:00 2001
From: Andres Suarez <23503930+glicerico@users.noreply.github.com>
Date: Tue, 11 Mar 2025 01:19:32 -0600
Subject: [PATCH] Open source performances module
---
 modules/performances/.gitignore               |   2 +
 modules/performances/CMakeLists.txt           | 215 ++++++
 modules/performances/README.md                | 125 +++
 modules/performances/cfg/Generator.cfg        |  42 +
 modules/performances/cfg/Performances.cfg     |  29 +
 modules/performances/cfg/Rules.cfg            |  58 ++
 modules/performances/cfg/Wholeshow.cfg        |  27 +
 modules/performances/cfg/rules_schema.yaml    | 292 +++++++
 modules/performances/cfg/yaml_config.py       |  36 +
 .../performances/depends/performances.deps    |   1 +
 modules/performances/launch/sdk.launch        |  27 +
 modules/performances/msg/Event.msg            |   2 +
 modules/performances/package.xml              |  41 +
 modules/performances/package/common.sh        | 138 ++++
 modules/performances/package/package.sh       |  54 ++
 modules/performances/scripts/runner.py        | 730 ++++++++++++++++++
 .../scripts/speech_motion_controller.py       | 243 ++++++
 modules/performances/setup.py                 |  28 +
 .../performances/src/performances/__init__.py |   0
 .../performances/src/performances/config.yaml | 209 +++++
 .../performances/src/performances/nodes.py    | 599 ++++++++++++++
 .../src/performances/speech_motion.py         | 595 ++++++++++++++
 .../src/performances/weak_method.py           |  33 +
 modules/performances/srv/Current.srv          |   5 +
 modules/performances/srv/Load.srv             |   4 +
 modules/performances/srv/LoadPerformance.srv  |   3 +
 modules/performances/srv/Pause.srv            |   3 +
 modules/performances/srv/Resume.srv           |   3 +
 modules/performances/srv/Run.srv              |   3 +
 modules/performances/srv/RunByName.srv        |   3 +
 modules/performances/srv/SetProperties.srv    |   4 +
 modules/performances/srv/Stop.srv             |   3 +
 modules/performances/test/test_speech.py      |  84 ++
 modules/performances/version                  |   1 +
 34 files changed, 3642 insertions(+)
 create mode 100644 modules/performances/.gitignore
 create mode 100644 modules/performances/CMakeLists.txt
 create mode 100644 modules/performances/README.md
 create mode 100755 modules/performances/cfg/Generator.cfg
 create mode 100755 modules/performances/cfg/Performances.cfg
 create mode 100755 modules/performances/cfg/Rules.cfg
 create mode 100755 modules/performances/cfg/Wholeshow.cfg
 create mode 100755 modules/performances/cfg/rules_schema.yaml
 create mode 100644 modules/performances/cfg/yaml_config.py
 create mode 100644 modules/performances/depends/performances.deps
 create mode 100644 modules/performances/launch/sdk.launch
 create mode 100644 modules/performances/msg/Event.msg
 create mode 100644 modules/performances/package.xml
 create mode 100644 modules/performances/package/common.sh
 create mode 100755 modules/performances/package/package.sh
 create mode 100755 modules/performances/scripts/runner.py
 create mode 100755 modules/performances/scripts/speech_motion_controller.py
 create mode 100644 modules/performances/setup.py
 create mode 100644 modules/performances/src/performances/__init__.py
 create mode 100644 modules/performances/src/performances/config.yaml
 create mode 100644 modules/performances/src/performances/nodes.py
 create mode 100644 modules/performances/src/performances/speech_motion.py
 create mode 100644 modules/performances/src/performances/weak_method.py
 create mode 100644 modules/performances/srv/Current.srv
 create mode 100644 modules/performances/srv/Load.srv
 create mode 100644 modules/performances/srv/LoadPerformance.srv
 create mode 100644 modules/performances/srv/Pause.srv
 create mode 100644 modules/performances/srv/Resume.srv
 create mode 100644 modules/performances/srv/Run.srv
 create mode 100644 modules/performances/srv/RunByName.srv
 create mode 100644 modules/performances/srv/SetProperties.srv
 create mode 100644 modules/performances/srv/Stop.srv
 create mode 100755 modules/performances/test/test_speech.py
 create mode 100644 modules/performances/version
diff --git a/modules/performances/.gitignore b/modules/performances/.gitignore
new file mode 100644
index 0000000..2a45ed7
--- /dev/null
+++ b/modules/performances/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+.vscode
diff --git a/modules/performances/CMakeLists.txt b/modules/performances/CMakeLists.txt
new file mode 100644
index 0000000..f0b2818
--- /dev/null
+++ b/modules/performances/CMakeLists.txt
@@ -0,0 +1,215 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+cmake_minimum_required(VERSION 2.8.3)
+project(performances)
+
+## Find catkin macros and libraries
+## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
+## is used, also find other catkin packages
+find_package(catkin REQUIRED COMPONENTS
+  rospy
+  std_msgs
+  message_generation
+  dynamic_reconfigure
+)
+
+## System dependencies are found with CMake's conventions
+# find_package(Boost REQUIRED COMPONENTS system)
+
+
+## Uncomment this if the package has a setup.py. This macro ensures
+## modules and global scripts declared therein get installed
+## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
+catkin_python_setup()
+
+################################################
+## Declare ROS messages, services and actions ##
+################################################
+
+## To declare and build messages, services or actions from within this
+## package, follow these steps:
+## * Let MSG_DEP_SET be the set of packages whose message types you use in
+##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
+## * In the file package.xml:
+##   * add a build_depend tag for "message_generation"
+##   * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
+##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
+##     but can be declared for certainty nonetheless:
+##     * add a run_depend tag for "message_runtime"
+## * In this file (CMakeLists.txt):
+##   * add "message_generation" and every package in MSG_DEP_SET to
+##     find_package(catkin REQUIRED COMPONENTS ...)
+##   * add "message_runtime" and every package in MSG_DEP_SET to
+##     catkin_package(CATKIN_DEPENDS ...)
+##   * uncomment the add_*_files sections below as needed
+##     and list every .msg/.srv/.action file to be processed
+##   * uncomment the generate_messages entry below
+##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
+
+## Generate messages in the 'msg' folder
+add_message_files(
+  FILES
+  Event.msg
+)
+
+## Generate services in the 'srv' folder
+add_service_files(
+  FILES
+  Run.srv
+  RunByName.srv
+  Stop.srv
+  Pause.srv
+  Resume.srv
+  Current.srv
+  Load.srv
+  LoadPerformance.srv
+  SetProperties.srv
+)
+
+## Generate actions in the 'action' folder
+# add_action_files(
+#   FILES
+#   Action1.action
+#   Action2.action
+# )
+
+## Generate added messages and services with any dependencies listed here
+generate_messages(
+  DEPENDENCIES
+  std_msgs
+)
+
+################################################
+## Declare ROS dynamic reconfigure parameters ##
+################################################
+
+## To declare and build dynamic reconfigure parameters within this
+## package, follow these steps:
+## * In the file package.xml:
+##   * add a build_depend and a run_depend tag for "dynamic_reconfigure"
+## * In this file (CMakeLists.txt):
+##   * add "dynamic_reconfigure" to
+##     find_package(catkin REQUIRED COMPONENTS ...)
+##   * uncomment the "generate_dynamic_reconfigure_options" section below
+##     and list every .cfg file to be processed
+
+## Generate dynamic reconfigure parameters in the 'cfg' folder
+generate_dynamic_reconfigure_options(
+  cfg/Performances.cfg
+  cfg/Rules.cfg
+  cfg/Generator.cfg
+
+)
+
+###################################
+## catkin specific configuration ##
+###################################
+## The catkin_package macro generates cmake config files for your package
+## Declare things to be passed to dependent projects
+## INCLUDE_DIRS: uncomment this if you package contains header files
+## LIBRARIES: libraries you create in this project that dependent projects also need
+## CATKIN_DEPENDS: catkin_packages dependent projects also need
+## DEPENDS: system dependencies of this project that dependent projects also need
+catkin_package(
+#  INCLUDE_DIRS include
+#  LIBRARIES performances
+#  CATKIN_DEPENDS rospy std_msgs
+#  DEPENDS system_lib
+)
+
+###########
+## Build ##
+###########
+
+## Specify additional locations of header files
+## Your package locations should be listed before other locations
+# include_directories(include)
+include_directories(
+  ${catkin_INCLUDE_DIRS}
+)
+
+## Declare a C++ library
+# add_library(performances
+#   src/${PROJECT_NAME}/performances.cpp
+# )
+
+## Add cmake target dependencies of the library
+## as an example, code may need to be generated before libraries
+## either from message generation or dynamic reconfigure
+# add_dependencies(performances ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Declare a C++ executable
+# add_executable(performances_node src/performances_node.cpp)
+
+## Add cmake target dependencies of the executable
+## same as for the library above
+# add_dependencies(performances_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
+
+## Specify libraries to link a library or executable target against
+# target_link_libraries(performances_node
+#   ${catkin_LIBRARIES}
+# )
+
+#############
+## Install ##
+#############
+
+# all install targets should use catkin DESTINATION variables
+# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
+
+## Mark executable scripts (Python etc.) for installation
+## in contrast to setup.py, you can choose the destination
+install(PROGRAMS
+  scripts/runner.py
+  scripts/speech_motion_controller.py
+  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+)
+
+## Mark executables and/or libraries for installation
+# install(TARGETS performances performances_node
+#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+# )
+
+## Mark cpp header files for installation
+# install(DIRECTORY include/${PROJECT_NAME}/
+#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
+#   FILES_MATCHING PATTERN "*.h"
+#   PATTERN ".svn" EXCLUDE
+# )
+
+## Mark other files for installation (e.g. launch and bag files, etc.)
+# install(FILES
+#   # myfile1
+#   # myfile2
+#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
+# )
+
+#############
+## Testing ##
+#############
+
+## Add gtest based cpp test target and link libraries
+# catkin_add_gtest(${PROJECT_NAME}-test test/test_performances.cpp)
+# if(TARGET ${PROJECT_NAME}-test)
+#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
+# endif()
+
+## Add folders to be run by python nosetests
+# catkin_add_nosetests(test)
diff --git a/modules/performances/README.md b/modules/performances/README.md
new file mode 100644
index 0000000..b72a1f0
--- /dev/null
+++ b/modules/performances/README.md
@@ -0,0 +1,125 @@
+# Performances
+
+A ROS-based system for controlling robot behaviors, animations, and speech for Hanson Robotics robots. This package provides a framework for sequencing and executing robot performances through a combination of speech, gestures, animations, and interactive behaviors.
+
+The Performances package allows you to:
+- Load and run predefined performance sequences
+- Control robot animations, gestures, and speech
+- Manage interactive behaviors through dialog rules
+- Coordinate multiple performance timelines
+- Configure automated gestures and expressions
+
+## Available Services:
+
+#### `/performances/reload_properties`
+`std_srvs.srv.Trigger`
+Reads and loads performance configurations from .properties files.
+##### Response
+* `boolean success`
+
+#### `/performances/set_properties`
+`performances.srv.SetProperties`
+Sets variables for a specific performance.
+
+##### Arguments
+* `string id` - performance id
+* `string properties` - a json string of an object containing key value pairs of variables to be set
+
+##### Response
+* `boolean success`
+
+#### `/performances/load`
+`performances.srv.Load`
+Loads performance with the specified id into current session.
+
+##### Arguments
+* `id` - performance id
+
+##### Response
+* `boolean success`
+* `string performance` - json data string of a loaded performance
+
+#### `/performances/load_sequence`
+`performances.srv.LoadSequence`
+Loads a sequence of performances.
+
+##### Arguments
+* `string[] ids` - ids of performances to load
+
+##### Response
+* `boolean success`
+* `string performances` - json data string of loaded performances
+
+#### `/performances/load_performance`
+`performances.srv.LoadPerformance`
+Load performance data directly.
+
+##### Arguments
+* `string performance` - json data of a performance to load
+
+##### Response
+* `boolean success`
+
+#### `/performances/run`
+`performances.srv.Run`
+Run currently loaded performance(s) at the given time.
+
+##### Arguments
+* `float64 startTime` - start time
+
+##### Response
+* `boolean success`
+
+#### `/performances/run_by_name`
+`performances.srv.RunByName`
+Load performance by id and run immediately.
+
+##### Arguments
+* `string id` - performance id
+
+##### Response
+* `boolean success`
+
+#### `/performances/run_full_performance`
+`performances.srv.RunByName`
+Load all performances in the specified directory and run immediately.
+
+##### Arguments
+* `string id` - path of the directory
+
+##### Response
+* `boolean success`
+
+#### `/performances/resume`
+`performances.srv.Resume`
+Resume runner if paused.
+
+##### Response
+* `boolean success`
+* `float64 time`
+	
+#### `/performances/pause`
+`performances.srv.Pause`
+Pause runner if currently running.
+
+##### Response
+* `boolean success`
+* `float64 time`
+	
+#### `/performances/stop`
+`performances.srv.Stop`
+Stop runner if active.
+
+##### Response
+* `boolean success`
+* `float64 time`
+	
+#### `/performances/current`
+`performances.srv.Current`
+Get information about the current state of runner.
+
+##### Response
+`string performances` - json array of currently loaded performances
+`float32 current_time` - current run time
+`bool running` - run status
+`bool paused` - pause status
diff --git a/modules/performances/cfg/Generator.cfg b/modules/performances/cfg/Generator.cfg
new file mode 100755
index 0000000..f39c9fb
--- /dev/null
+++ b/modules/performances/cfg/Generator.cfg
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+PACKAGE = 'performances'
+
+from dynamic_reconfigure.parameter_generator_catkin import *
+import yaml_config
+
+gen = ParameterGenerator()
+# Tracking parameters
+gen.add("name", str_t, 0, "Performance path", '')
+gen.add("lines", str_t, 0, "Sophia lines", '')
+gen.add("pause_between_sentences", double_t, 0, "Pause between sentences", 0.5, 0, 4)
+#gen.add("other_rules", str_t, 0, "other_rules", '[]')
+# UI schema for gestures and expressions
+gen.add("min_speed", int_t, 0, "Min speed of speech ", 100,50,150)
+gen.add("max_speed", int_t, 0, "Max speed of speech ", 100,50,150)
+gen.add("split_sentences", bool_t, 0, "Do not split to sentences", True)
+
+gen.add("lang", str_t, 0, "Language code (en-US or similar that supported by TTS)", 'en-US')
+
+gen.add("start", bool_t, 0, "Start Generation", True)
+gen.add("progress", str_t, 0, "Current Progress", 'idle')
+gen.add("node_schema", str_t, 0, '', '{"lines":{"type": "string","format": "textarea"}}')
+# package name, node name, config name
+exit(gen.generate(PACKAGE, "generator", "Generator"))
diff --git a/modules/performances/cfg/Performances.cfg b/modules/performances/cfg/Performances.cfg
new file mode 100755
index 0000000..ec3643e
--- /dev/null
+++ b/modules/performances/cfg/Performances.cfg
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+PACKAGE = 'performances'
+
+from dynamic_reconfigure.parameter_generator_catkin import *
+
+gen = ParameterGenerator()
+
+gen.add("autopause", bool_t, 0, "Enable autopause", True)
+
+# package name, node name, config name
+exit(gen.generate(PACKAGE, "performances", "Performances"))
diff --git a/modules/performances/cfg/Rules.cfg b/modules/performances/cfg/Rules.cfg
new file mode 100755
index 0000000..4f61961
--- /dev/null
+++ b/modules/performances/cfg/Rules.cfg
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+PACKAGE = 'performances'
+
+from dynamic_reconfigure.parameter_generator_catkin import *
+import yaml_config
+
+gen = ParameterGenerator()
+# Tracking parameters
+gen.add("interactive", bool_t, 0, "Only in interactive mode", True)
+gen.add("enable", bool_t, 0, "Enable keyword rules", True)
+gen.add("automated_arm_gestures", bool_t, 0, "Automated arm gestures", False)
+gen.add("automated_shoulder_gestures", bool_t, 0, "Automated shoulder gestures", False)
+gen.add("min_arms_hold_time", double_t, 0, "Min hold time for arm animations", 3,0,6)
+gen.add("max_arms_hold_time", double_t, 0, "Max hold time for arm animations", 5,0,6)
+gen.add("global_probability", double_t, 0, "Adjust all probabilities (-1 no rules applied, 1 all rules, 0 Unchanged)", 0,-1,1)
+# Add more positive gestures
+gen.add("generic_gestures", bool_t, 0, "Generic gestures", False)
+gen.add("generic_gestures_categories_excluded", str_t, 0, "Do not use these categories as generic gestures","")
+gen.add("generic_gestures_probability", double_t, 0, "Probability for each word to get gestures",0.1,0.01,1.0)
+gen.add("generic_gestures_head_filter", double_t, 0, "Generic head movement animation filter",0.9,0.0,1.0)
+gen.add("generic_gestures_brow_filter", double_t, 0, "Generic brow movement animation filter",0.6,0.0,1.0)
+gen.add("generic_gestures_eyelids_filter", double_t, 0, "Generic eyelids movement animation filter",0.3,0.0,1.0)
+gen.add("generic_gestures_eyes_filter", double_t, 0, "Generic eyes movement animation filter",0.3,0.0,1.0)
+gen.add("generic_gestures_arms_filter", double_t, 0, "Generic arms movement animation filter",0.9,0.0,1.0)
+gen.add("generic_gestures_happy_filter", double_t, 0, "Add some happy animations (0- none, 1 - every 2 words)",0.5,0.0,1.0)
+# Filters animations (can remove the head)
+gen.add("rules_head_filter", double_t, 0, "Head movement filter",1.0,0.0,1.0)
+gen.add("rules_brow_filter", double_t, 0, "Brow movement filter",1.0,0.0,1.0)
+gen.add("rules_eyelids_filter", double_t, 0, "Eyelid movement filter",1.0,0.0,1.0)
+gen.add("rules_eyes_filter", double_t, 0, "Eyes movement filter",1.0,0.0,1.0)
+gen.add("reduce_negativity", double_t, 0, "Reduce negativite categories of animations", 0.0, 0.0, 1.0)
+gen.add("negative_gesture_categories", str_t, 0, "Remove brows down, head shakes", "shake-short, shake-long, shake-firmly, brows-down, brows-doubt") 
+
+#gen.add("other_rules", str_t, 0, "other_rules", '[]')
+# UI schema for gestures and expressions
+gen.add("da_rules", str_t, 0, "Dialog Act Rules", '[]')
+gen.add("keyword_rules", str_t, 0, "Keyword based Rules", '[]')
+gen.add("node_schema", str_t, 0, '', yaml_config.parse('rules_schema') or '{}')
+# package name, node name, config name
+exit(gen.generate(PACKAGE, "rules", "Rules"))
diff --git a/modules/performances/cfg/Wholeshow.cfg b/modules/performances/cfg/Wholeshow.cfg
new file mode 100755
index 0000000..be13e0a
--- /dev/null
+++ b/modules/performances/cfg/Wholeshow.cfg
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+PACKAGE = 'wholeshow'
+
+from dynamic_reconfigure.parameter_generator_catkin import *
+
+gen = ParameterGenerator()
+gen.add("chat_during_performance", bool_t, 0, "Chat while running performances", False)
+gen.add("filter_stt", bool_t, 0, "Filter STT", True)
+exit(gen.generate(PACKAGE, "wholeshow", "Wholeshow"))
diff --git a/modules/performances/cfg/rules_schema.yaml b/modules/performances/cfg/rules_schema.yaml
new file mode 100755
index 0000000..ab0edbc
--- /dev/null
+++ b/modules/performances/cfg/rules_schema.yaml
@@ -0,0 +1,292 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+keyword_rules_ui:
+  type: array
+  format: table
+  items:
+    type: object
+    properties:
+      keywords:
+        title: 'Keywords'
+        propertyOrder: 1
+        type: string
+      priority:
+        title: 'Priority'
+        propertyOrder: 2
+        type: number
+        default: 50
+      probability:
+        title: 'Probability'
+        propertyOrder: 3
+        type: number
+        default: 0.5
+      headAA:
+        title: 'head AA'
+        propertyOrder: 4
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "nod-short"
+          - "head-shake"
+          - "look-up"
+          - "look-away"
+          - "head-tilt"
+      browAA:
+        title: 'Brow AA'
+        propertyOrder: 5
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "brows-up"
+          - "brows-down"
+          - "brow-center-up"
+      eyesAA:
+        title: 'Eyes AA'
+        propertyOrder: 6
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "eyes-away"
+          - "eyes-up"
+      armsAA:
+        title: 'Arms AA'
+        propertyOrder: 7
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "arm_unsure"
+          - "arm_beat"
+          - "arm_me"
+          - "arm_you"
+          - "arm_many"
+          - "arm_vawe"
+          - "arm_point"
+          - "arm_greeting"
+          - "arm_heart"
+          - "arm_frame_small"
+          - "arm_frame_big"
+          - "arm_compare_smaller"
+          - "arm_compare_bigger"
+          - "arm_contrast"
+          - "arm_offer"
+          - "arm_process"
+          - "arm_reject"
+da_rules:
+  type: array
+  format: table
+  items:
+    type: object
+    properties:
+      act:
+        title: 'Dialog Act'
+        propertyOrder: 1
+        type: string
+        default: "-"
+        enum:
+          - "STATEMENT_NON_OPINION"
+          - "ACKNOWLEDGE"
+          - "STATEMENT_OPINION"
+          - "AGREE"
+          - "ABANDONED"
+          - "APPRECIATION"
+          - "YES_NO_QUESTION"
+          - "NON_VERBAL"
+          - "YES_ANSWER"
+          - "CONVENTIONAL_CLOSING"
+          - "UNINTERPRETABLE"
+          - "WH_QUESTION"
+          - "NO_ANSWER"
+          - "RESPONSE_ACKNOWLEDGEMENT"
+          - "HEDGE"
+          - "DECLARATIVE_YES_NO_QUESTION"
+          - "OTHER"
+          - "BLACKCHANNEL_IN_QUESTION_FORM"
+          - "QUOTATION"
+          - "SUMMARIZE"
+          - "AFFIRMATIVE_NON_YES_ANSWER"
+          - "ACTION_DIRECTIVE"
+          - "COLLABORATIVE_COMPLETION"
+          - "REPEAT_PHRASE"
+          - "OPEN_QUESTION"
+          - "RHETORICAL_QUESTIONS"
+          - "HOLD_BEFORE_ANSWER"
+          - "REJECT"
+          - "NEGATIVE_NON_NO_ANSWER"
+          - "SIGNAL_NON_UNDERSTANDING"
+          - "OTHER_ANSWER"
+          - "CONVENTIONAL_OPENING"
+          - "OR_CLAUSE"
+          - "DISPREFERRED_ANSWER"
+          - "THIRD_PARTY_TALK"
+          - "OFFER"
+          - "SELF_TALK"
+          - "DOWNPLAYER"
+          - "MAYBE"
+          - "TAG_QUESTION"
+          - "DECLARATIVE_WH_QUESTION"
+          - "APOLOGY"
+          - "THANKING"
+      threshold:
+        title: 'Threshold'
+        propertyOrder: 2
+        type: number
+        default: 0.5
+      priority:
+        title: 'Priority'
+        propertyOrder: 3
+        type: number
+        default: 50
+      probability:
+        title: 'Probability'
+        propertyOrder: 4
+        type: number
+        default: 0.5
+      headAA:
+        title: 'head AA'
+        propertyOrder: 5
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "head-up"
+          - "head-down"
+          - "head-down"
+          - "head-left"
+          - "head-right"
+          - "head-tilt"
+          - "head-tilt-long"
+          - "nod-short"
+          - "nod-long"
+          - "nod-heavy"
+          - "shake-short"
+          - "shake-long"
+          - "shake-firmly"
+          - "shake-heavy"
+          - "wobbling"
+      browAA:
+        title: 'Brow AA'
+        propertyOrder: 6
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "brow-up-short"
+          - "brow-up-normal"
+          - "brow-up-long"
+          - "brow-up-normal"
+          - "brow-up-long"
+          - "brow-center-up"
+          - "brow-center-up-long"
+          - "brow-down-short"
+          - "brow-down-normal"
+          - "brow-down-long"
+          - "brow-doubt"
+          - "brow-doubt-long"
+      eyelidsAA:
+        title: 'EyeLids AA'
+        propertyOrder: 7
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "eyelid-half-close"
+          - "eyelid-widely-open"
+      eyesAA:
+        title: 'Eyes AA'
+        propertyOrder: 7
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "eye-left"
+          - "eye-right"
+          - "eye-up"
+          - "eye-down"
+          - "eye-around"
+          - "eye-corner"
+          - "eye-side"
+      armsAA:
+        title: 'Arms AA'
+        propertyOrder: 8
+        type: string
+        default: "-"
+        enum:
+          - "-"
+          - "arm-unsure"
+          - "arm-enjoy"
+          - "arm-beat"
+          - "arm-me"
+          - "arm-you"
+          - "arm-many"
+          - "arm-vawe"
+          - "arm-point"
+          - "arm-greeting"
+          - "arm-call"
+          - "arm-heart"
+          - "arm-frame-small"
+          - "arm-frame-big"
+          - "arm-compare-smaller"
+          - "arm-compare-bigger"
+          - "arm-contrast"
+          - "arm-offer"
+          - "arm-process-control"
+          - "arm-rejection"
+          - "arm-rolling"
+          - "arm-notkown"
+          - "arm-peace"
+          - "arm-stop"
+          - "arm-round"
+          - "arm-different"
+      apply:
+        title: "Which word of sentence to select"
+        type: string
+        propertyOrder: 9
+        default: "random"
+        enum:
+          - "random"
+          - "first"
+          - "last"
+other_rules:
+  type: array
+  format: table
+  items:
+    type: object
+    properties:
+      keywords:
+        title: 'Rule Desc'
+        propertyOrder: 1
+        type: string
+        default: "-"
+        enum:
+          - "Stress words based on impoortance"
+          - "Keep alive animations"
+          - "Emphasize question ending"
+      priority:
+        title: 'Priority'
+        propertyOrder: 2
+        type: number
+        default: 50
+      probability:
+        title: 'Probability'
+        propertyOrder: 3
+        type: number
+        default: 0.5
\ No newline at end of file
diff --git a/modules/performances/cfg/yaml_config.py b/modules/performances/cfg/yaml_config.py
new file mode 100644
index 0000000..a8d41c1
--- /dev/null
+++ b/modules/performances/cfg/yaml_config.py
@@ -0,0 +1,36 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+import yaml
+import json
+import os
+
+current_dir = os.path.dirname(os.path.realpath(__file__))
+
+def parse(filename):
+    with open(os.path.join(current_dir, filename + '.yaml'), 'r') as stream:
+        try:
+            return json.dumps(yaml.safe_load(stream))
+        except yaml.YAMLError as exc:
+            return False
+
+def load(filename):
+    with open(os.path.join(current_dir, filename + '.yaml'), 'r') as stream:
+        try:
+            return yaml.safe_load(stream)
+        except yaml.YAMLError as exc:
+            return False
diff --git a/modules/performances/depends/performances.deps b/modules/performances/depends/performances.deps
new file mode 100644
index 0000000..63e00ef
--- /dev/null
+++ b/modules/performances/depends/performances.deps
@@ -0,0 +1 @@
+debian:head-hr-msgs>=0.2.2
diff --git a/modules/performances/launch/sdk.launch b/modules/performances/launch/sdk.launch
new file mode 100644
index 0000000..87ce53d
--- /dev/null
+++ b/modules/performances/launch/sdk.launch
@@ -0,0 +1,27 @@
+
+
+
+    
+
+    
+        
+            
+        
+    
+
+
diff --git a/modules/performances/msg/Event.msg b/modules/performances/msg/Event.msg
new file mode 100644
index 0000000..682c6e0
--- /dev/null
+++ b/modules/performances/msg/Event.msg
@@ -0,0 +1,2 @@
+string event
+float64 time
diff --git a/modules/performances/package.xml b/modules/performances/package.xml
new file mode 100644
index 0000000..b2dea06
--- /dev/null
+++ b/modules/performances/package.xml
@@ -0,0 +1,41 @@
+
+
+
+  performances
+  0.3.11
+  The performances package.
+  GPLv3
+  Wenwei Huang
+  Vytas Krisciunas
+  Wenwei Huang
+  Vytas Krisciunas
+
+  catkin
+  rospy
+  std_msgs
+  dynamic_reconfigure
+  rospy
+  std_msgs
+
+
+  
+  
+    
+
+  
+
diff --git a/modules/performances/package/common.sh b/modules/performances/package/common.sh
new file mode 100644
index 0000000..3bc738d
--- /dev/null
+++ b/modules/performances/package/common.sh
@@ -0,0 +1,138 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+env() {
+    export HR_PREFIX=/opt/hansonrobotics
+    export HR_BIN_PREFIX=$HR_PREFIX/bin
+    export HRTOOL_PREFIX=${HR_PREFIX}/hrtool
+    export HR_ROS_PREFIX=${HR_PREFIX}/ros
+    export HR_TOOLS_PREFIX=$HR_PREFIX/tools
+    export HR_DATA_PREFIX=$HR_PREFIX/data
+    export VOICE_CACHE_DIR=$HOME/.hr/tts/voice
+    export URL_PREFIX=https://github.com/hansonrobotics
+    export GITHUB_STORAGE_URL=https://raw.githubusercontent.com/hansonrobotics/binary_dependency/master
+    export GITHUB_STORAGE_URL2=https://$GITHUB_TOKEN@raw.githubusercontent.com/hansonrobotics/binary_dependency2/master
+    export VENDOR="Hanson Robotics"
+    export PYTHON_PKG_PREFIX=$HR_PREFIX/py2env/lib/python2.7/dist-packages
+    export PYTHON3_PKG_PREFIX=$HR_PREFIX/py3env/lib/python3.6/dist-packages
+    export ROS_PYTHON_PKG_PREFIX=$HR_ROS_PREFIX/lib/python2.7/dist-packages
+}
+
+install_deps() {
+    if ! hash gem >/dev/null 2>&1; then
+        echo "Installing ruby-full"
+        sudo apt-get install ruby-full
+    fi
+
+    if ! hash fpm >/dev/null 2>&1; then
+        gem install fpm
+        gem install deb-s3
+    fi
+
+    if ! hash chrpath >/dev/null 2>&1; then
+        echo "Installing chrpath"
+        sudo apt-get install chrpath
+    fi
+
+    if ! hash autoconf >/dev/null 2>&1; then
+        echo "Installing autoconf"
+        sudo apt-get install autoconf
+    fi
+
+    if ! hash jq >/dev/null 2>&1; then
+        echo "Installing jq"
+        sudo apt-get install jq
+    fi
+
+    if [[ ! -f /usr/local/go/bin/go ]]; then
+        echo "Installing go"
+        wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz -O /tmp/go1.14.2.linux-amd64.tar.gz
+        sudo tar -C /usr/local -xzf /tmp/go1.14.2.linux-amd64.tar.gz
+    fi
+
+    export PATH=/usr/local/go/bin:$PATH
+}
+
+COLOR_INFO='\033[32m'
+COLOR_WARN='\033[33m'
+COLOR_ERROR='\033[31m'
+COLOR_RESET='\033[0m'
+info() {
+    printf "${COLOR_INFO}[INFO] ${1}${COLOR_RESET}\n" >&2
+}
+warn() {
+    printf "${COLOR_WARN}[WARN] ${1}${COLOR_RESET}\n" >&2
+}
+error() {
+    printf "${COLOR_ERROR}[ERROR] ${1}${COLOR_RESET}\n" >&2
+}
+
+source_ros() {
+    local ros_dists=(noetic melodic kinetic indigo)
+    for ros_dist in ${ros_dists[@]}; do
+        if [[ -e /opt/ros/$ros_dist/setup.bash ]]; then
+            info "ROS distribution $ros_dist"
+            source /opt/ros/$ros_dist/setup.bash
+            return
+        fi
+    done
+}
+
+add_control_scripts() {
+    local root_dir=${1:-${PACKAGE_DIR}/control}
+    local preinst="${root_dir}/preinst.sh"
+    local postinst="${root_dir}/postinst.sh"
+    local prerm="${root_dir}/prerm.sh"
+    local postrm="${root_dir}/postrm.sh"
+
+    local ms=""
+    [[ -f ${preinst} ]] && ms="$ms --before-install ${preinst}"
+    [[ -f ${postinst} ]] && ms="$ms --after-install ${postinst}"
+    [[ -f ${prerm} ]] && ms="$ms --before-remove ${prerm}"
+    [[ -f ${postrm} ]] && ms="$ms --after-remove ${postrm}"
+
+    if [[ -z $ms ]]; then
+        echo "Empty maintainer scripts"
+        return 1
+    fi
+    echo $ms
+}
+
+cleanup_ros_package_build() {
+    # clean up
+    pushd $1 >/dev/null
+    rm -r src build_isolated devel_isolated .catkin_workspace install
+    popd >/dev/null
+}
+
+get_version() {
+    local date=$(date +%Y%m%d%H%M%S)
+    local version_file=$BASEDIR/src/$reponame/version
+    local tag=$(git describe --tags --candidates=0)
+    if [[ -f $version_file ]]; then
+        version=$(head -n 1 $version_file)
+        # if 1 is present or the latest tag equals to version
+        if [[ $1 != 1 && ${tag#v} != $version ]]; then
+            version=${version}-${date}
+        fi
+    else
+        version=$date
+    fi
+}
+
+env
+install_deps
diff --git a/modules/performances/package/package.sh b/modules/performances/package/package.sh
new file mode 100755
index 0000000..7635a45
--- /dev/null
+++ b/modules/performances/package/package.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+package() {
+    local reponame=performances
+
+    mkdir -p $BASEDIR/src
+    rsync -r --delete \
+        --exclude ".git" \
+        --exclude "package" \
+        $BASEDIR/../ $BASEDIR/src/$reponame
+
+    get_version $1
+    source_ros
+    catkin_make_isolated --directory $BASEDIR --install --install-space $BASEDIR/install -DCMAKE_BUILD_TYPE=Release
+
+    local name=head-performances
+    local desc="Robot performances API"
+    local url="https://api.github.com/repos/hansonrobotics/$reponame/releases"
+
+    fpm -C "${BASEDIR}" -s dir -t deb -n "${name}" -v "${version#v}" --vendor "${VENDOR}" \
+        --url "${url}" --description "${desc}" ${ms} --force \
+        --deb-no-default-config-files \
+        -p $BASEDIR/${name}_VERSION_ARCH.deb \
+        install/include=${HR_ROS_PREFIX}/ \
+        install/share=${HR_ROS_PREFIX}/ \
+        install/lib=${HR_ROS_PREFIX}/
+
+    cleanup_ros_package_build $BASEDIR
+}
+
+if [[ $(readlink -f ${BASH_SOURCE[0]}) == $(readlink -f $0) ]]; then
+    BASEDIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
+    source $BASEDIR/common.sh
+    set -e
+
+    package $1
+fi
diff --git a/modules/performances/scripts/runner.py b/modules/performances/scripts/runner.py
new file mode 100755
index 0000000..f253183
--- /dev/null
+++ b/modules/performances/scripts/runner.py
@@ -0,0 +1,730 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+from threading import Thread, Lock, Condition
+import logging
+import json
+import time
+import yaml
+import os
+import fnmatch
+import random
+import copy
+
+try:
+    from pathlib import Path
+except:
+    # python2.7
+    from pathlib2 import Path
+
+import rospy
+import hr_msgs.srv as srv
+from dynamic_reconfigure.server import Server
+from hr_msgs.msg import ChatMessage
+from hr_msgs.msg import Event
+from hr_msgs.msg import MakeFaceExpr, PlayAnimation
+from hr_msgs.msg import SetAnimation, SetExpression, Target, SomaState
+from hr_msgs.msg import TTS
+from natsort import natsorted, ns
+from performances.cfg import PerformancesConfig
+from performances.nodes import Node
+from performances.weak_method import WeakMethod
+from std_msgs.msg import String, Int32, Float32
+from std_srvs.srv import Trigger, TriggerResponse
+from topic_tools.srv import MuxSelect
+
+logger = logging.getLogger('hr.performances')
+
+
+class Runner:
+    def __init__(self, ros, namespace = '~', background = False):
+        self.performances_dir = os.path.join(os.environ.get('PERFORMANCES_DIR', '/home/hr/workspace/hrsdk_configs/performances'))
+        self.robot_name = rospy.get_param('/hr/robot_name')
+        self.running = False
+        self.paused = False
+        self.autopause = False
+        self.pause_time = 0
+        self.start_time = 0
+        self.start_timestamp = 0
+        self.lock = Lock()
+        self.run_condition = Condition()
+        self.running_performance = None
+        self.running_nodes = []
+        self.unload_finished = False
+        # References to event subscribing node callbacks
+        self.interrupted_performances = []
+        # Performances that already played as alternatives. Used to maximize different performance in single demo
+        self.performances_played = {}
+        self.worker = Thread(target=self.worker_loop)
+        self.worker.setDaemon(True)
+        self.queue = []
+        logger.info('Starting performances node')
+        self.ros = ros
+        self.running_performance_pub = rospy.Publisher('{}running_performance'.format(namespace), String, queue_size=1)
+        self.events_pub =  rospy.Publisher('{}events'.format(namespace), Event, queue_size=1)
+        self.running_performance_pub = rospy.Publisher('{}running_performance'.format(namespace), String, queue_size=1)
+        self.interrupt_tts = True
+        self.load_properties()
+        rospy.Service('{}reload_properties'.format(namespace), Trigger, self.reload_properties_callback)
+        rospy.Service('{}set_properties'.format(namespace), srv.SetProperties, self.set_properties_callback)
+        rospy.Service('{}load'.format(namespace), srv.Load, self.load_callback)
+        rospy.Service('{}load_performance'.format(namespace), srv.LoadPerformance, self.load_performance_callback)
+        rospy.Service('{}unload'.format(namespace), Trigger, self.unload_callback)
+        rospy.Service('{}run'.format(namespace), srv.Run, self.run_callback)
+        rospy.Service('{}run_by_name'.format(namespace), srv.RunByName, self.run_by_name_callback)
+        rospy.Service('{}run_full_performance'.format(namespace).format(namespace), srv.RunByName, self.run_full_performance_callback)
+        rospy.Service('{}resume'.format(namespace), srv.PerformanceCommand, self.resume_callback)
+        rospy.Service('{}pause'.format(namespace), srv.PerformanceCommand, self.pause_callback)
+        rospy.Service('{}stop'.format(namespace), srv.PerformanceCommand, self.stop_callback)
+        rospy.Service('{}current'.format(namespace), srv.Current, self.current_callback)
+        rospy.Service('{}is_performance_loaded'.format(namespace), Trigger, self.check_is_performance_loaded)
+        # Shared subscribers for nodes
+        rospy.Subscriber('{}events'.format(namespace), Event, self.runner_event_callback)
+        # Shared subscribers for nodes
+        if namespace != '~':
+            # only default runner to interrupt performance
+            self.interrupt_tts = False
+            Server(PerformancesConfig, self.reconfig, namespace=namespace)
+        else:
+            if not background:
+                Server(PerformancesConfig, self.reconfig)
+
+        self.worker.start()
+
+    def reconfig(self, config, level):
+        with self.lock:
+            self.autopause = config.autopause
+
+        return config
+
+    def reload_properties_callback(self, request):
+        self.load_properties()
+        return TriggerResponse(success=True)
+
+    def unload_callback(self, request):
+        self.unload()
+        return TriggerResponse(success=True)
+
+    def unload(self):
+        self.stop()
+        with self.lock:
+            if self.running_performance:
+                logger.info('unloading')
+                self.running_performance = None
+                self.unload_attention_regions()
+                self.running_performance_pub.publish(String(json.dumps(None)))
+
+    def set_properties_callback(self, request):
+        self.ros.set_variable(request.id, json.loads(request.properties))
+        return srv.SetPropertiesResponse(success=True)
+
+    def load_callback(self, request):
+        return srv.LoadResponse(success=True, performance=json.dumps(self.load(request.id)))
+
+    def load_performance_callback(self, request):
+        self.load_performance(json.loads(request.performance))
+        return srv.LoadPerformanceResponse(True)
+
+    def run_by_name_callback(self, request):
+        self.stop()
+        # Load random timeline if its folder of timelines
+        if not self.load(request.id, random_timeline=True):
+            return srv.RunByNameResponse(False)
+        return srv.RunByNameResponse(self.run(0.0))
+
+    def run_full_performance(self, id, start_time=0.0, unload_finished=False):
+        self.stop()
+        performances = self.load_folder(id) or self.load(id)
+        if not performances:
+            return False
+        return self.run(start_time, unload_finished=unload_finished)
+
+    def run_full_performance_callback(self, request):
+        return self.run_full_performance(request.id, unload_finished=True)
+
+    def load_folder(self, id):
+        if id.startswith('shared'):
+            robot_name = 'common'
+        else:
+            robot_name = rospy.get_param('/hr/robot_name')
+
+        dir_path = os.path.join(self.get_path_by_robot_name(robot_name), id)
+        if os.path.isdir(dir_path):
+            root, dirs, files = next(os.walk(dir_path))
+
+            files = fnmatch.filter(files, "*.yaml")
+            if not files:
+                # If no folder is picked one directory
+                # Sub-directories are counted as sub-performances
+                if not dirs:
+                    return []
+                if id in self.performances_played:
+                    # All performances played. Pick any but last played
+                    if set(self.performances_played[id]) == set(dirs):
+                        dirs = self.performances_played[id][:-1]
+                        self.performances_played[id] = []
+                    else:
+                        # Pick from not played performances
+                        dirs = list(set(dirs) - set(self.performances_played[id]))
+                else:
+                    self.performances_played[id] = []
+                # Pick random performance
+                p = random.choice(dirs)
+                self.performances_played[id].append(p)
+                return self.load_folder(os.path.join(id, p))
+            # make names in folder/file format
+            return self.load(id)
+        return []
+
+    def load(self, id, random_timeline=False):
+        robot_name = 'common' if id.startswith('shared') else rospy.get_param('/hr/robot_name')
+        p = os.path.join(self.get_path_by_robot_name(robot_name), id)
+
+        if os.path.isdir(p):
+            root, dirs, files = next(os.walk(p))
+            files = natsorted(fnmatch.filter(files, "*.yaml"), key=lambda f: f.lower())
+            ids = ["{}/{}".format(id, f[:-5]) for f in files]
+            timelines = [self.get_timeline(i) for i in ids]
+            timelines = [t for t in timelines if t]
+            if random_timeline:
+                performance = random.choice(timelines)
+            else:
+                performance = {'id': id, 'name': os.path.basename(id), 'path': os.path.dirname(id),
+                               'timelines': timelines, 'nodes': self.get_merged_timeline_nodes(timelines)}
+        else:
+            performance = self.get_timeline(id)
+
+        if performance:
+            self.load_performance(performance)
+            return performance
+        else:
+            return None
+
+    def get_path_by_robot_name(self, name):
+        return os.path.join(self.performances_dir, name)
+
+    def get_timeline(self, id):
+        timeline = None
+        robot_name = 'common' if id.startswith('shared') else rospy.get_param('/hr/robot_name')
+
+        # search timeline, case insensitive
+        performance_dir = self.get_path_by_robot_name(robot_name)
+        target = '%s.yaml' % id.lower()
+        p = None
+        for f in Path(performance_dir).glob('**/*.yaml'):
+            name = str(f.relative_to(performance_dir))
+            if name.lower() == target:
+                p = f
+        if p:
+            try:
+                with p.open() as f:
+                    timeline = yaml.safe_load(f.read())
+                    timeline['id'] = id
+                    timeline['name'] = os.path.basename(id)
+                    timeline['path'] = os.path.dirname(id)
+                    self.validate_timeline(timeline)
+            except Exception as ex:
+                logger.error(ex)
+        else:
+            logger.error("Timeline with id %s was not found", id)
+        return timeline
+
+    def get_timeline_duration(self, timeline):
+        duration = 0
+
+        if 'nodes' in timeline and isinstance(timeline['nodes'], list):
+            for node in timeline['nodes']:
+                duration = max(duration, (node['duration'] if 'duration' in node else 0) + node['start_time'])
+
+        return duration
+
+    def get_merged_timeline_nodes(self, timelines):
+        merged = []
+        offset = 0
+
+        for timeline in timelines:
+            if 'enabled' in timeline and not timeline['enabled']:
+                continue
+
+            duration = 0
+            nodes = timeline.get('nodes', [])
+            nodes = copy.deepcopy(nodes)
+
+            for node in nodes:
+                duration = max(duration, node['duration'] + node['start_time'])
+                node['start_time'] += offset
+
+            merged += nodes
+            offset += duration
+
+        return merged
+
+    def validate_performance(self, performance):
+        self.validate_timeline(performance)
+        if 'timelines' in performance:
+            for timeline in performance['timelines']:
+                self.validate_timeline(timeline)
+        return performance
+
+    def validate_timeline(self, timeline):
+        if 'nodes' not in timeline or not isinstance(timeline['nodes'], list):
+            timeline['nodes'] = []
+
+        for node in timeline['nodes']:
+            if 'start_time' not in node:
+                node['start_time'] = 0
+            if node['name'] == 'pause':
+                node['duration'] = 0.1
+            if 'duration' not in node or not node['duration']:
+                node['duration'] = 0
+
+        return timeline
+
+    def load_performance(self, performance):
+        with self.lock:
+            logger.info('load: {0}'.format(performance.get('id', 'NO ID')))
+            self.validate_performance(performance)
+            self.load_attention_regions(performance.get('id','invalid'))
+            self.running_performance = performance
+            self.running_performance_pub.publish(String(json.dumps(performance)))
+
+    def run_callback(self, request):
+        return srv.RunResponse(self.run(request.startTime))
+
+    def load_attention_regions(self, id):
+        regions = rospy.get_param(
+            '/' + os.path.join('/hr', "control/performances", id,
+                               "properties/regions"), [])
+        rospy.set_param('/hr/control/performance_regions', regions)
+
+    def unload_attention_regions(self):
+        rospy.set_param('/hr/control/performance_regions', [])
+
+    def run(self, start_time, unload_finished=False):
+        start_time = float(start_time or 0)
+        self.stop()
+        # Wait for worker to stop performance and enter waiting before proceeding
+        self.run_condition.acquire()
+        with self.lock:
+            success = self.running_performance and len(self.running_performance) > 0
+            if success:
+                self.unload_finished = unload_finished
+                self.running = True
+                self.start_time = start_time
+                self.start_timestamp = time.time()
+                log_data = {
+                    'performance_report': True,
+                    'performance_id': self.running_performance.get('id', ''),
+                    'performance_time': start_time,
+                    'performance_action': 'run'
+                }
+                logger.info('Running performance #{} at: {}'.format(log_data['performance_id'], start_time), extra={'data': log_data})
+                # notify worker thread
+                self.run_condition.notify()
+
+
+            self.run_condition.release()
+            return success
+
+    def resume_callback(self, request):
+        success = self.resume()
+        with self.lock:
+            run_time = self.get_run_time()
+
+        return srv.PerformanceCommandResponse(success, run_time)
+
+    def resume(self):
+        success = False
+        with self.lock:
+            if self.running and self.paused:
+                run_time = self.get_run_time()
+                self.paused = False
+                self.start_timestamp = time.time() - run_time
+                self.start_time = 0
+                self.events_pub.publish(Event('resume', run_time))
+                log_data = {
+                    'performance_report': True,
+                    'performance_id': self.running_performance.get('id', ''),
+                    'performance_time': run_time,
+                    'performance_action': 'resume'
+                }
+                logger.info('Resume performance #{} at: {}'.format(log_data['performance_id'], run_time), extra={'data': log_data})
+                success = True
+
+        return success
+
+    def stop(self):
+        stop_time = 0.0
+        with self.lock:
+            if self.running:
+                stop_time = self.get_run_time()
+                for node in self.running_nodes:
+                    node.stop(stop_time)
+                self.running = False
+                self.paused = False
+                if self.interrupt_tts:
+                    self.ros.topics['tts_control'].publish('shutup')
+                log_data = {
+                    'performance_report': True,
+                    'performance_id': self.running_performance.get('id', '') if self.running_performance else '',
+                    'performance_time': stop_time,
+                    'performance_action': 'stop'
+                }
+                logger.info('Stopping performance #{} at: {}'.format(log_data['performance_id'], stop_time), extra={'data': log_data})
+        return stop_time
+
+    def stop_callback(self, request=None):
+        return srv.PerformanceCommandResponse(True, self.stop())
+
+    def pause_callback(self, request):
+        if self.pause():
+            with self.lock:
+                return srv.PerformanceCommandResponse(True, self.get_run_time())
+        else:
+            return srv.PerformanceCommandResponse(False, 0)
+
+    # Pauses current
+    def pause(self):
+        with self.lock:
+            if self.running and not self.paused:
+                self.pause_time = time.time()
+                self.paused = True
+                paused_time = self.get_run_time()
+                self.events_pub.publish(Event('paused', paused_time))
+                log_data = {
+                    'performance_report': True,
+                    'performance_id': self.running_performance.get('id', ''),
+                    'performance_time': paused_time,
+                    'performance_action': 'paused'
+                }
+                logger.info('Pause performance #{} at: {}'.format(log_data['performance_id'], paused_time), extra={'data': log_data})
+                return True
+            else:
+                return False
+
+    # Returns current performance
+    def current_callback(self, request):
+        with self.lock:
+            current_time = self.get_run_time()
+            running = self.running and not self.paused
+            return srv.CurrentResponse(performance=json.dumps(self.running_performance),
+                                       current_time=current_time,
+                                       running=running)
+
+    def check_is_performance_loaded(self, request):
+        success = self.running_performance and len(self.running_performance) > 0
+        return TriggerResponse(success=success)
+
+    def interrupt(self):
+        with self.lock:
+            if self.running_performance:
+                self.interrupted_performances.append({
+                    'performance': self.running_performance,
+                    'time': self.get_run_time(),
+                    # need to store this for node objects to stay alive and for callbacks to work
+                    'nodes': self.running_nodes
+                })
+        self.stop()
+
+    def resume_interrupted(self):
+        found = len(self.interrupted_performances)
+
+        if found:
+            data = self.interrupted_performances.pop()
+            time = data['time']
+            logger.info('Resuming interrupted #{0} at {1}. {2} performances left'.format(data['performance']
+                                                                                       .get('id', ''), time, found - 1))
+            self.load_performance(data['performance'])
+            self.run(time)
+
+        return found
+
+    def append_to_queue(self, id, time=0):
+        logger.info('Adding performance #{0} to the queue scheduled to run at {1}'.format(id, time))
+        self.queue.append({'id': id, 'time': time})
+
+    def load_scheduled(self):
+        data = None
+        with self.lock:
+            not_empty = len(self.queue)
+            if not_empty:
+                data = self.queue.pop()
+
+        if not_empty:
+            logger.info('Loading performance #{0} at {1} from the queue'.format(data['id'], data['time']))
+            self.run_full_performance(data['id'], start_time=data['time'])
+        elif not self.resume_interrupted():
+            return False
+
+        return True
+
+    def worker_loop(self):
+        self.run_condition.acquire()
+        while True:
+            with self.lock:
+                self.paused = False
+                self.running = False
+
+            self.events_pub.publish(Event('idle', 0))
+            self.run_condition.wait()
+            self.events_pub.publish(Event('running', self.start_time))
+
+            with self.lock:
+                if not self.running_performance:
+                    continue
+
+            behavior = True
+            offset = 0
+            timelines = self.running_performance['timelines'] if 'timelines' in self.running_performance else [
+                self.running_performance]
+
+            for i, timeline in enumerate(timelines):
+                if 'enabled' in timeline and not timeline['enabled']:
+                    continue
+
+                # check if performance is finished without starting
+                running = True
+                self.running_nodes = [Node.createNode(node, ros, self.start_time - offset, timeline.get('id', ''),
+                                                      runner=self) for node in timeline['nodes']]
+                pid = timeline.get('id', '')
+                finished = None
+                run_time = 0
+                pause = pid and self.get_property(os.path.dirname(pid), 'pause_behavior')
+                # Pause must be either enabled or not set (by default all performances are
+                # pausing behavior if its not set)
+
+                with self.lock:
+                    if not self.running:
+                        break
+
+                while running:
+                    if not finished:
+                        # Wait for a bit.
+                        time.sleep(0.02)
+                    with self.lock:
+                        run_time = self.get_run_time()
+                        if not self.running:
+                            self.events_pub.publish(Event('finished', run_time))
+                            break
+                        if self.paused:
+                            continue
+
+                    running = False
+                    # checks if any nodes still running
+                    for k, node in enumerate(self.running_nodes):
+                        running = node.run(run_time - offset) or running
+
+                    if finished is None:
+                        # true if all performance nodes are already finished
+                        finished = not running
+
+
+                log_data = {
+                    'performance_report': True,
+                    'performance_id': self.running_performance.get('id', '') if self.running_performance else '',
+                    'performance_time': run_time,
+                    'performance_action': 'finished'
+                }
+                if i == len(timelines) - 1:
+                    logger.warning('Finished performance #{} at: {}'.format(log_data['performance_id'], run_time), extra={'data': log_data})
+
+                offset += self.get_timeline_duration(timeline)
+
+                with self.lock:
+                    autopause = self.autopause and finished is False and i < len(timelines) - 1
+
+                if autopause:
+                    self.pause()
+
+            if self.unload_finished:
+                self.unload_finished = False
+                self.unload()
+
+    def get_run_time(self):
+        """
+        Must acquire self.lock in order to safely use this method
+        :return:
+        """
+        run_time = 0
+
+        if self.running:
+            run_time = self.start_time
+            if self.paused:
+                run_time += self.pause_time - self.start_timestamp
+            else:
+                run_time += time.time() - self.start_timestamp
+
+        return run_time
+
+
+
+    def load_properties(self):
+        robot_name = rospy.get_param('/hr/robot_name')
+        robot_path = os.path.join(self.performances_dir, robot_name)
+        common_path = os.path.join(self.performances_dir, 'common')
+        for path in [common_path, robot_path]:
+            for root, dirnames, filenames in os.walk(path):
+                if '.properties' in filenames:
+                    filename = os.path.join(root, '.properties')
+                    if os.path.isfile(filename):
+                        try:
+                            with open(filename) as f:
+                                properties = yaml.safe_load(f.read())
+                                dir = os.path.relpath(root, path)
+                                rospy.set_param(os.path.join('/hr/control/performances', dir).strip(
+                                    "/.") + '/properties', properties)
+                        except:
+                            rospy.logerr("Cant load properties file for {}".format(dir))
+
+
+    def get_property(self, path, name):
+        param_name = os.path.join('/hr/control/performances', path, 'properties', name)
+        return rospy.get_param(param_name, None)
+
+
+
+
+    def runner_event_callback(self, msg):
+        logger.info('Runner event: {0}'.format(msg.event))
+        self.ros.notify('RUNNER', msg.event)
+        if msg.event == 'idle':
+            self.load_scheduled()
+
+    @staticmethod
+    def is_param(param):
+        """ Checks if value is valid param.
+        Has to start with slash
+        """
+        validator = rospy.names.global_name("param_name")
+        try:
+            validator(param, False)
+            return True
+        except rospy.names.ParameterInvalid:
+            return False
+
+class SharedROSConnector:
+    # Class that provide ros interface for executing nodes, and can be shared by multiple runners
+    def __init__(self):
+        self.observers = {}
+        self.robot_name = rospy.get_param('/hr/robot_name')
+        self.variables = {}
+        self.topics = {
+            'look_at': rospy.Publisher('/hr/animation/set_face_target', Target, queue_size=1),
+            'gaze_at': rospy.Publisher('/hr/animation/set_gaze_target', Target, queue_size=1),
+            'head_rotation': rospy.Publisher('/hr/animation/set_head_tilt', Float32, queue_size=1),
+            'emotion': rospy.Publisher('/hr/animation/set_expression', SetExpression, queue_size=3),
+            'gesture': rospy.Publisher('/hr/animation/set_animation', SetAnimation, queue_size=3),
+            'arm_animation': rospy.Publisher('/hr/animation/set_arm_animation', SetAnimation, queue_size=3),
+            # 'interaction': rospy.Publisher('/behavior_switch', String, queue_size=1),
+            # 'bt_control': rospy.Publisher('/behavior_control', Int32, queue_size=1),
+            # 'chatbot': rospy.Publisher('/' + self.robot_name + '/speech', ChatMessage, queue_size=1),
+            # 'speech_events': rospy.Publisher('/' + self.robot_name + '/speech_events', String, queue_size=1),
+            'soma_state': rospy.Publisher("/hr/animation/set_soma_state", SomaState, queue_size=2),
+            'tts': rospy.Publisher('/hr/control/speech/say', TTS, queue_size=1),
+            'tts_control': rospy.Publisher('/hr/control/speech/tts_control', String, queue_size=1),
+            'arf': rospy.Publisher('/hr/interaction/arf', String, queue_size=1)
+        }
+        # rospy.Subscriber('/' + self.robot_name + '/speech_events', String,
+        #                  lambda msg: self.notify('speech_events', msg))
+        # rospy.Subscriber('/' + self.robot_name + '/speech', ChatMessage, self.speech_callback)
+
+    @staticmethod
+    def is_param(param):
+        """ Checks if value is valid param.
+        Has to start with slash
+        """
+        validator = rospy.names.global_name("param_name")
+        try:
+            validator(param, False)
+            return True
+        except rospy.names.ParameterInvalid:
+            return False
+
+    def set_variable(self, id, properties):
+        for key, val in properties.items():
+            rospy.logerr("id {} key {} val {}".format(id, key, val))
+            if id in self.variables:
+                self.variables[id][key] = val
+            else:
+                self.variables[id] = {key: val}
+
+    def get_variable(self, id, name):
+        if os.path.dirname(id) in self.variables and name in self.variables[os.path.dirname(id)] \
+                and self.variables[os.path.dirname(id)][name]:
+            return self.variables[os.path.dirname(id)][name]
+        else:
+            val = None
+            param_name = os.path.join('/hr/webui/performances', os.path.dirname(id),
+                                      'properties/variables', name)
+            if rospy.has_param(param_name):
+                val = rospy.get_param(param_name)
+                if self.is_param(val):
+                    if rospy.has_param(val):
+                        return str(rospy.get_param(val))
+                    if rospy.has_param("/{}{}".format(self.robot_name, val)):
+                        return str(rospy.get_param("/{}{}".format(self.robot_name, val)))
+
+                    return None
+            return val
+
+    # Notifies register nodes on the events from ROS.
+    def notify(self, event, msg):
+        if event not in list(self.observers.keys()):
+            return
+        for i in range(len(self.observers[event]) - 1, -1, -1):
+            try:
+                self.observers[event][i](msg)
+            except TypeError as e:
+                # Remove dead methods
+                del self.observers[event][i]
+
+    # Registers callbacks for specific events. Uses weak reference to allow nodes cleanup after finish.
+    def register(self, event, cb):
+        if not event in self.observers:
+            self.observers[event] = []
+        m = WeakMethod(cb)
+        self.observers[event].append(m)
+        logger.info('Registering event for "{0}" which now has {1} handlers'.format(event, len(self.observers[event])))
+        return m
+
+    # Allows nodes to unsubscribe from events
+    def unregister(self, event, ref):
+        if event in self.observers:
+            if ref in self.observers[event]:
+                self.observers[event].remove(ref)
+                logger.info('Unregistering event handler for "{0}" which now has {1} handlers'
+                            .format(event, len(self.observers[event])))
+
+    def speech_callback(self, msg):
+        self.notify('SPEECH', msg.utterance)
+
+
+
+
+if __name__ == '__main__':
+    rospy.init_node('performances')
+    ros = SharedROSConnector()
+    # Runner for UI
+    r1 = Runner(ros)
+    # Runner for background performances
+    r2 = Runner(ros, '/hr/control/performances/background/', background=True)
+    # Runner for automated gestures
+    r3 = Runner(ros, '/hr/control/performances/speech_animation/', background=True)
+
+    rospy.spin()
diff --git a/modules/performances/scripts/speech_motion_controller.py b/modules/performances/scripts/speech_motion_controller.py
new file mode 100755
index 0000000..fff5753
--- /dev/null
+++ b/modules/performances/scripts/speech_motion_controller.py
@@ -0,0 +1,243 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+
+import os
+import rospy
+import yaml
+import json
+import threading
+import time
+import logging
+import re
+from performances.nodes import Node
+from haipy.speech_motion.speech_motion import SpeechMotionUtils, SpeechMotionController
+#from performances.speech_motion import SpeechMotionUtils, SpeechMotionController
+from std_msgs.msg import String
+from performances.cfg import RulesConfig, GeneratorConfig
+from hr_msgs.srv import LoadPerformance, Run
+from hr_msgs.srv import TTSData
+from dynamic_reconfigure.server import Server
+from copy import deepcopy
+import random
+logger = logging.getLogger('hr.performances.speech_motion_controller')
+
+# RosNode for speech motion
+# HEAD Specific ROS Controller
+class SpeechMotionNode():
+
+    def __init__(self):
+        # Rules server
+        self.config = None
+        aa_library = rospy.get_param('/hr/control/animation_actions', {})
+        nlu_server = rospy.get_param('/hr/control/nlu_server', "http://127.0.0.1:8210")
+        lipsync_delay = rospy.get_param('/hr/control/speech/tts_talker/tts_delay', 0.2)
+        self.controller = SpeechMotionController(aa_library, nlu_server=nlu_server, lipsync_delay=lipsync_delay)
+        self.rules_server = Server(RulesConfig, self.rules_config_cb, '/hr/control/speech_motions')
+        self.current_state = 'idle'
+        rospy.Subscriber('/hr/behavior/current_state', String, self.update_state)
+        rospy.Subscriber('/hr/control/speech/data', String, self.get_tts_data)
+        self.loader = rospy.ServiceProxy('/hr/control/performances/speech_animation/load_performance', LoadPerformance)
+        self.runner = rospy.ServiceProxy('/hr/control/performances/speech_animation/run', Run)
+        self.tts_ready = rospy.Publisher('/hr/control/speech/tts_control', String, queue_size=2)
+        self.id = 1
+
+    def get_tts_data(self, msg):
+        # no generation on interacting, also dont animate perfromances itself to avoid confusion
+        if (self.config.interactive and not 'interacting' in self.current_state) or '|p|' in msg.data:
+            self.tts_ready.publish('ready')
+            return
+        # Prefer JSON loads, if only json format is used
+        try:
+            data = json.loads(msg.data)
+        except Exception as e   :
+            data = yaml.safe_load(msg.data)
+
+        nodes = SpeechMotionUtils.create_speech_data_from_tts_data(data)
+        animated = self.controller.animate_motion(nodes, animate_arms=self.config.automated_arm_gestures)
+        SpeechMotionController.clean_nodes(animated)
+        if len(animated) > len(nodes):
+            self.loader(json.dumps({'nodes': animated, 'id': "auto/{}".format(self.id)}, ensure_ascii=True))
+            self.id += 1
+            self.tts_ready.publish('ready')
+            self.runner(0)
+        else:
+            self.tts_ready.publish('ready')
+
+    def update_state(self, msg):
+        self.current_state = msg.data
+
+
+    def rules_config_cb(self, config, level):
+        if self.config is None:
+            self.controller.update_keyword_rules(yaml.safe_load(config.keyword_rules))
+            # # Sorted Rules on first load, later on the order should remain same to prevent unexpected UI sorting
+            config.keyword_rules = json.dumps(self.controller.get_keyword_rules())
+            self.controller.update_da_rules(yaml.safe_load(config.da_rules))
+            # # Sorted Rules on first load, later on the order should remain same to prevent unexpected UI sorting
+            config.da_rules = json.dumps(self.controller.get_da_rules())
+            self.config = config
+        if self.config.keyword_rules != config.keyword_rules:
+            self.controller.update_keyword_rules(yaml.safe_load(config.keyword_rules))
+        if self.config.da_rules != config.da_rules:
+            self.controller.update_da_rules(yaml.safe_load(config.da_rules))
+        self.config = config
+        self.controller.animated_shoulders = config.automated_shoulder_gestures
+        self.controller.min_arms_hold_time = config.min_arms_hold_time
+        self.controller.max_arms_hold_time = config.max_arms_hold_time
+        self.controller.skip_keyword_rules = not config.enable
+        self.controller.library.filter = config.negative_gesture_categories
+        self.controller.library.reduce_robability = config.reduce_negativity
+        self.controller.negative_gesture_categories = config.negative_gesture_categories
+        self.controller.set_gesture_filters(
+            config.rules_head_filter, config.rules_brow_filter, config.rules_eyelids_filter, config.rules_eyes_filter)
+        self.controller.happy_gestures_probability = config.generic_gestures_happy_filter
+        self.controller.set_generic_gestures_config(config.generic_gestures, config.generic_gestures_categories_excluded, \
+                                                    config.generic_gestures_probability, config.generic_gestures_head_filter, \
+                                                    config.generic_gestures_brow_filter, config.generic_gestures_eyelids_filter, \
+                                                    config.generic_gestures_eyes_filter, config.generic_gestures_arms_filter)
+        return config
+
+
+# Performance generator for HEAD
+class PerformanceGenerator():
+
+    def __init__(self, speech_motion):
+        self.speech_motion = speech_motion
+
+        self.performances_dir = os.path.join(
+            os.environ.get('PERFORMANCES_DIR', '/home/hr/workspace/hrsdk_configs/performances'))
+        self.robot_name = rospy.get_param('/hr/robot_name')
+        self.lipsync_delay = rospy.get_param('/hr/control/speech/tts_talker/tts_delay', 0.2)
+        self.tts_data = rospy.ServiceProxy('/hr/control/speech/data', TTSData)
+        self.in_progress = False
+        self.generator = None
+        self.cfg = None
+        self.srv = Server(GeneratorConfig, self.update_cfg, namespace='/hr/control/performance_generation')
+
+    def update_cfg(self, cfg, level):
+        if self.cfg is None:
+            self.cfg = cfg
+            return cfg
+        # Update progress
+        if self.in_progress:
+            self.cfg.progress = cfg.progress
+            return self.cfg
+        min_speed = min(cfg.min_speed, cfg.max_speed)
+        max_speed = max(cfg.min_speed, cfg.max_speed)
+        cfg.min_speed = min_speed
+        cfg.max_speed = max_speed
+        # Start Generation
+        cfg.name = cfg.name.strip()
+        cfg.name = cfg.name.replace(' ', '_')
+        cfg.name = cfg.name.replace('.', '_')
+        cfg.name = re.sub('[\W]&&[^/]+', '', cfg.name)
+        cfg.name =cfg.name.lower()
+        if cfg.start:
+            cfg.start = False
+            if cfg.name == "":
+                cfg.status = "Performance name is required"
+                self.cfg = cfg
+                return cfg
+            self.in_progress = True
+            self.cfg = cfg
+            self.generator = threading.Thread(target=self.genearate)
+            self.generator.setDaemon(True)
+            self.generator.start()
+        else:
+            self.cfg = cfg
+        return self.cfg
+
+    def add_speed_ssml(self, text, speed):
+        try:
+            if speed == 100:
+                return text
+            return '{}'.format(speed, text)
+        except Exception:
+            return text
+            
+    def genearate(self):
+        current_loc = 'start'
+        try:
+            lines = self.cfg.lines.splitlines()
+            for i, l in enumerate(lines):
+                current_loc = str(i+1)
+                self.srv.update_configuration({'progress': 'Working on  {} of {}'.format(i + 1, len(lines))})
+                sentences = SpeechMotionUtils.split_text(l, split_sentences=self.cfg.split_sentences)
+                nodes = []
+                current_sentence_start = 0
+                for s in sentences:
+                    try:
+                        s = s.lower()
+                        try:
+                            s = str(s)
+                        except:
+                            pass
+                        # Try add speed
+                        try:
+                            speed = random.randint(self.cfg.min_speed, self.cfg.max_speed)
+                        except Exception:
+                            speed = 100
+                        
+                        s_with_speed = self.add_speed_ssml(s, speed)
+                        tts_data = self.tts_data(s_with_speed, self.cfg.lang)
+                        tts_data = yaml.safe_load(tts_data.data)
+                        # matched with TTS words
+                        text, text_words, words = SpeechMotionUtils.match_tts(tts_data, s)
+                        if not text:
+                            continue
+                        # lipsync_delay needed to be added as sound file needs to be slightly delayed for lipsynch,
+                        # therefore actual duration is longer
+                        node = Node.create_empty_node_data(type='speech', duration=text['duration']+0.3, text=s,
+                                                        start_time=current_sentence_start,
+                                                        tts_data=tts_data, words=words, text_words=text_words, lang=self.cfg.lang, speed=round(speed/100.0, 2))
+                        nodes.append(node)
+                        current_sentence_start += text['duration'] + self.lipsync_delay + self.cfg.pause_between_sentences
+                    except Exception as e:
+                        logger.error(u"Exception {} while generating {}".format(e, s))
+                        # Wait for TTS server to recover
+                        time.sleep(10)
+                        pass
+                animated = self.speech_motion.controller.animate_motion(nodes)
+                nodes = nodes + animated
+                SpeechMotionController.clean_nodes(nodes)
+                if self.cfg.name != '':
+                    # Allow shared performances generations
+                    robot_name = 'common' if self.cfg.name.startswith('shared') else self.robot_name
+                    filename = os.path.join(self.performances_dir, robot_name, self.cfg.name, "{}.yaml".format(i + 1))
+                    if not os.path.exists(os.path.dirname(filename)):
+                        os.makedirs(os.path.dirname(filename))
+                    with open(filename, 'w') as f:
+                        yaml.dump({'nodes': deepcopy(nodes)}, f)
+
+            self.srv.update_configuration({'progress': 'idle'})
+            self.in_progress = False
+        # Unhandled exceptions should show in UI, and not prevent to retry
+        except Exception as e:
+            logger.error(u"Exception {} while generating {}".format(e, current_loc))
+            self.srv.update_configuration({'progress': f'Error while generating line {current_loc} exception:{e}'})
+            self.in_progress = False
+            
+
+if __name__ == "__main__":
+    rospy.init_node('SpeechMotionController')
+    rosnode = SpeechMotionNode()
+    generator = PerformanceGenerator(rosnode)
+    rospy.spin()
diff --git a/modules/performances/setup.py b/modules/performances/setup.py
new file mode 100644
index 0000000..886e8f8
--- /dev/null
+++ b/modules/performances/setup.py
@@ -0,0 +1,28 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+# DO NOT USE
+# python setup.py install
+
+from distutils.core import setup
+
+setup(
+    version='0.3.11',
+    name='performances',
+    packages=['performances'],
+    package_dir={'': 'src'}
+)
diff --git a/modules/performances/src/performances/__init__.py b/modules/performances/src/performances/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/modules/performances/src/performances/config.yaml b/modules/performances/src/performances/config.yaml
new file mode 100644
index 0000000..a032881
--- /dev/null
+++ b/modules/performances/src/performances/config.yaml
@@ -0,0 +1,209 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+speech_motions:
+  da_rules: '[{"browAA":"-","probability":1,"armsAA":"arm-vawe","priority":90,"eyelidsAA":"-","headAA":"-","act":"CONVENTIONAL_OPENING","threshold":0.5,"apply":"first","eyesAA":"-"},{"browAA":"-","probability":1,"armsAA":"arm-vawe","priority":90,"eyelidsAA":"-","headAA":"-","act":"CONVENTIONAL_CLOSING","threshold":0.5,"apply":"last","eyesAA":"-"}]'
+  enable: true
+  keyword_rules: '[{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "me, my, mine, we, our, ours, ourselves, own, we, our, ours, ourselves, own, ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "yours, yourself, them, those, that, these, you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "nod-short","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "-", "eyesAA": "-"},{"priority": 100, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "love you, big love, big heart, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "nod-heavy","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "shake-heavy","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "nod-short","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "shake-short","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "shake-short","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "what, where, when, how, ", "armsAA": "-", "eyesAA": "-"},{"priority": 55, "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "can you, could you, do you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.8,"headAA": "head-tilt-long","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 85, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "nod-short","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "nod-heavy","keywords": "must, should, ought to, must need, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "you know, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.8,"headAA": "head-tilt-long","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "head-down","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "nod-short","keywords": "alike, comparable, related, similar, familiar", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.8,"headAA": "head-aside","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.8,"headAA": "head-tilt-long","keywords": "always, consistently, constantly, invariably, regularly, repeatedly, perpetually, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": " continue, advance, endure, extend, go on, will last, linger, maintain, progress, promote, pursue, remain, will stay, survive, sustain, hold, sustaining, continuing, lasting, enduring, extending, remaining, promoting, progressing, lingering, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "kind of, slightly, lightly, somewhat, at least, rather, moderately, sort of, to some extent, at least", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "of course, sure, absolutely, actually, certainly, genuinely, honestly, indeed, legitimately, literally, surely, truly, undoubtedly, unquestionably, well, actual, certain, definite, substantial, substantive, absolute, authentic, concrete, confirmed, factual, for real, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "conflicting, oppose, argue, assail, attack, debate, defy, deny, disagree, dispute, fight, prevent, protest, resist, assault, bar, battle, bombard, combat, confront, contradict, controvert, counter, counterattack, disapprove, encounter, expose, gainsay, hinder neutralize, reverse, taunt, thwart, withstand, object to, opposed, abide, combat, confront, continue, curb, defy, endure, forgo, maintain, prevent, refuse, repel, thwart, turn down, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "Wobbling","keywords": "adaptable, adventurous, affable, affectionate, agreeable, ambitious, amiable, amicable, amusing, brave, bright, broad-minded, calm, careful, charming, communicative, compassionate, conscientious, considerate, convivial, courageous, courteous, creative, decisive, determined, diligent, diplomatic, discreet, dynamic, easygoing, emotional, energetic, enthusiastic, exuberant, fair-minded, faithful, fearless, forceful, friendly, funny, generous, gentle, good, gregarious, hard-working, helpful, honest, humorous, imaginative, impartial, independent, intellectual, intelligent, intuitive, inventive, kind, loving, loyal, modest, neat, nice, optimistic, passionate, patient, persistent, pioneering, philosophical, placid, plucky, polite, powerful, practical, pro-active, quick-witted, quiet, rational, reliable, reserved, resourceful, romantic, self-confident, self-disciplined, sensible, sensitive, shy, sincere, sociable, straightforward, sympathetic, thoughtful, tidy, tough, unassuming, understanding, versatile, warmhearted, willing, witty, attractive, absorbing, alluring, amiable, appealing, attractive, charismatic, cute, delightful, elegant, engaging, engrossing, fascinating, glamorous, graceful, inviting, likable, lovable, lovely, pleasant, provocative, sweet, loyal, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "beautiful, appealing, charming, cute, dazzling, delicate, delightful, elegant, exquisite, fascinating, good-looking, gorgeous, graceful, grand, handsome, lovely, magnificent, marvelous, pleasing, pretty, splendid, stunning, superb, wonderful, admirable, angelic, beauteous, bewitching, classy, famous, honored, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "evil, gloomy, nasty, ominous, rough, evil, gloomy, nasty, ominous, rough, unattractive, unpleasant, disagreeable,disgusting, repugnant, repulsive, unappealing, bad-looking, gross, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-aside","keywords": "suspicious, doubtful", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.8,"headAA": "nod-long","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-up","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "Sorry, sad, pitiful, apologies, apology, sorrowful,unhappy,", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "hello, welcome, bye, see you, good bye, Hi, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "shake-long","keywords": "depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, bitter, displeasing, failing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "nod-short","keywords": "valuable, good at, useful, worthy, skilled, experienced, proficient, expert, competent, efficient, experienced, licensed, qualified, skillful, professional, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "hate", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "complex, headache, baffle, befuddle, bemuse, complicate, confound, daze, demoralize, disconcert, disorient, distract, embarrass, fluster, frustrate, involve, misinform, mislead, baffling, bewildering, complex, complicated, confounding, difficult, disconcerting, perplexing, upsetting", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "call me. contact me, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "altercation, argue, battle, brawl,clash, combat, conflict, confrontation, contest, controversy, disagreement, dispute, duel, exchange, feud, match, melee, quarrel, riot, rivalry, scuffle, skirmish, struggle, war, wrangling, fight, attack, battle, challenge, clash, protect, resist, argue, combat, engage in, force, oppose, resist, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "altercation, arguing, clashing, combating, conflicting, confrontation, Struggling, wrangling, fighting, attacking, clashing, resisting, arguing, combating, forcing, opposing, resisting,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "nod-short","keywords": "dependable, enduring, lasting, permanent, reliable, stable, strong, tenacious, abiding, constant, diuturnal, fast, firm, fixed, reliable, safe, solid, substantial, abiding, enduring, high tech, advanced, leading, cutting-edge, forward, excellent, distinguished, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-up","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "head-tilt-long","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "short", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "longer, larger", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "head-down","keywords": "shorter, briefer, curtailed, diminished, less, lessened, lower,more concise, reduced, reducing, diminishing, briefing, lowering, lesser ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "nod-short","keywords": "enlarge, bigger, more, larger, largest, better, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "head-tilt","keywords": "a few, a little, a bit, barely, hardly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "none, nothing, noway, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "a lot,  many, massive, lots of, countless, substantial, considerable, extensive, enormous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "Wobbling","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "nod-long","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "nod-heavy","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "-", "eyesAA": "-"},{"priority": , "browAA": "-", "probability": 0.5,"headAA": "head-tilt-long","keywords": "comfortable, elementary, reachable, possible, comfy, peaceful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "nod-short","keywords": "lovely, nicely, cute, sweet, cheerful,delighted, glad, pleasant, alluring, captivating, delicate, delicious, delightful, enchanting, engaging, exquisite, gorgeous, graceful, handsome, pleasant, pleasing, pretty, splendid, stunning, sweet, adorable, charming", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "nod-heavy","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "shake-heavy","keywords": "awful, distressing, dreadful,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "difficult, tough, ambitious, arduous, burdensome, challenging, troublesome, puzzle, impossible, hard, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "easy, accessible,clear,effortless,obvious,painless,simple,smooth,straightforward,uncomplicated, reachable, cozy", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "me, my, mine, we, our, ours, ourselves, own, we, our, ours, ourselves, own, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "nod-long","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "shake-short","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "nod-long","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "head-aside","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "what, where, when, how, ", "armsAA": "-", "eyesAA": "-"},{"priority": 55, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "can you, could you, do you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "must, should, ought to, must need, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "you know, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.8,"headAA": "shake-short","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "-"},
+{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "Wobbling","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "alike, comparable, related, similar, familiar", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.8,"headAA": "shake-long","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "always, consistently, constantly, invariably, regularly, repeatedly, perpetually, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "nod-heavy","keywords": "of course, sure, absolutely, actually, certainly, genuinely, honestly, indeed, legitimately, literally, surely, truly, undoubtedly, unquestionably, well, actual, certain, definite, substantial, substantive, absolute, authentic, concrete, confirmed, factual, for real, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "nod-short","keywords": "adaptable, adventurous, affable, affectionate, agreeable, ambitious, amiable, amicable, amusing, brave, bright, broad-minded, calm, careful, charming, communicative, compassionate, conscientious, considerate, convivial, courageous, courteous, creative, decisive, determined, diligent, diplomatic, discreet, dynamic, easygoing, emotional, energetic, enthusiastic, exuberant, fair-minded, faithful, fearless, forceful, friendly, funny, generous, gentle, good, gregarious, hard-working, helpful, honest, humorous, imaginative, impartial, independent, intellectual, intelligent, intuitive, inventive, kind, loving, loyal, modest, neat, nice, optimistic, passionate, patient, persistent, pioneering, philosophical, placid, plucky, polite, powerful, practical, pro-active, quick-witted, quiet, rational, reliable, reserved, resourceful, romantic, self-confident, self-disciplined, sensible, sensitive, shy, sincere, sociable, straightforward, sympathetic, thoughtful, tidy, tough, unassuming, understanding, versatile, warmhearted, willing, witty, attractive, absorbing, alluring, amiable, appealing, attractive, charismatic, cute, delightful, elegant, engaging, engrossing, fascinating, glamorous, graceful, inviting, likable, lovable, lovely, pleasant, provocative, sweet, loyal, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-short","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.5,"headAA": "shake-heavy","keywords": "evil, gloomy, nasty, ominous, rough, evil, gloomy, nasty, ominous, rough, unattractive, unpleasant, disagreeable,disgusting, repugnant, repulsive, unappealing, bad-looking, gross, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "suspicious, doubtful", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-down","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "head-down","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.8,"headAA": "head-tilt","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-tilt","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "head-aside","keywords": "complex, headache, baffle, befuddle, bemuse, complicate, confound, daze, demoralize, disconcert, disorient, distract, embarrass, fluster, frustrate, involve, misinform, mislead, baffling, bewildering, complex, complicated, confounding, difficult, disconcerting, perplexing, upsetting", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "wobbling","keywords": "dependable, enduring, lasting, permanent, reliable, stable, strong, tenacious, abiding, constant, diuturnal, fast, firm, fixed, reliable, safe, solid, substantial, abiding, enduring, high tech, advanced, leading, cutting-edge, forward, excellent, distinguished, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-right","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "head-aside","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "head-aside","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "wobbling","keywords": "a few, a little, a bit, barely, hardly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "none, nothing, noway, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-firmly","keywords": "a lot,  many, massive, lots of, countless, substantial, considerable, extensive, enormous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "wobbling","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "nod-long","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "head-tilt-long","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "nod-long","keywords": "lovely, nicely, cute, sweet, cheerful,delighted, glad, pleasant, alluring, captivating, delicate, delicious, delightful, enchanting, engaging, exquisite, gorgeous, graceful, handsome, pleasant, pleasing, pretty, splendid, stunning, sweet, adorable, charming", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "shake-long","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "shake-firmly","keywords": "awful, distressing, dreadful,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "me, my, mine, we, our, ours, ourselves, own, we, our, ours, ourselves, own, ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "brow-up-short", "probability": 0.8,"headAA": "-","keywords": "yours, yourself, them, those, that, these, you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "-", "eyesAA": "-"},{"priority": 100, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "love you, big love, big heart, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.8,"headAA": "-","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "what, where, when, how, ", "armsAA": "-", "eyesAA": "-"},{"priority": 55, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "can you, could you, do you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-center-up-long", "probability": 0.8,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 85, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-short", "probability": 0.8,"headAA": "-","keywords": "must, should, ought to, must need, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "you know, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.8,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.2,"headAA": "-","keywords": "alike, comparable, related, similar, familiar", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-down-long", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "always, consistently, constantly, invariably, regularly, repeatedly, perpetually, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": " continue, advance, endure, extend, go on, will last, linger, maintain, progress, promote, pursue, remain, will stay, survive, sustain, hold, sustaining, continuing, lasting, enduring, extending, remaining, promoting, progressing, lingering, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "of course, sure, absolutely, actually, certainly, genuinely, honestly, indeed, legitimately, literally, surely, truly, undoubtedly, unquestionably, well, actual, certain, definite, substantial, substantive, absolute, authentic, concrete, confirmed, factual, for real, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "conflicting, oppose, argue, assail, attack, debate, defy, deny, disagree, dispute, fight, prevent, protest, resist, assault, bar, battle, bombard, combat, confront, contradict, controvert, counter, counterattack, disapprove, encounter, expose, gainsay, hinder neutralize, reverse, taunt, thwart, withstand, object to, opposed, abide, combat, confront, continue, curb, defy, endure, forgo, maintain, prevent, refuse, repel, thwart, turn down, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "forget, ignore, avoid, discount, fail, forget, neglect, overlook, reject, scorn, forgeting, ignoring, avoiding, discounting, failling, forgeting, neglect, overlooking, rejecting, scorn, forgetful, ignored, avoided, discounted, failed, forgot, overlooked, rejected,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "adaptable, adventurous, affable, affectionate, agreeable, ambitious, amiable, amicable, amusing, brave, bright, broad-minded, calm, careful, charming, communicative, compassionate, conscientious, considerate, convivial, courageous, courteous, creative, decisive, determined, diligent, diplomatic, discreet, dynamic, easygoing, emotional, energetic, enthusiastic, exuberant, fair-minded, faithful, fearless, forceful, friendly, funny, generous, gentle, good, gregarious, hard-working, helpful, honest, humorous, imaginative, impartial, independent, intellectual, intelligent, intuitive, inventive, kind, loving, loyal, modest, neat, nice, optimistic, passionate, patient, persistent, pioneering, philosophical, placid, plucky, polite, powerful, practical, pro-active, quick-witted, quiet, rational, reliable, reserved, resourceful, romantic, self-confident, self-disciplined, sensible, sensitive, shy, sincere, sociable, straightforward, sympathetic, thoughtful, tidy, tough, unassuming, understanding, versatile, warmhearted, willing, witty, attractive, absorbing, alluring, amiable, appealing, attractive, charismatic, cute, delightful, elegant, engaging, engrossing, fascinating, glamorous, graceful, inviting, likable, lovable, lovely, pleasant, provocative, sweet, loyal, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "beautiful, appealing, charming, cute, dazzling, delicate, delightful, elegant, exquisite, fascinating, good-looking, gorgeous, graceful, grand, handsome, lovely, magnificent, marvelous, pleasing, pretty, splendid, stunning, superb, wonderful, admirable, angelic, beauteous, bewitching, classy, famous, honored, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "evil, gloomy, nasty, ominous, rough, evil, gloomy, nasty, ominous, rough, unattractive, unpleasant, disagreeable,disgusting, repugnant, repulsive, unappealing, bad-looking, gross, ", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-long", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "Sorry, sad, pitiful, apologies, apology, sorrowful,unhappy,", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "brow-up-normal", "probability": 0.8,"headAA": "-","keywords": "hello, welcome, bye, see you, good bye, Hi, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "impact, astonishing, extraordinary, shocking, amazed, amazing, astonish, astonished, impacted, shocked, impacting, surprise, surprising, dominant, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, bitter, displeasing, failing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "valuable, good at, useful, worthy, skilled, experienced, proficient, expert, competent, efficient, experienced, licensed, qualified, skillful, professional, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-long", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "hate", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.8,"headAA": "-","keywords": "complex, headache, baffle, befuddle, bemuse, complicate, confound, daze, demoralize, disconcert, disorient, distract, embarrass, fluster, frustrate, involve, misinform, mislead, baffling, bewildering, complex, complicated, confounding, difficult, disconcerting, perplexing, upsetting", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "altercation, argue, battle, brawl,clash, combat, conflict, confrontation, contest, controversy, disagreement, dispute, duel, exchange, feud, match, melee, quarrel, riot, rivalry, scuffle, skirmish, struggle, war, wrangling, fight, attack, battle, challenge, clash, protect, resist, argue, combat, engage in, force, oppose, resist, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "altercation, arguing, clashing, combating, conflicting, confrontation, Struggling, wrangling, fighting, attacking, clashing, resisting, arguing, combating, forcing, opposing, resisting,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "dependable, enduring, lasting, permanent, reliable, stable, strong, tenacious, abiding, constant, diuturnal, fast, firm, fixed, reliable, safe, solid, substantial, abiding, enduring, high tech, advanced, leading, cutting-edge, forward, excellent, distinguished, ", "armsAA": "-", "eyesAA": "-"},
+{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "short", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "longer, larger", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "shorter, briefer, curtailed, diminished, less, lessened, lower,more concise, reduced, reducing, diminishing, briefing, lowering, lesser ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "enlarge, bigger, more, larger, largest, better, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "smaller, lesser", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "a few, a little, a bit, barely, hardly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "none, nothing, noway, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "a lot,  many, massive, lots of, countless, substantial, considerable, extensive, enormous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.8,"headAA": "-","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "lovely, nicely, cute, sweet, cheerful,delighted, glad, pleasant, alluring, captivating, delicate, delicious, delightful, enchanting, engaging, exquisite, gorgeous, graceful, handsome, pleasant, pleasing, pretty, splendid, stunning, sweet, adorable, charming", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-down-normal", "probability": 0.8,"headAA": "-","keywords": "awful, distressing, dreadful,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "difficult, tough, ambitious, arduous, burdensome, challenging, troublesome, puzzle, impossible, hard, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "easy, accessible,clear,effortless,obvious,painless,simple,smooth,straightforward,uncomplicated, reachable, cozy", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.8,"headAA": "-","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "what, where, when, how, ", "armsAA": "-", "eyesAA": "-"},{"priority": 55, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "can you, could you, do you, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-doubt", "probability": 0.8,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 85, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.8,"headAA": "-","keywords": "must, should, ought to, must need, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "you know, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "-"},{"priority": 35, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "-", "eyesAA": "-"},{"priority": 30, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.8,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.2,"headAA": "-","keywords": "alike, comparable, related, similar, familiar", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 50, "browAA": "brow-down-short", "probability": 0.5,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-short", "probability": 0.5,"headAA": "-","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "of course, sure, absolutely, actually, certainly, genuinely, honestly, indeed, legitimately, literally, surely, truly, undoubtedly, unquestionably, well, actual, certain, definite, substantial, substantive, absolute, authentic, concrete, confirmed, factual, for real, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "conflicting, oppose, argue, assail, attack, debate, defy, deny, disagree, dispute, fight, prevent, protest, resist, assault, bar, battle, bombard, combat, confront, contradict, controvert, counter, counterattack, disapprove, encounter, expose, gainsay, hinder neutralize, reverse, taunt, thwart, withstand, object to, opposed, abide, combat, confront, continue, curb, defy, endure, forgo, maintain, prevent, refuse, repel, thwart, turn down, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "forget, ignore, avoid, discount, fail, forget, neglect, overlook, reject, scorn, forgeting, ignoring, avoiding, discounting, failling, forgeting, neglect, overlooking, rejecting, scorn, forgetful, ignored, avoided, discounted, failed, forgot, overlooked, rejected,  ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "-", "eyesAA": "-"},{"priority": 75, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "evil, gloomy, nasty, ominous, rough, evil, gloomy, nasty, ominous, rough, unattractive, unpleasant, disagreeable,disgusting, repugnant, repulsive, unappealing, bad-looking, gross, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.8,"headAA": "-","keywords": "suspicious, doubtful", "armsAA": "-", "eyesAA": "-"},{"priority": 65, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "-", "eyesAA": "-"},{"priority": 80, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-"},{"priority": 40, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-doubt", "probability": 0.8,"headAA": "-","keywords": "complex, headache, baffle, befuddle, bemuse, complicate, confound, daze, demoralize, disconcert, disorient, distract, embarrass, fluster, frustrate, involve, misinform, mislead, baffling, bewildering, complex, complicated, confounding, difficult, disconcerting, perplexing, upsetting", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "altercation, arguing, clashing, combating, conflicting, confrontation, Struggling, wrangling, fighting, attacking, clashing, resisting, arguing, combating, forcing, opposing, resisting,", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-up-short", "probability": 0.5,"headAA": "-","keywords": "dependable, enduring, lasting, permanent, reliable, stable, strong, tenacious, abiding, constant, diuturnal, fast, firm, fixed, reliable, safe, solid, substantial, abiding, enduring, high tech, advanced, leading, cutting-edge, forward, excellent, distinguished, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-down-short", "probability": 0.5,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "-"},{"priority": 70, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-long", "probability": 0.5,"headAA": "-","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up-long", "probability": 0.5,"headAA": "-","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-center-up", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-down-normal", "probability": 0.5,"headAA": "-","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-doubt", "probability": 0.5,"headAA": "-","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "-", "eyesAA": "-"},{"priority": 60, "browAA": "brow-up-normal", "probability": 0.5,"headAA": "-","keywords": "easy, accessible,clear,effortless,obvious,painless,simple,smooth,straightforward,uncomplicated, reachable, cozy", "armsAA": "-", "eyesAA": "-"},{"priority": 100, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "love you, big love, big heart, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 55, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "can you, could you, do you, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "must, should, ought to, must need, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 35, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 30, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 65, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "suspicious, doubtful", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 65, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},
+{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Sorry, sad, pitiful, apologies, apology, sorrowful,unhappy,", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "impact, astonishing, extraordinary, shocking, amazed, amazing, astonish, astonished, impacted, shocked, impacting, surprise, surprising, dominant, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "hate", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "altercation, argue, battle, brawl,clash, combat, conflict, confrontation, contest, controversy, disagreement, dispute, duel, exchange, feud, match, melee, quarrel, riot, rivalry, scuffle, skirmish, struggle, war, wrangling, fight, attack, battle, challenge, clash, protect, resist, argue, combat, engage in, force, oppose, resist, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "shorter, briefer, curtailed, diminished, less, lessened, lower,more concise, reduced, reducing, diminishing, briefing, lowering, lesser ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": , "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "comfortable, elementary, reachable, possible, comfy, peaceful, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "lovely, nicely, cute, sweet, cheerful,delighted, glad, pleasant, alluring, captivating, delicate, delicious, delightful, enchanting, engaging, exquisite, gorgeous, graceful, handsome, pleasant, pleasing, pretty, splendid, stunning, sweet, adorable, charming", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 30, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "altercation, argue, battle, brawl,clash, combat, conflict, confrontation, contest, controversy, disagreement, dispute, duel, exchange, feud, match, melee, quarrel, riot, rivalry, scuffle, skirmish, struggle, war, wrangling, fight, attack, battle, challenge, clash, protect, resist, argue, combat, engage in, force, oppose, resist, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-half-close",},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "-", "eyesAA": "-", "eyelidsAA": "eyelid-widely-open",},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 85, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "eye-around"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "you know, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 35, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 35, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "alike, comparable, related, similar, familiar", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 65, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 75, "browAA": "-", "probability": 1,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "-", "eyesAA": "eye-around"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Sorry, sad, pitiful, apologies, apology, sorrowful,unhappy,", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, bitter, displeasing, failing, ", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "none, nothing, noway, ", "armsAA": "-", "eyesAA": "eye-down"},{"priority": 85, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "you know, ", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "-", "eyesAA": "eye-around"},{"priority": 35, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 35, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "-", "eyesAA": "eye-side"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "-", "eyesAA": "eye-corner"},{"priority": 70, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "-", "eyesAA": "eye-around"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "me, my, mine, we, our, ours, ourselves, own, we, our, ours, ourselves, own, ", "armsAA": "arm-me", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "yours, yourself, them, those, that, these, you, ", "armsAA": "arm-you", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 100, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "love you, big love, big heart, ", "armsAA": "arm-heart", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "refuse, reject, decline, deny, ignore, trash, waste, wasted, dismiss, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "what, where, when, how, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 55, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "can you, could you, do you, ", "armsAA": "arm-you", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 85, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "must, should, ought to, must need, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "um, uh, well, let''s see, let me think", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "arm-contrast", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "arm-contrast", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 1,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "arm-contrast", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "alike, comparable, related, similar, familiar", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 1,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 1,"headAA": "-","keywords": "always, consistently, constantly, invariably, regularly, repeatedly, perpetually, ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "arm-process-control", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": " continue, advance, endure, extend, go on, will last, linger, maintain, progress, promote, pursue, remain, will stay, survive, sustain, hold, sustaining, continuing, lasting, enduring, extending, remaining, promoting, progressing, lingering, ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "kind of, slightly, lightly, somewhat, at least, rather, moderately, sort of, to some extent, at least", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "of course, sure, absolutely, actually, certainly, genuinely, honestly, indeed, legitimately, literally, surely, truly, undoubtedly, unquestionably, well, actual, certain, definite, substantial, substantive, absolute, authentic, concrete, confirmed, factual, for real, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "conflicting, oppose, argue, assail, attack, debate, defy, deny, disagree, dispute, fight, prevent, protest, resist, assault, bar, battle, bombard, combat, confront, contradict, controvert, counter, counterattack, disapprove, encounter, expose, gainsay, hinder neutralize, reverse, taunt, thwart, withstand, object to, opposed, abide, combat, confront, continue, curb, defy, endure, forgo, maintain, prevent, refuse, repel, thwart, turn down, ", "armsAA": "arm-process-control", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "forget, ignore, avoid, discount, fail, forget, neglect, overlook, reject, scorn, forgeting, ignoring, avoiding, discounting, failling, forgeting, neglect, overlooking, rejecting, scorn, forgetful, ignored, avoided, discounted, failed, forgot, overlooked, rejected,  ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "adaptable, adventurous, affable, affectionate, agreeable, ambitious, amiable, amicable, amusing, brave, bright, broad-minded, calm, careful, charming, communicative, compassionate, conscientious, considerate, convivial, courageous, courteous, creative, decisive, determined, diligent, diplomatic, discreet, dynamic, easygoing, emotional, energetic, enthusiastic, exuberant, fair-minded, faithful, fearless, forceful, friendly, funny, generous, gentle, good, gregarious, hard-working, helpful, honest, humorous, imaginative, impartial, independent, intellectual, intelligent, intuitive, inventive, kind, loving, loyal, modest, neat, nice, optimistic, passionate, patient, persistent, pioneering, philosophical, placid, plucky, polite, powerful, practical, pro-active, quick-witted, quiet, rational, reliable, reserved, resourceful, romantic, self-confident, self-disciplined, sensible, sensitive, shy, sincere, sociable, straightforward, sympathetic, thoughtful, tidy, tough, unassuming, understanding, versatile, warmhearted, willing, witty, attractive, absorbing, alluring, amiable, appealing, attractive, charismatic, cute, delightful, elegant, engaging, engrossing, fascinating, glamorous, graceful, inviting, likable, lovable, lovely, pleasant, provocative, sweet, loyal, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "beautiful, appealing, charming, cute, dazzling, delicate, delightful, elegant, exquisite, fascinating, good-looking, gorgeous, graceful, grand, handsome, lovely, magnificent, marvelous, pleasing, pretty, splendid, stunning, superb, wonderful, admirable, angelic, beauteous, bewitching, classy, famous, honored, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "arm-unsure", "eyesAA": "-"},
+{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "suspicious, doubtful", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "exciting, appealing, astonishing, breathtaking, dramatic, flashy, hectic, impressive, interesting, intriguing, lively, provocative, stimulating, thrilling, agitated, annoyed, delighted, disturbed, eager, enthusiastic, hysterical, nervous, passionate, thrilled, animated, aroused, awakened, charged, discomposed, disconcerted, inflamed, moved, piqued, provoked, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Sorry, sad, pitiful, apologies, apology, sorrowful,unhappy,", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "hello, welcome, bye, see you, good bye, Hi, ", "armsAA": "arm-wave", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "panic, scare, anxious, nervous, scared, scary, frightened, suspicious, chilling, concern, worry, horror, horrify, fear, spooky, ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "impact, astonishing, extraordinary, shocking, amazed, amazing, astonish, astonished, impacted, shocked, impacting, surprise, surprising, dominant, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "collapse, earthquake, shocking, shock, collapsing, scare, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "arm-process-control", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, bitter, displeasing, failing, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "valuable, good at, useful, worthy, skilled, experienced, proficient, expert, competent, efficient, experienced, licensed, qualified, skillful, professional, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "hate", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "complex, headache, baffle, befuddle, bemuse, complicate, confound, daze, demoralize, disconcert, disorient, distract, embarrass, fluster, frustrate, involve, misinform, mislead, baffling, bewildering, complex, complicated, confounding, difficult, disconcerting, perplexing, upsetting", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "call me. contact me, ", "armsAA": "arm-call", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "altercation, argue, battle, brawl,clash, combat, conflict, confrontation, contest, controversy, disagreement, dispute, duel, exchange, feud, match, melee, quarrel, riot, rivalry, scuffle, skirmish, struggle, war, wrangling, fight, attack, battle, challenge, clash, protect, resist, argue, combat, engage in, force, oppose, resist, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "altercation, arguing, clashing, combating, conflicting, confrontation, Struggling, wrangling, fighting, attacking, clashing, resisting, arguing, combating, forcing, opposing, resisting,", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "destroy, consume, crush, damage, dismantle, eradicate, gut, impair, kill, maim, ravage, raze, ruin, sabotage, shatter, smash, wipe out, wreck, destroying, damaging, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "long, deep, great, high, lengthy, protracted, tall, continued, elongate, elongated, enduring, enlarged, expanded, lasting, lengthened, lingering, prolonged, running, stretch, stretching, sustained, towering, distant, ", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "short", "armsAA": "arm-compare-smaller", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 1,"headAA": "-","keywords": "longer, larger", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "shorter, briefer, curtailed, diminished, less, lessened, lower,more concise, reduced, reducing, diminishing, briefing, lowering, lesser ", "armsAA": "arm-compare-smaller", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "enlarge, bigger, more, larger, largest, better, ", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "smaller, lesser", "armsAA": "arm-compare-smaller", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "several, some", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "a few, a little, a bit, barely, hardly, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "none, nothing, noway, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "a lot,  many, massive, lots of, countless, substantial, considerable, extensive, enormous, ", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "arm-greeting", "eyesAA": "-"},{"priority": , "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "comfortable, elementary, reachable, possible, comfy, peaceful, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "arm-greeting", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "awful, distressing, dreadful,  ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "difficult, tough, ambitious, arduous, burdensome, challenging, troublesome, puzzle, impossible, hard, ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "easy, accessible,clear,effortless,obvious,painless,simple,smooth,straightforward,uncomplicated, reachable, cozy", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "yours, yourself, them, those, that, these, you, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": " yes, yeah, i do, i am, we have, we do, you have, true, ok, i like, i love, you like, ya, ", "armsAA": "arm-me", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": " agree, admit, accept, accustomed, acknowledged, allowed, approved, authorized, established, confirmed, supported, permitted, allow, comply, welcomed, agreed, grant, granted, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "no, nothing, cannot, can''t, unable, never, don''t know", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "correct, right, appropriate, equitable, factual, legitimate, perfect, precise, proper, strict, true, okay, accurately, justly, nicely, perfectly, precisely, properly, rightly, ", "armsAA": "arm-greeting", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "incorrect, wrong, erroneous, false, faulty, flawed, imprecise, improper, inaccurate, inappropriate, mistaken, unreliable, unsound, untrue, not true, not okay, fake, untrue, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 55, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "can you, could you, do you, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 85, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "well, i guess , i suppose, i think, maybe, perhaps, could, probably, might, actually, only, i believe, i suggest, likely, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "have to, must, need to, ought to, ought to, should, shall, going to, will, willing to, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "but, although, however, nevertheless, on the other hand, though, yet, aside from, other than, nonetheless, after all, despite, rather", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 35, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "and, along with, also, as a consequence, as well as, including, together with, besides, additionally, also, still, too, additionally, along with, as well, besides, in addition, likewise, withal, again, ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "likewise, again, more, still, further,  besides, additionally, furthermore, moreover, beyond, besides, as a consequence, better, longer,  beyond, in addition, what''s more, better, longer, higher,  ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 1,"headAA": "-","keywords": "really, very,  quite, completely,  great, absolutely,  just, quite,  incredible, epic, certainly, actually, indeed, literally, surely, truly, undoubtely, unquestionably", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "normal, ordinary, simple, general, familiar, typical, common, so so, regular, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Profound, progressive, advanced, outstanding, Knowledgeable, enlightened, forward-looking, Visionary, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "alike, comparable, related, similar, familiar", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "abnormal, atypical, different, irregular, special, uncommon, unconventional, untraditional, unusual, exceptional, rare, anomalous, changing, disorderly, eccentric, extraordinary, imbalanced, inconsistent, infrequent, unsteady, variable, outstanding, exclusive, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "rare, extraordinary, limited, occasional, scarce, singular, strange, subtle, uncommon, unique, unlikely, unusual, narrow, cramped, definite, limited,  ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 1,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "stop, pause, freeze, bar, block, break, conclusion, pause, drop, end, hold on, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": " continue, advance, endure, extend, go on, will last, linger, maintain, progress, promote, pursue, remain, will stay, survive, sustain, hold, sustaining, continuing, lasting, enduring, extending, remaining, promoting, progressing, lingering, ", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "done, finished, completed, compassed, complete, completed, concluded, consummated, depleted,  drained, effected, ended, executed, exhausted, fixed, fulfilled, perfected, performed, realized, rendered, succeeded, terminated, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "uncertain, ambiguous,ambivalent, dubious, erratic, hazy, hesitant, insecure, precarious, questionable, risky, unclear, undecided, undetermined, unpredictable, unreliable,unresolved, unsettled, unsure, suspicous, doubtable, doubtful, questionable, ambiguous, arguable, puzzling, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 50, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "kind of, slightly, lightly, somewhat, at least, rather, moderately, sort of, to some extent, at least", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "conflicting, oppose, argue, assail, attack, debate, defy, deny, disagree, dispute, fight, prevent, protest, resist, assault, bar, battle, bombard, combat, confront, contradict, controvert, counter, counterattack, disapprove, encounter, expose, gainsay, hinder neutralize, reverse, taunt, thwart, withstand, object to, opposed, abide, combat, confront, continue, curb, defy, endure, forgo, maintain, prevent, refuse, repel, thwart, turn down, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "adaptable, adventurous, affable, affectionate, agreeable, ambitious, amiable, amicable, amusing, brave, bright, broad-minded, calm, careful, charming, communicative, compassionate, conscientious, considerate, convivial, courageous, courteous, creative, decisive, determined, diligent, diplomatic, discreet, dynamic, easygoing, emotional, energetic, enthusiastic, exuberant, fair-minded, faithful, fearless, forceful, friendly, funny, generous, gentle, good, gregarious, hard-working, helpful, honest, humorous, imaginative, impartial, independent, intellectual, intelligent, intuitive, inventive, kind, loving, loyal, modest, neat, nice, optimistic, passionate, patient, persistent, pioneering, philosophical, placid, plucky, polite, powerful, practical, pro-active, quick-witted, quiet, rational, reliable, reserved, resourceful, romantic, self-confident, self-disciplined, sensible, sensitive, shy, sincere, sociable, straightforward, sympathetic, thoughtful, tidy, tough, unassuming, understanding, versatile, warmhearted, willing, witty, attractive, absorbing, alluring, amiable, appealing, attractive, charismatic, cute, delightful, elegant, engaging, engrossing, fascinating, glamorous, graceful, inviting, likable, lovable, lovely, pleasant, provocative, sweet, loyal, ", "armsAA": "arm-rolling", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "Arrogant, Big-headed,  Self-centred, Vain, Boastful, Pompous, Aloof, Impolite, Inconsiderate, Thoughtless, Confrontational, Defensive, Hostile, Belligerent, Bitchy, Nasty, Bossy, Cruel, Domineering, Sneaky, Impatient, Unreliable, Jealous,  Careless, Irresponsible, Untidy, Cowardly,  Foolish,  Gullible,  Indecisive,  Weak-willed, Grumpy, Silly, infamous, disgraceful, egregious, hateful, heinous, ignominious, despicable, humiliating, shameful, immoral, corrupt, depraved, dishonest, indecent, nefarious, obscene, pornographic, shameless, sinful, unethical, unscrupulous, corrupted, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 75, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "evil, gloomy, nasty, ominous, rough, evil, gloomy, nasty, ominous, rough, unattractive, unpleasant, disagreeable,disgusting, repugnant, repulsive, unappealing, bad-looking, gross, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 65, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "cheerful, contented, delighted, ecstatic, elated, glad, joyful, joyous, jubilant, livelymerry,overjoyed, peaceful, pleasant, pleased, thrilled, upbeat, blessed", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, unhappy, pathetic, deplorable, feeble, heartbreaking, miserable, pitiful, poignant, sorry, woeful, ", "armsAA": "arm-unsure", "eyesAA": "-"},{"priority": 30, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "hello, welcome, bye, see you, good bye, Hi, ", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "impact, astonishing, extraordinary, shocking, amazed, amazing, astonish, astonished, impacted, shocked, impacting, surprise, surprising, dominant, ", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 80, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "angry, annoyed, bitter, enraged, exasperated, furious, heated, impassioned, indignant, irate, irritable, irritated, offended, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 40, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "love, like, wonder, admire, adore, approve, cherish, love, commend, compliment", "armsAA": "arm-greeting", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "unhappy, aversion, disapproval, disgust, displeasure, dislike,", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "hate", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "poor, poorly, impoverished, inconsiderable, insignificant, miniature, poor, teeny, thin, tiny, unimportant, delicate, feeble, frail, weak, fragile, junky, crummy, cheesy, crappy, cruddy, garbage, disappointing, ", "armsAA": "arm-notknow", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "huge, enormous, extensive, giant, gigantic, great, humongous, immense, magnificent, mammoth, massive, tremendous, vast, immeasurable, oversize, big, large, ", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 70, "browAA": "-", "probability": 1,"headAA": "-","keywords": "cramped, limited, meager, microscopic, miniature, minuscule, modest, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, mini, cramped, limited, meager, microscopic, miniature, minuscule, narrow, paltry, poor, short, slight, small-scale, young, baby, bantam, diminutive, little, miniminute, petite, petty, scanty, shrimp, toy, trifling, bitty, humble, immature, inadequate, inconsequential, inconsiderable, insufficient, picayune, piddling, pint-sized, pitiful, pocket-sized, puny, runty, scrubby, stunted, tensy, teeny, trivial, undersized, unpretentious", "armsAA": "arm-compare-smaller", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "enlarge, bigger, more, larger, largest, better, ", "armsAA": "arm-contrast", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "several, some", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.2,"headAA": "-","keywords": "a few, a little, a bit, barely, hardly, ", "armsAA": "arm-point", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "a lot,  many, massive, lots of, countless, substantial, considerable, extensive, enormous, ", "armsAA": "arm-many", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "entirely, exactly, fully, purely, totally, wholly, utterly, completely", "armsAA": "arm-frame-big", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "everything, all, whole, several, plenty, full, entire, exact, full, quite, total, altogether, all in all, just, ", "armsAA": "arm-offer", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "exclusive, integral, total, unabridged,  choate, completed, concentrated, conclusive, consummate, every, exhaustive, fixed, fulfilled, full-length, in one piece, inclusive, outright, plenary, rounded, unabbreviated, uncut, undivided, unexpurgated, unqualified, utter, exceptional, conclusive, certain, accomplished, concentrated, ", "armsAA": "arm-frame-small", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "important, considerable, leading, main, popular, powerful, serious, significant, substantial, valuable, big league, big-time, consequential, eminent, heavy-duty, heavyweight, influential, major league, material, meaningful, momentous, paramount, prime, principal, prominent, super, super colossal,  weighty, ", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "contradict, diverge, vary, bracket, collate, conflict, depart, deviate, differentiate, mismatch, oppose, separate", "armsAA": "arm-greeting", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "amazing, affected, affect, affecting, astonishing, astounding, impressing, perplex, , stunning, awesome, amazed, astonish, impresive, outstanding, phenomenal", "armsAA": "arm-beat", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "astonishing, astounding, awesome, breathtaking, fantastic, incredible, marvelous, outrageous, phenomenal, remarkable, spectacular, superb, terrific,   unbelievable,  fabulous, ", "armsAA": "arm-compare-bigger", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.5,"headAA": "-","keywords": "narrow, cramped, definite, limited, precarious, precise, slender, slim, thin, tight, sad, bad, disgust, worse, shame, evil, inappropriate, rotten, nasty, horrible, debris, droppings, junk, litter, residue, rubbish, rubble, sediment, waste,awful, cheap, crummy, dreadful, lousy, poor, rough, sad, unacceptable, blah, bummer, diddly, downer, garbage, gross, imperfect, inferior, junky, synthetic, abominable, amiss, bad news, beastly, bottom out, careless, cheesy, crappy, cruddy, defective ,deficient, dissatisfactory, erroneous, fallacious, faulty, godawful, grody, grungy, depressing, disconcerting, discouraging, disheartening, distasteful, frustrating, mediocre, unpleasant, unsatisfying, awkward, ", "armsAA": "arm-rejection", "eyesAA": "-"},{"priority": 60, "browAA": "-", "probability": 0.8,"headAA": "-","keywords": "awful, distressing, dreadful,  ", "armsAA": "arm-beat", "eyesAA": "-"}]'
+animation_actions:
+  head-up:
+    - {name: 'ADD_HeadUp', duration: 1.6, begin: 0.21, max: 0.73, end: 0.92, channel: ['head']}
+  head-down:
+    - {name: 'ADD_HeadDownShort', duration: 1.6, begin: 0.21, max: 0.73, end: 0.94, channel: ['head']}
+    - {name: 'ADD_HeadDownLong', duration: 2.46, begin: 0.21, max: 0.75, end: 1.69, channel: ['head']}
+  head-left:
+    - {name: 'ADD_HeadL', duration: 1.85, begin: 0.02, max: 0.52, end: 1.08, channel: ['head']}
+  head-right:
+    - {name: 'ADD_HeadR', duration: 2.04, begin: 0.02, max: 0.54, end: 1.19, channel: ['head']}
+  head-aside:
+    - {name: 'ADD_HeadRUp', duration: 1.81, begin: 0.02, max: 0.42, end: 1.06, channel: ['head']}
+    - {name: 'ADD_HeadR', duration: 2.04, begin: 0.02, max: 0.54, end: 1.19, channel: ['head']}
+    - {name: 'ADD_HeadL', duration: 1.85, begin: 0.02, max: 0.52, end: 1.08, channel: ['head']}
+    - {name: 'ADD_HeadLUp', duration: 1.6, begin: 0.02, max: 0.38, end: 0.94, channel: ['head']}
+  head-tilt:
+    - {name: 'ADD_TiltRightShort', duration: 2.38, begin: 0.21, max: 0.73, end: 1.77, channel: ['head']}
+  head-tilt-long:
+    - {name: 'ADD_TiltRightLong', duration: 4.02, begin: 0.42, max: 0.94, end: 3.33, channel: ['head']}
+  nod-short:
+    - {name: 'ADD_AgreeTiltFront', duration: 2.1, begin: 0.04, max: 1.6, end: 1.67, channel: ['head']}
+    - {name: 'ADD_NodShort', duration: 2.38, begin: 0.33, max: 1.98, end: 2.08, channel: ['head']}
+  nod-long:
+    - {name: 'ADD_NodLong', duration: 2.77, begin: 0.19, max: 2.02, end: 2.21, channel: ['head']}
+  nod-heavy:
+    - {name: 'ADD_NodHeavy', duration: 1.81, begin: 0.08, max: 1.1, end: 1.46, channel: ['head']}
+    - {name: 'ADD_NodShort', duration: 2.38, begin: 0.33, max: 1.98, end: 2.08, channel: ['head']}
+  shake-short:
+    - {name: 'ADD_ShakeShort', duration: 1.19, begin: 0.02, max: 0.88, end: 1.08, channel: ['head']}
+    - {name: 'ADD_Shakeshort2', duration: 1.25, begin: 0.06, max: 0.83, end: 1.02, channel: ['head']}
+  shake-long:
+    - {name: 'ADD_ShakeLong', duration: 2.67, begin: 0.02, max: 1.85, end: 2.31, channel: ['head']}
+    - {name: 'ADD_ShakeSoft', duration: 2.98, begin: 0.31, max: 1.46, end: 1.77, channel: ['head']}
+    - {name: 'ADD_ShakeSoft2', duration: 0, begin: 0, max: 0, end: 0, channel: ['head']}
+  shake-firmly:
+    - {name: 'ADD_ShakeFirmly', duration: 2.15, begin: 0.25, max: 1.5, end: 1.75, channel: ['head']}
+  shake-heavy:
+    - {name: 'ADD_ShakeHeavy', duration: 1.79, begin: 0.21, max: 1.15, end: 1.35, channel: ['head']}
+  wobbling:
+    - {name: 'ADD_Wobbling1', duration: 2.35, begin: 0.21, max: 0.58, end: 1.71, channel: ['head']}
+    - {name: 'ADD_Wobbling2', duration: 2.48, begin: 0.21, max: 0.83, end: 1.83, channel: ['head']}
+    - {name: 'ADD_Wobbling3', duration: 2.38, begin: 0.04, max: 0.71, end: 1.69, channel: ['head']}
+  brow-up-short:
+    - {name: 'ADD_BrowsUpShort', duration: 1.54, begin: 0.02, max: 0.48, end: 0.88, channel: ['brows']}
+  brow-up-normal:
+    - {name: 'ADD_BrowsUpNormal', duration: 1.31, begin: 0.02, max: 0.81, end: 0.92, channel: ['brows']}
+  brow-up-long:
+    - {name: 'ADD_BrowsUpLong', duration: 2.98, begin: 0.02, max: 2.19, end: 2.42, channel: ['brows']}
+  brow-center-up:
+    - {name: 'ADD_CenterUpShort', duration: 1.33, begin: 0.21, max: 0.6, end: 0.73, channel: ['brows']}
+  brow-center-up-long:
+    - {name: 'ADD_CenterUpLong', duration: 3.25, begin: 0.21, max: 2.42, end: 2.63, channel: ['brows']}
+    - {name: 'ADD_CenterUpLong2', duration: 4.85, begin: 0.25, max: 1.83, end: 3.54, channel: ['brows']}
+  brow-down-short:
+    - {name: 'ADD_BrowsDownShort', duration: 1.08, begin: 0.02, max: 0.48, end: 0.65, channel: ['brows']}
+    - {name: 'ADD_BrowsDown', duration: 2.79, begin: 0.21, max: 1.29, end: 2.08, channel: ['brows']}
+  brow-down-normal:
+    - {name: 'ADD_BrowsDownNormal', duration: 1.31, begin: 0.02, max: 0.71, end: 0.88, channel: ['brows']}
+  brow-down-long:
+    - {name: 'ADD_BrowsDownLong', duration: 2.27, begin: 0.02, max: 1.67, end: 1.83, channel: ['brows']}
+  brow-doubt:
+    - {name: 'ADD_DoubtShort', duration: 1.79, begin: 0.13, max: 1.15, end: 1.25, channel: ['brows']}
+  brow-doubt-long:
+    - {name: 'ADD_DoubtLong', duration: 3.04, begin: 0.19, max: 2.58, end: 2.71, channel: ['brows']}
+    - {name: 'ADD_DoubtLong2', duration: 3.98, begin: 0.21, max: 2.19, end: 2.71, channel: ['brows']}
+    - {name: 'ADD_DoubtLong3', duration: 2.79, begin: 0.21, max: 1.29, end: 2.08, channel: ['brows']}
+  eyelid-half-close:
+    - {name: 'ADD_EyeHalfCloseLong', duration: 1.94, begin: 0.02, max: 1.38, end: 1.46, channel: ['eyelids']}
+    - {name: 'ADD_EyeHalfCloseShort', duration: 1.21, begin: 0.02, max: 0.23, end: 0.67, channel: ['eyelids']}
+  eyelid-widely-open:
+    - {name: 'ADD_EyesWideOpenSmall', duration: 2.5, begin: 0.02, max: 1.56, end: 2.13, channel: ['eyelids']}
+    - {name: 'ADD_EyesWideOpenBig', duration: 2.19, begin: 0.02, max: 1.21, end: 1.88, channel: ['eyelids']}
+  eye-left:
+    - {name: 'ADD_EyesLeft', duration: 1.54, begin: 0.02, max: 0.23, end: 0.96, channel: ['eyes']}
+  eye-right:
+    - {name: 'ADD_EyesRight', duration: 1.48, begin: 0.02, max: 0.25, end: 1, channel: ['eyes']}
+  eye-up:
+    - {name: 'ADD_EyesUp', duration: 1.58, begin: 0.02, max: 0.38, end: 1.06, channel: ['eyes']}
+  eye-down:
+    - {name: 'ADD_EyesDown', duration: 2.19, begin: 0.02, max: 0.44, end: 1.23, channel: ['eyes']}
+  eye-around:
+    - {name: 'ADD_EyesLeftRightUp', duration: 4.81, begin: 0.02, max: 2.29, end: 3.23, channel: ['eyes']}
+  eye-corner:
+    - {name: 'ADD_EyesRightDown', duration: 1.9, begin: 0.02, max: 0.4, end: 1.02, channel: ['eyes']}
+    - {name: 'ADD_EyesRightUp', duration: 2.21, begin: 0.02, max: 0.42, end: 1.17, channel: ['eyes']}
+    - {name: 'ADD_EyesLeftDown', duration: 1.56, begin: 0.02, max: 0.31, end: 0.83, channel: ['eyes']}
+    - {name: 'ADD_EyesLeftUp', duration: 1.69, begin: 0.02, max: 0.25, end: 0.94, channel: ['eyes']}
+  eye-side:
+    - {name: 'ADD_EyesLeft', duration: 1.54, begin: 0.02, max: 0.23, end: 0.96, channel: ['eyes']}
+    - {name: 'ADD_EyesRight', duration: 1.48, begin: 0.02, max: 0.25, end: 1, channel: ['eyes']}
+    - {name: 'ADD_EyesUp', duration: 1.58, begin: 0.02, max: 0.38, end: 1.06, channel: ['eyes']}
+    - {name: 'ADD_EyesDown', duration: 2.19, begin: 0.02, max: 0.44, end: 1.23, channel: ['eyes']}
+  arm-unsure:
+    - {name: 'SIT_0-R_approximation', duration: 3.38, begin: 0.71, max: 2.21, end: 2.63, channel: ['arms']}
+  arm-beat:
+    - {name: 'SIT_1-R_Important', duration: 4.67, begin: 0.83, max: 3.25, end: 3.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Important', duration: 4.13, begin: 0.29, max: 2.42, end: 3.13, channel: ['arms']}
+    - {name: 'SIT_0-R_beat_chop_up', duration: 3.25, begin: 0.63, max: 1.67, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_0-R_beat_chop_down', duration: 2.58, begin: 0.63, max: 1.25, end: 1.88, channel: ['arms']}
+    - {name: 'SIT_0-R_beat_fist_in', duration: 2.5, begin: 0.75, max: 1.46, end: 2.08, channel: ['arms']}
+    - {name: 'SIT_0-R_beat_fist_out', duration: 2.92, begin: 0.42, max: 1.13, end: 1.67, channel: ['arms']}
+  arm-me:
+    - {name: 'SIT_0-R_deictic_gestures_me', duration: 3.25, begin: 0.92, max: 1.75, end: 2.42, channel: ['arms']}
+    - {name: 'SIT_1-R_Me', duration: 4.75, begin: 0.83, max: 2, end: 3.25, channel: ['arms']}
+    - {name: 'SIT_1-L_Me', duration: 5.08, begin: 0.83, max: 2.33, end: 3.58, channel: ['arms']}
+  arm-you:
+    - {name: 'SIT_0-R_deictic_gestures_you', duration: 3.42, begin: 0.67, max: 1.46, end: 2.33, channel: ['arms']}
+    - {name: 'SIT_0-L_deictic_gestures_left', duration: 3.92, begin: 0.79, max: 1.67, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_0-R_deictic_gestures_right', duration: 3.71, begin: 0.67, max: 1.67, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_0-L_deictic_gestures_we', duration: 3.13, begin: 0.71, max: 2.29, end: 2.75, channel: ['arms']}
+    - {name: 'SIT_1-L_Youall', duration: 5.13, begin: 0.63, max: 3.33, end: 3.83, channel: ['arms']}
+    - {name: 'SIT_1-R_Youall', duration: 5.13, begin: 0.63, max: 3.33, end: 3.83, channel: ['arms']}
+    - {name: 'SIT_1-R_Likesth', duration: 4.63, begin: 0.67, max: 1.71, end: 2.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Likesth', duration: 4.63, begin: 0.67, max: 1.71, end: 2.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Intorducesomeone', duration: 3.58, begin: 0.5, max: 1.83, end: 2.67, channel: ['arms']}
+    - {name: 'SIT_1-R_Intorducesomeone', duration: 3.58, begin: 0.79, max: 1.83, end: 2.67, channel: ['arms']}
+    - {name: 'SIT_1-R_Present', duration: 4.17, begin: 0.71, max: 1.58, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_1-L_Present', duration: 4.17, begin: 0.71, max: 1.58, end: 2.5, channel: ['arms']}
+  arm-many:
+    - {name: 'SIT_1-L_3things', duration: 8.13, begin: 0.71, max: 5.08, end: 6.25, channel: ['arms']}
+    - {name: 'SIT_1-R_3things', duration: 8.13, begin: 0.71, max: 5.08, end: 6.25, channel: ['arms']}
+    - {name: 'SIT_1-L_Thanksfor3', duration: 7.54, begin: 0.83, max: 5, end: 5.83, channel: ['arms']}
+    - {name: 'SIT_1-R_Thanksfor3', duration: 7.54, begin: 0.83, max: 5, end: 5.83, channel: ['arms']}
+  arm-vawe:
+    - {name: 'SIT_0-L_hello', duration: 2.83, begin: 0.63, max: 2.08, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_1-R_Hello', duration: 3.83, begin: 0.42, max: 2.33, end: 2.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Hello', duration: 3.83, begin: 0.42, max: 2.33, end: 2.71, channel: ['arms']}
+    - {name: 'SIT_0-R_bye', duration: 2.54, begin: 0.63, max: 1.25, end: 1.67, channel: ['arms']}
+  arm-point:
+    - {name: 'SIT_1-R_Idea', duration: 4.79, begin: 0.5, max: 1.25, end: 2.29, channel: ['arms']}
+    - {name: 'SIT_1-L_Idea', duration: 4.79, begin: 0.5, max: 1.25, end: 2.29, channel: ['arms']}
+    - {name: 'SIT_1-L_Click', duration: 5, begin: 0.75, max: 2.13, end: 3.13, channel: ['arms']}
+    - {name: 'SIT_1-R_Click', duration: 5, begin: 0.75, max: 2.13, end: 3.13, channel: ['arms']}
+  arm-greeting:
+    - {name: 'SIT_1-L_Thumb_up', duration: 2.88, begin: 0.58, max: 1.33, end: 1.96, channel: ['arms']}
+    - {name: 'SIT_1-R_Thumb_up', duration: 2.88, begin: 0.58, max: 1.33, end: 1.96, channel: ['arms']}
+    - {name: 'SIT_1-B_Yo', duration: 3.79, begin: 0.83, max: 1.88, end: 2.88, channel: ['arms','arms']}
+  arm-heart:
+    - {name: 'SIT_1-B_Heart', duration: 6.5, begin: 1.33, max: 4.5, end: 5.46, channel: ['arms','arms']}
+  arm-frame-small:
+    - {name: 'SIT_0-B_frame_small', duration: 3.42, begin: 0.83, max: 1.42, end: 2.38, channel: ['arms','arms']}
+  arm-frame-big:
+    - {name: 'SIT_0-B_frame_big', duration: 3.25, begin: 0.42, max: 1.25, end: 1.83, channel: ['arms','arms']}
+  arm-compare-smaller:
+    - {name: 'SIT_0-B_contrasts_smaller', duration: 5.08, begin: 0.63, max: 3.33, end: 3.63, channel: ['arms','arms']}
+  arm-compare-bigger:
+    - {name: 'SIT_0-B_contrasts_bigger', duration: 4.21, begin: 0.5, max: 2.5, end: 2.92, channel: ['arms','arms']}
+    - {name: 'SIT_1-B_Smallandbig', duration: 6.21, begin: 1.04, max: 3.92, end: 4.79, channel: ['arms','arms']}
+  arm-contrast:
+    - {name: 'SIT_1-R_1and2', duration: 5.17, begin: 0.58, max: 3.33, end: 4.17, channel: ['arms']}
+    - {name: 'SIT_1-L_1and2', duration: 5.17, begin: 0.58, max: 3.33, end: 4.17, channel: ['arms']}
+  arm-offer:
+    - {name: 'SIT_0-L_offer', duration: 3.54, begin: 0.92, max: 1.88, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_0-R_deictic_gestures_you', duration: 3.42, begin: 0.67, max: 1.46, end: 2.33, channel: ['arms']}
+    - {name: 'SIT_0-L_deictic_gestures_left', duration: 3.92, begin: 0.79, max: 1.67, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_0-R_deictic_gestures_right', duration: 3.71, begin: 0.67, max: 1.67, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_1-L_Intorducesomeone', duration: 3.58, begin: 0.5, max: 1.83, end: 2.67, channel: ['arms']}
+    - {name: 'SIT_1-R_Intorducesomeone', duration: 3.58, begin: 0.5, max: 1.83, end: 2.67, channel: ['arms']}
+    - {name: 'SIT_1-R_Present', duration: 4.17, begin: 0.71, max: 1.58, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_1-L_Present', duration: 4.17, begin: 0.71, max: 1.58, end: 2.5, channel: ['arms']}
+    - {name: 'SIT_1-L_Youall', duration: 5.13, begin: 0.63, max: 3.33, end: 3.83, channel: ['arms']}
+    - {name: 'SIT_1-R_Youall', duration: 5.13, begin: 0.63, max: 3.33, end: 3.83, channel: ['arms']}
+    - {name: 'SIT_1-R_Likesth', duration: 4.63, begin: 0.67, max: 1.71, end: 2.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Likesth', duration: 4.63, begin: 0.67, max: 1.71, end: 2.71, channel: ['arms']}
+  arm-process:
+    - {name: 'SIT_0-L_process_control', duration: 2.67, begin: 0.63, max: 1.54, end: 1.88, channel: ['arms']}
+    - {name: 'SIT_0-R_process_control', duration: 2.54, begin: 0.5, max: 1.38, end: 1.71, channel: ['arms']}
+    - {name: 'SIT_1-R_Important', duration: 4.67, begin: 0.83, max: 3.25, end: 3.71, channel: ['arms']}
+    - {name: 'SIT_1-L_Important', duration: 4.13, begin: 0.29, max: 2.42, end: 3.13, channel: ['arms']}
+    - {name: 'SIT_1-R_Idea', duration: 3.79, begin: 0.5, max: 1.42, end: 2.29, channel: ['arms']}
+    - {name: 'SIT_1-L_Idea', duration: 3.79, begin: 0.5, max: 1.42, end: 2.29, channel: ['arms']}
+    - {name: 'SIT_1-L_Click', duration: 5, begin: 0.75, max: 2.13, end: 3.13, channel: ['arms']}
+    - {name: 'SIT_1-R_Click', duration: 5, begin: 0.75, max: 2.13, end: 3.13, channel: ['arms']}
+  arm-reject:
+    - {name: 'SIT_0-R_rejection', duration: 2.88, begin: 0.63, max: 1.33, end: 2.08, channel: ['arms']}
+    - {name: 'SIT_0-R_rejection2', duration: 3.83, begin: 1.46, max: 2.75, end: 3.33, channel: ['arms']}
+    - {name: 'SIT_1-R_No', duration: 4.79, begin: 0.71, max: 3, end: 3.5, channel: ['arms']}
+    - {name: 'SIT_1-L_No', duration: 4.79, begin: 0.71, max: 3, end: 3.5, channel: ['arms']}
+  arm-rolling:
+    - {name: 'SIT_1-B_rolling', duration: 4.17, begin: 0.83, max: 2.92, end: 4.17, channel: ['arms']}
+  arm-notknow:
+    - {name: 'SIT_1-B_notknow', duration: 1.92, begin: 0.42, max: 0.88, end: 1.33, channel: ['arms']}
+    - {name: 'SIT_1-L_notknow', duration: 1.92, begin: 0.42, max: 0.88, end: 1.33, channel: ['arms']}
+    - {name: 'SIT_1-R_notknow', duration: 1.92, begin: 0.42, max: 0.88, end: 1.33, channel: ['arms']}
\ No newline at end of file
diff --git a/modules/performances/src/performances/nodes.py b/modules/performances/src/performances/nodes.py
new file mode 100644
index 0000000..2fa54c2
--- /dev/null
+++ b/modules/performances/src/performances/nodes.py
@@ -0,0 +1,599 @@
+#!/usr/bin/env python
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+# Nodes factory
+import os
+import pprint
+import time
+import logging
+import random
+import urllib
+import re
+
+from hr_msgs.msg import ChatMessage
+from hr_msgs.msg import Event
+from hr_msgs.msg import SetAnimation, SetExpression, Target, SomaState
+from hr_msgs.msg import TTS
+from performances.srv import RunByNameRequest
+from std_msgs.msg import String, Int32, Float32
+from threading import Timer
+from topic_tools.srv import MuxSelect
+import dynamic_reconfigure.client
+import requests
+import rospy
+from six import string_types
+
+logger = logging.getLogger('hr.performances.nodes')
+
+
+class Node(object):
+    # Create new Node from JSON
+    @staticmethod
+    def subClasses(cls):
+        return cls.__subclasses__() + [g for s in cls.__subclasses__()
+                                       for g in cls.subClasses(s)]
+
+    @classmethod
+    def createNode(cls, data, ros, start_time=0, id='', runner=None):
+        for s_cls in cls.subClasses(cls):
+            if data['name'] == s_cls.__name__:
+                # Runner is still needed for Pause
+                node = s_cls(data, ros, runner=runner)
+                node.id = id
+                if start_time > node.start_time:
+                    # Start time should be before or on node starting
+                    node.finished = True
+
+                    if start_time < node.end_time():
+                        node.started = True
+
+                return node
+        logger.error("Wrong node description: {0}".format(str(data)))
+
+    @classmethod
+    def create_empty_node_data(cls, type='speech', *args, **kwargs):
+        data = {
+            'name': type,
+            'start_time': 0.0,
+            'duration': 0.0,
+        }
+        for s_cls in cls.subClasses(cls):
+            if data['name'] == s_cls.__name__:
+                if hasattr(s_cls, 'data'):
+                    data.update(s_cls.data)
+        data.update(kwargs)
+        return data
+
+
+    def replace_variables_text(self, text):
+        variables = re.findall("{(\w*?)}", text)
+        for var in variables:
+            val = self.ros.get_variable(self.id, var) or ''
+            text = text.replace('{' + var + '}', val)
+        return text
+
+    def __init__(self, data, ros, **kwargs):
+        self.data = data
+        self.duration = max(0.1, float(data['duration']))
+        self.start_time = data['start_time']
+        self.started = False
+        self.started_at = 0
+        self.finished = False
+        self.id = ''
+        # Ros connections for accessing ROS topics and method
+        # TODO make ROS topics and services singletons class for shared use.
+        self.ros = ros
+
+    # By default end time is started + duration for every node
+    def end_time(self):
+        return self.start_time + self.duration
+
+    # Manages node states. Currently start, finish is implemented.
+    # Returns True if its active, and False if its inactive.
+    # TODO make sure to allow node publishing pause and stop
+    def run(self, run_time):
+        # ignore the finished nodes
+        if self.finished:
+            return False if not self.started else run_time < self.end_time()
+
+        if self.started:
+            # Time to finish:
+            if run_time >= self.end_time():
+                self.finished = True
+                self.stop(run_time)
+                return False
+            # elif self.ros.paused:
+            #     self.paused(run_time)
+            else:
+                self.cont(run_time)
+        else:
+            if run_time > self.start_time:
+                try:
+                    self.start(run_time)
+                except Exception as ex:
+                    logger.error(ex)
+                self.started = True
+                self.started_at = time.time()
+        return True
+
+    def __str__(self):
+        return pprint.pformat(self.data)
+
+    # Method to execute if node needs to start
+    def start(self, run_time):
+        pass
+
+    # Method to execute while node is stopping
+    def stop(self, run_time):
+        pass
+
+    # Method to call while node is running
+    def cont(self, run_time):
+        pass
+
+    # # Method to call while runner is paused
+    # def paused(self, run_time):
+    #     pass
+
+    # Method to get magnitude from either one number or range
+    @staticmethod
+    def _magnitude(magnitude):
+        try:
+            return float(magnitude)
+        except TypeError:
+            try:
+                # Randomize magnitude
+                return random.uniform(float(magnitude[0]), float(magnitude[1]))
+            except:
+                return 0.0
+
+
+class speech(Node):
+
+    data = {
+        'lang': 'en-US',
+        'voice': '',
+    }
+
+    def __init__(self, data, ros, **kwargs):
+        Node.__init__(self, data, ros)
+        if 'pitch' not in data:
+            self.data['pitch'] = 1.0
+        if 'speed' not in data:
+            self.data['speed'] = 1.0
+        if 'volume' not in data:
+            self.data['volume'] = 1.0
+        if 'voice' not in data:
+            self.data['voice'] = ''
+        # Backward compatibility
+        if self.data['lang'] in ['en', 'zh']:
+            self.data['lang'] = {'en': 'en-US', 'zh': 'cmn-Hans-CN'}[self.data['lang']]
+
+    def start(self, run_time):
+        self.say(self.data['text'], self.data['lang'], self.data['voice'])
+
+    def say(self, text, lang, voice):
+        # SSML tags for non-Cantonese
+        text = "|p|"+text
+        if 'HK' not in lang:
+            text = self._add_ssml(text)
+        if 'NONE' in lang:
+            return
+        text = self.replace_variables_text(text)
+        tts = TTS()
+        tts.text = text
+        tts.lang = lang
+        tts.voice = voice
+        self.ros.topics['tts'].publish(tts)
+
+    # adds SSML tags for whole text returns updated text.
+    def _add_ssml(self, txt):
+        # Ignore SSML if simplified syntax is used.
+        if re.search(r"[\*\@]\w+", txt):
+            return txt
+        attrs = ""
+        if self.data['speed'] != 1:
+            attrs += " rate=\"{:.2f}\"".format(self.data['speed'])
+        if self.data['pitch'] != 1:
+            attrs += " pitch=\"{:+.2f}%\"".format((self.data['pitch']-1)*100)
+        if self.data['volume'] != 1:
+            attrs += " volume=\"{:+.0f}dB\"".format((self.data['volume']-1)*100)
+        if len(attrs) > 0:
+            txt = "" + txt + ""
+        return txt
+
+class gesture(Node):
+    def start(self, run_time):
+            self.ros.topics['gesture'].publish(
+                SetAnimation(self.data['gesture'], 1, float(self.data['speed']), self._magnitude(self.data['magnitude'])))
+
+    def stop(self, run_time):
+        if not self.finished and self.started:
+            self.ros.topics['gesture'].publish(
+                SetAnimation(self.data['gesture'], 1, 0, -0.5))
+
+class arm_animation(Node):
+    def start(self, run_time):
+        self.ros.topics['arm_animation'].publish(
+            SetAnimation(self.data['arm_animation'], 1, float(self.data['speed']), self._magnitude(self.data['magnitude'])))
+
+    def stop(self, run_time):
+        if not self.finished and self.started:
+        # Remove arm animation by setting magnitude to 0
+            self.ros.topics['arm_animation'].publish(
+                SetAnimation(self.data['arm_animation'], 1, 0, 0))
+
+
+class emotion(Node):
+    def start(self, run_time):
+        self.ros.topics['emotion'].publish(
+            SetExpression(self.data['emotion'], self._magnitude(self.data['magnitude']),
+                         rospy.Duration.from_sec(self.data['duration'])))
+
+
+# Behavior tree
+class interaction(Node):
+    def start(self, run_time):
+        self.ros.topics['bt_control'].publish(Int32(self.data['mode']))
+        if self.data['chat'] == 'listening':
+            self.ros.topics['speech_events'].publish(String('listen_start'))
+        if self.data['chat'] == 'talking':
+            self.ros.topics['speech_events'].publish(String('start'))
+        time.sleep(0.02)
+        self.ros.topics['interaction'].publish(String('btree_on'))
+
+    def stop(self, run_time):
+        # Disable all outputs
+        self.ros.topics['bt_control'].publish(Int32(0))
+
+        if self.data['chat'] == 'listening':
+            self.ros.topics['speech_events'].publish(String('listen_stop'))
+        if self.data['chat'] == 'talking':
+            self.ros.topics['speech_events'].publish(String('stop'))
+        time.sleep(0.02)
+        self.ros.topics['interaction'].publish(String('btree_off'))
+
+
+# Rotates head by given angle
+class head_rotation(Node):
+    def start(self, run_time):
+        self.ros.topics['head_rotation'].publish(Float32(self.data['angle']))
+
+
+class soma(Node):
+    def start(self, run_time):
+        s = SomaState()
+        s.magnitude = 1
+        s.ease_in.secs = 0
+        s.ease_in.nsecs = 1000000 * 300
+        s.name = self.data['soma']
+        self.ros.topics['soma_state'].publish(s)
+
+    def stop(self, run_time):
+        s = SomaState()
+        s.magnitude = 0
+        s.ease_in.secs = 0
+        s.ease_in.nsecs = 0
+        s.name = self.data['soma']
+        self.ros.topics['soma_state'].publish(s)
+
+
+class expression(Node):
+    pass
+    # def __init__(self, data, ros, **kwargs):
+    #     Node.__init__(self, data, ros)
+    #     self.shown = False
+    #
+    # def start(self, run_time):
+    #     try:
+    #         self.ros.services['head_pau_mux']("/" + self.ros.robot_name + "/no_pau")
+    #         logger.info("Call head_pau_mux topic {}".format("/" + self.ros.robot_name + "/no_pau"))
+    #     except Exception as ex:
+    #         logger.error(ex)
+    #     self.shown = False
+    #
+    # def cont(self, run_time):
+    #     # Publish expression message after some delay once node is started
+    #     if (not self.shown) and (run_time > self.start_time + 0.05):
+    #         self.shown = True
+    #         self.ros.topics['expression'].publish(
+    #             MakeFaceExpr(self.data['expression'], self._magnitude(self.data['magnitude'])))
+    #         logger.info("Publish expression {}".format(self.data))
+    #
+    # def stop(self, run_time):
+    #     try:
+    #         self.ros.topics['expression'].publish(
+    #             MakeFaceExpr('Neutral', self._magnitude(self.data['magnitude'])))
+    #         time.sleep(min(1, self.duration))
+    #         logger.info("Neutral expression")
+    #         self.ros.services['head_pau_mux']("/blender_api/get_pau")
+    #         logger.info("Call head_pau_mux topic {}".format("/blender_api/get_pau"))
+    #     except Exception as ex:
+    #         logger.error(ex)
+
+
+class kfanimation(Node):
+    pass
+    # def __init__(self, data, ros, **kwargs):
+    #     Node.__init__(self, data, ros)
+    #     self.shown = False
+    #     self.blender_disable = 'off'
+    #     if 'blender_mode' in self.data.keys():
+    #         self.blender_disable = self.data['blender_mode']
+    #
+    # def start(self, run_time):
+    #     self.shown = False
+    #     try:
+    #         if self.blender_disable in ['face', 'all']:
+    #             self.ros.services['head_pau_mux']("/" + self.ros.robot_name + "/no_pau")
+    #         if self.blender_disable == 'all':
+    #             self.ros.services['neck_pau_mux']("/" + self.ros.robot_name + "/cmd_neck_pau")
+    #     except Exception as ex:
+    #         # Dont start animation to prevent the conflicts
+    #         self.shown = True
+    #         logger.error(ex)
+    #
+    # def cont(self, run_time):
+    #     # Publish expression message after some delay once node is started
+    #     if (not self.shown) and (run_time > self.start_time + 0.05):
+    #         self.shown = True
+    #         self.ros.topics['kfanimation'].publish(
+    #             PlayAnimation(self.data['animation'], int(self.data['fps'])))
+    #
+    # def stop(self, run_time):
+    #     try:
+    #         if self.blender_disable in ['face', 'all']:
+    #             self.ros.services['head_pau_mux']("/blender_api/get_pau")
+    #         if self.blender_disable == 'all':
+    #             self.ros.services['neck_pau_mux']("/blender_api/get_pau")
+    #     except Exception as ex:
+    #         logger.error(ex)
+
+
+class pause(Node):
+    def __init__(self, data, ros, runner, **kwargs):
+        Node.__init__(self, data, ros)
+        self.runner = runner
+        self.event_callback_ref = False
+        self.timer = False
+
+        if 'topic' not in self.data.keys():
+            self.data['topic'] = False
+        if 'on_event' not in self.data.keys():
+            self.data['on_event'] = False
+        if 'event_param' not in self.data.keys():
+            self.data['event_param'] = False
+
+    def start_performance(self):
+        if self.timer:
+            self.timer.cancel()
+
+        if 'break' in self.data and not self.data['break']:
+            self.runner.interrupt()
+            self.runner.append_to_queue(self.data['on_event'])
+        else:
+            self.runner.run_full_performance(self.data['on_event'])
+
+    # This function needs to be reused in wholeshow to make sure consistent matching
+    @staticmethod
+    def event_matched(param, msg):
+        params = str(param).lower().split(',')
+        matched = False
+        for p in params:
+            try:
+                str(msg or '').lower().index(p.strip())
+                matched = True
+                continue
+            except ValueError:
+                matched = matched or False
+        return matched
+
+    def event_callback(self, msg=None):
+        self.delete_callback_ref()
+
+        if self.data['event_param']:
+            # Check if any comma separated
+            if not self.event_matched(self.data['event_param'], msg):
+                return False
+
+        if self.data['on_event']:
+            self.start_performance()
+        else:
+            self.resume()
+
+    def resume(self):
+        if not self.finished:
+            self.runner.resume()
+        if self.timer:
+            self.timer.cancel()
+
+    def start(self, run_time):
+        self.runner.pause()
+
+        if 'topic' in self.data:
+            topic = str(self.data['topic'] or '').strip()
+            if topic != 'ROSPARAM':
+                self.event_callback_ref = self.ros.register(topic, self.event_callback)
+                # Paused SPEECH event should not be forwarded to chatbot if its enabled.
+                # The filtering is in wholeshow node
+                if self.data['event_param']:
+                    # Currently only single PAUSE node can listen for keywords, so global param is fine.
+                    rospy.set_param('/performances/keywords_listening', self.data['event_param'])
+            else:
+                if self.data['event_param']:
+                    if rospy.get_param(self.data['event_param'], False):
+                        # Resume current performance or play performance specified
+                        self.timer = Timer(0.0, lambda: self.event_callback(self.data['event_param']))
+                        self.timer.start()
+                        return
+        try:
+            timeout = float(self.data['timeout'])
+            if timeout > 0.1:
+                self.timer = Timer(timeout, self.resume)
+                self.timer.start()
+        except (ValueError, KeyError) as e:
+            logger.error(e)
+
+    def delete_callback_ref(self):
+        if self.event_callback_ref:
+            self.ros.unregister(str(self.data['topic'] or '').strip(), self.event_callback_ref)
+            self.event_callback_ref = None
+
+    def stop(self, run_time):
+        self.delete_callback_ref()
+        if self.timer:
+            self.timer.cancel()
+
+    def end_time(self):
+        return self.start_time + 0.1
+
+
+class attention(Node):
+    # Find current region at runtime
+    def __init__(self, data, ros, **kwargs):
+        Node.__init__(self, data, ros)
+        self.topic = ['look_at', 'gaze_at']
+        self.times_shown = 0
+
+    @staticmethod
+    def get_random_axis_position(regions, axis):
+        """
+        :param regions: list of dictionaries
+        :param axis: string 'x' or 'y'
+        :return: position and matched regions
+        """
+
+        position = 0
+        matched = []
+
+        if regions:
+            regions = sorted(regions, key=lambda r: r[axis])
+            prev_end = regions[0][axis]
+            length = 0
+            lengths = []
+
+            for r in regions:
+                begin = r[axis]
+                end = begin + (r['width'] if axis == 'x' else r['height'])
+
+                if prev_end > begin:
+                    diff = prev_end - begin
+                    lengths.append([length - diff, length - diff + end - begin])
+                    begin = prev_end
+                else:
+                    lengths.append([length, length + end - begin])
+                length += max(0, end - begin)
+                prev_end = max(begin, end)
+
+            rval = random.random() * length
+
+            for i, length in enumerate(lengths):
+                if length[0] <= rval <= length[1]:
+                    matched.append(regions[i])
+                    if not position:
+                        position = regions[i][axis] + (regions[i]['width'] if axis == 'x' else regions[i]['height']) * (
+                            (rval - length[0]) / (length[1] - length[0]))
+        return position, matched
+
+    @staticmethod
+    # Gets x,y,z from given regions based on region type
+    def get_point_from_regions(all_regions, region_type):
+        regions = [{'x': r['x'], 'y': r['y'] - r['height'], 'width': r['width'], 'height': r['height']} for r in
+                   all_regions
+                   if r['type'] == region_type]
+        if regions:
+            y, matched = attention.get_random_axis_position(regions, 'x')
+            z, matched = attention.get_random_axis_position(matched, 'y')
+            # invert Y to match image in bg
+            return {
+                'x': 1,
+                'y': -y,
+                'z': z,
+            }
+        else:
+            # Look forward
+            return {'x': 1, 'y': 0, 'z': 0}
+
+    # returns random coordinate from the region
+    def get_point(self, region):
+        #  regions = rospy.get_param(
+        #     '/' + os.path.join("/hr/control/performances", os.path.dirname(self.id),
+        #                        "properties/regions"), [])
+        # if not(len(regions)):
+        regions = rospy.get_param('/hr/control/regions', [])
+        return self.get_point_from_regions(regions, region)
+
+    def set_point(self, point):
+        speed = 1 if 'speed' not in self.data else self.data['speed']
+        for topic in self.topic:
+            self.ros.topics[topic].publish(Target(point['x'], point['y'], point['z'], speed))
+
+    def cont(self, run_time):
+        if 'attention_region' in self.data and self.data['attention_region'] != 'custom':
+            if 'interval' in self.data and run_time > self.times_shown * self.data['interval'] or not self.times_shown:
+                self.set_point(self.get_point(self.data['attention_region']))
+                self.times_shown += 1
+
+        if not self.times_shown:
+            self.set_point(self.data)
+            self.times_shown += 1
+
+
+class look_at(attention):
+    # Find current region at runtime
+    def __init__(self, data, ros, **kwargs):
+        attention.__init__(self, data, ros)
+        self.topic = ['look_at', 'gaze_at']
+
+
+class gaze_at(attention):
+    # Find current region at runtime
+    def __init__(self, data, ros, **kwargs):
+        attention.__init__(self, data, ros)
+        self.topic = ['gaze_at']
+
+class scene(Node):
+    def start(self, run_time):
+        self.ros.topics['arf'].publish(self.data['scene'])
+
+    def stop(self, run_time):
+        pass
+
+class settings(Node):
+
+    def setParameters(self, rosnode, params):
+        try:
+            cl = dynamic_reconfigure.client.Client(rosnode, timeout=0.1)
+            params = self.set_variables(params)
+            cl.update_configuration(params)
+            cl.close()
+        except:
+            pass
+
+    def set_variables(self, params):
+        for k, v in params.items():
+            if isinstance(v, string_types):
+                params[k] = self.replace_variables_text(v)
+            else:
+                params[k] = v
+        return params
+
+    def start(self, run_time):
+        if self.data['rosnode']:
+            self.setParameters(self.data['rosnode'], self.data['values'])
diff --git a/modules/performances/src/performances/speech_motion.py b/modules/performances/src/performances/speech_motion.py
new file mode 100644
index 0000000..e6f3b69
--- /dev/null
+++ b/modules/performances/src/performances/speech_motion.py
@@ -0,0 +1,595 @@
+# -*- coding: utf-8 -*-
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+import os
+import yaml
+import requests
+import random
+import re
+import logging
+from copy import deepcopy
+import random
+
+logger = logging.getLogger('hr')
+if not logger.handlers:
+    logging.basicConfig()
+
+class SpeechMotionUtils:
+    SENTENCE_DELIMITERS = '(? 0:
+                actions = [a for a in actions if a['duration'] > 0]
+            animation = deepcopy(random.choice(actions))
+        except:
+            return None
+        return animation
+
+
+class SpeechMotionController:
+
+    def __init__(self, animation_library, nlu_server='http://127.0.0.1:8210/da', lipsync_delay=0.1, arms_main=False, min_arms_hold_time = 3, max_arms_hold_time = 5, animated_shoulders = False):
+        self.lipsync_delay = lipsync_delay
+        self.nlu_cache = {}
+        self.nlu_timeout = 2
+        self.keyword_rules = []
+        self.da_rules = []
+        self.library = AnimationActionLibrary(animation_library)
+        self.probability_modifier = 0  # 0 unchanged, -1 none rules applied and 1 all rules applied
+        self.min_arms_hold_time = min_arms_hold_time
+        self.max_arms_hold_time = max_arms_hold_time
+        self.animated_arms = True
+        self.animated_shoulders = animated_shoulders
+        self.nlu_server = nlu_server
+        self.skip_keyword_rules = False
+        pass
+
+    def arms_interval(self):
+        return random.uniform(self.min_arms_hold_time, self.max_arms_hold_time)
+
+    # Currently timeline format with TTS nodes are supported. All other nodes will be left untouched.
+    def animate_motion(self, motion, animate_arms=True):
+        animated = []
+        arms = self.animated_arms
+        self.animated_arms = animate_arms
+        self.motion_length = 0
+        for n in motion:
+            if n['name'] == 'speech':
+                animated += self.animate_speech_node(n)
+            if n.get('start_time', 0) + n.get('duration', 0) > self.motion_length:
+                self.motion_length =  n.get('start_time', 0) + n.get('duration', 0)
+        # Restore original setting
+        self.animated_arms = arms
+        return self.filter_animations(animated)
+
+    def apply_probability_modifier(self, probability):
+        return probability + probability * self.probability_modifier if self.probability_modifier < 0 \
+            else probability + (1 - probability) * self.probability_modifier
+
+    def neutral_arms(self, time):
+        return SpeechMotionUtils.create_node_data(name='arm_animation', duration=1, speed=1, magnitude=1, start_time=time, arm_animation='MAIN-2')
+
+    def filter_animations(self, animated):
+        # Needs to shuffle, so its not dependant on rule order
+        if len(animated) == 0:
+            return animated
+        random.shuffle(animated)
+        prioritized = sorted(animated, key=lambda k: 0 if 'sc_meta' not in k.keys() else k['sc_meta']['priority'],
+                             reverse=True)
+        i = 0
+        arm_animations = []
+
+        # Remove conflicting gestures by priority on channel
+        while i < len(prioritized):
+            if 'sc_meta' in prioritized[i].keys():
+                try:
+                    channels = prioritized[i]['sc_meta']['channel']
+                    # Gesture begin time
+                    block_time = [prioritized[i]['sc_meta']['begin'] + prioritized[i]['start_time'],
+                                  prioritized[i]['sc_meta']['end'] + prioritized[i]['start_time'],
+                                  ]
+                    j = i + 1
+                    while j < len(prioritized):
+                        try:
+                            if len(set(channels).intersection(prioritized[j]['sc_meta']['channel'])) > 0:
+                                # Same channel, so check if any lower priority animations are interupting
+                                if max(block_time[0], prioritized[j]['start_time']) <= \
+                                        min(block_time[1], prioritized[j]['start_time'] + prioritized[j]['duration']):
+                                    prioritized.pop(j)
+                                    continue
+                            j += 1
+                        except:
+                            j += 1
+                except Exception as e:
+                    logger.error("Filter animation error {}".format(e))
+            # capture all arm animation ending times, in case need to reset to neutral pose
+            if prioritized[i].get('name','') == 'arm_animation':
+                arm_animations.append(prioritized[i])
+            # update length of motion if it exceeds previous
+            if prioritized[i]['start_time'] + prioritized[i]['duration'] > self.motion_length:
+                self.motion_length = prioritized[i]['start_time'] + prioritized[i]['duration']
+            i += 1
+        # Need to reset to neutral after 5 seconds or so
+        if len(arm_animations) > 0:
+            #Sort by start time
+            arm_animations = sorted(arm_animations, key=lambda k: k['start_time'])
+            prev = {}
+            start_with_main = False
+            for a in arm_animations:
+                curr_name = a['arm_animation']
+                if not start_with_main:
+                    # Check for first arm animation, and if its not MAIN it together it will neutralize the psoe
+                    start_with_main = True
+                    if not 'MAIN' in curr_name:
+                        prioritized.append(self.neutral_arms(max(0,a['start_time']-0.5)))
+
+                prev_name = prev.get('arm_animation', '')
+                # Return to neutral pose for main animations only
+                if 'MAIN' in prev_name:
+                   # If there is transition in MAIN, he neutral should be added only if othe MAIN starts after more than max hold time
+                    if 'MAIN' in curr_name:
+                        if prev['start_time'] + prev['duration'] + self.max_arms_hold_time < a['start_time']:
+                            # Neutralize arms after interval
+                            prioritized.append(self.neutral_arms(prev['start_time'] + prev['duration'] + self.arms_interval()))
+                    # If next animation not a MAIN then always return to neutral, either at a time of the animation or (3-5secs later) or then the next animation starts
+                    else:
+                        prioritized.append(self.neutral_arms(min(prev['start_time'] + prev['duration'] + self.arms_interval(), a['start_time'])))
+                prev = a
+            if 'MAIN' in prev.get('arm_animation', ''):
+                prioritized.append(self.neutral_arms(min(prev['start_time'] + prev['duration'] + self.arms_interval(), self.motion_length)))
+
+        return prioritized
+
+    # returns update speech node merged with animations
+    def animate_speech_node(self, node):
+        try:
+            if not node.get('NLUData', False):
+                self.get_nlu_data(node)
+        except Exception as e:
+            logger.exception("NLU data exception {}".format(e))
+
+        added = []
+        if not self.skip_keyword_rules:
+            added += self.apply_keyword_rules(node)
+        added += self.apply_da_rules(node)
+
+        # # Add the speech for visualization
+        # added.append(Node.create_empty_node_data(type='speech', duration=node['duration'],
+        #                                          text=node['text'], lang='NONE', start_time=node['start_time']))
+        return added
+
+    # tries get NLUData, Should execute on another thread with timeout
+    def get_nlu_data(self, node):
+        r = requests.get(self.nlu_server, {'language': 'en-US', 'text': node['text']})
+        node['nlu_data'] = yaml.safe_load(r.text)
+        node['nlu_data']['word_tokens'] = SpeechMotionUtils.match_NLU_to_text_words(node['text_words'],
+                                                                                    node['nlu_data']['tokens'])
+        lemma = [(j, i['lemma'], i['pos']) for j,t  in enumerate(node['nlu_data']['word_tokens']) for i in t]
+        node['nlu_data']['words_index'] = [x[0] for x in lemma]
+        node['nlu_data']['lemma_words'] = [x[1] for x in lemma]
+        node['nlu_data']['pos_words'] = [x[2] for x in lemma]
+
+    def update_keyword_rules(self, rules):
+        sorted_rules = sorted(rules, key=lambda k: k.get('priority',0))
+        for r in sorted_rules:
+            r['words'] = [SpeechMotionUtils.split_text(k.strip(), to_words=True) for k in r['keywords'].split(',') if
+                          len(k.strip()) > 0]
+            r['index_words'] = [str(w.encode('ascii', 'ignore').decode()) for l in r['words'] for w in l]
+        self.keyword_rules = sorted_rules
+
+    def get_keyword_rules(self):
+        return self.keyword_rules
+
+    def apply_keyword_rules(self, node):
+        added = []
+        for rule in self.keyword_rules:
+            try:
+                added += self.process_keyword_rule(node, rule)
+            except Exception as e:
+                #logger.error("ERROR processing rule {} ith exception {}".format(rule, e))
+                pass
+        return added
+
+    @staticmethod
+    def subset(words, sentence):
+        matches = [sentence[i:i + len(words)] == words for i in range(0, len(sentence) - len(words) + 1)]
+        try:
+            return matches.index(True)+len(words)-1
+        except:
+            return False
+
+    @staticmethod
+    def negative_word_around(node, w):
+        # skip rules if they have negative words: no, not, can't don't
+        negatives = ['no', 'not', 'don\'t', 'can\'t']
+        if w > 0:
+            if node['text_words'][w - 1] in negatives:
+                return True
+        if w + 1 < len(node['words']):
+            if node['text_words'][w + 1] in negatives:
+                return True
+        return False
+
+
+    def process_keyword_rule(self, node, rule):
+
+        nodes = []
+        pos = rule.get('pos', False)
+        lemma = rule.get('lemma', False)
+        if pos and lemma:
+            # Fast check
+            matched = set(node['nlu_data']['lemma_words']).intersection(rule['index_words'])
+            if not matched:
+                return nodes
+            for word in matched:
+                try:
+                    lw = node['nlu_data']['lemma_words'].index(word)
+                    w = node['nlu_data']['words_index'][lw]
+                    if self.negative_word_around(node, w):
+                        continue
+                    nodes += self.apply_rule(rule, node, node['words'][w])
+                except Exception as e:
+                    logger.error("Error {} processing lemmas {} in  {}".format(e, w, node['text_words']))
+
+        # Check if there any overlapping words, for fast checking
+        if not set(node['text_words']).intersection(rule['index_words']):
+            return nodes
+        for phrase in rule['words']:
+            w = self.subset(phrase, node['text_words'])
+            if w is not False:
+                if self.negative_word_around(node, w):
+                    continue
+
+                if pos:
+                    skip = True
+                    # Need to match single POS for any of the phrase words
+                    for i in range (w-len(phrase)+1, w+1):
+                        for t in node['nlu_data']['word_tokens'][i]:
+                            if t['pos'] == pos:
+                                skip = False
+                    if skip:
+                        continue
+                try:
+                    nodes += self.apply_rule(rule, node, node['words'][w])
+                except:
+                    logger.info("Word {} {} failed.".format(w, node['words'][w]))
+        return nodes
+
+
+    def apply_rule(self, rule, node, word, ):
+        # Adds animations to rule KW and DA rule
+        nodes = []
+        if self.apply_probability_modifier(rule['probability']) > random.random():
+            # Add keyword gestures
+            animation = self.library.pick_animation(rule.get('browAA','-'))
+            if animation:
+                nodes.append(self.create_gesture(animation, node, word, rule))
+            animation = self.library.pick_animation(rule.get('headAA','-'))
+            if animation:
+                nodes.append(self.create_gesture(animation, node, word, rule))
+            animation = self.library.pick_animation(rule.get('eyesAA','-'))
+            if animation:
+                nodes.append(self.create_gesture(animation, node, word, rule))
+            animation = self.library.pick_animation(rule.get('eyelidsAA', 'none'))
+            if animation:
+                nodes.append(self.create_gesture(animation, node, word, rule))
+            if self.animated_arms:
+                animation = self.library.pick_animation(rule.get('armsAA','-'))
+                if animation:
+                    nodes.append(self.create_gesture(animation, node, word, rule, head_gestrue=False))
+            if self.animated_shoulders:
+                animation = self.library.pick_animation(rule.get('shouldersAA','-'))
+                if animation:
+                    nodes.append(self.create_gesture(animation, node, word, rule, head_gestrue=False))
+
+            # Special case for procedural animations:
+            # if rule['headAA'] == 'head-tilt':
+            #     nodes += self.create_head_tilt(node, word, rule)
+        return nodes
+
+
+    def update_da_rules(self, rules):
+        sorted_rules = sorted(rules, key=lambda k: k['priority'])
+        self.da_rules = sorted_rules
+
+
+    def get_da_rules(self):
+        return self.da_rules
+
+
+    def apply_da_rules(self, node):
+        added = []
+
+        for rule in self.da_rules:
+            try:
+                added += self.process_da_rule(node, rule)
+            except Exception as e:
+                logger.error("ERROR with DA rule: {}, exception {}".format(rule, e))
+        return added
+
+
+    def process_da_rule(self, node, rule):
+        try:
+            for da in node['nlu_data']['dialog_act_ranking']:
+                if da['confidence'] > rule['threshold']:
+                    if da['name'] == rule['act']:
+                        word = random.choice(node['words'])
+                        if rule['apply'] == 'first':
+                            word = node['words'][0]
+                        if rule['apply'] == 'last':
+                            word = node['words'][-1]
+                        if rule['apply'] == 'most important':
+                            try:
+                                m = w = -1
+                                for i, k in enumerate(node['nlu_data']['tokens']):
+                                    if k['attention'] > m:
+                                        m = k['attention']
+                                        w = i
+                                word = node['words'][w]
+                            except:
+                                pass
+                        return self.apply_rule(rule, node, word)
+
+                else:
+                    break
+        except:
+            pass
+        # nodes += self.apply_rule(rule, node, word)
+        return []
+
+    def create_gesture(self, animation, node, word, rule, head_gestrue=True):
+        start_time = node['start_time'] + word['end'] - animation['max']+self.lipsync_delay
+        start_time = max(0, start_time)
+        # speech_controller metadata
+        sc_meta = animation
+        sc_meta['priority'] = rule['priority']
+        if rule.get('act', False):
+            debug = 'Dialog ACT: {}'.format(rule.get('act'))
+        else:
+            debug = 'Keyword rule for word {} lemma {}'.format(word['name'], rule.get('lemma', False))
+        if head_gestrue:
+            gesture = SpeechMotionUtils.create_node_data(name='gesture', duration=animation['duration'], speed=round(random.uniform(animation.get('speed_min',1.0), animation.get('speed_max',1)),2),
+                                                  magnitude=[animation.get('magnitude_min',1), animation.get('magnitude_max',1)],
+                                                  start_time=start_time, gesture=animation['name'], sc_meta=sc_meta,  debug=debug)
+        else:
+            gesture = SpeechMotionUtils.create_node_data(name='arm_animation', duration=animation['duration'], speed=round(random.uniform(animation.get('speed_min',1.0), animation.get('speed_max',1)),2),
+                                                  magnitude=[animation.get('magnitude_min',1), animation.get('magnitude_max',1)],
+                                                  start_time=start_time, arm_animation=animation['name'], sc_meta=sc_meta, debug=debug)
+        return gesture
+
+
+    def create_head_tilt(self, node, word, rule):
+        start_time = max(0, node['start_time'] + word['end'] - 0.2)
+        duration = round(0.5 + 1 * random.random(), 2)
+        rad = round((0.05 + 0.1 * random.random()) * random.choice([1, -1]), 2)
+        sc_meta = {
+            'begin': 0.1,
+            'max': 0.2,
+            'end': duration + 0.05,
+            'channel': ['head_tilt'],
+            'priority': rule['priority']
+        }
+        nodes = []
+        nodes.append(SpeechMotionUtils.create_node_data(name='head_rotation', duration=duration, speed=2,
+                                                 angle=rad, start_time=start_time, sc_meta=sc_meta))
+        # Reset
+        nodes.append(SpeechMotionUtils.create_node_data(name='head_rotation', duration=0.1, speed=2,
+                                                 angle=0, start_time=start_time + duration))
+        return nodes
+
+        # Cleanup metadata, and ttsdata, not required
+
+
+    @staticmethod
+    def clean_nodes(nodes):
+        for n in nodes:
+            try:
+                del (n['sc_meta'])
+            except KeyError:
+                pass
+            try:
+                del (n['tts_data'])
+            except KeyError:
+                pass
+            try:
+                del (n['words'])
+            except KeyError:
+                pass
+            try:
+                del (n['nlu_data'])
+            except KeyError:
+                pass
+            try:
+                del (n['text_words'])
+            except KeyError:
+                pass
+
+class SpeechMotionAPI():
+    def __init__(self, cfg = None, nlu_server="http://127.0.0.1:8210/da"):
+        if cfg is None:
+            cfg=os.path.join(os.path.dirname(__file__), 'config.yaml')
+        with open(cfg, 'r') as stream:
+            try:
+                self.config = yaml.safe_load(stream)
+            except yaml.YAMLError as exc:
+                logger.error("error reading config. Exception: {}".format(exc))
+                return
+        self.controller = SpeechMotionController(self.config['animation_actions'], nlu_server=nlu_server)
+        self.controller.update_keyword_rules(yaml.safe_load(self.config['speech_motions']['keyword_rules']))
+        self.controller.update_da_rules(yaml.safe_load(self.config['speech_motions']['da_rules']))
+
+    def get_animations(self, ttsdata):
+        # no generation on interacting
+        nodes = SpeechMotionUtils.create_speech_data_from_tts_data(ttsdata)
+        animated = self.controller.animate_motion(nodes, animate_arms=True)
+        SpeechMotionController.clean_nodes(animated)
+        return animated
diff --git a/modules/performances/src/performances/weak_method.py b/modules/performances/src/performances/weak_method.py
new file mode 100644
index 0000000..efedc10
--- /dev/null
+++ b/modules/performances/src/performances/weak_method.py
@@ -0,0 +1,33 @@
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+import weakref
+
+
+class WeakMethod:
+
+    def __init__(self, f):
+        try:
+            self.f = f.im_func
+        except Exception: 
+            self.f = f.__func__
+        self.c = weakref.ref(self.f)
+
+    def __call__(self, *arg):
+        if self.c() is None:
+            raise TypeError('Method called on dead object')
+        self.f((self.c(), ) + arg)
diff --git a/modules/performances/srv/Current.srv b/modules/performances/srv/Current.srv
new file mode 100644
index 0000000..69efeb6
--- /dev/null
+++ b/modules/performances/srv/Current.srv
@@ -0,0 +1,5 @@
+---
+string performance
+float32 current_time
+bool running
+bool paused
diff --git a/modules/performances/srv/Load.srv b/modules/performances/srv/Load.srv
new file mode 100644
index 0000000..c3c2e35
--- /dev/null
+++ b/modules/performances/srv/Load.srv
@@ -0,0 +1,4 @@
+string id
+---
+bool success
+string performance
diff --git a/modules/performances/srv/LoadPerformance.srv b/modules/performances/srv/LoadPerformance.srv
new file mode 100644
index 0000000..393469b
--- /dev/null
+++ b/modules/performances/srv/LoadPerformance.srv
@@ -0,0 +1,3 @@
+string performance
+---
+bool success
diff --git a/modules/performances/srv/Pause.srv b/modules/performances/srv/Pause.srv
new file mode 100644
index 0000000..9f6a297
--- /dev/null
+++ b/modules/performances/srv/Pause.srv
@@ -0,0 +1,3 @@
+---
+bool success
+float64 time
diff --git a/modules/performances/srv/Resume.srv b/modules/performances/srv/Resume.srv
new file mode 100644
index 0000000..9f6a297
--- /dev/null
+++ b/modules/performances/srv/Resume.srv
@@ -0,0 +1,3 @@
+---
+bool success
+float64 time
diff --git a/modules/performances/srv/Run.srv b/modules/performances/srv/Run.srv
new file mode 100644
index 0000000..96e421b
--- /dev/null
+++ b/modules/performances/srv/Run.srv
@@ -0,0 +1,3 @@
+float64 startTime
+---
+bool success
diff --git a/modules/performances/srv/RunByName.srv b/modules/performances/srv/RunByName.srv
new file mode 100644
index 0000000..04d5d1b
--- /dev/null
+++ b/modules/performances/srv/RunByName.srv
@@ -0,0 +1,3 @@
+string id
+---
+bool success
\ No newline at end of file
diff --git a/modules/performances/srv/SetProperties.srv b/modules/performances/srv/SetProperties.srv
new file mode 100644
index 0000000..dd072b9
--- /dev/null
+++ b/modules/performances/srv/SetProperties.srv
@@ -0,0 +1,4 @@
+string id
+string properties
+---
+bool success
diff --git a/modules/performances/srv/Stop.srv b/modules/performances/srv/Stop.srv
new file mode 100644
index 0000000..9f6a297
--- /dev/null
+++ b/modules/performances/srv/Stop.srv
@@ -0,0 +1,3 @@
+---
+bool success
+float64 time
diff --git a/modules/performances/test/test_speech.py b/modules/performances/test/test_speech.py
new file mode 100755
index 0000000..2d85b74
--- /dev/null
+++ b/modules/performances/test/test_speech.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+##
+## Copyright (C) 2017-2025 Hanson Robotics
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see .
+##
+
+TEST_DATA = [{'duration': 3.605771,
+             'end': 3.605771,
+             'name': 'Hello there. I am Sophia. What is your name?',
+             'start': 0.0,
+             'type': 'text'},
+            {'end': 0.33539584279060364,
+             'name': 'hello',
+             'start': 0.030000001192092896,
+             'type': 'word'},
+            {'end': 0.6391458511352539,
+             'name': 'there',
+             'start': 0.33539584279060364,
+             'type': 'word'},
+            {'end': 1.1891666650772095,
+             'name': 'i',
+             'start': 1.0391458421945572,
+             'type': 'word'},
+            {'end': 1.2893333435058594,
+             'name': 'am',
+             'start': 1.1891666650772095,
+             'type': 'word'},
+            {'end': 1.8942708373069763,
+             'name': 'sophia',
+             'start': 1.2893333435058594,
+             'type': 'word'},
+            {'end': 2.4396458864212036,
+             'name': 'what',
+             'start': 2.294270873069763,
+             'type': 'word'},
+            {'end': 2.5999792218208313,
+             'name': 'is',
+             'start': 2.4396458864212036,
+             'type': 'word'},
+            {'end': 2.777625024318695,
+             'name': 'your',
+             'start': 2.5999792218208313,
+             'type': 'word'},
+            {'end': 3.205770790576935,
+             'name': 'name',
+             'start': 2.777625024318695,
+             'type': 'word'}]
+
+
+
+from performances.speech_motion import SpeechMotionAPI
+import yaml
+import os
+if __name__ == '__main__':
+    if os.path.dirname(__file__):
+        fn = os.path.dirname(__file__)+'/test.yaml'
+    else:
+        fn = 'test.yaml'
+    with open(fn, 'r') as f:
+        data = yaml.safe_load(f)
+        data = yaml.safe_load(data['data'])
+    api =SpeechMotionAPI(nlu_server='http://127.0.0.1:8102/v1.0/nlu/da')
+    import time
+    print('start')
+    t = time.time()
+    animations = api.get_animations(data)
+    print(time.time() -t)
+    #print(animations)
+
+
diff --git a/modules/performances/version b/modules/performances/version
new file mode 100644
index 0000000..0b9c019
--- /dev/null
+++ b/modules/performances/version
@@ -0,0 +1 @@
+0.3.12