mimoLive® - 用户手册

通用选择器
仅限精确匹配
在标题中搜索
在内容中搜索
帖子类型选择器

手册 - 内容表

遥控预置API

目录

如果你正在创建一个自定义图层,甚至有可能在你的图层中包括自定义控制预置。如果你的图层有控制你的图层的实时行为的按钮,这就很方便了。

数据结构

下面的数据结构是一个输出样本,需要在你的组合中的`tvOut_ControlRepresentations`结构输出键下出现:

{
  "tvOut_ControlRepresentations": [
    {
      "title": "Compact Cut's",
      "buttons": [
        {
          "actions": [
            {
              "layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
              "variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
              "type": "signal",
              "signalKey": "tvGroup_Control__Cut_1_TypeSignal",
              "signalName": "Cut 1"
            }
          ],
          "liveState": {
            "layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
            "variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
            "dynamicSourceId": "tvIn_VideoSourceAImage"
          },
          "sourcePreview": {
            "layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
            "variantId": "F6F52194-06DE-462E-983A-8D505C533A69",
            "dynamicSourceId": "tvIn_VideoSourceAImage"
          },
          "color": "#BBBBBB",
          "width": 1,
          "height": 1,
          "x": 0,
          "y": 0,
          "icon": "facetime-video",
          "dynamicText": {
            "template": "{{inputputValues.tvIn_VideoSourceAName}}",
            "layerId": "03627C25-CC8A-474F-A738-C4DEB3353FA4",
            "variantId": "F6F52194-06DE-462E-983A-8D505C533A69"
          }
        }
      ]
    }
  ]
}

一个预设有一个 "标题 "和一个 "按钮 "阵列,但一个单一的按钮也是可以的。

*

键 "layerId "和 "variantId "需要用组合输入键 "tvIn_LayerIdentifier "和 "tvIn_RuntimeIdentifier "中的字符串数据动态地填写。

使用远程控制预设 API 在Quartz Composer中

mimoLive的内置层使用的是 LUA 脚本来动态生成这个数据结构,因为Quartz Composer并不支持自己生成数据结构。这 LUA 脚本包含一个复杂的函数addButton(),可以用来创建单个按钮的结构。通常情况下,你只需要使用这个函数,不需要修改它。因此,为你自己的层建立新的远程控制默认设置是非常容易的。

例如,这就是 LUA 脚本来生成停表层的远程控制。请注意,你可以通过改变代码的第15行到第29行来采用这段代码。

inLayerIdentifier = QC_STRING
inVariantIdentifier = QC_STRING
outControlRepresentations = QC_STRUCT
main = function()
  controlRepresentations = {}
  -- first representation
  controlRepresenation = {}
  -- {
    controlRepresenation["Title"] = "Stop Watch"
    buttons = {}
    -- {
      -- addButton(buttonsTable, buttonTitle, subTitle, positionX, positionY, width, height, color, icon, actionTarget, liveStateSource, previewSource)
      -- first row
      addButton(buttons, "{{outputValues.tvOut_TimeString}}", "", 0, 0, 2, 1, "#333333", "", "", "", "")
      addButton(buttons, "Live", "{\{name\}}", 2, 0, 1, 1, "#333333", "", "toggleLive", "layerVariant", "")
      -- second row
      addButton(buttons, "Start", "", 0, 1, 1, 1, "#33cc33", "play", "tvGroup_Control__Start_TypeSignal", "", "")
      addButton(buttons, "Stop", "", 1, 1, 1, 1, "#cc3333", "pause", "tvGroup_Control__Stop_TypeSignal", "", "")
      addButton(buttons, "Reset", "", 2, 1, 1, 1, "#cccc33", "stop", "tvGroup_Control__Reset_TypeSignal", "", "")
    -- }
    controlRepresenation["buttons"] = buttons
  -- }
  table.insert(controlRepresentations , controlRepresenation)
  outControlRepresentations = controlRepresentations
end
function addButton(buttonsTable, buttonTitle, buttonSubTitle, positionX, positionY, width, height, color, icon, actionTarget, liveStateSource, previewSource)
  local button = {}
  -- {
  if #buttonTitle > 0 then
    if string.find(buttonTitle, "{{") then
      -- dynamic titel
      local dynamicText = {}
      -- {
        dynamicText["layerId"] = inLayerIdentifier
        dynamicText["variantId"] = inVariantIdentifier
        dynamicText["template"] = buttonTitle
      -- }
      button["dynamicText"] = dynamicText
    else
      -- static title
      button["text"] = buttonTitle
    end -- if dynamic
  end -- if buttonTitle
  if #buttonSubTitle > 0 then
    if string.find(buttonSubTitle, "{{") then
      -- dynamic titel
      local dynamicSubText = {}
      -- {
        dynamicSubText["layerId"] = inLayerIdentifier
        dynamicSubText["variantId"] = inVariantIdentifier
        dynamicSubText["template"] = buttonSubTitle
      -- }
      button["dynamicSubText"] = dynamicSubText
    else
      -- static title
      button["subtext"] = buttonSubTitle
    end -- if dynamic
  end -- if buttonSubTitle
  button["x"] = positionX
  button["y"] = positionY
  button["width"] = width
  button["height"] = height
  if #color > 0 then
    button["color"] = color
  end -- if
  if #actionTarget > 0 then
    local actions = {}
    -- {
      local action = {}
      -- {
        action["layerId"] = inLayerIdentifier
        action["variantId"] = inVariantIdentifier
        if string.ends(actionTarget, "_TypeSignal") then
          action["type"] = "signal"
          action["signalKey"] = actionTarget
          action["signalName"] = buttonTitle
        elseif actionTarget == "toggleLive" then
          action["type"] = "toggleLive"
        else
          action["type"] = "toggleSwitch"
          action["toggleSwitchKey"] = actionTarget
          action["toggleSwitchName"] = buttonTitle
        end -- if
      -- }
      table.insert(actions , action)
    -- }
    button["actions"] = actions
  end -- if actionTarget
  if #liveStateSource > 0 then
    local liveState = {}
    -- {
      liveState["layerId"] = inLayerIdentifier
      liveState["variantId"] = inVariantIdentifier
      if string.starts(liveStateSource,"tvIn_VideoSource") then
        -- get the live state from a dynamic video source
        liveState["dynamicSourceId"] = liveStateSource
      elseif liveStateSource == "layerVariant" then
        -- nor more information needed
      else
        liveState["propertyPath"] = liveStateSource            end -- if
    -- }
    button["liveState"] = liveState
  end -- if liveState Source
  if #previewSource > 0 then
    local sourcePreview = {}
    -- {
      sourcePreview["layerId"] = inLayerIdentifier
      sourcePreview["variantId"] = inVariantIdentifier
      sourcePreview["dynamicSourceId"] = previewSource
    -- }
    button["sourcePreview"] = sourcePreview
  end -- if
  if #icon > 0 then
    -- See bottom of documentation page for list of avaiable icon names
    button["icon"] = icon
  end -- if
  -- }
  table.insert(buttonsTable, button)
end -- func
function string.starts(String,Start)
   return string.sub(String,1,string.len(Start))==Start
end
function string.ends(String,End)
   return End=='' or string.sub(String,-string.len(End))==End
end

1TP7吨的定位

当使用多个按钮时,按钮的布局必须手动控制。这意味着按钮是用 "x "和 "y "属性在网格上定位的,就像 "宽度 "和 "高度 "属性一样,是以网格单元的倍数给出的。位置是相对于按钮组被拖到的左上角网格单元而言的。

1TP7吨的行动

Buttons可以有多个行动,一个单一的行动,或者根本没有行动。有各种有效的行动目标和行动类型的组合。
请注意,"textInput "和 "numericInput "动作应该是独立的,因为不能保证在远程控制中的用户体验一致。

行动目标

行动目标是mimoLive文件内的元素。它们以分层的方式被处理:

文档ID "总是在运行时绘制,所以它不必出现在预设中。

  • 如果 "layerId "和 "variantId "都没有给出,行动将在文档本身被触发。
  • 如果给了 "layerId",该动作将在指定的层上被触发。
  • 如果 "layerId" 给出 "variantId",该动作将在指定的变量上被触发。只有在这种情况下,可以指定额外的 "toggleSwitchKey "或 "signalKey"(见下面的动作类型)。

行动类型

行动类型解释附加属性有效目标
拨动活页切换实时状态没有文件(开始/停止显示),层,变量
设置Live将直播状态设置为 "直播"没有文件(开始显示),层,变量
设置关闭将直播状态设置为 "关闭"没有文件(停止显示),层,变量
信号触发一个信号signalKey, signalName(推荐)。变体
拨动开关切换一个布尔型输入值toggleSwitchKey, toggleSwitchName(推荐)。变体
文本输入打开一个文本输入字段,在提交时,更新输入键的值。inputKey, inputName (推荐)层、变体、源
数字输入控制输入键的数值的滑块。inputKey, inputDescription (有最小值和最大值的对象), inputName (推荐)层、变体、源
*

"textInput" 和 "numericInput" 动作类型从 mimoLive 5.2 开始可用。

Button活的状态

"liveState "对象可用于配置按钮的理货灯状态,它可以是开(红色标记)、过渡(黄色标记)或关(无标记)。

真实的国家来源

与按钮动作目标类似,实时状态可以从多个来源获得:

  • 文档ID "总是在运行时绘制,所以它不必出现在预设中。
  • 如果 "layerId "和 "variantId "都没有给出,则使用文档的实时状态(展示已经开始或没有)。
  • 如果给出 "layerId",则使用该层的实时状态。
  • 如果给了 "layerId "和 "variantId",就会使用变体的实时状态。
    - 只有在这种情况下,可以指定额外的 "propertyPath",以表明必须使用变体的输入或输出值的布尔属性。
    - 另一种可能性(与propertyPath相互排斥!)是指定一个 "dynamicSourceId "属性,将实时状态查找重定向到一个源(通过ID获取),它尊重所选源的动态变化(例如在视频切换器中)。dynamicSourceId "的值在变体的输入值中被查找。

*给出属性的完整路径,从变体开始作为根,例如 "inputValues.some_Boolean_Property "或 "outputValues.other_Property"。

  • 如果给出 "sourceId",则使用源的实时状态。

Button Text

行动按钮可以显示主要和次要的文本行,两者都可以是静态或动态的。

初级文本

这个文本将是按钮将为用户做什么的主要指标。如果按钮预设包含一个文本属性,它是一个静态文本,将按原样显示。

另外,可以给一个dynamicText,使其包含mimoLive层或使用简单模板语法的变体属性。在模板字符串中,常规字符可以与大括号中的属性路径相结合:

"template": "{\{propertyPath\}}"

属性路径是相对于使用 "layerId"、"variantId"、"sourceId "和 "filterId "解析的对象而评估的。目标解析遵循这些规则:

  • 文档ID "总是在运行时绘制,所以它不必出现在预设中。
  • 如果 "layerId "和 "variantId "都没有给出,那么属性路径将相对于文档进行评估。
  • 如果给出了 "layerId"(和可选的 "variantId"),则属性路径是相对于一个层/变体进行评估的。
  • 一个变体的父层可以通过以 "layer "开头的路径来访问,例如 "aslayer.name"。
*

输入值和输出值的第一个路径段必须是camelCased("inputValues.tvIn..."),而不是API文档中的kebab-cased("input-values.tvIn...")。

  • 静态文本将始终优先于动态文本,因为这允许用户用一些可能对他们的情况更有用的自定义文本来覆盖动态文本。

二级文本

为了给用户提供关于一个按钮的更多信息,比如它的父层的名字,可以使用 "subtext "或 "dynamicSubText "属性给出一个辅助文本。

模板语法和对象解析遵循与主要文本完全相同的规则。

Button文字和图标尺寸

按钮上的文字和图标的大小可能根据上下文而变化。通过 "fontScale "选项,你可以指定一个相对于当前屏幕尺寸计算的默认尺寸的比例。"1 "将是默认尺寸。小于1(如0.8)将降低字体大小,大于1(如1.5)将增加字体大小。

Button预览

动作按钮可以显示它们所控制的源的预览图像,或文档中任何其他可用的源。

取决于来源是否是静态的(只有被拖入mimoLive的图像),一个静态的 PNG 表示的源被加载一次,它确实支持一个alpha通道。对于任何其他来源,一个 录像带 源的表现形式会定期更新。动态来源的目标刷新率是每秒5帧,但当发现网络连接速度不足以重复加载预览帧时,这个刷新率就会降低。

目前不支持在动作按钮上显示文件的程序输出。图层默认图像虽然在来源列表中不可见,但可供预览。

为了指定一个源预览,使用了一个对象解析机制:

  • 文档ID "总是在运行时绘制,所以它不必出现在预设中。
  • 如果给了 "sourceId",则使用该ID的源来进行预览。
  • 如果 "layerId"、"variantId "和 "dynamicSourceId "都给定了,源的ID将在 "dynamicSourceId "中的键下的指定层的变体上查找。这可以用来引用像视频切换器的源A-G,即使它们在文件中被改变。

Button 颜色

通过使用 "color "属性,按钮可以用任何颜色代码进行着色,这些代码可以在 HTML (例如,"#f80"、"#ff0088"、"橙色 "或 "rgb(255,66,88)")。

Button Icon

Buttons可以显示一个图标来表示它们的功能。要查看所有可用的图标列表,在mimoLive运行时打开http://localhost:8989/icons/demo.html,并启用远程控制。
使用图标的普通名称。例如,"向后 "或 "向下箭头"。

您的反馈

您如何评价您对mimoLive这个功能的体验?

电子邮件通讯

简体中文

加入全天候实时 Zoom® 演示

*必须

您需要从 验证码 提交表格。请注意,这样做会与第三方供应商共享数据。

更多信息