V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
Croath
V2EX  ›  分享创造

做了一个可以为小程序生成朋友圈分享图片的服务

  •  8
     
  •   Croath · 2019-10-25 13:47:27 +08:00 · 8730 次点击
    这是一个创建于 1887 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上一篇图挂了,用 V2EX 图床重新发一个。

    我们最近开发了一些小程序,每次要上线之前都想快速添加到分享朋友圈功能,但是做了几次之后发现好麻烦啊,要么效果不好,要么成本高,要么不能动态更新,所以顺手做了这个解决方案出来,大家有什么问题或者想讨论的可以一起讨论:)欢迎建议:)以下正文:


    小程序生成图片分享朋友圈

    小程序开发者都希望自己的小程序得以广泛传播,因为不少小程序都设计了很多转发激励行为,但分享小程序到朋友圈(或其他外部平台)一直是一个难题。一个常见的方案就是生成分享海报、分享图片。但生成分享图片在技术上却也是一个难题。


    技术选型

    目前常用技术方案基本分为三种:

    1. 使用 canvas 绘图并生成
    2. 使用后端绘图库进行绘制,返回给小程序端
    3. 使用服务端开一个浏览器进行 HTML 渲染,并截图返回给小程序端

    第一种方案:要求较高,canvas 和纯 html 布局相去甚远,零基础学习成本较高,而且在不同的微信浏览器中效果不可预期,想短时间内做出精美可控的生成图片不容易。实操的时候发现了一个非常麻烦的事情:网络图片或者 base64 图片都无法直接在 canvas 里渲染显示,要先下载好传进去。

    第二种方案:后端库可以完成较为简单的需求,但字体加载、阴影、圆角、透明等方案效果需要精调,如果文字需要截断或动态伸缩长度时并不容易处理。图片的截取和伸缩自适应也不灵活。而且选用这种方案相当于需要把 UI 布局的工作丢给后端工程师去解决,这不是他们擅长的范围,效果未必会好。

    第三种方案:页面的绘制方面,纯前端技术即可完成,难度低,完成度高,但是需要在后端起一个 node 服务开启 puppeteer 去控制服务端 Chrome 浏览器。这种方案的缺点就是成本太高,我们和业界同行都测算过,结果差不多:4 核 16G 的服务器生成图片的 QPS 大概只有 10-20,相当于一秒钟较差情况只能生成 10 张图片,这对于突发的大量分享需求并不能满足,而且这种配置的服务器,不能部署其他服务,只跑这个服务就会用尽大部分资源。

    费用上:只单单算 5M 带宽的服务器费用一个月就要 700+ 人民币,流量和图片托管费用另算。此方案的最小化实现:至少需要 1 核 2G 的服务器才能较为顺畅地完成一次顺利截图,但是还是要处理浏览器无响应假死等情况,较为复杂。但综合来看,这种方案是效果最好最为灵活的。

    快海报小程序分享图生成服务

    快海报 kuaihaibao.com 是专门提供小程序分享海报生成服务的,技术上用的就是上面所述的第三种方案,但是只需要调用他的 API 就可以完成,不需要开发者维护 puppeteer 和 headless Chrome,而且成本较低,一张分享图的最低生成成本是 0.033 元。

    其实真正集成到自己的服务中时,平均成本要比这个低,因为有些生成的图片的二维码,如果不带用户个人信息(不给分享的用户返利)时,可以生成一次之后永久缓存起来,其他用户再分享同一个东西都用缓存好的图片,综合成本就降下来了。

    算一下成本:

    • 比方说一个刚起步的小程序日活 5000 (对于刚起步的小程序其实已经很高了吧)
    • 假设有 5% 的用户生成分享图
    • 也就是每天生成 250 张分享图,一个月会生成 7500 张分享图

    这样的话每个月成本就是 250 元人民币左右,相比 700+ 人民币的服务器成本省太多了。这是测算比较高的指标,而且是完全不应用缓存方案的情况。

    如果你的小程序还处于冷启动的阶段:

    • 日活 500
    • 假设有 5% 的用户生成分享图
    • 也就是每天生成 25 张分享图,一个月会生成 750 张分享图

    每月成本 25 元。比 1 核 2G 的最小化自部署方案也要便宜。但带来的收益是无穷的,750 张分享图发到朋友圈,每张分享图 1000 受众浏览,一个月就是将近 750000 人次分享受众。

    调用 API

    首先去 https://kuaihaibao.com/ 注册账号,验证邮箱激活之后,其实就可以先测试用了,每个账号有 100 次测试额度,测试生成的图片带水印。

    网站左侧的 [文档] 页面能找到集成文档,非常简单,一共就只有一个核心 API,通过 HTTP 调用的。

    先在 [开发] -> [设置] 中激活 token

    激活 token

    目前支持三种生成方式:

    1. 直接传 URL 进行渲染
    2. 传 HTML 渲染
    3. 使用内置的模板进行选择

    这里演示使用模板渲染,因为比较简单

    打开 [开发] -> [模板] 中,找到自己喜欢的模版。因为我只想生成一个简单的分享图片,所以最简单的方式就是使用网站内置的模版,内置模板目前有 8 款,应该能满足大部分小程序的需求了,抽奖、打卡、图文、文字、电商都有,改一改文案和图片就可以了。

    我选了这个抽奖模板:

    抽奖模板

    按照 https://kuaihaibao.com/doc/docs/template/kzccda95.html 文档描述的 JSON 改成我需要的:

    {
      "backgroundColor": "#fafafa",
      "backgroundImage": "",
      "user": {
        "avatar": "https://khb-sample.oss-cn-shanghai.aliyuncs.com/sample/girl_2.jpg",
        "nickname": "我是测试账号",
        "color": "#666"
      },
      "tip": "邀请你来抽奖",
      "qrcode": "https://khb-sample.oss-cn-shanghai.aliyuncs.com/sample/sample_qr_0.png",
      "records": [
        {
          "title": "一等奖",
          "desc": "2019 年 11 月 16 日 10:00 开奖",
          "image": "https://s3.cn-northwest-1.amazonaws.com.cn/res.weiyidan.com/production/10000002/4109f8e51a8f43b9816dbc8fe636e22a.jpeg"
        }
      ],
      "brand": "我的测试抽奖小程序",
      "slogan": "快来和我一起抽吧!",
      "metaColor": "#999"
    }
    

    然后打开 Terminal 做一次请求试试:

    curl -X "POST" "https://api.kuaihaibao.com/services/screenshot" \
         -H 'Authorization: Bearer 这里写你自己的 token' \
         -H 'Content-Type: application/json; charset=utf-8' \
         -d /pre>{
      "template": "kzccda95",
      "data": {
        "qrcode": "https://khb-sample.oss-cn-shanghai.aliyuncs.com/sample/sample_qr_0.png",
        "records": [
          {
            "title": "一等奖",
            "desc": "2019 年 11 月 16 日 10:00 开奖",
            "image": "https://s3.cn-northwest-1.amazonaws.com.cn/res.weiyidan.com/production/10000002/4109f8e51a8f43b9816dbc8fe636e22a.jpeg"
          }
        ],
        "tip": "邀请你来抽奖",
        "slogan": "快来和我一起抽吧!",
        "metaColor": "#999",
        "brand": "我的测试抽奖小程序",
        "backgroundImage": "",
        "backgroundColor": "#fafafa",
        "user": {
          "avatar": "https://khb-sample.oss-cn-shanghai.aliyuncs.com/sample/girl_2.jpg",
          "nickname": "我是测试账号",
          "color": "#666"
        }
      }
    }'
    

    返回了结果:

    {
      "success": true,
      "data": {
        "name": "iPhone 5",
        "image": "https://khb-test-oss.oss-cn-shanghai.aliyuncs.com/screenshot/4fa63f2a3605cbdece90c659cbccea619d9cf9fa?x-oss-process=style/test_watermark"
      }
    }
    

    打开图片地址看看:

    生成测试图片

    速度很快,图片很漂亮,只是中间带水印,充值后成为付费用户,再生成的图片水印就自动取掉了。

    后端集成

    这里参考快海报官方给的最佳实践的逻辑参考图:

    集成逻辑

    所以后端只需要做一件事,就是提供一个 API 给客户端用,这个 API 被调用的时候去请求快海报的服务器,再把结果返回给小程序就好了。

    第 1 条附言  ·  2020-10-20 15:03:23 +08:00
    价格下调为原始价格 1/3,最低均价 0.01 元 /张。
    33 条回复    2019-12-03 14:08:52 +08:00
    o00o
        1
    o00o  
       2019-10-25 13:50:26 +08:00 via Android
    建议水印换个地方,这样免费用的也可以帮你传播。现在的位置基本上不会有免费调用的吧
    paicha
        2
    paicha  
       2019-10-25 15:29:22 +08:00
    支持一个
    Wichna
        3
    Wichna  
       2019-10-25 18:50:22 +08:00
    idea 不错,最好能够支持自定义模板。另外请求缓存的海报应该不计算费用吧?
    Croath
        4
    Croath  
    OP
       2019-10-25 19:29:44 +08:00
    @Wichna 可以传 url 或者直接传 html 进行渲染,参考文档: https://kuaihaibao.com/doc/docs/html.html
    Croath
        5
    Croath  
    OP
       2019-10-25 19:30:10 +08:00
    @o00o 感谢建议,在考虑如何让水印更美观一些
    Croath
        6
    Croath  
    OP
       2019-10-25 19:30:19 +08:00
    @paicha 谢谢
    paicha
        7
    paicha  
       2019-10-25 19:35:21 +08:00
    建议可以去小程序开放社区推广一下
    Croath
        8
    Croath  
    OP
       2019-10-25 19:46:15 +08:00
    @paicha 好主意,我去发一下
    Croath
        9
    Croath  
    OP
       2019-10-25 19:53:08 +08:00
    @Wichna 忘掉一个问题了。

    缓存其实是说开发者应该自己判断是否要做缓存:

    - 如果每个用户分享的图片都一样,那么应该做一个全局缓存
    - 如果用户分享同一篇文章(商品)的图片都一样,应该针对商品(文章做缓存)
    - 如果一个用户可能多次分享同一张图片(比如自己的邀请图),那么应该针对用户做缓存
    - 如果每个用户每次生成的图都有差别(比方说用户头像的差别或二维码的差别),那么不应该做缓存,每次都应该重新生成
    natforum
        10
    natforum  
       2019-10-25 20:57:45 +08:00
    我看错了,我以为这个是提取微信朋友圈图片的
    musi
        11
    musi  
       2019-10-25 22:09:30 +08:00
    我之前做了一个用的是第二种方案,对于特定的海报来说可能就是用户的信息不一样,直接基于设计师给的底图再用程序直接绘制就好了,所以大部分工作还是设计师做的,后端只需要调整一下字体和位置就行了。写好程序后直接扔到阿里云的函数计算上,调用次数前多少次还免费来着。生成的海报直接上传到 oss 里,用户再次生成的时候直接从 oss 里取就好了。
    Croath
        12
    Croath  
    OP
       2019-10-25 23:43:57 +08:00 via iPhone
    @musi 嗯你这个开发流程也不短…做这个服务还是主要服务新手和小团队吧
    Blacate
        13
    Blacate  
       2019-10-26 00:22:46 +08:00 via iPhone
    我们现在就是用方案 3 自己开发了一个
    Croath
        14
    Croath  
    OP
       2019-10-26 01:12:16 +08:00
    @Blacate 成本怎么样
    dqsife
        15
    dqsife  
       2019-10-26 14:04:55 +08:00
    注册需要邀请码?
    Croath
        16
    Croath  
    OP
       2019-10-26 15:43:38 +08:00
    @dqsife 不填也可以呀。
    Blacate
        17
    Blacate  
       2019-10-27 14:00:12 +08:00
    @Croath 额 使用频率不高 所以就随便用一台服务器跑着
    quietjosen
        18
    quietjosen  
       2019-10-27 17:17:40 +08:00
    当初用了方案 1,痛苦…这个对个人开发者和小团队,是很好的东西。
    gaowhen
        19
    gaowhen  
       2019-10-30 15:34:12 +08:00
    https://developers.weixin.qq.com/community/develop/article/doc/00008c6f3f83888b176946d3d51413

    试了一下,接入很方便。这件事情吧,我觉得重点不是实现成本,而是性能一般的服务器根本抗不住多少请求,性能好的服务器,如果到不了一定请求量,绝大部分资源都被浪费了,根本就是得不偿失。一年 1000+ 的服务器费用,能买 20000+ 次调用,对个人开发者或者小团队来说,足够用很久了。
    Croath
        20
    Croath  
    OP
       2019-10-30 15:51:29 +08:00
    @quietjosen 如果有新项目想迁移过来,我可以协助解决
    Croath
        21
    Croath  
    OP
       2019-10-30 15:52:42 +08:00
    @gaowhen 小团队和独立开发者来说,综合成本降低 2/3 以上应该问题不大。
    Rwing
        22
    Rwing  
       2019-11-04 14:45:13 +08:00
    不错,挺好的
    Croath
        23
    Croath  
    OP
       2019-11-04 14:55:20 +08:00
    @Rwing 谢谢
    marvinemao
        24
    marvinemao  
       2019-11-04 15:53:48 +08:00
    不错,赞
    littleb
        25
    littleb  
       2019-11-07 17:38:45 +08:00
    用过一个类似的,叫创客贴
    Croath
        26
    Croath  
    OP
       2019-11-08 11:41:05 +08:00
    @littleb 嗯嗯见过,类似的产品有不少,但是这些主要是 C 端客户用的,自己拼一个单一成果。

    我们的服务是给 B 端客户用的,动态去为每一位 C 端客户实时生成不同的海报图。
    takashiki
        27
    takashiki  
       2019-11-26 10:53:04 +08:00
    我也选了方案一,确实比较麻烦,但是用服务的话就会对可靠性和是否长期维护有顾虑。
    Croath
        28
    Croath  
    OP
       2019-12-03 13:04:15 +08:00
    @takashiki 我们自己有几个小程序已经全部依赖这套服务了,长期服务没有问题,越多人使用共享均摊成本越低,目前客户规模已经能 cover 成本所以不存在因为亏损关闭服务的情况。

    后续我考虑将核心模块开源出来供大家使用,但是如果小团队搭建这套服务的话,成本就高了很多了。
    Croath
        29
    Croath  
    OP
       2019-12-03 13:04:39 +08:00
    @takashiki canvas 有个额外的问题我最近也没有找到特别好的处理方案,就是 emoji 绘制。
    ming
        30
    ming  
       2019-12-03 13:15:47 +08:00
    我们也做了一个内部服务,同时支持方案 1 和方案 2,但是方案三我们自己测试的时候发现首次渲染太慢了,你们做出来首次渲染需要多久啊?
    Croath
        31
    Croath  
    OP
       2019-12-03 13:18:39 +08:00
    @ming 我们不存在首次渲染和后续渲染的时间差异。200ms~500ms 不等,图片等资源如果都准备好了 200ms 就没问题。
    mzlzero
        32
    mzlzero  
       2019-12-03 13:42:15 +08:00
    好东西,帮转
    huhking
        33
    huhking  
       2019-12-03 14:08:52 +08:00 via iPhone
    支持,可以试试
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3078 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:11 · PVG 21:11 · LAX 05:11 · JFK 08:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.