我在优酷OTT端做自动化制图 | 《优酷OTT互联网大屏前端技术实践》第五章

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 谈到自动化制图,主要有两种模式:一是自动化模式:依赖于服务化能力包装,将核心制图能力进行抽取,任何三方通过直接调用服务能力即可完成图片的合成,此种模式完全自动化,无需任何人工干预即可制作出符合指定条件的业务图片;二是半自动化模式:主要依赖于业务共性的提取与升华,将繁琐的重复的业务流程通过统一的范式来解决,或多或少的需要人工干预。人工干预一方面需要人力投入,另一方面意味着可以发挥人的主观创造性。成品图除了满足指定的共性外,也可以保证输出个性,这种个性与共性并存的方式不失为一种好的折中。

上一章:OTT端技术赋能之前端收单能力建设 | 《优酷OTT互联网大屏前端技术实践》第四章>>>

下一章:不一样的烟火:记OTT端半屏互动能力建设 | 《优酷OTT互联网大屏前端技术实践》第六章>>>

点击免费下载
《优酷OTT互联网大屏前端技术实践》>>>

test

作者| 阿里巴巴文娱技术 罄天

一、背景

图片作为网页中的重要组成元素,广泛存在于各种站点中,有些站点中的图片内容已经远远超过了其他网页内容总和。如何高效的、快速的制作业务图片就被广泛的提出来。阿里有很多自动化图片生产平台,如海棠,鲁班等。

谈到自动化制图,主要有两种模式:
一是自动化模式:依赖于服务化能力包装,将核心制图能力进行抽取,任何三方通过直接调用服务能力即可完成图片的合成,此种模式完全自动化,无需任何人工干预即可制作出符合指定条件的业务图片;

二是半自动化模式:主要依赖于业务共性的提取与升华,将繁琐的重复的业务流程通过统一的范式来解决,或多或少的需要人工干预。人工干预一方面需要人力投入,另一方面意味着可以发挥人的主观创造性。成品图除了满足指定的共性外,也可以保证输出个性,这种个性与共性并存的方式不失为一种好的折中。

二、OTT自动化制图

1、OTT自动化制图的起源

以前,优酷OTT侧有自动化制图的雏形,主要依据前端提供制图的工具平台,并将OTT主要合作厂商坑位图配置信息进行固化,然后运营在工具平台上做相应的坑位图合成。此模式在一定程度上满足了运营的合图需求。

在2019年,OTT侧开始尝试自动化制图。深入自动化制图的目的也很明显,主要基于以下痛点:

image.png

1)内容源与成品沉淀

我们观察到,阿里集团开始大面积的做自动化制图的尝试,有影响力的包括鲁班系统。从OTT的业务场景出发,这些平台存在一些不足:比如,所生产物料的最终落地形式是一次性的,忽略了物料的源和产物最核心的内容价值。从渠道维度来讲,OTT侧坑位图具有高度的同质性,不仅包括内容源如节目,而且从产物的角度也如此。例如《爱我就别想太多》,某电视厂商对资源位有明确的要求,而且优酷等平台方也需要这一内容源,内容源的价值就应该被放大。另外,优酷需要将同一个成品图,投放到不同渠道上,如果能从产物角度做沉淀,成品图才能发挥最大价值。

2)场景单一

制图工具解决的问题非常有限,主要是节目图的制作。前文提到,从内容源到成品图都缺少相应沉淀,这使得自动化制图服务的场景单一,和当前平台能力相比有明显差距。

现阶段OTT自动化制图涵盖了节目图、轮播、专题、动图等常见的制图场景,并结合自动化与半自动化双轨模式。半自动化场景下可以充分发挥运营创造性,基于原材料做创新性尝试;在自动化场景下,直接对接专题轮播系统,使得依赖于特定模板的制图无需人工参与。更近一步,在大数据推荐上也有相应场景,比如依赖于客户端唯一标识实现个性化的专题类推荐,这使得自动化制图一改之前"自动化"包装的外表。

3)分发效率

平台建立之初,从素材源到成品的完整链路都在本地环境完成,依赖于工具平台下载的成品图对接给运营、第三方进行投放。严重依赖于运营的人力投入,分发效率低,其原因是从内容源到成品库,到最终的分发链路缺乏一致性,所以使得整个系统没有“活”起来。

所以从平台建立开始,我们就在探索一条"活"的完整链路。通过链路的升级,不仅能完成内容源、成品库的沉淀,也包括最终分发链路的升级,从而摆脱传统工具平台面临的点状而非面状链路。

4)TOB厂商

"巧妇难为无米之炊",在自动化制图场景下,所谓的“米”就是模板,模板的格式包括但不限于PSD、SKETCH等,也包括如SVG,比如海棠。“米”是最核心的内容,如果不能从特定的场景中提取内容共性,那么自动化制图领域下的效率提升就非常有限,因此共性才是最应该被重视的特征。
并且,这种共性不仅存在于单个内容提供商,也存在于提供商之间。

2、OTT自动化制图的模式

自动化制图的优势非常明显:

第一是链路的升级:通过自动化制图的流程,可将原来"线下讨论-UED设计-效果确认-开发使用图片"的一次性长链路,转化为"UED设计模板-运营制图-自动/半自动分发"的非一次性完整流程,缩短沟通成本。

image.png

第二,内容共享红利:基于系统设计的高质量毛料库,产品库可进一步沉淀,打通多方,减少任何三方重复设计的可能性,将内容价值从原来的一方扩展到整个合作方生态,形成完整的内容回流链路;

第三,分发链路的建设:基于系统设计的成品图无需任何人工对接,可直接输出到渠道三方或者对接任何系统。现有可行的尝试,如专题系统自动化,大数据的个性化推荐场景等,完成从内容生产到内容自动分发的一体化能力建设。

制图效率环节:在半自动化制图场景,站外投放时间可从原来周级缩短为小时级,计件的时间成本减低50%~60%。而在自动化制图场景,无需任何人工干预的方式,使得自动化制图能真正发挥价值。

二、OTT自建自动化制图平台

可能会有人问,阿里已经有鲁班系统等自动化制图平台,为什么优酷OTT要自建?

1、为什么考虑自建?

与鲁班系统服务的(侧重商品化属性)场景不同, OTT场景更侧重媒资属性。图片主体维度的偏差,使得很多原本在商品制图场景下的规则被打破。比如一个简单的元素缩放操作,常规是按照等比加移动的方式解决。但是在以人物为中心的场景,这可能并不合理。因为在以人为主体的场景中,所有模板的指定需要考虑“人物”,而非人物所在元素图片的缩放,简单的说就是人脸,否则可能面临着人物缩放不满足模板要求的场景。因此,我们需要更进一步引入算法或人工打标的新思路。而且,除了元素缩放的特有场景,其实这种区别还很多。比如特定场景的模糊效果、动图绘制、自动化能力输出等等,这种基于特定业务特性的需求海棠确实难以做到定制。

2、商品图使用海棠

除了生产媒资海报图以外,OTT业务也需要生产商品图。比如天猫魔盒:

image.png

在没有自建系统之前,所有天猫魔盒的图片生产全部依赖于海棠。设计师从海棠后台传入模板,然后基于此模板在海棠上做相应的坑位图。但自建系统后也慢慢尝试切回到自有系统,主要原因有两个:

第一,内容回流: OTT业务本身是一闭环系统,媒资图和商品图缺一不可。这使得内容隔离渐渐不被接受。内容回流到自有系统后可以做统一管理、分发,享受现有系统提供的能力;

第二,定制化能力:设计师的需求往往依据业务的迭代渐渐变化,渐进增强成为一个常态。因此,当自己的述求不被满足或者不会被满足后可能会渐渐的丧失信心,进而转向新的平台。而自建系统正好提供了这样一个契机。下图提供了一个基于多模板拼接的述求。任何模板可以随意拖进工作区,然后对模板元素加工并设置模板特性,比如模板间距等。

image.png

三、OTT自动化制图的流程

关于自动化制图我们是如何实现的?整体流程可以简化为下图:

image.png

1、模板解析与数据格式化

自动化制图的前提是内容的共性,共性点更近一步的提取,就是模板,模板格式包括但不限于PSD、SKETCH、SVG等。任意一张成品图都可以看做是基于某一种模板生产出来的,这张成品图由不同图层构成,这和Photoshop中的图层是同一个道理。比如以下示例图就包含了角标、文案卖点、主题、主角、蒙版,背景图等诸多图层。通过对不同图层的自由组合、编辑,得到最终的成品图。

image.png

上面讲到模板是由不同的图层所描述的,更形象的,模板就是解析后得到的格式化数据,描述了模板中的元素信息,如位置、尺寸、数量等等。而成品图可以看做是基于这些约定(也可以看做是图纸)生产出来的最终元素。

image.png

上图就是对PSD的解析后获取到的模板缩略图。当然,正如前文所讲,解析后图片的存在形式也不再是图片本身,而是格式化的数据,一般是对应的JSON。该JSON包含了模板指定的所有元素信息:

const templateInfo = {
      "modelBase": {
        // 包括模板本身的信息,如尺寸等
      },
      "psdLayerInfoList": null,
      "person": [
        // 模板包含的主体个数,主体可以是人或者其他元素
        // 也包括主体的人脸信息等
      ],
      "bgPic": {
        //背景图
      },
      "themeGradientMask": [{
        //主题渐变
      }],
      "showNameH": [{
      }],
      "showNameV": [{
      }],
      "mMask": [{}],
      "mAppLogo": [{
      }],
      "mFontAppName": [{}]
 }

2、前端依据模板绘制流程

服务端做了统一的数据格式化后,给到前端的是格式化的数据,数据指定了模板包含的所有元素信息,前端基于该元素信息进行绘制。

1)分层绘制

HTML5页面中图层的概念大家应该已经很熟悉了。讲到HTML5的网页分层就需要深入理解Chrome渲染原理中的RenderObject,、RenderLayer、Graphiclayer等几棵树。

除了网页会分层以外,Canvas中绘制的元素也可以分层,分层绘制有很多优势。比如在游戏场景中,很多背景类的图层需要重绘的可能性远比动态元素,如障碍物低得多。因此,在每一帧的绘制行为中,可以绕过相应背景图的绘制,直接绘制当前场景变化的图层即可,这与Chrome网页分层要解决的问题是一样的。

class SmallMultiLayerCanvas {
  constructor(id) {
    this.id = id;
    this.canvas = document.getElementById(id);
    this.ctx2d = this.canvas.getContext('2d');
    this.layers = [];
  }
  static extend = function (defaults, options) {
    var extended = {}, prop;
    for (prop in defaults) {
      if (Object.prototype.hasOwnProperty.call(defaults, prop))
        extended[prop] = defaults[prop];
    }
    for (prop in options) {
      if (Object.prototype.hasOwnProperty.call(options, prop))
        extended[prop] = options[prop];
    }
    return extended;
  };
 // 添加图层
  addLayer(obj) {
    const layer = SmallCanvas.extend({
      id: Math.random().toString(36).substr(2, 5),
      show: true,
      render: function (canvas, ctx) { }
    }, obj);
    if (this.getLayer(layer.id) !== false) {
      return false;
    }
    this.layers.push(layer);
    return this;
  };
  //渲染所有图层
  render() {
    var canvas = this.canvas;
    var ctx = this.ctx2d;
    this.layers.forEach(function (item, index, array) {
      if (item.show)
        item.render(canvas, ctx);
    });
  };
  //获取一个图层
  getLayer(id) {
    var length = this.layers.length;
    for (var i = 0; i < length; i++) {
      if (this.layers[i].id === id)
        return this.layers[i];
    }
    return false;
  };
  // 移除一个图层
  removeLayer(id) {
    var length = this.layers.length;
    for (var i = 0; i < length; i++) {
      if (this.layers[i].id === id) {
        removed = this.layers[i];
        this.layers.splice(i, 1);
        return removed;
      }
    }
    return false;
  };
}

以上是一个简单的分层绘制的类,通过该类可以随意新增、移除、获取、渲染任意的图层。这也是很多复杂的多图层绘制框架的最核心思想,比如fabric.js或者konvajs。有了这样的图层管理框架,就可以根据服务端下发的格式化数据来绘制模板中指定的任意元素,以模板为图纸,生产出符合设计规定的核心产品。例如:

<canvas id="theCanvas" width="512" height="512"></canvas>

在该Canvas上,我们绘制出几个指定的图形看看效果如何:

const myCanvas = new SmallMultiLayerCanvas("theCanvas");
myCanvas.addLayer({
  id: 'background',
  render: function (canvas, ctx) {
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  }
})
  .addLayer({
    id: 'squares',
    render: function (canvas, ctx) {
      ctx.fillStyle = "#E5E059";
      ctx.fillRect(50, 50, 150, 150);
      ctx.fillStyle = "#BDD358";
      ctx.fillRect(350, 75, 150, 150);
      ctx.fillStyle = "#E5625E";
      ctx.fillRect(50, 250, 100, 250);
    }
  })
  .addLayer({
    id: 'circles',
    render: function (canvas, ctx) {
      ctx.fillStyle = "#558B6E";
      ctx.beginPath();
      ctx.arc(75, 75, 80, 0, 2 * Math.PI);
      ctx.fill();
      ctx.beginPath();
      ctx.fillStyle = "#88A09E";
      ctx.arc(275, 275, 150, 0, 2 * Math.PI);
      ctx.fill();
      ctx.beginPath();
      ctx.fillStyle = "#704C5E";
      ctx.arc(450, 450, 50, 0, 2 * Math.PI);
      ctx.fill();
    }
  })
  .addLayer({
    id: 'triangles',
    render: function (canvas, ctx) {
      ctx.fillStyle = "#DAF7A6";
      ctx.beginPath();
      ctx.moveTo(120, 400);
      ctx.lineTo(250, 300);
      ctx.lineTo(300, 500);
      ctx.closePath();
      ctx.fill();

      ctx.fillStyle = "#FFC300";
      ctx.beginPath();
      ctx.moveTo(400, 100);
      ctx.lineTo(350, 300);
      ctx.lineTo(230, 200);
      ctx.closePath();
      ctx.fill();

      ctx.fillStyle = "#C70039";
      ctx.beginPath();
      ctx.moveTo(100, 100);
      ctx.lineTo(100, 300);
      ctx.lineTo(300, 300);
      ctx.closePath();
      ctx.fill();
    }
  });
myCanvas.render();

上面的代码通过链式调用在Canvas中添加了4个对象,id分别为background、squares、circles、triangles。而且每一个对象都有相应的render方法,该方法指定了元素本身在Canvas的上下文是如何绘制的。基于以上代码可以看到在Canvas中绘制的效果:

image.png

2)单量与批量模式实时渲染

本小节将讲述首轮绘制后如何基于用户输入做相应的更新。其实所有的半自动化绘图场景,运营不可能只根据某一个模板进行绘制,换句话说,多模板同时绘制的场景必须加以考量。

比如,大多数场景下,运营需要同时基于模板来绘制海信、康佳、歌华、LG的所有坑位图然后导出或者投放,进而摆脱每次只能单独绘制导出单模板的低效模式。因此基于多模板实时绘制渲染的方式就亟待解决。基于此,在半自动化绘制场景中,天生支持多模板实时渲染绘制的模式,正如下面的动图所示:

image.png

上图展示的是多模板实时修改的场景,也就是所谓的联动模式。但在未开启联动模式的场景下,所有的修改只针对单模板生效。因此在满足成品图共性的同时又保证了模板的个性。

3、数据统一存储在服务端

前面讲过,工具化平台的设计思路没法做到链路的完整串联,进而完成内容的回流,这在平台化的思路下是行不通的。平台化解决问题的思路是:从内容生产到内容消费的完整链路串联。

image.png

基于此,从输入到输出,到最终的分发都需要流动起来,这一切的前提都基于数据的存储,从输入源到输出结果。基于存储的结果,完成了从自动化生产,个性化等自由推荐。

四、OTT蜂鸟制图场景的主要输出与输入

下图展示了制图平台在业务上所做的尝试,也总结了在支撑业务的同时,如何在技术上做范式的探索。

image.png

从1.0到2.0,是整个系统架构的升级。系统现有支持能力在OTT场景下已经逐渐完善起来。

image.png

1、技术侧主要输出

1)服务化的能力

image.png

服务化的能力是上面所述的解决问题范式的具体形式,而制图平台服务化的能力已经涵盖了包括:通用模板解析能力,图片合成服务化能力,素材服务化能力,统一分发能力等等。
a) 通用模板解析能力,不仅适用于制图场景的数据格式化,在智能化领域也有涉及;
b) 图片合成服务化能力,不仅可用于制图场景,对于动画合成场景也有渗透;
c) 至于素材的服务化,分发能力的联合在业务赋能的同时,也能谋求业务发展方向的新思路。

2)半自动化合图尝试

服务化能力将制图的触角做了极大的延展,但在半自动化的制图场景,依然需要探究新的制图范式。基于此,我们产出了自有的Canvas合图尝试,这与鲁班、海棠的模式有极大的差异。这条路没有太多的参考,很多问题需要自己去挖坑和填坑。

2、无人工自动化制图

自动化制图具有极大的吸引力,无需运营任何手动制图干预,直接在系统中选择相应的内容集合即可。因此,这种业务赋能尝试也被极大的重视起来。在OTT业务范围内比较成功的案例就是专题系统:

image.png

通过指定内容集合(scgid)以及相应的封面图生成规则就可生成相应的专题推荐内容,极大的节省了人力成本。

相关文章
|
6月前
|
前端开发 JavaScript jenkins
构建高效前端项目:从模块化到自动化
【2月更文挑战第13天】 随着Web技术的不断进步,前端项目的复杂性日益增加。为了确保可维护性和性能,前端工程师必须采用模块化和自动化的策略来优化开发流程。本文将探讨如何使用现代前端工具和最佳实践来构建一个高效的前端项目架构,包括模块打包、代码分割和持续集成等方面。
|
3月前
|
JSON 前端开发 JavaScript
革新Admin.NET框架:前端体验飞跃与代码生成自动化的双重革命,引领高效开发新时代!
【8月更文挑战第3天】Admin.NET是一款专为现代企业应用打造的高效框架,凭借强大的后台管理和灵活的扩展性深受开发者喜爱。本文探讨如何优化其前端体验与开发效率。首先,通过采用Flexbox和CSS Grid等技术实现响应式布局重构,确保了不同设备上的一致体验。其次,引入Vue.js或React实现组件化开发,提高代码复用性和维护性。再者,利用Webpack等工具进行性能优化,提升页面加载速度。此外,开发了代码生成器以自动生成CRUD模块,极大提高了开发效率。这些改进使Admin.NET前端开发更高效、灵活且易于维护。
55 0
|
6月前
|
前端开发 Java Go
从前端到后端:构建现代化Web应用的技术实践
本文将介绍如何通过前端和后端技术相结合,构建现代化Web应用的技术实践。我们将探讨前端开发、后端架构以及多种编程语言(如Java、Python、C、PHP、Go)在构建高效、可扩展的Web应用中的应用。
|
6月前
|
前端开发 测试技术 持续交付
【Flutter 前端技术开发专栏】Flutter 中的 UI 测试与自动化测试
【4月更文挑战第30天】本文探讨了 Flutter 应用中UI测试和自动化测试的重要性,包括保障质量、提高效率和增强开发信心。Flutter提供`flutter_test`库进行Widget测试,以及`flutter_driver`进行集成测试。UI测试涵盖界面布局、交互和状态变化的验证,最佳实践建议尽早引入测试、保持用例简洁,并结合手动测试。未来,随着Flutter技术发展,UI测试和自动化测试将更加完善,助力开发高质量应用。
210 0
【Flutter 前端技术开发专栏】Flutter 中的 UI 测试与自动化测试
|
6月前
|
监控 前端开发 jenkins
Jenkins在前端项目持续部署中的应用,介绍了Jenkins作为自动化部署工具的基本概念和流程
【4月更文挑战第29天】本文探讨了Jenkins在前端项目持续部署中的应用,介绍了Jenkins作为自动化部署工具的基本概念和流程。前端持续部署涉及代码提交、构建、测试和部署四个步骤。实现过程中需配置代码仓库、构建、测试和部署任务,安装相关插件并确保环境一致性。注意事项包括代码质量控制、环境一致性、监控预警和安全管理。通过Jenkins,可提升前端开发效率和质量,但需不断学习以应对技术发展。
93 0
|
6月前
|
前端开发 JavaScript 数据可视化
前端vite+vue3——自动化配置路由布局
前端vite+vue3——自动化配置路由布局
110 0
|
6月前
|
人工智能 前端开发 算法
未来互联网发展趋势分析与前端技术应用探讨
【2月更文挑战第3天】随着人工智能、大数据、物联网等新兴技术的快速发展,未来互联网的发展方向和趋势变得更加多样化和复杂。在这种背景下,前端技术作为用户与系统之间的桥梁,扮演着至关重要的角色。本文将从未来互联网发展趋势的角度出发,探讨前端技术在不断变革的互联网时代的应用与发展。
|
6月前
|
编解码 前端开发 安全
大屏前端技术要求
大屏前端技术要求
86 0
|
6月前
|
存储 移动开发 前端开发
优酷OTT互联网大屏前端技术实现
优酷OTT互联网大屏前端技术实现
70 0
|
6月前
|
缓存 前端开发 JavaScript
构建可靠的前端工程:自动化、代码质量与性能优化
构建可靠的前端工程:自动化、代码质量与性能优化
构建可靠的前端工程:自动化、代码质量与性能优化