Repository: easychen/lean-side-bussiness Branch: main Commit: a9545f7213a5 Files: 173 Total size: 2.0 MB Directory structure: gitextract_d63l_4fw/ ├── README.md ├── book.toml ├── docs/ │ ├── .nojekyll │ ├── 01.html │ ├── 0101.html │ ├── 010101.html │ ├── 010102.html │ ├── 010103.html │ ├── 0102.html │ ├── 010201.html │ ├── 010202.html │ ├── 010203.html │ ├── 0103.html │ ├── 010301A.html │ ├── 010302.html │ ├── 02.html │ ├── 0201.html │ ├── 020101.html │ ├── 020102.html │ ├── 0202.html │ ├── 020201.html │ ├── 020202.html │ ├── 020203.html │ ├── 0203.html │ ├── 020301.html │ ├── 020302.html │ ├── 020303.html │ ├── 03.html │ ├── 0301.html │ ├── 030101.html │ ├── 030102.html │ ├── 030103.html │ ├── 030104.html │ ├── 0302.html │ ├── 030201.html │ ├── 04.html │ ├── 0401.html │ ├── 040104.html │ ├── 040105.html │ ├── 0402.html │ ├── 040207.html │ ├── 040209.html │ ├── 040210.html │ ├── 040211.html │ ├── 040212.html │ ├── 040213.html │ ├── 040214.html │ ├── 040215.html │ ├── 040216.html │ ├── 040217.html │ ├── 040218.html │ ├── 040219.html │ ├── 0403.html │ ├── 040301.html │ ├── 040302.html │ ├── 040303.html │ ├── 040304.html │ ├── 040305.html │ ├── 040306.html │ ├── 040307.html │ ├── 040308.html │ ├── 040309.html │ ├── 040310.html │ ├── 040311.html │ ├── 040312.html │ ├── 0404.html │ ├── 040401.html │ ├── 404.html │ ├── FontAwesome/ │ │ └── css/ │ │ └── font-awesome.css │ ├── ayu-highlight.css │ ├── book.js │ ├── css/ │ │ ├── chrome.css │ │ ├── general.css │ │ ├── print.css │ │ └── variables.css │ ├── fonts/ │ │ ├── OPEN-SANS-LICENSE.txt │ │ ├── SOURCE-CODE-PRO-LICENSE.txt │ │ └── fonts.css │ ├── highlight.css │ ├── highlight.js │ ├── index.html │ ├── print.html │ ├── searcher.js │ ├── searchindex.js │ ├── searchindex.json │ └── tomorrow-night.css └── src/ ├── 01.md ├── 0101.md ├── 010101.md ├── 010102.md ├── 010103.md ├── 0102.md ├── 010201.md ├── 010202.md ├── 010203.md ├── 0103.md ├── 010301.md ├── 010301A.md ├── 010302.md ├── 02.md ├── 0201.md ├── 020101.md ├── 020102.md ├── 0202.md ├── 020201.md ├── 020202.md ├── 020203.md ├── 0203.md ├── 020301.md ├── 020302.md ├── 020303.md ├── 03.md ├── 0301.md ├── 030101.md ├── 030102.md ├── 030103.md ├── 030104.md ├── 030105.md ├── 030106.md ├── 030107.md ├── 0302.md ├── 030201.md ├── 030202.md ├── 030203.md ├── 030204.md ├── 030205.md ├── 04.md ├── 0401.md ├── 040101.md ├── 040102.md ├── 040103.md ├── 040104.md ├── 040105.md ├── 040106.md ├── 0402.md ├── 040201.md ├── 040202.md ├── 040203.md ├── 040204.md ├── 040205.md ├── 040206.md ├── 040207.md ├── 040208.md ├── 040209.md ├── 040210.md ├── 040211.md ├── 040212.md ├── 040213.md ├── 040214.md ├── 040215.md ├── 040216.md ├── 040217.md ├── 040218.md ├── 040219.md ├── 040220.md ├── 0403.md ├── 040301.md ├── 040302.md ├── 040303.md ├── 040304.md ├── 040305.md ├── 040306.md ├── 040307.md ├── 040308.md ├── 040309.md ├── 040310.md ├── 040311.md ├── 040312.md ├── 040313.md ├── 0404.md ├── 040401.md ├── README.md └── SUMMARY.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # 精益副业:程序员如何优雅地做副业 UPDATE:🎈 [《一人企业方法论2.0》已在CC-BY-NC-SA协议下发布,建议先读完后继续阅读本书](https://github.com/easychen/one-person-businesses-methodology-v2.0) ![](https://github.com/easychen/one-person-businesses-methodology-v2.0/raw/master/src/images/opb-book-cover.jpg) --- > 本书部分内容已被收录于《全栈路线图》,[可点此查看高清版PDF和源文件](https://github.com/easychen/stack-roadmap) [![方糖全栈路线图](https://user-images.githubusercontent.com/1294760/210160612-68e4a551-47d8-4137-b2f1-4dd5fdf6d49d.jpg)](https://github.com/easychen/stack-roadmap) 本书扩展了《程序员如何优雅地挣零花钱》的基本内容,将其放到更大的副业视角;同时,引入经过互联网行业验证的「精益创业」流程,并优化为副业专用的「精益副业」流程。 在书籍第二部分,以实际案例为主,添加了「独立开发变现」和「网课变现实践」的内容。 本书成书于2020年12月,晚于[一人公司方法论](https://github.com/easychen/one-person-businesses-methodology),在阅读完本书后,可以阅读[一人公司方法论](https://github.com/easychen/one-person-businesses-methodology)。将来如有机会,我会尝试把「精益副业」和「一人公司方法论」整合到一个体系下。可扫[这个二维码](qrcode.jpeg)订阅更新通知。 ![cover.jpg](cover.jpg) [在线阅读](http://r.ftqq.com/lean-side-bussiness/) # 目录 * [为什么副业特别重要](src/01.md) * [职业可能性](src/0101.md) * [职业的四大象限](src/010101.md) * [没有副业的职业](src/010102.md) * [副业带来的可能性](src/010103.md) * [职业自由度](src/0102.md) * [从中指备用金说起](src/010201.md) * [PlanB和反脆弱](src/010202.md) * [全新的工作自由度](src/010203.md) * [职业成长性](src/0103.md) * [新技术练兵场](src/010301A.md) * [业务敏感度](src/010302.md) * [如何优雅地做副业](src/02.md) * [想明白核心资源和核心优势](src/0201.md) * [副业的核心资源](src/020101.md) * [副业的核心优势](src/020102.md) * [时间片](src/0202.md) * [时间片的销售](src/020201.md) * [时间片的优化](src/020202.md) * [突破时间片限制](src/020203.md) * [资产和被动收入](src/0203.md) * [什么是资产](src/020301.md) * [资产的获得方式](src/020302.md) * [资产的量化评估](src/020303.md) * [优选资产](src/03.md) * [知识和人脉的变现](src/0301.md) * [付费视频课](src/030101.md) * [付费专栏](src/030102.md) * [付费社群](src/030103.md) * [图书出版](src/030104.md) * [自有产品和服务](src/0302.md) * [半成品市场](src/030205.md) * [开源/免费+收费模式](src/030204.md) * [应用市场卖APP](src/030201.md) * [精益副业](src/04.md) * [精益副业流程](src/0401.md) * [什么是精益创业](src/040101.md) * [精益副业:为副业优化的精益流程](src/040102.md) * [商业模式画布](src/040104.md) * [最小可行产品和产品市场契合](src/040105.md) * [精益独立开发实践](src/0403.md) * [独立开发的精益流程](src/040301.md) * [福利单词项目简介](src/040302.md) * [福利单词的商业模式画布](src/040303.md) * [通过用户画像细化客户](src/040304.md) * [画像→场景→功能和分期](src/040305.md) * [什么是好的商业设计](src/040306.md) * [人人能用的四大原则](src/040307.md) * [独特Logo解决方案](src/040308.md) * [使用AdobeXD设计界面](src/040309.md) * [个人支付解决方案](src/040310.md) * [使用「兔小巢」处理用户反馈](src/040311.md) * [2A3R漏斗和增长优化](src/040312.md) * [精益网课变现实践](src/0402.md) * [网课的精益流程](src/040201.md) * [如何确定选题的基本方向](src/040202.md) * [网课的商业模式设计](src/040203.md) * [网课市场分析](src/040204.md) * [形成有竞争力的价值主张](src/040205.md) * [大纲的注意点](src/040207.md) * [通过预售验证销量](src/040209.md) * [常见的课程片段类型](src/040210.md) * [文稿讲义类课程片段的制作](src/040211.md) * [屏幕录制类课程片段的制作](src/040212.md) * [真人出镜类课程片段的制作](src/040213.md) * [虚拟形象类课程片段的制作](src/040214.md) * [最常用的视频剪辑操作](src/040215.md) * [最常用的音频处理操作](src/040216.md) * [字幕的制作和自动生成](src/040217.md) * [流量池和二次购买](src/040218.md) * [如何有效地反盗版](src/040219.md) * [进一步提升副业的鲁棒性](src/0404.md) * [网课+独立开发的双引擎副业模式](src/040401.md) ================================================ FILE: book.toml ================================================ [book] authors = ["Easy"] language = "zh-cn" multilingual = false src = "src" title = "精益副业" ================================================ FILE: docs/.nojekyll ================================================ This file makes sure that Github Pages doesn't process mdBook's output. ================================================ FILE: docs/01.html ================================================ 为什么副业特别重要 - 精益副业

为什么副业特别重要

在很多人的印象中,副业也许只是挣点零花钱补贴家用的小打小闹。但实际上,它对于我们的整个职业有非常大的影响,甚至会改变我们的人生。

本章我们将从「职业可能性」、「职业自由度」以及「职业成长性」三个方面来进行说明。

================================================ FILE: docs/0101.html ================================================ 职业可能性 - 精益副业
================================================ FILE: docs/010101.html ================================================ 职业的四大象限 - 精益副业

职业的四大象限

2014年的时候,我做过一个「程序员拍卖」的项目。听起来很神奇,其实就是将我们遴选过的优质程序员推送给各家在招聘的公司,让他们来竞价,从而帮程序员们找到一份满意的工作。

那两年,我们为上千名程序员找到了工作。后来我把从中学到的对于程序员职业的理解写成了一本小书,叫做《程序员跳槽全攻略》

书里我创造了一个用来分析程序员职业的工具,叫做「方糖职业路线图」。它根据现金流将程序员的职业空间分布到了E、S、B、I 四个象限中,我们依次来说说。

E象限(雇员象限)、帮别人挣钱

E象限是雇员象限。别人给我们发工资,我们帮别人挣钱。这是风险最小的象限,我们的工作任务是别人分配的,只要认真完成,每个月都能得到预期中的收益。

在从开发走向高级开发后,往往就可以开始选择发展路线。E象限的典型的发展路线有两种,专家线和管理线。

E象限的优点是稳定,缺点是天花板非常明显。

S象限(自雇象限)、为自己挣钱

S象限是自雇象限,自己挣钱自己花,一般不雇用别人。比如做独立开发、组建工作室做外包和建站,甚至也可能做一些和编程没有关系的事情。

S象限最大的优点是,自己的业务自己做主,挣的钱也都是自己的。一个三五十万的外包做下来,一年的基本生活保障就有了。

S象限的缺点是,收益未必能比E象限多多少,而风险却高很多。光靠单纯的编程技能往往搞不定,还需要把接活拉活的能力、协调沟通的能力都培养起来。这些能力往往在程序员的舒适区外,需要花精力和时间去培养。因为收入是业务驱动的,所以行业的风险也会直接转嫁到我们这里。

B象限(创业象限)、让雇员挣钱

B象限是创业象限,和S象限最大的不同是我们不是自己干活,而是雇用其他人来帮我们干活挣钱。

它的优点在于,可以让我们从S象限的天花板中解脱出来,拥有规模化成长的可能性。

而缺点在于,它有一个比较大的固定成本。即使是对于轻资产的互联网公司来说,也是如此。比如人力成本。招聘、组建、培养一个团队是非常耗费时间和精力的,所以即使当业务不好的时候,我们还是需要支付大量的工资来维持团队,以便之后能快速恢复业务。

I象限(投资象限)、让钱挣钱

I象限是投资象限,是在我们有了一定的资本之后的一种让钱挣钱的方式。在B象限里,我们需要创办企业来挣钱,这需要大量的精力。即使你的精力异常充沛,同时运营三五家公司也就到上限了。I象限让我们以投资的方式参与到大量的公司中去,共享这些公司的增长,从而实现资产的增值。

在了解了四大象限以后,我们可以发现,如果赶不上公司上市这种可遇不可求的事情、或者能一路升迁做到大公司高层,先不说财务自由,光是要想在北上深买房安家,只留在E象限都是非常困难的 —— 我们必须向其他象限发展。

================================================ FILE: docs/010102.html ================================================ 没有副业的职业 - 精益副业

没有副业的职业

然而在没有副业的情况下,我们的职业就是单进程、只能做单选题。

我们在象限之间的移动,往往只能是突发式的。前一天还在E象限做雇员,第二天突然就辞职创业或者做外包去了。然而贸然进入一个新象限,将面临非常大的风险。因为每一个象限,它背后的商业模式是不同的,对人的能力、思维、精力的要求也都完全不一样。

E→B,辞职创业

先来说说「辞职创业」。

媒体很喜欢把创业宣传得一蹴而就,仿佛只要有一个独特的想法,就可以一夜暴富、咸鱼翻身。

程序员群体的理想主义趋向又比较明显,加上有无数包装出来的成功案例,所以这是程序员从E象限移动到B象限最常见的途径。

有激进派的,拿着自己的一点积蓄就英勇地加入的创业的队伍;有稳健点的,在搞定了天使投资以后再离职的。

但创业的光环在市场的面前毫无用处,要找到一个真正有商业价值的需求非常困难,往往要花很长的时间试错。而后,还要针对这个需求做出比现有方案至少好十倍的新方案。同时,还有大量公司管理、人力招聘、融资沟通方面的事务,这些都会让创业新手难以招架。

不少程序员朋友找我聊他们的创业想法,我发现他们真的只有想法 —— 完全没有进行过验证,他们并不了解B象限的生存法则。

E→S,回老家开工作室

S象限,在这里可以看成是 Easy 难度的B象限,因为自雇没有员工,可以不处理公司管理相关事务。

最熟悉的讨论就是回老家结婚,不,开工作室。我有不少北漂朋友都选择了这条路。本质上来说,这其实是一个好选择,但问题在于,如果没有做好前期准备,失败率也是非常高的。

在大公司工作的人容易产生一种幻觉,那就是把平台的能力当做自己的能力。以大公司的身份去和别人谈合作的时候,感觉都很容易。等到自己离完职才发现,同样的客户,你根本都见不到人。

我知道不少朋友都是因为高估了自己拉业务的能力,最后不得不又重返北上深。

加上全球经济放缓、美元投资减少,这种单线切换的方式又包含巨大的风险,所以很多程序员都选择了被锁死在E象限,成为永久的打工人。

我并不是说打工不好,但如果你不能较快地晋升到高级职位的话,就要仔细考虑如何应对正在形成的35岁新门槛。

================================================ FILE: docs/010103.html ================================================ 副业带来的可能性 - 精益副业

副业带来的可能性

当我们有了副业,情况就完全不一样了。

因为我们从单进程变成了多进程,可以并行地进行尝试。最重要的是,这种尝试并不会影响我们的主业,不会降低我们的生活质量。

我们还是以上一节的两个例子来看。

E→S,回老家开工作室

采用副业的方式操作,我们在离开北上深之前就可以创立自己的工作室,并开始接活。一方面拓展客户,累积口碑,另一方面,我们还可以从客户的案例中提取重复需求,将其产品化、服务化。等到有了自己的客户和产品,我们在哪个城市已经不那么重要了,甚至可以在全国一个城市住上那么一两个月,一边旅行一边工作。

E→B,创业

有了副业,B象限等于完全开放了。不要纠结于是否成立了公司,那只是一个形式。真正驱动公司的是业务能力和运营公司的能力,而这些我们都可以通过副业练出来。

把创业想法以 Side Project 的方式来运作,以最简单的产品直扑最核心的需求。没有经验和所谓的产品感都不要紧,因为副业我们是输得起的。这个项目找不到需求,那么复盘以后开始下一个。那些创业公司花大价钱验证的认知,我们通过 Side Project 同样能获得,只是时间可能更长一些而已。

这种低风险的创业模式,也是非常契合当下的创业环境的。创新工场的汪华在2020年4月的一场分享中提到,移动互联网信息、交易等纯界面层的战争已经基本结束,那种靠想法和快速扩张的打法,已经很难奏效了。

所以通过副业的方式,扎扎实实地经营一家企业,靠对市场的理解、优质的产品、良好的管理和持续发展取胜,才是新时代更好的选择。

可以看到,引入副业后,我们可以以低风险、并行的方式在职业象限中移动,为职业的发展带来了无穷的可能性。

================================================ FILE: docs/0102.html ================================================ 职业自由度 - 精益副业
================================================ FILE: docs/010201.html ================================================ 从中指备用金说起 - 精益副业

从中指备用金说起

前面说了副业给我们的职业带来了更多的可能性,接下来我们就来看,副业给我们的职业带来的更大的自由度。

首先是职业选择的自由。

这里我们先来讲一个比较有意思的概念,它叫做 F*** you money。这是国外的一个词,我们把它翻译成「中指备用金」。

它指的是一笔钱,数量大概是这个样子:突然有一天你跟老板闹翻了,你可以竖起中指,跟他讲说老子不干了,然后辞职回家。在这种情况下,你的生活质量也不会受到影响。

标准意义上的「中指备用金」,其实是和财务自由差不多额度的一笔钱,是以「不工作」为前提的。如果大家在北上深,要做到财务自由还是很难的。

我们这里要讲的是以「换工作」为前提的一个低配版本。也就是说,你可以随意裸辞,在找到下一份满意的工作之前,这段可能会长达半年甚至一年的时间里,没有任何收入,但你的生活品质不会受到太大影响。

很多年轻一点的同学可能觉得根本不需要这种备用金,因为现在的 90 后 00 后正是这么干的。但是当你的年龄稍微大一些,还着房贷车贷、养着老人小孩的时候,要是突然没有收入来源,压力实际上是非常大的。

而副业,恰恰可以为我们提供这么一笔钱。可能总额不大,但可以持续不断的提供。

比如我现在的课程放到网易云课堂上,即使自己不在微博去做主动的营销推广,通过网易平台上的自然流量进行的课程转化,也会有几千块钱。

我现在在重庆生活,这边房租非常的便宜,一个近七十平的小两居,房租每月不到两千。加上日常花销,也就几千块钱。所以现在即使不去上班挣钱,副业也可以在相当长的一段时间里保证我的基本生活不受影响。

这种情况下,我们就可以花更多的时间去思考自己的职业、未来和人生。去做一些短期内收入不明显,但长期收益巨大的决定。

这也就是副业带来的选择自由。

================================================ FILE: docs/010202.html ================================================ PlanB和反脆弱 - 精益副业

PlanB和反脆弱

除了可以给我们的职业带来自由度,副业更可以为我们的职业引入反脆弱结构。

「反脆弱」这个概念,它来自塔勒布的书《反脆弱——从不确定性中获益》。

picture 1

在书里边,塔勒布说,他之所以要专门造一个词,是因为大家往往对脆弱的反面有所误解,以为是「坚强」,也就是类似软件的「鲁棒性」。但事实上,反脆弱性比鲁棒性更棒。

什么意思呢?鲁棒性是说在风险来临的时候我们要做到不受影响。而反脆弱性更上一层楼,它说的是,当风险来临的时候,我们不但不受负面影响,还能从风险中受益,变得比原来更好。

具体到职业上,鲁棒性是说,万一现在公司发展不好,我们可以很容易地跳到平级的其他公司,继续我们之前的职业路线图。

而反脆弱性是说,当现在公司发展不好,我们可以很轻松的切换到另一个职业象限,实现跨越式的职业发展。

如果我们精心选择并发展合适的副业,它能带给我们的,正是后者。为什么这么说呢?这是由副业的天然特性决定的。因为它是我们用业余时间、在资源紧缺的情况下发展出来的。如果我们能把它转为主业,而它依然保留了对时间、资源需求不多的特性,那么这份工作就会极为舒适。

================================================ FILE: docs/010203.html ================================================ 全新的工作自由度 - 精益副业

全新的工作自由度

接着上一节,我们来看看副业带来的、全新的工作自由度。这里我们多展望一下未来,主要是给大家鼓气。副业是很累的,要把别人用来休息的时间用到额外的工作上,多想想它的好处可以鼓励我们坚持下去。

当然,就像前边提过的,工作自由度最高当然是财务自由,上不上班都行,完全没有压力。我们这一节要讨论的是,在暂时还必须上班的情况下,我们可以取得的一些自由——我们就叫它「工作自由」吧。

我一般从三点上来看工作自由度:

  1. 工作地点的自由
  2. 工作时间的自由
  3. 工作内容的自由。

不同的工作方式,有着不同的自由度。

远程办公

比如最近新冠流行,很多公司都开始搞远程办公了,有些大公司甚至宣布员工可以永久远程办公。远程办公这种工作方式,就实现了工作地点自由。你可以去公司的办公室、也可以在自己的家里,甚至是在旅游的路上办公。

但是,远程办公并没有实现工作时间和工作内容的自由,你依然要和其他人同时办公,区别只是以前面对面,现在改成视频了而已。

freelancer

freelancer,就是那种在网上接单并收取报酬的工作者。这种工作方式在工作地点上同样是自由的,而且经常全部内容都是自己做,需要和别人沟通协调的内容不多,客户主要卡交工时间,只要能赶上进度,时间是可以自己安排的。所以它还实现了工作时间自由。

但freelancer没有实现工作内容自由,因为工作内容都是由客户指定的,绝大部分情况下,都不是你自己想要开发的东西。

独立开发

再来看独立开发这种工作方式。它通过售卖独立的软件、游戏或者在线服务来赚取收益。所以在工作地点、工作时间上都是自由的。

由于是自主售卖产品,它在工作内容上,也是自由的。

这里是举个例子,实际上还有很多在地点、时间和内容上都很自由的工作。比如网课讲师。

picture 2

有意思的是,正是因为这些工作自由度高,所以适合作为副业来操作。反过来,一旦实际成熟,我们可以让副业反客为主,变成主业,从而随心所欲的掌控我们的日常工作。

================================================ FILE: docs/0103.html ================================================ 职业成长性 - 精益副业
================================================ FILE: docs/010301A.html ================================================ 新技术练兵场 - 精益副业

新技术练兵场

前边说的都是当职业需要跨象限的时候,副业能提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,它也能提供非常大的帮助。

首先,副业可以成为新技术的练兵场。

现在社区里边吐槽得很多的一个现象是「面试造火箭,上班拧螺丝」。去面试一个前端岗位,问一些前端框架的最新版细节、底层原理,这是合理的,属于前端的业务范围。但如果把深度学习、大数据、云原生、容器编排、区块链甚至量子计算都拿来面试,就有点装了。

picture 1

但是面试本质上就不是合格考试,而是竞争考试 —— 是要在一群人中选择最好的,所以这也还可以理解。但最不好理解的是,当我们过五关斩六将入职以后,发现这家公司还在用十年前的技术栈,代码管理用的还是 SVN。

不光是小公司、也不光是传统行业;甚至在一些互联网行业的大公司的某些部门里,也会出现这种情况。吐槽规吐槽,但为什么这种情况相当普遍呢?这其实是由于「技术债务驱动的架构更新」导致的。

什么是「技术债务驱动的架构更新」?

把时间拉回五年前,现在有一个业务需要上线,于是我们用当下(也就是五年前)最新的技术构建了这套系统。然后,随着时间慢慢过去,新技术不断涌出,但是线上系统依然能用,业务团队要求稳定;产品团队需要的是不断添加新功能;根本没有机会对技术栈本身进行大幅更新。虽然技术栈逐渐变得陈旧,但是「又不是不能用,理解万岁」嘛。在这种想法下,技术债务不断累积,直到有一天,技术债务快把整个架构压垮了,甚至业务被迫中止一两天后,公司终于决定了 —— 要重新整套系统。于是,又会选用当前时间点最先进的技术来重新开发一套全新的系统。所以你会发现很多公司的系统,它并不是持续不断地更新、不是随时保持最新;而是在新旧之间反复横跳。

由于五年中,业务变动的可能性和幅度都非常大,所以对公司来讲,重写系统是可能比维护系统更合理的。但对于那些在五年里一直用原来技术栈持续不断地维护旧系统的同学来讲,他们的技术栈被迫变旧了。

而当决定开发新系统的时候,公司又希望使用当下最新的技术栈。这就要求原系统的程序员在一瞬间学会新技术,并开发出一套稳定的系统来。大部分人是做不到的,但从公司的角度讲没有关系,淘汰掉,招聘新人组建新团队就好了,说不定成本还能更低点呢。

picture 2

所以在这种结构的架构更新里边,如果程序员自己不想办法去学新技术,不去找地方去应用新技术,那么就像温水里的青蛙,最后终会用后即弃。

我很喜欢一句话,它听起来有些残酷,但真实,也时时推动着我去学习最新的技术。

一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。 —— Stewart Brand

副业给了我们一个坐上压路机,避免被碾压的机会。程序员这个行业跟其他行业还不一样,它对新技术的要求并不只是认知,光知道新知识、了解新思路是不够的,还需要一个实打实的练手环境,花上相当长时间去踩坑,才能稳妥地做出一个稳定的方案。副业提供了一个真实业务,让我们可以把最新的技术用到上面,随时保持技术栈最新,增强主业的职业竞争力。

================================================ FILE: docs/010302.html ================================================ 业务敏感度 - 精益副业

业务敏感度

除了技术,副业也可以帮助我们在业务上获得新认知,保持敏感性。

之前我们在做程序员职业成长服务的时候,发现了一个问题。很多初阶的程序员没法升到中高阶,有两个很大的非技术影响因素,一个是管理能力、另一个是业务理解能力。

管理能力比较好理解。每一个程序员即使把自己的潜力发挥到极致,成为十倍开发者( 10x developer),他可以处理的事情也是有限的。

但是如果管理能力好,他就可以培养出很多拥有和自己同等技能的人,这样就不只是十倍、而是可以成百上千倍地复制能力,为公司增加更多的生产力。

业务理解能力这一块,是因为在绝大部分的公司里,技术都是为业务服务的。所以需要针对业务的各种需求、各种流程来做解决方案。

如果对业务不了解,那么即使技术很不错,因为不知道某些业务细节,最后设计出来的方案可能也不是最优的。这就像我们小学时做应用题,有一个隐藏条件包含在业务逻辑中,如果忽视了它,即使数学再好,做出来的答案也是错的。

所以,程序员应该需要培养自己对业务的理解能力。但比较讽刺的是,很多公司的初阶程序员,恰恰没有机会去了解业务。尤其是一些比较大的公司,很多业务相关的问题都是在中高阶的技术决策层就已经解决掉了,分配到初阶程序员这里,就只剩下一些规划好的、待实现的技术方案了。

这就会形成职业上的一个断层,让初阶程序员无法变成行业专家。很多公司是无意的,也有极少数公司是有意为之。因为高阶的岗位是有限的,如果你成长起来后没有位置,就会跳槽了。所以,公司不培养我们的时候,我们就只能自己培养自己。

而副业正是磨练自己的好方法。我们可以做一个跟我们主业相关的副业,通过自己的项目来了解需求、理解业务,从而弄明白公司在做什么样的事情,怎样才能做得更好。将自己从一个纯粹的螺丝钉,变成独当一面的解决方案高手。

================================================ FILE: docs/02.html ================================================ 如何优雅地做副业 - 精益副业
================================================ FILE: docs/0201.html ================================================ 想明白核心资源和核心优势 - 精益副业

想明白核心资源和核心优势

在通过大量章节充分了解了副业的重要意义之后,相信大家已经明白了「为什么」。下边我们开始来讲「是什么」和「怎么做」。

在做一件事情之前,我的习惯是要想明白它的本质,弄清楚它的核心资源,了解它的核心优势。

================================================ FILE: docs/020101.html ================================================ 副业的核心资源 - 精益副业

副业的核心资源

来看我们这本书的副标题 —— 「程序员如何优雅地做副业」。它有两个重点,一个是「优雅」、一个是「副业」。

既然是「副业」,就表明我们还有一份作为「主业」的正职工作。副业只是我们从本来已经很繁忙的工作、生活时间里面活活挤出来的一点时间精力去做的业务。

所以对于副业来讲,最核心、最宝贵的资源,就是我们的时间片。

为什么这么说呢?

因为对于一家企业来讲,它有足够多的资源可以调配。它可以通过雇人的方式,批量增加可用的时间片。但是对于我们处于「副业」状态的业务来讲,精力和资源都是非常有限的。

副业本来挣得就很少,如果还要去雇人的话,每一个人分下来就会更少,会有入不敷出的风险。另外,人多了以后,在沟通上、管理上的成本也会飙升。所以副业的人应该尽可能少。

于是,时间片就成为了整个副业中,最为有限、最难拓展的资源。我们应该围绕紧缺的核心资源来规划副业。

================================================ FILE: docs/020102.html ================================================ 副业的核心优势 - 精益副业

副业的核心优势

我们的目标读者是程序员。大部分的程序员要么是在写软件、要么是在写网站、要么是在写APP,通常属于软件或者互联网行业。

软件行业和互联网行业的竞争是非常激烈的。而我们在上一节里面说过,副业它有一个先天的特点,或者说是不足,也就是我们能在这个业务上可以投入的时间和精力是非常有限的。

市场是非常残酷的,它并不会管你这个产品的制作方是个人还是公司,开发它的程序员是全职还是兼职。最终用户会以同样的标准来看评判产品,优胜劣汰。

那在一个竞争如此激烈的市场里面,一个先天投入不足的业务,凭什么可以战胜其他的项目,获得成功呢?这是我们开始之前就要想明白的问题。只有想明白了这个问题,我们在做副业的时候才是有的放矢,而不是随波逐流。

这个问题困扰了我挺久,后来在读《创业就是要细分垄断》时,里边一段话让我觉得非常有启发。

它大概意思是说,所谓的「快鱼吃慢鱼」,并不是说人家加班到晚上12点,你就天天逼着员工加班看凌晨四点的中关村。快鱼的快不是这种意义上的快,而是策略上的快。

书里还举了 AirBnb 的例子。它通过共享的方式来创造供应,AirBnb 增加一个民宿只需要几天,而连锁酒店可能要花上半年。就算连锁酒店的员工每天工作85 个小时,也赶不上 AirBnb 的速度。这就是策略上的快。

所以,回到副业上面来,如果想要我们的副业具备很强的竞争力,我们就必须根据其独有的特点,为其制定一个有竞争力的策略。

比如说,我们的副业项目往往规模不用做到特别大。因为如果我们想做到财务自由,那么1000万左右的人民币基本上也就够了。1000万这个数字对个人来讲可能很多,但是对于企业来讲,其实是一个非常小的市场。尤其对于一些以融资方式发展的创业公司和上市公司来讲,这种规模的市场根本就没有办法生存。所以,如果我们选择的目标市场足够好的话,是可以避免很大一部分公司的竞争的。

当然,即使是在一两千万的市场里边,仍然会有不少的竞争对手。我们仍然需要结合副业的特点来构造自己的优势。这里给大家介绍其中一种,叫做「副产品优势」。我们本身是有正职工作的,通过日常工作,会积累很多的经验知识和其他资源。如果我们把这些东西利用起来,把它做成副业的产品的话,它的成本是非常低的,而在深度上,往往又会有很高的门槛。

举一个实际的例子。

比如,我一个朋友是云平台的架构师,他的工作是专门为传统企业往云平台上做业务迁移提供解决方案,方便这些企业购买他所在公司的云计算产品。

但是在这个过程中,他接触了大量的、各行各业的公司的迁移需求,并为他们做了架构方案。这让他的架构能力突飞猛进,架构经验也远超旁人。

这个时候,如果他以副业的形式,开设讲授架构技巧的课程,对他来讲成本是非常低的。因为无论他做不做这个副业,都要投同样多的精力在这件事情上。

作为对比,如果一位全职网课讲师想要来做同样主题的课程,那么就需要从头开始学习完整的架构知识,并花足够长的时间,比如说几个月甚至几年,去接触大量的实际案例,最终才可能做出同样品质的课程。

而对专职讲师来讲,他的收益仅仅是课程收益,并不包含主业的薪资,所以最终收益甚至可能还赶不上他为了制作课程进行的投入。在这种情况下,全职反而成为了一种劣势,这就是我们所谓的副产品优势。

当然,我们还可以根据副业的其他特点,发掘出各种独特的竞争力。但只有围绕核心的稀缺资源进行规划,并从策略上建立我们的核心优势,才能真正做到优雅地做副业。

================================================ FILE: docs/0202.html ================================================ 时间片 - 精益副业

时间片

这一节开始,我们就来讲讲副业的核心资源——时间片。

================================================ FILE: docs/020201.html ================================================ 时间片的销售 - 精益副业

时间片的销售

前边说过,时间片是我们副业的核心资源,所以直接把它以一个比较低的价格销售出去,是不划算的。这种方式和「优雅」这两个字不太匹配,但我们这里还是会简单介绍一下。

它不会作为我们这本书的重点,但大家有一个简单的了解也是好的,至少可以作为其他副业方式的对比。

私单

不经任何加工直接销售时间片,最主要是以「私单」的方式来进行的。

外包

传统的私单主要是外包模式。也就是说,一家公司有一个项目要做,它把这个独立项目完整的包给你。双方约定完成的时间、验收的标准和价格。大一点的项目,还会有阶段性的交付和付款。

除了这种完全线下的外包,还有基于网络的 freelancer 方式。大体上是基于网络接单,然后按发包方的要求进行开发。因为没有地域的制约,可以承接国外的业务。

目前的情况看,中国程序员在海外外包市场上并不占据优势,尤其是个人。因为现在海外接单平台上有大量的印度、巴基斯坦等国家的程序员,他们要价非常的低,而且平均而言,英文沟通能力比中国程序员要强一点。接这些单子会比较累。

做起来比较舒服、利润比较多、沟通上比较容易的私单,往往是通过行业人脉和开源项目来的。

外包的坑

大部分的外包在我看来都是很痛苦的,因为它其实和程序员的技术栈不对应。

沟通问题

我们平时在公司开发时,都是产品经理把需求梳理好,然后和程序员进行沟通,好一点的还有高保真原型。即使在这样的情况下,进行需求调整的时候,我们还是会很难受。大量的代码需要改动,如果上线时间表比较紧,我们就会被逼着加班。

而外包模式下,需求方往往就变成了外部的人群。因为个人的工作量有限,所以通常不会是特别大的单子,这就有可能遇到大量不靠谱的发包方。他们很可能并不了解开发的流程,也表达不清自己的需求。

这就要求我们有相当的沟通技巧。如果是基于网络的沟通,效率会进一步降低,问一句得等半天才能有响应。

甚至,很多时候我们会被迫去做需求分析工作,因为整个环节中缺失了产品经理 —— 很多发包方觉得根本不需要这个中间角色。

尾款问题

即使熬过了开发阶段,还有一个尾款收取问题。新手容易因为太过信任对方先交工再收钱;老手也逃不掉那种开发完了对方的创业公司倒闭了的情况。

比较大的项目或者面向特定行业的项目,在签单之前可能会有招投标,然后可能会有层层的审批。在款项的时间预期上要有心理准备,经常会有项目都做完了审批还没有走完的情况。

项目全部由自己开发还好,如果需要其他人的配合,那我们就需要自己垫付资金。这些风险需要合理的控制。

开票问题

个人做私单还有一个烦心的事情,就是大部分的单子都是需要开具发票的。这时候就只能去找一些公司代开。这种代开是有费用的,所以在定价的时候要把这些也考虑进去。

按需雇用

正是因为这种整单外包的方式会带来各种麻烦,最近开始出现一个更加「简单粗暴」的私单方式,叫做「按需雇用」。这是面向发包方的说法,对于程序员来讲其实应该叫做「驻场开发」。

我们平时都有正职工作,但是如果不是去了黑心企业的话,周末的时间还是空出来的。这时候我们就可以到其他公司去上一两天班。通常是一些创业公司,去解决一些他们的开发没有能力或者精力解决的问题。

在这种模式下,费用是按时薪结算,沟通也更为顺畅。只要像平时一样多上一天班就可以获得好几倍的回报。而且当天晚上就可以获得收入,也没有尾款的烦恼。

所以如果非要销售时间片的话,我觉得这种方式更高效一些。

更优雅的方式

但是正如我们前面所说的,你的时间片是非常有限的。像按需雇用这种方式,虽然收益看起来高一点,但它的天花板也是非常明显的。

我们可以很容易地算出来。假设我们每周末拿出一天,一个月也就只有四天而已。就算一天能挣2000块钱,一个月也就是8000块钱。

这是最理想的情况下,因为只能周末工作,所以往往并不是每周都会有活;同时,如果遇到开发内容不是特别熟悉的情况,可能还要花一点时间去学习相关的资料。

整体来讲,我们认为私单,尤其是按需雇用,属于一个中高收益、中低风险、但是也有明显的收入天花板的一个副业。

================================================ FILE: docs/020202.html ================================================ 时间片的优化 - 精益副业

时间片的优化

时间片的优化有两个思路。

提升单位时间的收益

提升单位时间的收益其实就是提升时薪(但并不一定局限于按时薪支付的副业,其他形式可以折算成时薪),有几个简单的思路。

切换地域

「切换地域」就是说,我们同样是干活,但如果服务对象所在的位置不同的话,单位时间的收益也是不同的。

比如你在重庆,给本地公司去做一些外包,那整个项目的基础价格就是参照当地程序员的人工成本来进行比价的。但如果是在重庆可以给北京的公司做外包,那发包方就会更多地参照北京的各种成本来进行相应的股价,这样我们就可以把自己单位时间的收益提升上去。当然,需要考虑沟通的效率和成本。

把这个思路扩大一点,就变成在国内做国外的业务了。

因为和国内相比,国外的人力成本通常会贵很多,如果你在二三线城市,那么成本又更低。这样就出现了一个价格差,如果能控制好这个价格差,我们就能挣到更多的钱。

当然前边也说过,这里边有竞争和外语沟通的问题,需要根据自己的实际情况来选择。

从外包到二次开发

在没有建立起自己的知名度之前,非常单纯地去做外包,面对的往往是价格战的红海。地球那么大,总有人的时间比你不值钱。

而且外包它是一个开放性的需求,如果真要把很多雇主的需求细细做好的话,对技术栈的广度要求还挺高的。因为每一个项目它要求的技术栈可能不一样。项目做的越多,用到的偏门技术就可能越多。

所以我们要想办法解决竞争的问题。细分市场就是一个很好的思路,比如说我们可以给一些标准化的开源产品做二次开发来挣钱。

这其实不是什么特别新的思路,早在个人站长时代就有人专门给 Discuz!这个开源论坛软件写插件和定制功能挣钱,而且还真养活了不少小公司。

现在我们可以把这个思路更扩展开一些,比如说我们把从「支持国内项目」变成「支持国际知名的项目」。

这样的话,我们就能解决掉出海接活面临的大部分起步问题。

你看:

  • 我们从什么地方来获得客户?直接从开源社区获取客户。
  • 如何证明我们的开发能力? 可以写一些高质量的开源插件,给大家免费使用,并作为我们的demo。
  • 如何来获取比较高的收益?专门给一个项目写插件的团队并不是太多,选择够好的话,就可以成为这个细分领域的No.1,获得一些品牌上的溢价。

提升单位时间的效率

提升单位时间的效率对于按工作量支付的副业来说特别重要。

比如说我们现在有一个项目,交付后的收益是10万块钱。以原来的方式完成它,可能需要花100个小时。现在我们想到了一种新办法,把效率提升了10倍,那么原来100个小时才能完成的活,现在10个小时就能做完了,这就是效率的提升。

多出来的90个小时我们可以用到其他项目上,哪怕是用来休息,也是很好的。

打鸡血难以奏效

当然,通过增强意志力来强迫自己去提升生产效率,其实是很难奏效的。

因为我们本来就是在利用工作之余的时间。在这个时间上,很难保证精力非常充沛。别说提升工作效率,能保证在做这些事情的时候尽可能的不被干扰,不让自己的生产效率降下去,已经是非常不错了。

自动化

但是非常幸运的是,我们是程序员。我们从事的工作,它本身就有一部分是由机器来完成的,所以我们可以引入自动化来提升效率。机器是使用电来工作,它的效率提升空间是非常大的,而且它也不需要休息,可以7×24小时地进行工作。

代码生成器

对于程序员的日常工作来说,最主要的自动化方式就是代码生成器。

但一说到代码生成器,就会听到很多反对声音。如果你用过一些比较早期的代码生成器产品,很可能你也会会有一些负面印象。

在大概十多年前吧,我当时所在的公司也就购买了一套代码生成工具。根据说明书,配置好业务逻辑,然后就可以同时生成ASP、PHP和JSP的代码。

公司买来以后就强制性行推广,但在硬推了两个月以后,发现推不动,只好放弃了。

最主要的原因是因为它没有办法处理我们特有的一些逻辑,加上每一个部门有自己独立的规范和周边库,在那个工具里边没法用上。之后很长的时间里,我们整个部门的人都对代码生成器非常反感。

但是后来还是经不住偷懒的诱惑,我自己一直在偷偷地不断尝试。渐渐地发现,其实要做一套全世界通用的代码生成系统可能会特别难;但是如果只是给自己做一个专用的代码生成工具却非常简单,只要遵循以下两个原则。

只为自己设计

第一个原则是「只为自己设计」。

因为每一个公司,每一个部门甚至每一个岗位它所面临的需求是千差万别的,很难通过一个通用工具来解决,所以我们也很难买到为自己量身定制的工具。

但如果自己来开发工具的话,就完全不同了。我们可以完全按照自己的工作流程、按照每天写代码的需求来进行设计。我们非常清楚写代码的时候,元数据是存放到什么地方的、通过什么样的方式进行加工、以及最终要生成怎样的代码。所以可以开发出非常好用的自用代码生成工具。

能自动化的自动化,不能自动化的半自动化

第二个原则是「能自动化的自动化,不能自动化的半自动化」,后半句特别重要。

很多程序员在设计代码生成工具的时候,往往太过完美主义,老想着要做一个系统把所有的工作都做完,最好点一下按钮后,什么事情都不用去做了。

这当然是最理想的方式,但是我们的开发环境和其他的办公软件之间不一定存在交互接口,很多软件只有图形界面,不支持通过 API 进行数据交换。所以,很多时候我们就没法做成全自动。完美主义或者叫强迫症的同学就会说,既然这个东西不能完全自动化,那就直接手动来处理吧。

但我们开发代码生成器的根本目标并不是要做一个完整的自动化产品,而是要提升我们的生产效率。所以,即使有一些地方不能做到完全的自动化,我们也可以把它做成半自动化。

半自动化有两个思路。第一个思路是,我们可以通过交互方式来解决一些不能自动化,或者需要花很多时间去处理的细节问题。

举一个例子,这个例子发生的年代比较久远,现在可能已经不适用了。

我们当初在做网站的时候,有很多的资料都是编辑给的。那个年代还没有产品经理,都是由网站编辑给我们资料。他们都使用 office 软件来存放数据。

当时是没有比较好的 office 格式解析包的,所以很多同学都放弃了数据的解析,改为手工输入。我给了一个解决方案,就是直接在 office 里复制数据表格,然后再粘贴到一个 textarea 里,最后用 PHP 分析 tab 和换行符号,把数据分离出来。为了防止分析错误,还做了一个界面来进行确认和手动修正。虽然没能实现全自动,但是比起手工输入数据,这个方案效率的提升是几十倍的。所以不要过分纠结于全自动化,有的解决方案不完美,但也可以很精彩。

另外一个思路是,只对小操作做自动化,用来生成代码片段。比如说,我们在写输入处理的时候,往往需要根据数据表字段来对输入进行验证,这往往是一个重复劳动。所以,我就写了一个命令行的小工具,它可以直接读取数据表里边的字段和对应的注释,根据注释里的标记来判断对应的字段的验证信息,最后会自动生成验证部分的代码。我把这些代码粘贴到编辑器后,再进行相应的修改,就可以很快的完成验证工作。这没有什么技术含量,但是它可以切实提高我们的生产效率。

这些只是我想到的思路,当然还有很多其他的。比如有的同学是通过工具链,通过命令行交互,来实现自动化。

人工智能

代码模板呢,只能解决相对比较死板的规则。但最近随着人工智能的进步,在某些特定的场景下,原来很多低效率的人工操作其实可以交给 AI 了。

现在,AI 的正确率确实达不到和人类同等水平。但是,还是前边那句话,「不能完全自动化的,可以考虑做成半自动化」。针对 AI 正确率不高的场景,我们可以通过人机结合的方式来处理。

比如说,我们要进行图片分类,之前可能需要花上十几个小时的人工。现在使用 AI 进行分类,只需要十几秒。但是它可能有20%的图片分类是错的。

我们就可以先让 AI 来进行分类,然后再人工确认一遍。确认花的时间可能是两个小时,但即使这样,比起之前的十个小时来讲,效率也提升到了五倍。

最近很多人工智能接口的品质已经不错了。比如说,熟悉我微博的同学都知道,我经常会用语音的合成和识别服务来提升内容生产效率。

比如我经常会发一些技术视频,但是又不想自己录音,于是就会使用人工智能来生成语音。而大家正在看的这本书里,至少有一半的内容我是通过语音识别APP,以每分钟100多字的速度记录下来,然后再二次进行修改、校正完成的。

所以不管你对 AI 有什么看法,它现在已经在实实在在地改变着我们的生活。我们要思考的是,如何更好地利用它。

如果服务足够可靠,我们就可以做成自动化服务,直接提供给最终用户;如果服务还不够可靠,我们可以把它放到中间流程里来提升效率。

比如,同样是代码生成技术,如果我们把它做成面向不懂技术的人群的产品,服务不是很可靠的话,最终效果就会很惨;但同样品质的接口,如果我们把它做成面向开发者的服务,而且是在编辑器里面实时地进行代码补全和建议的工具,它就会显得非常好用,可以极大地提升生产效率。

================================================ FILE: docs/020203.html ================================================ 突破时间片限制 - 精益副业

突破时间片限制

前面我们讲了时间片的优化,敏锐的同学可能已经感受到了,时间片的限制其实是有办法突破的。下边我们就专门来讲一下怎么突破时间片限制。

倍增

第一个思路叫「倍增」,就是让时间片的数量成倍的增加。但这里有一个前提,就是不能过多的增加我们的精力消耗和风险。

因为不考虑这个前提的时间片倍增非常容易,只需要增加雇员就可以了。但我们随时都要提醒自己,这是在做副业。

如果我们雇用全职人员,就需要有办公场地、还需要到现场进行人员管理。这对于有正职工作的同学来说,是很难分身的。除非你把办公场地放到正职工作的公司附近,用空闲时间去管理。但这依然有精力上的风险,搞不好既没做好副业,又影响了正职工作,这就本末倒置了。

既然雇用全职的路子走不通,我们就只能考虑雇用兼职。

外包

主要的方式就是将部分业务外包。前边我们其实刚聊过外包,只不过在这里,我们从接单方变成了发包方。

外包的方式,可以将大块的业务交给别人去做,自己只需要花少量的时间片来做沟通和管理。等于接单方的时间片也为我们所用了,所以整体来看,时间片是倍增了。

外包还会带来一些潜在的风险。

我们的时间片是倍增了,但我们的成本也在成倍地增加,也就是说本身我们的项目需要有足够的利润空间才适合使用这种方式。如果控制不好,很可能最后整个项目做下来不挣钱甚至亏本。

另外,外包方式下,沟通和项目管理也是比较大的挑战。因为它不是那种每天在一起的沟通环境、也不是直接的上下级关系。只能以合同的形式来进行约束,很多时候甚至连合同都没有。这种情况下,其中某些环节出现问题,我们就需要为整个项目承担风险。

众包

其实还存在其他的雇用兼职的方式,比如众包。众包和外包类似,但粒度更细,接单方更多,甚至我们都不知道接单方是谁。

一个典型的例子是 Facebook 的多语言翻译工作,他们提供了一个在线翻译工具,让懂该语言的用户每人来翻译几句,因为用户数量庞大,很快就能完成整个翻译工作。

众包的收益非常不错,一方面是成本上的,因为接单方多,所以会产生竞价。如果分摊的工作量非常小,甚至可以是免费的。另一方面是时间上的,同样因为接单方多,完成的速度会非常惊人。

不过,为了支持大量的接单方,我们的业务结构需要进行相应的调整。

比如说,通常我们可以把一个系统分成平台部分和扩展部分。平台部分,我们可以自己制作;扩展部分就可以把它设计成插件、扩展、中间件,将这些东西以众包的方式分出去。即使其中的组件出问题,对我们核心平台的影响也是小的。

这样对接单方来讲还有一个突出的好处,就是这种组件本身的逻辑和它的相关资源是闭合的,只需要知道输入输出,内部实现完全可以自己决定。组件开发者之间也不需要沟通,只需要跟平台以文档、API的形式来进行沟通,在使用细节上以工单的方式来进行反馈就可以了。这可以大幅度降低我们的管理成本。更进一步,我们可以开发工具来对众包进行支持,进一步提高效率。

所以,如果能培养起好的众包生态,我们是可以实现低投入的时间片倍增的。对于不想开公司、对时间片又需求大的业务来说,是非常值得尝试的。

超卖

另外一个突破时间片限制的方式我叫它「超卖」,就是把一份时间片卖给多个人。

在很多非常个性化的业务里边,我们是为对方专门定制的服务和内容,所以一份时间片只能卖给一个人。但是,当我们业务做得足够久了之后,就会聚集起来很多有相同需求的人。

这时候我们就可以把他们的公共需求抽取出来,做一份面向这个公共需求的产品或者服务。这样的话,我们只需要花一份时间来做产品,就可以把它卖给多个人,也就间接地实现了时间片的超卖。

比较典型的例子是建站。这曾经是很多小公司赖以生存的业务。在最开始的时候呢,建站公司都是去跟客户谈,想建一个什么样的网站,然后找设计师进行界面设计,完了以后再进行开发。这种服务就是一对一的时间片售卖。

但后来很多公司发现其中重复的需求太多,于是就把建站的需求做成了一个系统。在这个系统上,客户可以自行选择模板,添加功能模块,输入内容,通过浏览器就可以很快地生成自己想要的网站。整个过程甚至不需要其他人参与。

从个性化服务到标准化服务,是实现时间片超卖的主要思路。

再举一个更明显一点的例子。熟悉我的同学都知道,网课是我一个很重要的业务。但和其他的机构不同,我从来不做直播课。所谓直播课是说,我提前准备好教学内容,等大家都上线了,然后我们在一个直播房间里边,一边讲课一边学习。相对的是录播课,是说我提前把这个内容录好,然后大家自己找时间去看视频就好了。

从讲师的角度来看呢,直播课就是一对一的时间片消耗模式,每讲一次,都要消耗一次我的时间片。而录播课则是一对多的时间片消耗模式,不管有多少学员,他们只需要去看录制好的视频就行,我付出的时间片不会增加。这也实现了时间片的超卖。

从上边的两个例子可以看出,时间片的超卖背后,实际上是商业模式的调整。

最理想的情况下,我们只需要付出一份时间片,然后即使我们什么都不做,它都可以持续不断地进行售卖。不管我们是在吃饭睡觉、看电影逛街、还是在旅行休假,这个产品都会持续不断地给我们带来收入。这种收入我们称为被动收入,能带来被动收入的东西,我们叫它资产。

================================================ FILE: docs/0203.html ================================================ 资产和被动收入 - 精益副业
================================================ FILE: docs/020301.html ================================================ 什么是资产 - 精益副业

什么是资产

资产的定义见仁见智了,我比较习惯用罗伯特·清崎在《穷爸爸富爸爸》里的定义,那就是「能把钱放进你口袋的东西」就是资产。换句话说,能产生被动收入的东西,其实就是资产。

《穷爸爸富爸爸》这本书很多人都读过,罗伯特·清崎后来还写了一个系列,核心是富人不为钱工作,而是让钱为自己工作

在书里边,主要通过「购买」的方式来获得资产。这里是书中列出来的资产类型:

  • 股票
  • 债券
  • 能够产生收入的房地产
  • 票据(借据)
  • 版税,如音乐、手稿、专利
  • 其他任何有价值、可产生收入或者增值潜力且有很好销路的东西

这个系列后来就跑去教人投资和理财了。

其实投资也可以视为一种副业。优点很多,比如占用精力相对较少、没有收入天花板等;但也有两个明显的缺点。

最主要的缺点是风险高,且不易评估。还有一个缺点是,投资你得先有资理财你得先有财。在风险可控的范围内,大部分投资理财的回报率差异不会特别大。如果你手上一百万都不到,可能折腾一年、背着挺大的风险也就是多挣了几万块钱。

投资理财是一门深奥的学问,我们不在本书中展开,大家可以阅读相关的专门书籍。

在罗伯特的资产清单中,还有一个可以无成本获得类别 —— 版税。但其实在中国因为书卖得特别便宜,而版权又普遍不受重视,一些大公司都堂而皇之地侵权,其实很难获得高收益。

如果没有初步的积累、或者不想背负过大的风险,怎样才能获得资产?

================================================ FILE: docs/020302.html ================================================ 资产的获得方式 - 精益副业

资产的获得方式

资产最简单粗暴的获得方式当然是通过购买。但好的资产未必人家愿意卖,当然更可能的是,我们未必买得起。

但是除了购买,其实还有一个逐渐被遗忘的方式 —— 直接「创造资产」。对于很多传统行业的人来说,创造资产会大量的消耗精力,最后成本可能并不会比购买资产低多少。

但现在软件吞噬了世界,数字化业务已经茁壮成长,数字资产的生产资料日益廉价。而我们是程序员,正是那个可以通过自己的技能栈低成本、低风险的创造数字资产的群体。

并不是每个人都有我们这么幸运,其实大部分的程序员,离完整地做出一个商业产品,缺的可能只是一点美感和设计能力。

================================================ FILE: docs/020303.html ================================================ 资产的量化评估 - 精益副业

资产的量化评估

当然,并不是所有的数字资产都适合我们以副业的方式去创造。不过就像前面不断重复的,副业是一个资源和精力都非常缺乏的状态,我们也只能从庞大的可能性中,选择那些适合的产品和服务。

适合副业的几个特征

说到底有哪些产品和服务适合副业呢?下边是我觉得值得留意的几个特征。

自传播

首先是「自传播」,就是说这个东西做出来了以后,它本身有很强的感染力,它的用户会主动地去推荐给其他用户,这样的话我们就不用花很大的成本去做营销。

对于大部分程序员来讲,把程序写出来只是时间和精力问题。写不出来程序的程序员很少,但卖不出去程序的程序员非常多。所以,如果我们做的东西本身就能传播,那么我们就可以在零市场预算的情况下获得成长。

UGC

第二类叫做「UGC」,用户贡献内容,它其实可以理解为一种更广意义上的众包。核心也是突破时间片限制。比如说我现在经营一个原创博客,天天都是自己写,就会觉得自己累得都不行了。

但如果我们去做一个访谈类的博客,弄一个相对固定的问题列表,然后拿着这个列表去采访各行各业的人,把结果做成一期一期的内容。这样用户就贡献了至少一半的内容了。

如果我们再改成办一个杂志,每一期大家根据主题投稿,你就从主创变身成编辑了。虽然投稿里有好有坏,良莠不齐,但我们的主要任务已经变成去筛选了,只要贡献内容的用户足够的多,那整体质量还是有保证的。最主要是内容的量就上来了。一个人的话,不管你多么努力,总是有一个上限的,因为你毕竟是人类。

自动化

自动化」前边有提过。

就是说应用做起来以后,它所有的环节全部都可以由机器完成,我们什么都不用管,只需要把它扔到云平台上,然后定期给云平台打钱。当然这是一个理想的情况,意外总是会出现的,而且各种意外会约好在同一天出来逛街,别问我为啥知道。但是在绝大部分情况下,我们都可以不去管它,它都可以自动化运行。这种被动资产是非常适合副业来做的。

量化评估标准

我们也可以更为量化地给资产定一个评估标准,确定好要考察的几个方面,每个方面做一个满分为5分的评分,对每一项评分就可以得到一个多边形,从而一目了然的看到各类资产的状况。

这个标准每个人的想法可能不同,这里分享的是我自己用得比较多的标准。

投入

项目的一般投入都是三项:「人」、「钱」、「时间」。

「人」和「时间」不多说,通常就是我们自己和挤出来的那点时间了。

「钱」方面,我们也需要一点启动资金,但不用花大钱去购买各种固定资产。这也是我们这个行业能自己动手创造资产的一个重要原因。尤其是现在,云计算已经普及了。即使是很大访问量的网站,我们直接租用云服务,按用量付费,省钱又省心。我大学刚毕业的时候,要是做大点的网站,还要自己去买服务器,自己扛去机房托管。现在只需要点点鼠标就能买到一堆 vps ,其实是蛮幸福的。

要提醒大家的是,一定不要忘记维护成本。我们卖时间片的时候,活干完就完了,钱就拿到手了。 但是在自己创造资产的时候,资产的每个细节基本都得自己来 cover 的,所以维护成本一定要算进去

维护成本往往不是那么显而易见。比如说吧,网课也是有维护成本的,尤其是技术类的,它的更新成本其实相当高。

产出

在评估产出的时候,可以分为「一次性的回报」和「周期性的回报」。

一次性回报,比如我们给人家做技术顾问。可能就是在周三拿到一个邮件介绍说是什么样的一个需求,有什么问题要解答。我们花上2~3个小时来准备,在周末约一个时间,面谈一个小时,把之前准备的内容聊清楚,聊完了以后,回报就拿到手了。这就是一次性回报。

周期性回报,比如说我们在掘金上写了一个小册,那只要有人在购买,我们就会不停的有收益,这种收入一般按月结,所以每次看起来没多少,但加起来还是挺多的。我之前算了一下,发现在我创造的各种资产中,掘金小册的投入产出比是最高的

可持续性

持续性是以前忽略掉的评分项,后来被我追加上来。这其实是一个非常浅显的道理,一个资产放在那个地方,它不可能一直就持续地挣钱。就像电池光用不充电的话,总会有用光的一天(别和我提太阳能电池)。

这是因为我们创造这个资产的时候,它是面对一个市场需求的,而需求本身它会随时间变动。绝大部分的情况下,需求和我们提供的解决方案之间的契合度,会随着时间越来越差。最后就会变成,要么我们就不去管它,让它慢慢地随着时间去消亡;要么我们又要花成本去维护它,把它从偏差的地方给拉回来,重新覆盖到需求上面。把用户的满意度、用户的体验、市场的趋势给重新考虑进去,让我们资产的生命期变得更长。

对于不同的资产,只是过程的快慢会不一样,但整体来讲,都是会有这么一个过程的。

风险

程序员创造产品最大的风险是「没人用」,因为虽然大部分科班出身的程序员都学过需求分析,但仍然各种喜欢拿着锤子找钉子。

当然,这对于没有做过独立开发或者自己产品的同学来讲,是一个必经的阶段。所以早期项目的风险都会非常高,但并不是说风险高我们就不做了,我们可以相对的调低投入,原来要投入三个月上线的产品,可以花三天做个最小可行产品(MVP,后文会说明)上线,测试到需求以后,再继续加码。这样也能慢慢的获取到一个平衡点。

门槛

最后我加了一个评估标准叫做门槛。因为「副业」的关系,我们的各项资源都是受限的,这个评估标准体现了受限情况下创造资产的难度。

================================================ FILE: docs/03.html ================================================ 优选资产 - 精益副业

优选资产

在这一部分,我们整理了大量的副业,并从中拿出适合程序员的来进行评估和讨论。

================================================ FILE: docs/0301.html ================================================ 知识和人脉的变现 - 精益副业
================================================ FILE: docs/030101.html ================================================ 付费视频课 - 精益副业

付费视频课

picture 2

总体来讲,付费视频课是一个中等投入,然后产出极高的副业。

低投入 ★

前期需要做一些课程内容的准备;后期你需要对视频进行剪辑;录音还需要购买硬件。大部分的程序员并没有视频剪辑技能,所以这里有学习成本。硬件的话倒不算贵,便宜点的不到一千就能搞定。但是这是在我们赚到钱之前就要投入进去的。

高产出 ★★★★★

从产出上来讲,课程是一个非常好的品类。中国人有良好的为教育花钱的传统,大部分的用户都愿意为好的课程花钱。一些优质的、上百节的大课可以卖到几千甚至几万。相比其他的副业,它的产出是非常高的。

可持续性 ★★

我们是做技术类的课程。技术内容本身的变更是非常快的,除非我们做一些非常经典的基础课,比如说计算机原理、算法等等。

如果是跟语言、框架、实战相关的各种前沿课程,大概半年到一年就需要更新一次。如果我们使用屏幕录制方式来制作课程,在修改的时候,很可能需要重录相当部分,修改起来成本很高。

低风险 ★★

风险不低。如果做的课程比较长,比如几十上百集的大课,用业余时间来做可能会花上几个月甚至一两年,有时候做完技术都更新了。如果最终卖不出去的话,损失是很大的。

低门槛 ★★★

门槛不算高也不算低。如果经常在公司里面给团队做分享的话,那对你来讲这个门槛就很低。如果一直都是默默无闻地在做技术的话,可能就需要去练习一下怎么讲课。

因为我们最终是可以通过剪辑来进行调整的,所以也只是一个时间投入上的问题。讲得不好,你就多讲几遍;哪一句讲错了,就重新再讲。所以它本身的硬性门槛并不高。

关于风险和维护成本这两点,其实是有办法可以解决的,我们会在后续用专门的章节来讨论,这里就不展开了。

================================================ FILE: docs/030102.html ================================================ 付费专栏 - 精益副业

付费专栏

picture 3

付费专栏就是付费的系列文章,绝大部分是技术教程,也有一些面向程序员的「心灵鸡汤」。我们可以简单地把它看成是传统出版的网络化。

对于技术内容来说,传统的纸书出版方式有一些明显的缺点。比如,不是彩页的话代码不能高亮,彩页的话书又特别贵。书里的代码也不能边看边调试。纸书的出品周期也较长,更新也慢,一些最新的技术会有一个较长的空白期。

而在线的付费专栏恰恰可以解决掉这些问题:它基于浏览器,自然可以通过 JS 来进行代码高亮;内容可以在线修改,几乎可以实时生效;做得细的技术专栏往往还内嵌了基于浏览器的调试环境,可以做到边学边练。

再加上原来技术博客的群众基础很好,于是技术平台和社区纷纷添加了付费专栏功能。这其中,做得比较好的应该算掘金的小册

picture 6

下面我们来看一下付费专栏作为副业资产的各项评分。

低投入 ★★★

从投入上来讲,文字专栏比视频课程投入要低很多。但是技术内容比起其他文章的写作来讲,需要有技术实践作为基础,经常还要嵌入代码,调整格式,投入相对要高些。

高产出 ★★★

文字专栏的售价普遍比视频课程要低,像掘金小册的话,一般就在20~30块钱之间,还经常打折促销。

可持续性 ★★★

前面已经说过,技术内容一般更新频次高。但是图文专栏的更新成本很低,只需要编辑文字、加入新的内容就好,不需要像视频那样重新录制和剪辑。

低风险 ★★★★

文章的创作成本很低,而且我们可以通过发布短文来测试主题是否受欢迎,在确认后再开始系列文章的书写。

低门槛 ★★★★★

只要会写文章,就可以做付费专栏。

================================================ FILE: docs/030103.html ================================================ 付费社群 - 精益副业

付费社群

picture 4

所谓付费社群就是指一些收费的微信群,QQ群或者付费可见的信息流、圈子类产品。

之所以把付费社群单独拿出来讲,是因为它更偏重于销售的不是内容本身,而是一种人脉关系、社区氛围或者互动型的服务。

像付费课程,通常是类似于出版。我提供内容,你来进行学习。通过文章评论和回复进行互动,时效性和效率比较低。

而在付费社群里边,大家互动起来会比较方便。比如在群里,你一句我一语很快就可以讨论起来。所以,付费课程和付费社群其实是有互补关系的两个产品。

我们可以把付费课程放到课程平台,然后把实时的学员答疑或者其他服务,再做成付费社群。

低投入 ★★★★

付费社群的投入是非常低的。如果我们要做课程的话,需要累积相当多的内容。但是付费社群它卖的不是内容本身,所以即使它没有内容,也可以立刻进行销售。

而且因为社群的互动环境在形式上比较随意,有个什么想法随时发一段文字或者几张照片都可以,内容创作的成本很低。

高产出 ★★★

产出方面就要看具体销售的是什么东西。氛围和讨论环境本身,通常不会特别值钱。但是如果能利用起来,价值就会非常高。比如用付费社群来做中高端猎头服务。

可持续性 ★

需要持续不断的有内容更新。当然也可以引导其他用户贡献内容。如果一段时间没有内容和话题,就很难维持社群的活跃,氛围会随着时间慢慢变冷,严重影响第二年的续费。

低风险 ★★★★★

没什么特别的风险。

低门槛 ★★★★★

会建群会聊天就可以开始。

================================================ FILE: docs/030104.html ================================================ 图书出版 - 精益副业

图书出版

picture 5

如果把电子书也算进来,目前可以分发图书的方式大概有三类。

第一类是自己独立撰写图书,并生成 PDF 等电子书格式通过自己的渠道进行销售。这种更类似于数字商品售卖,所以并不包含在本节图书出版中。

第二类是通过出版商单独发行电子版。因为电子书不需要印刷,所以比起纸版图书门槛更低一些。我之前用 BookDNA 出版过电子书,只需要将书提交给他们,就可以上架到亚马逊、苹果、京东、多看等多个平台。收入他们会代收,按分成结算回来。

第三类就是通过出版社出纸书,有时候也会同时把电子书版权签下来。一般纸版的门槛会高一些,需要有一定的影响力或者完成度已经较高的书稿作为参考。

低投入 ★

图书出版的投入非常大。一般至少需要花费3到6个月来编写初稿,加上审校印刷等环节,最后出版可能还需要花上半年,整个周期很长。

基于现有的内容,比如课程、文章整理创作书稿投入会相对较低,但仍有大量的工作要做。

高产出 ★★★

产出要把物质回报和非物质回报分开来看。

通过 BookDNA 等出版社专门出版电子书,可以按图书销售收入获得分成,大概在 70% ,还算不错。如果是纸版书,一般版税就只有 8%~15%,整体收入相当有限。

但纸版书对个人品牌提升的效果明显,而且可以通过线下书店等渠道获得读者,所以在非物质回报上比较高。

可持续性 ★★★★

图书的更新频次都很低,一般只有销售得不错,才会在再版时进行修订。所以我们可以认为它的可持续性还算不错。

低风险 ★★★★

主要还是时间投入,没有太多额外的风险。因为我们主要是出版技术书籍,内容方面的风险也非常小。

低门槛 ★

不管是电子版还是纸版,都要经过图书编辑审核,通过以后才能出版。尤其是纸书,要考虑至少收回印刷成本,所以门槛还是很高的。

如果在 GitHub 或者其他地方有发布电子书,且有较好的反馈,那么纸版的出版谈起来门槛就会低很多。

================================================ FILE: docs/0302.html ================================================ 自有产品和服务 - 精益副业

自有产品和服务

那接下来我们就来聊聊程序员的专业领域 —— 通过开发自有的产品和服务、作为 side project 运营来变现。

需求的发现

首先要说的是很多同学都很困扰的问题。

我以前以为最困扰的问题应该是如何抽出时间和精力来做一个项目,但后来发现还有一个同样甚至更为困扰大家的问题,那就是有了时间以后,不知道做什么。

通常来讲,解决方案有两种。

一种是通过日常的工作和生活发现原生需求;另一种是通过观察分析和阅读报告来发现。

原生需求

最靠谱的方式就是,留意那些我们自己在日常的生活和工作中遇到的困扰,然后为它去做解决方案,最后把这个解决方案做成产品,出售给有同样需求的人。

这种需求叫做原生需求,不是我们因为有了某个技术而幻想出来的应用场景。原生需求不是等我我们去寻找,而是它会主动找到我们。这种需求非常真实可靠。

但有一个问题,我们程序员相对于整个大众来讲,其实是一个非常小众的人群。这个人群有一些独特的文化、行为和思考方式。所以程序员遇到的原生需求,很可能只适合程序员人群,而不适合其他更为大众的市场。这就让它的目标市场比较小。

而程序员又是一个动手能力非常强、开源文化深入骨髓的群体,绝大部分的解决方案都能找到开源项目,或者改几行代码就能实现了。一些大公司还时不时的开源一堆非常强悍的工具,所以面向这个群体的免费或开源工具很受欢迎,但收费工具却是非常难做的。

反而是如果你在非专业领域有一些更为大众的兴趣爱好,从那些方面来发现需求的话,难度就会下降很多。

需求的验证

另外要重复强调的就是,需求的验证不能以口头承诺甚至免费用户来验。做需求分析的时候你去问,很多都会说我觉得这个东西挺好的。但你让他们付钱的时候情况就完全不同了。

大家可以回想下自己在过去一年里边,为哪些软件或服务支付超过 100 元人民币。我之前发过一篇微博问我的粉丝(大部分是程序员),后来发现绝大部分都是一些资源型的服务,比如视频会员、云主机、网课、网盘;软件就非常少了。所以我们还是要尽可能的从更广泛的人群里去发掘更值钱的需求来做。

降低起始难度

上边并不是说程序员人群的需求不能做,而是说难度比较高。

作为副业,我们投入的精力是有限的,如果一上来就是玩 Hard 模式,失败的概率会非常高。如果经常失败的话,最后就变成一种习惯了,渐渐的,也就会不再想去做副业,甚至连创业的冲动也跟着没有了,这就非常可惜。

观察分析和阅读报告

另一个路径是观察分析那些已经在挣钱的应用,阅读它的用户评论,发现可以改良的点,制作更好的产品。这个工作量还是很大的,所以也可以考虑直接购买一些分析报告。

这里的分析报告不是那种行业的通用报告,那是针对创业公司和大公司的,需要投入很多资源,以爆发式增长的方式去推动,并不适合副业。

最近在国外开始有一些专门针对副业和 Side project 的分析报告。他们收集整个市场的信息,然后针对大致一亿美金以下的细分市场做趋势分析。这种市场一般冲着上市去的创业公司看不上,所以留下了比较大的市场空间。

我最近读过报告的有两家,一家是 Trends.vc,另一家是 SoftwareIdeas.io。不过这两家本身也是初创或副业业务,不知道各位读到这本书的时候是否还在运营。这里最主要的还是给大家提供一种思路。

我们在做副业的时候,也需要慢慢来改变我们的一些习惯。比如说对于程序员来讲,绝大部分的东西都是可以自力更生的。所有能自己做的就自己做,不能自己做的,我们会找开源项目。这样我们会更有安全感,做的事情也会更加靠谱。但是我们在做商业的时候,尤其是在做副业的时候,遇到的问题就在于我们的精力是非常有限的,在价格适中、又有购买能力的情况下,更好的方式是通过购买而不是自己开发。

================================================ FILE: docs/030201.html ================================================ 应用市场卖APP - 精益副业

应用市场卖 APP

picture 5

对于我们绝大部分程序员来讲,开发是自己的本职工作,所以都比较擅长。但是在做副业的时候,我们还不可避免地需要把自己的软件卖出去。而销售往往是我们的弱项,有没有一个办法让我们可以避免它呢?

答案就是应用商店。早期的应用商店是一个非常好的入口,它会分门别类的将软件陈列在上面,有需求的用户会通过分类浏览或者搜索查询的方式来安装或者购买。

但经过一段时间的发展,应用商店里边的软件已经越来越多,各种需求被满足得也越来越充分。

现在大部分的应用商店已经是红海市场,也就意味着说,即使你在应用商店上架了软件,也不等于其他的用户有机会看见它,因为软件实在是太太太多了。

所以,我们需要想办法在应用市场的应用海洋中获取流量。一般来讲免费获得流量的途径有两个。

关键字搜索

一个是通过关键字搜索。一般应用商店都会有搜索入口,用户输入关键字,商店则会列出匹配的应用列表。如果我们指定的关键字被搜得更多,那就更容易覆盖到更多的人群。

编辑推荐

另外一个途径是编辑推荐。一些看起来有创意、格调比较高的APP更容易被推荐。而同样功能但是界面不好看的应用,则很难被推荐。所以界面设计不光是用户体验的问题,甚至还直接影响我们的获客。

虽然现在应用市场很多,但是有强用户付费习惯的国内市场,其实也就是苹果商店,所以我们如果以挣钱为主要目标的话,就应该优先考虑苹果商店这个市场。Google 在国内没有商店业务,如果是面向全球市场的业务,可以上 Google Play。

下边来看看评分项。

低投入 ★★★

从投入上来说,如果你本身不是 iOS 开发者,又没有苹果电脑,那么可能需要为 iOS APP 开发购买一些硬件,同时苹果开发者还有一个至少 699 的开发者年费。

高产出 ★★★★

一旦进入市场某个分类排行前列,可以获得的流量还是很多的。

可持续性 ★★★

需要跟上操作系统的更新升级。应用市场会定期下架一些 SDK 版本过低的APP。大部分时候只重新编译就好了,但如果使用的一些库出现了兼容性问题,那么就需要有大量的维护工作了。

低风险 ★★★★

软件应用商店托管,数据同步可以用 iCloud 等,没什么特别风险。

低门槛 ★★★

对移动客户端的开发者来讲,基本上没有门槛。其他开发者要进入这个市场,需要学习移动开发技能。当然也有桌面应用市场,但数据比移动市场差很多。

================================================ FILE: docs/04.html ================================================ 精益副业 - 精益副业
================================================ FILE: docs/0401.html ================================================ 精益副业流程 - 精益副业
================================================ FILE: docs/040104.html ================================================ 商业模式画布 - 精益副业

商业模式画布

前边我们说到,在精益创业方法论里,有两个非常重要的假设,第一个就是「价值创建假设」。

因为不管是向用户销售软件还是在线服务,它本质上来讲其实是一种价值交换。也就是我们「给什么样的客户」「提供什么样的服务」,然后「收多少钱」的一个简单逻辑。

而围绕着价值的定义、创造和传播,我们可以使用一个非常棒的工具来描述它,这个工具叫做商业模式画布。商业模式听起来是一个很高大上的名词,但它具体化以后就很容易理解。

商业模式画布是以价值为中心的一张图,让我们把所有和价值相关的内容都放到上面,从而可以一目了然地纵观全局。

那下面,我们就来看一下商业模式画布是怎么围绕核心价值,一层一层建立起来的。

价值的定义

商业模式的核心,就是「价值主张」。也就是刚刚提过的,对谁,提供什么样的服务,收多少钱。 picture 6

创造价值

定义好价值以后,我们会从两方面来考虑它。首先是如何把这个价值给创造出来;然后是如何把这个价值给销售出去。

在价值创造这边,我们可以把它细化为三个方面。

picture 7

包括:

  • 我们需要进行什么样的活动?这里的「活动」是「activity」,其实也可以叫做动作。
  • 我们需要什么样的资源?
  • 我们需要进行哪些合作?

销售价值

在价值销售这边呢,我们就要思考:

picture 8

  • 我们的价值主张定义得够不够好?
  • 我们的渠道通路是不是足够的通畅,到达是不是有效?
  • 我们的客户关系要怎么来建立和维系?

其实价值主张应该放到价值定义里边,但因为价值主张它直接涉及到了客户细分,又直接影响到了销售,所以我暂时把它放到销售这一边。

分层结构

按前面的描述,我们比较容易把商业模式画布当成一张图。但事实上,它其实更类似于Photoshop 软件中 的 PSD 文件,是分层的。其中每一层针对一个细分人群。

这主要是因为我们提出的价值主张,很难同时覆盖多个人群。同样的价值主张对一类人来讲可能是非常棒的东西;而对于另一类人来讲可能就毫无用处。

所以,我们提出价值主张之前,就需要进行客户细分,把我们的客户分成几类典型的角色,再针对每一类角色来提出更为具体、更有针对性的价值主张。

画布结构

下面我们就实际来看一下商业模式画布的布局。

picture 9

在表格的最中间,就是我们的价值主张。在最右边,是客户细分。我们可以用不同颜色的文字,来代表不同的细分客户和针对他们的价值主张。

在价值主张表格的左边,是关于价值创造的区域,有「关键活动」、「关键资源」、「关键合作伙伴」;在价值主张表格的右边,是关于价值销售的区域,除了我们刚才已经说过的「客户细分」,还包含了「客户关系」和「渠道通路」。

表格的最下边一行,分成了两部分,左边是「成本构成」,右边是「收入来源」,它们都是根据我们上面的表格来进行计算的。一旦计算完,我们就可以预先知道这个项目做下来能不能挣钱,或者说挣钱的可能性有多大。

价值主张画布

在整个商业模式画布里边,「价值主张」和「客户细分」是最为基础、也最为关键的地方。如果价值主张没定义好,其他的做得再好也没有用。

所以,为了更好地进行价值主张设计,我们还有一张专门针对这两个部分的、更为详尽的「价值主张画布」。

picture 10

上边这张图就是「价值主张画布」。它左边是「价值主张」,右边是「客户细分」。

客户细分

在「客户细分」这里,它更为详尽地描述了客户的情况。

这个圆分为三部分,最右侧描述了客户想要进行的工作、要完成的业务;下方是他在完成这些工作的时候所感受到的痛苦;上方是在完成工作后可以得到的收益。

价值主张

图左边的正方形就是我们的价值主张。可以看到,价值主张是针对需求提供的解决方案。比如:针对痛点,我们会提供「痛点缓释方案」,让客户在完成工作的过程中,没有那么痛苦;针对收益,提出「收益创造方案」,让收益变得更多。

在这两个方案的基础上,我们通过产品和服务的形式来将其落地,也就是正方形的左侧部分。

契合

大家可以注意到,在「客户细分」的圆形和「价值主张」的方形中间,有两个正对着的箭头,它表示「价值主张」和「客户细分」之间要达成契合。

因为我们会把整个客户群体分成多个细分群体,所以价值主张画布,它其实也是多份的。针对每一个细分的客户群体,都会有一张自己的价值主张画布。

================================================ FILE: docs/040105.html ================================================ 最小可行产品和产品市场契合 - 精益副业

最小可行产品和产品市场契合

上一节讲了如何通过商业模式画布来规划商业逻辑,但是「所有的战略和规划都是假设」,只有被验证以后的认知才是可靠、可信的。所以接下来,我们就需要用实验的方式来对它们进行验证。

通常,我们会采用「最小可行产品」(Minimum Viable Product,缩写为 MVP)来进行验证。

「最小可行产品」有两个关键词。一个是「可行」,它其实并不是指用户拿过去能用,而是指它可以很好地验证我们的假设。

另一个关键词是「最小」。它是说,除了验证所必需的功能以外,其他的功能都应该先不做。那些功能应该在验证完成之后再去添加,不然如果我们验证失败的话,功能就白做了。在我们的精力非常有限的情况下,这种浪费是非常可惜的。

严格意义上来讲,我们可以针对整个商业规划里边的每一个假设来做一个最小可行产品对其进行验证。但是我们的精力是有限的,所以通常只对核心假设通过MVP来验证。这个核心假设就是我们之前提到过的「价值创建假设」。

一旦这个假设被证实了,我们就认为我们找到了「产品和市场之间的契合」(Product-Market Fit,缩写为 PMF)。

具体而言,我们会在验证假设之前,定下一些量化的指标。在我们验证的时候,进行相应的衡量。最后根据指标的数据,来判断是否达到了 PMF。如果是,就可以进一步的增加功能,往前推进;如果不是,则需要调整,甚至需要通过战略转型来重新找到 PMF。

这种转型可以是针对原有市场的细分市场重新提出价值主张;也可能是扩大需求,让它支持更广泛的人群。但无论如何,在找到 PMF 之前,我们都应该专注于价值假设的验证,而不是功能的丰富和市场的推广。

================================================ FILE: docs/0402.html ================================================ 精益网课变现实践 - 精益副业
================================================ FILE: docs/040207.html ================================================ 大纲的注意点 - 精益副业

大纲的注意点

这一节我们来讲大纲。大纲大家都会做,所以我们不全面的展开,只挑其中一些需要注意的点和大家交流。

条理性

最重要的一点,就是大纲一定要有条理性。如果在条例性上做得不够好,其他细节做得再好,这个课做出来在逻辑上也是乱的,最后学起来就会很别扭。

具体来说,我们要保证大纲的层次足够清楚,逻辑足够严密。有一个比较常用的结构推荐给大家,尤其适合知识性为课程。

三段式

这个结构分成三段,是一个总、分、总的结构。

在课程的最开始,我们会简明扼要地讲明白整个课程包含哪些内容;课程中的一些基础、原理也会放到这里。

之后呢,我们就可以按照章节进行展开,对每一个部分进行详细地讲解。

在最后我们会进行一个总结,同时放入一个大的实践章节。这样不但可以复习内容,还可以学以致用。当然在每一章结尾也可以安排小实践内容。

绝大部分以知识讲授为主的课程都可以采用这种总分总的结构,非常好用。

提问式

我们也可以用问问题的方式来引出我们的每一部分结构。比如「是什么」——「为什么」——「怎么做」。这种结构可以是全局的,也可以是针对每一部分的。它会让我们的逻辑和层次更清晰。

覆盖面

第二个需要注意的点是覆盖面。因为我们的课程往往是出于自己的实践经验,有时候会局限于我们所在的公司和所在的行业节点,它的覆盖不一定特别的全。所以我们的视角不一定能覆盖到所有的需求方。

有时候我们的课程是为了一类人做的,但另外一类人,实际上也可以学习我们的课程,就差一点点的周边知识。在这种情况下,如果我们可以注意到大纲的覆盖面,把缺少的那点知识补上,就可以扩大受众,让我们的销售变得更为容易。

那具体怎么保证大纲的覆盖面呢?

那首先大纲应该覆盖该领域的主要内容,这些内容通常来源于以下几个地方:

  1. 官方文档:官方会处理几乎所有来自社区和其他客户的需求,即使一些边缘的需求,因为囤积的时间比较长,也会慢慢地累积起来,所以一般来讲官方资料的覆盖度是最为全面的
  2. 行业的权威文档:虽然不是官方出品的,但因为日积月累它最后可能变成了事实标准,也是我们作为参考的一个主要来源
  3. 图书:这也是大参考源,对于经典知识来讲,一些销量比较好的图书,会经过多次的再版,并会加入一些之前没有覆盖的内容。使用微信读书的无限卡,无需购买就可以直接搜索大量计算机图书,对查资料来讲非常好用
  4. 同类课程:国外的同类课程往往也是非常好的参考,尤其是面向新技术的课程

然后呢,我们的大纲应该覆盖该领域最频繁出现的问题,那我们到什么地方找问题呢?

  1. 搜索关键词
  2. 专业问答网站,比如 stackoverflow.com
  3. GitHub 的 issue 区
  4. 课程平台的答疑区

粒度

除了条例性和覆盖面,那我们最后,而且其实也是非常想强调的一个问题,就是大家一定要注意我们大纲的粒度。

大纲这名字听起来就像一个目录,很具备误导性。很多同学做大纲的时候,通常做两个层次就算是做得细的了。事实上,大纲的粒度越细,课程的品质就越可控,后期制作起来速度就越快。而且我们要拿大纲去做预售来验证需求,它越细,验证的效果就越好。

所以呢,建议大家把大纲至少细化到段落这个级别,同时把段落以下的一些知识点所涉及到的素材和资料,全部都整理到这个节点上去。

这里推荐大家使用 Dynalist 这种无限分级的树状笔记软件来做大纲,会特别方便。

================================================ FILE: docs/040209.html ================================================ 通过预售验证销量 - 精益副业

通过预售验证销量

为什么要验证

随机抽样了某云课堂上近 500 门付费课程(通过搜索「课」字),其中销售不到 30 的有 24%,销售小于等于 1 的 10%

这是我之前分析某课程平台时的抽样数据,有十分之一的课程销量小于等于一,这个一还很可能是作者;而销售不到 30 套的课程约四分之一。

这些失败的课程背后,每一个都可能有几十几百个小时的制作时间,既然我们把宝贵的副业时间投入其中,就应该尽量避免重蹈覆辙。

如何验证

回到我们这一节课的标题上来,「通过预售验证销量」。两个关键词「预售」,「销量」。

  1. 预售,我们用什么来做预售?简单一点可以用「课程介绍」,复杂一些则可以提供「试学章节」,但我们测试下来最合适的是「课程大纲」。它能非常清楚的描述内容范围。
  2. 销量,如何来评估?我们需要给自己设定一个达标的销售额,一般设定为比成本略高,预售结束时如果销售不达标,我们就退款,不制作这个课程了。

抓住这两个关键,就可以做好验证。在此基础上,可以扩展出一个完整的流程:

  1. 准备课程介绍资料,主要是大纲和试学章节
  2. 设定验证的目标,设定预售达标值
  3. 开始预售
  4. 每天统计销售量,并根据反馈调整介绍
  5. 预售达标则进入课程制作
  6. 预售不达标则进行退款,并反思价值主张

要支撑这个流程,我们大致有三种方案:

  1. 通过众筹/预售平台来完成
  2. 自建众筹/预售平台
  3. 通过付费群简单解决下

下边我们分别来说:

众筹/预售平台

使用现成的众筹/预售平台是最省心的。其实最方便的是微博提供的众筹功能,集传播和销售于一体,很适合在微博有影响力的同学。

picture 49

之前我用的时候还挺好找,现在这个功能藏得有点深,在微博的钱包二级菜单里。当然,其他的平台也是可以的。大体来讲,这类平台的问题在于操作相对麻烦,对个人的话,除了收取服务费,往往还会代扣 20% 左右的税。

另一方面,课程还不是实物商品,众筹完了可以直接寄送;我们众筹完以后,可能还要提供在线观看课程的功能。如果放到其他平台,还有一个账号统一的问题要解决。

自建众筹/预售平台

对于我们程序员来讲,自建众筹/预售平台是很容易的事情。找不到满意的平台,当然是自己动手丰衣足食。功能开发上很简单,但这里有一个非技术因素,那就是支付接口往往需要公司资质来申请,个人很难申请下来。所以还没有搞定支付的同学们在动手前要留意,不要花几周写完系统要上线时才想起来。

付费群

付费群就不需要任何的开发,交易完全走一对一支付,只要自己在年终走个税申报就行。它的缺点在于维护成本有点高,需要手工跟进整个众筹的流程;群功能也相对有限,甚至出现过仿冒老师的账号进行收款的事情。

这里也分享一个微信批量退款的小技巧:将要退款的同学拉到一个微信群中,然后发一个人数乘以金额的普通红包就可以了。注意是普通红包,不是拼手气红包。

综合以上,我们的建议是,早期通过付费群或者一对一付费就可以了。等到付费用户多了以后,再专门开发一个系统来做预售/众筹。

我们也做了一个众筹+课程托管的一体化平台自用,等成熟以后会考虑开放出来,感兴趣的同学可以关注下我的微博。

================================================ FILE: docs/040210.html ================================================ 常见的课程片段类型 - 精益副业

常见的课程片段类型

这一节开始我们来讲课程的制作。

我们将常见的课程分成四种片段:

  1. 文稿讲义类:这是我们最熟悉的PPT+语音的形式
  2. 屏幕录制类:在实战和演示时用得最多的形式
  3. 真人出镜类:技术类课程用得较少,一般在右下角放一个小窗显示真人
  4. 虚拟形象类:不想真人出镜时,可以用虚拟形象来代替

几乎所有的课程都是由以上四类课程片段组合而成,所以一旦学会了每种片段的制作,也就学会了几乎所有课程的制作。

================================================ FILE: docs/040211.html ================================================ 文稿讲义类课程片段的制作 - 精益副业

文稿讲义类课程片段的制作

这里的文稿讲义,主要指使用幻灯片软件来进行播放的资料。如果是使用PDF这类材料,其实是属于「屏幕录制」类,我们会在下一节里详细讲解。

对于文稿讲义类课程片段,我们的画面、图文内容都已经做到了幻灯片里面,要录制的主要是声音。但我们有三种截然不同的方式来录制声音:

  1. 第一种是最通用的,通过全局录屏来完成。不管是使用什么软件,只要在电脑里,都会被录下来。
  2. 第二种是使用幻灯片软件自带的「演讲录制」功能来完成。
  3. 第三种是最不为人知的,通过幻灯片软件的「导出为视频」来完成,这种方式有一个非常大的优点,可以极大地降低修改成本,在后文中会详细说明

下边我们分别说明。

全局录屏

下一节会详细讲,这里就略过了。

使用幻灯片软件自带的「演讲录制」功能

picture 50

目前用得最多的幻灯片软件,分别是苹果公司的 Keynote 和微软的 PowerPoint。下边我们就以它们为例进行讲解。

首先,我们需要使用幻灯片软件将内容制作完成。课程完成度越高,修改起来成本就越高,所以要仔细检查有无错别字或其他疏漏,然后再进入音频录制阶段。

如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程

我们先来看在 Keynote 中如何录制。

在 Keynote 菜单「播放」里选择「录制幻灯片放映」

picture 52

然后我们就会进入一个深色背景的幻灯片录制的环境,在这个界面的最下方有一个红色的录制按钮。

picture 53

点击它就可以开始进行录音,可以随时暂停和停止。需要注意的是,这里录制的音频不是仅仅当前这页幻灯片的,而是整个幻灯片的。你可以来回切换幻灯片来录制音频,如果界面看到的有些不一样,可以通过调整预览界面的配置来修改。

当我们在录制环境中完成了整个课程的音频录制后,就可以回到主界面。从菜单中选择「文件」→「导出为」→「影片」。

picture 54

这样,Keynote 就会为刚才的录制生成视频。有一个需要特别注意的地方,就是导出窗口中,「播放」选项要选择为「幻灯片放映录制」。

picture 55

如果觉得导出的视频文件过大,可以使用HandBrake来进行压缩。这是一款开源的视频压缩软件,默认的预置(比如 fast1080p )就很好用。

picture 56

如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程

下边我们来看 PowerPoint 中如何操作,其实很类似,只是菜单名称和个别细节不同。选择菜单「幻灯片放映」→「录制幻灯片演示」。

picture 57

同样会进入一个暗色的录制界面。

picture 58

在左上角有一个时间正在走,在旁边有控制按钮,可以暂停。默认已经开始录制了,我们可以选择幻灯片进行讲解。全部讲解完成后,一样是导出视频。

picture 59

在顶部菜单中选择「文件」→「导出」。

picture 60

也有一个需要特别注意的地方,就是在导出窗口中要选中「使用录制时的计时和旁白」。

幻灯片导出为视频

单从录制来讲,前一种方法就非常方便了,可以说是一气呵成。但如果录制完成后我们发现有几句话讲错了需要修改,那么就相当麻烦了。究其原因,主要在于虽然幻灯片是一页一页的,但音频却是整体录制的,所以音频出问题就只能重录。

那么我们能不能让音频也变成一段一段的,对应到每一页呢?这样我们以后再修改的时候,只需要重新录制那一页的音频。

picture 62

这就是我们第三种方案的思路。Keynote 和 PowerPoint 虽然没有提供分页录制的功能,但它们都能往幻灯片上添加音频,并将其合并到视频中统一输出。

所以我们要做的,就是在每一页幻灯片上,添加上语音讲解的音频。比较方便的地方是,这两个软件都支持直接录制语音讲解,而且一页幻灯片上可以录制多段,还能手工调整顺序。

下边我们来看具体如何操作。

如何使用 Keynote 以「导出为视频」的方式生成视频课程

还是先来看 Keynote。第一步依然是制作好图文部分的内容,最好把要讲的文稿放到演讲者注释区域,这样录制的时候可以参考。

然后先选中要添加语音讲解的幻灯片,从菜单中选择「插入」→「录制音频」。

picture 63

在弹出的小窗口中点击录音按钮就可以开始录音。

picture 64

录制完成可以试听,没问题后再插入到当前幻灯片。当一张幻灯片有多个音频时,可以选择右上角的「动画效果」菜单,再点击右下角的「构建顺序」就可以看到当前幻灯片中的音频列表了。被选中的时候,会有蓝色描边,通过拖拽可以很方便地调整顺序。

picture 65

导出和之前类似,还是通过「文件」→「导出为」→「影片」。 picture 66

但需要注意的是,这次在导出窗口中,播放选项要选为「自动播放」。

picture 67

同时,我们还要把下边两个等待时间设置为「0」秒钟。

picture 68

如何使用 PowerPoint 以「导出为视频」的方式生成视频课程

再来看看 PowerPoint 里边的做法。给幻灯片添加语音讲义也在菜单「插入」→「音频」中。

picture 69

选择「录制音频」可以直接录制。

picture 70

下边我们看看怎么调整多个音频的顺序。点击「动画」菜单,在右边会出现一个「动画窗格」,再点击它,在最右边就可以看到当前幻灯片上所有的音频的列表。

音频前边还有编号,可以一一对应到幻灯片上的音频。通过调节它们的上下顺序就可以手动的指定最终的音频播放顺序。

细心的同学可能会留意到这些音频都会被放到一个叫做动画的菜单里面,其实这个菜单的功能是指定动画播放的顺序,音频被当做动画的一种,所以也在里边了。通过同样的方式还可以控制插入的视频的播放顺序。

picture 71

最后依然是通过「文件」→「导出」来生成视频,但是记得去掉「使用录制的计时和旁白」前的小勾,同时把「没有设置时间的每张幻灯片所用的秒数」设置为「0」。

picture 72

================================================ FILE: docs/040212.html ================================================ 屏幕录制类课程片段的制作 - 精益副业

屏幕录制类课程片段的制作

屏幕录制的原理

屏幕录制软件的原理,是不停地截取屏幕画面,然后和音频合成为最终视频。屏幕录制的优点是可以把电脑屏幕上显示的所有东西都录下来,不管你在哪个应用里边,不受应用本身功能的限制。所以可以非常直观地向学员展示完整的操作。

屏幕录制的软件

在试用了很多屏幕录制软件以后,我们选择了 OBS 。它的优点主要有:

  1. 功能强大
  2. 开源免费
  3. 跨平台

功能强大

OBS 不但可以录制屏幕,还有一个非常强大的功能就是直播。现在很多视频网站的直播都支持用 OBS 来进行推流。所以学会了它,不但可以录制屏幕,而且可以进行直播,一箭双雕、非常划算。

然后,OBS 可以非常容易地进行屏幕之间的叠加,比如画中画模式,这就非常适合我们马上要讲到的「真人出镜」和「虚拟形象」类型的课程片段。

同时呢,OBS 还支持通过快捷键在各个场景之间来回切换,在录制课程的时候可以非常方便的进行转场,这个功能不少收费软件都没有。

开源免费

和那些昂贵的收费软件不同,OBS 是开源而且免费的,这意味着使用它没有任何版权风险。我们在制作付费课程的时候,需要特别留意版权方面的问题。因为平时以个人身份在免费文章和视频中用一些字体、图片是没问题的;但在收费的商业课程中,就可能面临被起诉索赔的风险。

跨平台

再来说一下,为什么跨平台的特性非常重要。在课程中,尤其是编程类课程中,我们经常会遇到需要讲解某个工具软件在各个操作系统上的安装和使用的情况,这时候就需要在多个平台上录屏。

如果使用一个特有平台上的录屏软件,在录制其他平台上的课程内容时,就不能使用了。只能重新购买和学习一个新的录屏软件。这不但浪费钱,更浪费时间和精力。

而使用 OBS 就没有这种困扰,它不但支持 Windows 和 Mac 系统,连主流 Linux 系统都是支持的。

所以,在我们后续课程中,将以 OBS 为例进行讲解。

OBS 的层次逻辑

OBS 的功能非常强大,还有包含了直播相关的功能,所以需要理解它特有的一些概念后,用起来才会更加顺手。

像一般的屏幕录制软件,只需要启动后点击录制按钮,进行录制就完了。但 OBS 中,它有自己的层次逻辑。

picture 73

场景

OBS 的第一个层次叫做「场景」,你可以把它理解为一种预设。

为什么需要场景?比如我们一个讲师,他每天上午要进行直播,这个时候视频的来源是摄像头和电脑屏幕;然后他每天下午要录制课程,这时视频的来源就只需要电脑屏幕,但他有两块屏幕,他希望都录进去。

如果没有场景这个概念,那我们每天上午到下午的时候,就需要不停的修改配置,非常麻烦。而有了场景以后,我们只需要把上午和下午定义成两个场景,使用的时候切换下就OK了。

你可能会想为什么要叫「场景」而不是直接叫「预设」呢?因为 OBS 中场景比预设更为常用和强大,它是可以实时切换的。

也就是说,如果我们有三个显示器ABC,可以在场景一里显示A;在场景二中显示BC;然后根据需求通过键盘快捷键来切换,甚至还能给它添加转场特效。

来源

picture 74

在定义好「场景」以后,就可以往里面添加「来源」。最常用的来源其实就两类,也就是视频和音频。视频最主要的是显示器,也就是电脑屏幕,偶尔还有摄像头。音频的话主要就是麦克风。

picture 75

来看一下 OBS 的来源菜单。

首先它提供了「图像」和「图像幻灯片放映」,如果我们想在视频上面显示一张固定的图片或者图片轮播可以用它。

比较有意思的是,我们还可以把一个场景指定为来源,这样就可以非常容易地实现场景嵌套。也可以把媒体作为一个来源,这样就会在画面上面播放另外一个视频。

文本来源这里可以输入一些文字,指定它的颜色、字号和字体,然后它就会显示到屏幕上方。可用来显示我们机构的品牌名称之类的。可以看到,一些本来是后期才进行处理的功能,在 OBS 里都可以通过来源来实现。

显示器采集也就是我们的屏幕;视频采集设备通常就是指摄像头;音频输入采集这里通常就是耳机、麦克风或者外接的USB声卡之类。

这里还有一个音频输出采集,可以用来做多层次的音频加工。比如说我们电脑上有一个软件,就像柯南的蝴蝶结一样,可以对输入的声音进行变声,那我们就可以把这个软件的输出作为来源接入到 OBS 里边,录制下来的声音就是变声后的效果。

来源的层次

在多个来源之间,其实是有上下层级的概念的。打开 OBS 的来源小窗口,我们可以看见当前已经添加的所有来源。

来源是从上至下进行覆盖的。也就是说来源窗口的最上边一层,在最终视频中也会显示到最上面,上一层的内容会压住下边各层的内容。

picture 77

这个对于我们制作真人出镜类型的课程片段很重要,因为它通常是通过摄像头和显示器两个来源叠加得到的。摄像头的画面小、通常显示在右下角;显示器的画面大,往往覆盖整个视频画面。在来源窗口里,摄像头需要在显示器上层才看得见,不然会被显示器画面完全挡住。

滤镜

picture 78

如果通过来源采集的信息不是百分之百符合我们的需求,还可以通过滤镜来进行进一步加工。OBS带有两类滤镜,一类叫做「音视频滤镜」,可以对音视频进行处理,比如进行噪音的抑制或者把音量放大;另一类叫「效果滤镜」,包括各种各样的特效,比如「色度键」可以用来抠背景。

================================================ FILE: docs/040213.html ================================================ 真人出镜类课程片段的制作 - 精益副业

真人出镜类课程片段的制作

虽然前面其实已经陆续讲到了真人出镜类课程片段的基本原理,这里还是再明确下。

什么是真人出镜类课程片段

「真人出镜」类的视频非常简单,只需要使用摄像头、手机或者摄影机直接录制就好了。而「真人出镜」类的课程反而要复杂一些。这是因为在课程中,讲师其实并不是主体,课程内容才是。所以我们往往会采用「画中画」的模式,将讲师的头像部分做成一个小方块放到画面中。

picture 79

但这有一个小问题,就是这个方块会带背景。如果它的背景和作为主体的课程不搭,看起来就会比较别扭。要是能把背景变成透明的,它就能更好地融入到课程中。

抠图

那么,怎么才能让背景变成透明的呢?答案是「抠图」。对于计算机来讲,将数字内容的一部分变成透明是非常简单的,真正的麻烦在于它不知道哪一些像素是背景、哪一些像素是讲师,所以我们需要一个方式来告诉计算机。

现在最常用的,也是最简单有效的一个办法,叫做「绿幕抠图」。就是在讲师身后放上绿色的背景布,再告诉计算机,绿色的部分都是背景,把它抠掉。这样就实现了背景的透明。

有同学可能会问说,为什么非要绿色,其他的颜色行不行?答案是可以的,但如果把背景设置成黑色,很多人的眼睛和头发都是黑色的,这些部分也会被透明,看起来会很灵异。

而绿色在日常生活中出现的频次比较低,所以一般默认用绿色来作为背景。但如果有天你穿了个绿色的衣裳,那就可以考虑换用蓝色的背景了。

picture 80

这一部分的具体操作是这样:

  1. 在场景中添加一个「显示器采集」来源,选为我们想要录制的电脑屏幕,放到来源窗口最底层。
  2. 在场景中再添加一个「视频采集设备」来源,选为摄像头,将其放置到屏幕右下方,在来源窗口中位于显示器之上。
  3. 在摄像头来源的右键菜单中,选择「滤镜」,在「效果滤镜」中添加一个「色度键」滤镜,背景为默认的绿色。
  4. 调整「相似度」和「平滑」的值,让背景消失得更为柔和。

picture 82

picture 83

关掉滤镜窗口,这时候在 OBS 的预览界面上我们看到的摄像头画面背景就应该已经透明了。

picture 84

真人出镜的其他细节

如果你是使用笔记本电脑,通常自带一个摄像头;如果是台式机,就需要自己装一个。摄像头需要对着讲师的脸,因为摄像头看到的,就是学员最后在课程里面看到的角度。

然后我们在讲师背后竖一个比较大的绿幕,充满整个摄像头的背景区域。一般两米宽高就够了,不够的话可以调整摄像头。

绿幕可以在电商网站输入「绿幕布」关键词搜索购买。有一些专业的幕布会比较贵,但我们早期可以买便宜的幕布来试水,一般几十块钱就能搞定。

为了让讲师和背景之间分离得更清晰一些,可以再通过光源进行补光。这里我们用手办做了个示意图给大家。这个灯的色温不能调,所以看起来稍微有点偏黄。实际录制的时候,可以用白色的灯来补光。

picture 81

================================================ FILE: docs/040214.html ================================================ 虚拟形象类课程片段的制作 - 精益副业

虚拟形象类课程片段的制作

虚拟形象的原理

最后,我们再来看一下虚拟形象类课程片段的制作。虚拟形象实际上跟真人出镜差不多,但因为可以用卡通的形象来代表真人,所以形式上看起来会更加有意思,更适合年轻的同学。

在上一节里面,摄像头里拍到的是真实的画面,现在我们要想将真实的变成虚拟的,就要使用虚拟摄像头。

所谓的虚拟摄像头,就是其实并不存在这么一个物理上的摄像头,这个摄像头是用软件来模拟的。但是其他软件并不知道,它们会以为这个摄像头是真实的,于是它们之间就可以无缝地进行整合。

FaceRig

我们使用的是 FaceRig 这个虚拟摄像头软件,它提供了很多的3D模型,还支持导入 Live2D 这个游戏和动画用得较多的模型格式。如果是通过 Steam 购买的 FaceRig,那么在创意工坊里边可以看到全球玩家上传的各种模型,喜欢的可以直接订阅,它就会出现在我们的 FaceRig 里边。

当然,我们也可以制作自己的卡通形象,生成模型并导入。顺便说一下,对于多人参与的课程来讲,虚拟IP是非常有用的。如果我们将大量的精力和推广资源放到真人讲师的IP上面,万一这个讲师离开团队,之前的投入就废掉了,甚至会变成竞争对手的资源。但是如果我们采用虚拟IP,就完全没有这个问题。

步骤

为了模拟摄像头,FaceRig 构造了一个 3D 空间。这个空间由「模型」和「背景」两部分组成。选好模型、配好背景,打开跟踪器让模型和我们的表情同步,就实现了用虚拟形象代替真人形象。

下边我们更为详细地讲述下步骤:

  1. 购买和安装
  2. 选择模型
  3. 选择背景
  4. 打开追踪器
  5. 打开广播

购买和安装

最方便的方式是在 Steam 这个平台上进行购买,它会帮你自动安装各种依赖,确保能运行起来。如果想用 Live2D 的模型,还需要购买对应的插件。

picture 85

选择模型

启动完成以后,点击顶部菜单最右边的UI按钮就可以切换右侧的面板;这个面板的第一格就是我们的模型。

点开以后可以选择喜欢的模型。

picture 86

选择背景

还是在右侧的面板,第二个图标就是。点开它可以看见预置的各种背景。如果想要最终背景透明,可以选择绿色背景方便下一步抠图。

picture 87

打开追踪器

现在虽然模型都有了,但它跟我们真人说话的表情语气没有关联起来,所以要打开追踪器。点击顶部导航,「切换追踪」按钮(图上画红圈的),摄像头就会通过人脸识别来捕捉我们的表情。这个时候我们摇脑袋和做出各种表情的话,就会同步到模型上。

picture 88

打开广播

这些都做完了以后,一定要记得还有最后一步就是要打开广播。所谓广播就是 FaceRig 把画面虚拟成一个摄像头,并同步到整个系统里,其他的软件就会把它当做一个真实的摄像头。

picture 89

打开广播也非常简单,就是点击顶部的这个像电台一样的按钮。点击打开,再点一下关闭。

当广播打开后,在 OBS 里去添加一个新的视频捕捉设备的时候,就会发现有一个名字包含 FaceRig 的摄像头,把它作为来源,就可以引入和真人表情同步的虚拟形象了。

picture 90

================================================ FILE: docs/040215.html ================================================ 最常用的视频剪辑操作 - 精益副业

最常用的视频剪辑操作

视频剪辑是我们做课时用得非常多的技巧。剪辑是一门细节很多的技术,幸运的是,做课所需的只是非常基础的一些功能,所以我们才有可能花很少的时间学会。这也是我们这一节的内容。

剪辑软件

视频剪辑的软件非常多,但整体功能上大同小异。经过一系列的试用,我个人用得最多的是这两个软件:

  1. 苹果公司出品的 iMovie
  2. Adobe 公司出品的 Premiere(一般简称PR)

iMovie 是 Mac 专有的免费软件,完全可以胜任大部分的常规剪辑工作。后来苹果公司还开发了 iOS 版本,这样我们在 iPhone 和 iPad 上也能使用它。

如果我们只是想简单地调整下视频片段的顺序、删除某个片段、或者对某部分进行速度调整的话,iMovie 是个不错的选择。

PR 则是系统复杂、功能强大的专业剪辑软件,很多专业人士都在使用它。PR 是一个付费软件,但同时支持 Mac 和 Windows。

我们后续以 PR 为例进行讲解,在其他的剪辑软件里相关的操作也是非常类似的,往往只是菜单位置不同,大家可以自行摸索。

视频片段的调整

视频片段的调整是最常遇到的需求。因为我们在录课的时候很可能其中有一段讲错了,会想把它去掉,再把后边的内容给接上去;或者讲课时有一部分内容讲丢了,在后边补讲的,想把它给挪到前面去。这些情况时常发生。

比如说我们现在有一段视频,希望删除其中红色的部分,应该怎么操作呢?

picture 3

直观来讲,应该是选中一个片段然后按删除键。有一些编辑软件就是这样做的。但在 PR 中,这个操作通常被分两步:先分段、再删除。

picture 2

所以我们会先用剃刀工具将视频给切割成三段,切割的位置正好在红色部分的开始和结束,这样它就会变成一个独立的片段。

然后切换到选择工具,选择这个片段,再按删除键,片段就会被删除。

picture 4

但我们会发现,视频中间空出来了一段空白。

picture 1

这是因为在 PR 里边,连续视频并不是一种常态,所以它没有自动去掉两个视频片段之间的空白。可以在这段空白上点右键,选择「波纹删除」,这样后边的视频就会自动补上来了。

picture 5

当然,在删除视频的时候,如果不是直接按删除键,而是点击右键,选择「波纹删除」会更加方便一些。

柔软的视频片段

这里有一个需要特别注意的概念。在我最初的想象中,视频片段应该是很「硬」的,当两个视频片段有重合时,后一个片段会自动后移并紧跟前一个视频对齐。但在 PR 中,视频片段是很「软」的,当两个片段重合的时候,重叠部分会被覆盖掉,再也分不开了。可以把它们想象成两个透明胶带,一旦粘上,就很难无损分开了。

picture 6

所以,对于不熟悉 PR 的新手来讲,想要两个片段紧密连接,最简单的方式还是分开放,然后「波纹删除」中间的空白来自动对齐。

视频片段顺序的调整

正因为这些片段很「软」,当我们在进行顺序调整时,也要倍加小心。这里我们可以利用 PR 的多轨道。我们可以暂时把要移动的片段放到另一个轨道上,然后调整原来轨道上片段的顺序,挪出一个新的位置,再从外轨上把片段给挪回来。

picture 7

视频片段速度的调整

速度调整在做课时也很常见,比如说我们通过网络安装软件的时候可能就很慢,得操作二三十分钟,但我们不可能让学员一直等二三十分钟。一个方式是直接减掉这个过程,但如果其中又包含了一些操作细节,我们可能就需要把这一段视频加速。

picture 8

在需要调整速度的视频片段上边点击右键,选择「速度/持续时间」选项,会弹出设定窗口。 窗口上默认的速度是100,如果想加速,就改为大于100;想减速,就小于100。

有一个需要注意的问题,就是如果减速,视频片段会变长。如果前后有其他片段,就可能造成覆盖,所以这种情况下,最好放到另一个轨道上再调整速度。

另外,在加速的时候,原来的声音会变调,如果想要保持正常,记得选中「保持音频音调」。

视频中的音频处理

这个操作也是很常见的,比如讲课中有几句讲错了,但是不方便删除视频,可以只删除这一部分的音频。

但是,默认情况下,音频和视频是绑定的。所以我们需要将要处理音频的部分切割成独立的片段,然后在右键菜单→「音频增益」中把它的音量调到听不到(比如-100dB)。

picture 9

当然我们也可以通过选中片段后点右键菜单,选择「取消连接」来解除音频和视频的绑定。这样就可以随意编辑音频了。

除了像视频一样分段、调整顺序等,我们可能还需要对音频进行去噪、调音等更进一步的操作,这时候我们可以在对应的片段上点击右键,选择「在 Adobe Audition 中编辑剪辑」在另一个软件中来处理。具体的操作我们将放到下一节讲解。

picture 10

================================================ FILE: docs/040216.html ================================================ 最常用的音频处理操作 - 精益副业

最常用的音频处理操作

音频的后期处理和视频类似,也是非常专业的领域,所以我们这里也只讲最简单的处理。在我们做课时,经常会用到的技巧主要包括:

  1. 去噪
  2. 标准化
  3. 混响
  4. 去齿音和嘶声

下边我们依次来看看。

去噪

「去噪」就是「去除噪音」。一般分为两个步骤:

  1. 定义噪音
  2. 去除噪音

为什么会有「定义噪音」这个步骤呢?因为对于计算机来讲,它并不知道哪一部分声音叫做噪音。 比如我们在录一首歌的时候,邻居家的猫在旁边叫,这个声音就算是噪音。但如果是想录一个宠物视频,猫在里面就不是噪音,它可能是主角。所以是否是噪音,是需要根据场景来进行定义的,计算机理解不了这点。

当然,这个例子比较特殊。通常来讲,要去掉的噪音叫做「底噪」。就是声音很小的背景噪音,比如电流声,远处汽车和行人的声音。这种时候,只需要选取一段只有这些背景音的音频,将其定义为噪音,那么软件就可以把和它类似的声音去掉。

音频处理也有很多软件能做,但因为我们视频剪辑用 PR,所以音频用 Audition(简称 AU )来做会更为方便。它在我们修改音频后,会自动更新 PR 里边的片段。

下边我们来看 AU 中具体怎么操作。首先选中一段只有背景噪音的音频,在顶部菜单中选择「效果」→「降噪/恢复」→「捕捉噪音样本」,就可以把它定义为噪音。

picture 11

然后,在顶部菜单中选择「效果」→「降噪/恢复」→「降噪(处理)」,开始去噪。

picture 12

记得在弹出的窗口中点击「选择完整文件」,再点「应用」就会开始处理。

picture 13

标准化

标准化也是一个很有用的功能。我们录音的时候,尤其是换了场地和设备录音的时候,可能声音的范围(最高音和最低音)就不一致。这种时候,就需要通过「标准化」来将这个范围统一,这样听起来音量差异才不至于太大。

picture 14

在 AU 中的具体操作如下:

在顶部菜单中选择「效果」→ 「振幅与压限」→「标准化(处理)」。

picture 15

然后在弹出的窗口中,可以将其标准化到 0 dB (如果觉得音量过大,也可以试试 -6 dB)。

picture 16

混响

我不知道大家有没有这种感受,就是有时候听一些电脑生成的音频时,会觉得声音非常纯粹,很好听,但听起来不像是真的。而一些现场录制的音频,音质可能没那么好,但听起来却会有种非常强的空间感。

这是因为我们日常在说话的时候,声音会分成两个层次到达我们的耳朵。

picture 17

一个层次是直接从发声处传到了耳朵里,另一个层次是声波打到周围的环境上,比如墙面、地面、桌椅上,被反射后,有一些很弱的声音以稍微延迟一点的时间进入我们的耳朵。我们日常听到的多是这种叠加后的声音。

在电脑中生成的音频如果不特意处理,是没有这种叠加的。这就让声音有点「平」或者「干」。为了增强声音的空间感,很多编辑软件提供了叫做「混响」的功能。其原理就是模拟现实中的声音叠加,将一部分声音强制延迟后混音,这样的声音更有立体感。

下边我们看看在 AU 中怎么具体操作。

在顶部菜单中选择「效果」→ 「混响」→「混响」。

picture 18

在弹出窗口中,可以调节各项参数。点击播放按钮可以试听。

picture 19

选择好以后,点「应用」进行处理。

齿音和嘶声

齿音是指我们说话时,呼入呼出的气流和嘴唇、牙齿之间摩擦产生的声音;嘶声则有些类似于广播电台中常听见的嘶嘶嘶的声音。这些声音混在音频中,可能听起来不那么舒服,所以 AU 也提供了工具来清除它们。这部分的操作很简单,这里就不详细说明了,这两个功能的菜单分别在:

  • 齿音:「效果」→「振幅与压限」→「消除齿音」
  • 嘶声:「效果」→「降噪/恢复」→「降低嘶声」

建议顺序

其实顺序并不是强制的,怎么都行。但考虑到标准化时有可能把底噪放大,所以我一般会按下图的顺序来进行各项音频处理操作。

picture 20

整个过程中,去噪和标准化才是最重要的,其他的三项时间紧张时可以偷懒不做。

================================================ FILE: docs/040217.html ================================================ 字幕的制作和自动生成 - 精益副业

字幕的制作和自动生成

对于技术类课程来讲,字幕是非常有用的。一些技术名词光是读出来,有时候很难明白它是什么意思。而如果有字幕,就可以一目了然了。

字幕及其格式

所谓字幕呢,是指我们在播放视频的时候,显示在屏幕下方的、和语音同步的文字。为了让计算机正确地显示出字幕,我们需要告诉它两个信息:

  1. 这个字幕的文本是什么
  2. 这个文本应该在什么时间开始显示,在什么时间结束

也就是说,最基本的字幕信息应该包含「文字本身」以及「文字显示的时间段」。

当我们把多条字幕的信息合并放到一起,就有了字幕文件。字幕文件可以是单独的文件,在播放视频时载入并显示,这种方式称为「外挂」;也可以在压制视频时直接压制到视频里,这样即使播放器不支持字幕功能,也可以正常显示。

字幕的格式有很多种,srt 格式是最简单的格式之一。

picture 21

它由多段文本组成,每段文本分为三行:

  1. 第一行是序号,一般从 0 开始递增
  2. 第二行是显示时间段,中间用箭头分隔
  3. 第三行是这个时间段应该显示的文字

字幕编辑软件

我们使用的字幕编辑软件是 ArcTime,它是一款跨平台的免费软件。启动以后的界面是这样的:

picture 22

左上部分区域是视频的预览区,可以从顶部菜单的「文件」→「导入音视频文件」载入要编辑字幕的视频。然后它就会显示预览区。

预览区下方就是字幕区,有根据音频生成的波形在上边。在这个区域点击右键,选择「插入空白字幕」,就会插入一个空白的字幕条,双击可以输入字幕,拖拽可以调整显示的时长和起止时间。

添加好字幕以后,点击预览区的播放按钮,可以实时地看到新添加的字幕效果。需要注意的是,目前的版本中,删除某条字幕的操作是不能撤销的。这可能是这个软件为数不多的缺点了。

整个视频的全部字幕添加完以后,点击顶部菜单中的「导出」→「字幕文件」就会将刚才编辑的字幕生成一个字幕文件了。

picture 23

如果想要把字幕直接压制到视频里边,则可以选择「快速压制视频」选项。

字幕的自动生成

ArcTime 还内置了一个为视频生成字幕的功能,放置在「语音识别」菜单中,但这些功能是收费的。

对于程序员来讲,有一个更为廉价的方式获得同样的效果,那就是直接写代码去调用云服务商提供的 API。比如阿里云、腾讯云和百度翻译平台就提供了相关接口。

更有开发者已经在 GitHub 上开源了基于这些接口的命令行和客户端软件。大家可以在 GitHub 搜索「VideoSrt」,自行安装试用。

picture 24

================================================ FILE: docs/040218.html ================================================ 流量池和二次购买 - 精益副业

流量池和二次购买

课程制作完成上线以后,并没有结束。长征才刚刚开始,我们需要不断得去运营它。这一节就来聊一聊流量池和二次购买。

没有流量池的情况

先来看一下在没有流量池的情况下,课程转化是什么样子的。

picture 26

首先,我们将自有的或者购买的流量引导到课程页面,以触发销售转化。但如果我们没有采取更多措施,之后这个流量就走掉了。当上架新课时,又需要重新寻找或购买流量。

这种方式优点是简单,但今天操作起来问题很大,因为我们已经错过了之前流量爆炸的时代,现在流量已经很贵了,这么浪费太可惜。那么,能不能把流量囤起来,供以后使用呢?

学员池

picture 27

最简单的操作就是,把购买过课程的学员放到「学员池」里。当上架新课程以后,可以直接给他们发通知进行销售。这样就实现了流量的二次使用。很多同学觉得这是显而易见的,但事实上在操作的时候却很容易出问题。

比如说,很多讲师只是直接使用课程平台进行学员管理,而很多的平台不允许讲师给学员批量发送私信,甚至还会做关键字过滤。这种情况下,我们对学员的触达能力是非常弱的,需要建立更可控的流量池来替代。

访客池

picture 28

学员池重用了已经购买过课程的流量,但更多的没有购买课程的访客流量还是流失了。所以我们还可以更进一步,来做访客池。

把我们课程中有意思、有传播点的内容做成免费的素材,进行多渠道分发,把用户吸引过来并放到这个池子里,以备以后发送通知、触发销售。

常用的渠道包括:

  1. 搜索引擎
  2. 社交网络
  3. 媒体平台
  4. 课程平台
  5. 行业网站

学员池和访客池是我们最主要的两种流量池。

构造流量池的工具

互联网发展到现在,各种产品已经极大的丰富,所以有大量的工具可以用来构造流量池。因为课程销售有非常明确的商业诉求,所以我们对流量池也有相对明确的评判标准。这里分享下我常用的三个标准:

  1. 进入门槛低:最好能免除用户注册,尽快获得用户的基本信息和触达权限
  2. 可触达率高:这样我们的销售信息才能被更多人看到
  3. 触达免费或廉价:太贵了用不起

如果想要获取种子用户用来验证大纲,还需要考虑互动性。

针对微博、公众号、企业信号、微信群、自建 APP 这几种最常用的方案,我们整理了一个对比表格以供大家参考:

picture 30

多级流量池

各种流量池都有自己的优缺点,我们应该选取当前阶段最适合的来进行流量的存储。我们也可以分阶段、渐进式地建立多级流量池,以在投入和收益上获得平衡。

比如早期我们可以直接使用微博的关注、哔哩哔哩的订阅来做流量池;然后将一部分核心用户引导到微信群和企业微信一对一服务中。这样把微博的获客门槛低和微信的触达率高这两个优点结合起来了。

在用户规模大一些以后,我们再去开发自己的App,实现对用户流量更高级别的控制。

picture 31

================================================ FILE: docs/040219.html ================================================ 如何有效地反盗版 - 精益副业

如何有效地反盗版

树立反盗版的正确思路

虽然几乎所有讲师都认为反盗版是必须做的,但未必都明白反盗版的意义,觉得就是少挣了钱。实际上并不是这么简单,盗版最大的问题,是对正版用户带来的不公平。同样的课程,有人花了几千块钱买过来,有人却一分钱不付就可以得到,这让正版用户显得很傻。

其次,很多讲师以为把课程放到课程平台上,平台就会帮着进行反盗版,自己就不用管了。事实上,大部分平台的反盗版措施都非常有限,通常只能由讲师提交盗版链接,他们投诉下架。如果对方将课程放到境外网站,连下架都做不到。而且有些平台每周定时收集处理一次盗版信息,还不如自己直接投诉效率高。所以我们不能把反盗版推给平台去做,他们只能起到辅助作用,我们自己还是要足够重视。

还有一个普遍的错误想法,就是很多程序员觉得盗版是不可能完全杜绝的,所以干脆就不防范了。我们的确没有办法从技术上来完全杜绝视频课的盗版,但却可以采取各种措施来降低被盗版的概率。

要从做盗版的人的经济收益的角度来思考盗版这件事情,如果我们的课盗版门槛很低,就可能导致大量盗版,因为不需要付出太多的代价。相反,如果我们课的盗版门槛很高,那就要花很多功夫才能盗版。

很多盗版手段是针对平台的,当我们课程的盗版门槛变高以后,盗版狗有两个选择,一个是投入时间和金钱去升级盗版手段,另一个选择是用原来的盗版方法继续盗版其他门槛低的课程。绝大部分情况下,它们会选择后者。

有同学可能会说,这样其实并没有解决盗版的问题。是的,从宏观上来讲,确实没有解决盗版问题;但从个体的角度来看,我们又的确避免了自己的课程被盗版。

要从宏观层面上去解决知识产权问题,需要国家、法律、以及社会各方面一起持续不断地推动,我们作为个体,积极响应国家的政策,并保护好自己的知识产权,就是在为这事添砖加瓦。

picture 32

如何有效地反盗版

所以反盗版其实就是要不断提升盗版的门槛,降低盗版狗的收益,让它们无利可图。我们自己实践过的方法中,最有效的可以归纳成四个字、两个词:卖空和卖多。

卖空

卖空其实就是预售,还没有课程,就开始销售。你很难盗版一个还不存在的课程。而且在我们精益网课流程中,本来就是通过预售来验证需求的,所以做起来很顺手。

这个思路再扩展一下,比起一次性提供课程,连载课程的反盗版门槛更高。因为它每周只更新一到两节课程,持续时间很长。这样盗版的成本一下被提升了 N 倍。

卖空的思路很简单,但效果却非常明显,强烈推荐大家尝试。

卖多

卖多是说,现在大家课程放到平台上,盗版门槛是一样高的。但是我们可以多提供一些平台没有的、盗版不了的服务来反盗版。这些服务可以包括:

  1. 答疑
  2. 督学
  3. 社群
  4. 线下服务

在进行这些服务的时候,我们可以先进行身份确认,无法提供购买证明的人就不能享受这些服务了。

更进一步,如果我们把课程中不可或缺的部分挪到这些服务中来,那么看盗版视频的人甚至不能完整的学完课程,这就让盗版课程失去了意义。

有一个不错的实践可以分享给大家。我们的主要课程是全栈课,既有前端又有后端。为了反盗版,我们开发了一个云端的编程环境,将后端课程放在其中,然后限制只有正版学员才能登录这个系统,采用这个系统的课程后来就再也没有被盗版过。

这个系统的开发很简单,只需要在云平台上启动一个基于容器的、带有桌面的系统,然后再运行一个基于 Web 的 VNC 去连接它,就可以实现在浏览器中远程操作桌面系统了。感兴趣的同学可以去了解下NoVNC这个开源项目。

================================================ FILE: docs/0403.html ================================================ 精益独立开发实践 - 精益副业

精益独立开发实践

前面我们给大家介绍了精益副业的基本概念,因为只有理论,所以看起来可能比较抽象。

从这一章开始,我们就以实际的副业实践为例,看看如何使用精益副业流程贯穿始终,多快好省地发展副业。我们安排了两个深度实践,一个是独立开发、一个是网课。下边我们开始第一部分。

================================================ FILE: docs/040301.html ================================================ 独立开发的精益流程 - 精益副业

独立开发的精益流程

picture 1

前面我们了解了精益创业的一些核心理念,接下来我们就在「独立开发」这个更为具体的副业活动中来看看如何应用精益流程。

这个流程和很多硅谷公司的产品流程很像,但是针对副业做了一些调整和优化。经过三年多时间的使用,我们自己用起来已经很顺手。

  1. 首先定义价值主张,然后围绕着价值来设计商业模式画布。
  2. 完成画布以后,我们把画布里的「客户细分」部分拿出来,做成「用户画像」。这是一个将细分客户具体化、变得有血有肉的工具
  3. 有了画像,再据此还原用户使用产品的各个场景,他们是用电脑还是用手机、是在家里还是在车上使用等等。
  4. 想象为了在上述场景下向用户传递价值,我们需要什么样的功能,这样就会得到一个功能列表
  5. 功能列表会很长,不同功能的优先级也不同。所以我们会对功能进行分期,其中最重要也是最靠前的一个功能分期,就是用来开发「最小可行产品」的分期。
  6. 当「最小可行产品」开发完成后,进行「产品市场契合」的验证,如果达不到设定的验证目标,就需要调整功能,甚至重新设计价值主张。
  7. 当通过「产品市场契合」后,我们就可以按照分期迭代开发产品的其他功能了。
  8. 在迭代过程中,我们会持续对新上线的部分功能进行增长优化,保证每一部分功能达到预定的目标。

以上就是我们为独立开发优化的精益流程,虽然讲起来比较多,但实际操作起来还是比较简单的。而且我们其实省略了不少大公司流程中的环节,比如用户访谈、焦点小组等。

下一节开始,我们将用一个具体的例子来讲解。

================================================ FILE: docs/040302.html ================================================ 福利单词项目简介 - 精益副业

福利单词项目简介

先来介绍一下我们的实战项目 —— 福利单词。

它来自于我在学习过程中的一个原生需求。最开始我是使用 Anki 这个软件来背单词,软件很好用,但是每次都有一种逼着自己去背的感觉,背完以后如释重负。为了提醒自己不要逃避,我还定了一个闹钟每天催自己。

有一天,我又因为上Pixiv(一个二次元内容创作社区)看图忘记了时间。突然间我想到,能不能把背单词和看图片这两个行为绑定到一起呢?

你看,背单词虽然有用,但让我痛苦,度日如年;看图片很欢乐,流连忘返,但似乎不是很「有用」。如果我们把两者结合到一起,一边看图一边背单词,是不是就可以让背单词不那么难受,可以持续不断地背下去了?

这就是福利单词的出发点。

接下来,我们就来看看,怎么从这个还有些模糊的想法中提出一个明确的价值主张,然后围绕它进行商业模式规划、功能和界面设计、验证和迭代开发,最终使其成为一个商业产品。

picture 2

需要说明的是,开发过程很难在有限的篇幅中讲解清楚,也偏离了本书的主题,所以我们只会简略地提及一些需要注意的地方,并不会进行开发的教学。

================================================ FILE: docs/040303.html ================================================ 福利单词的商业模式画布 - 精益副业

福利单词的商业模式画布

前边我们已经讲解过商业模式画布,这一节我们就以「福利单词」为例,来看看怎么使用。

价值主张

picture 3

首先来看一下价值主张。它的核心价值就是,让那些觉得学习起来很痛苦的人不那么痛苦,给一点糖,让其可以持续地、无痛地学习下去。它试图给学习过程添加一些乐趣来综合不是那么爱学习的人的痛苦,从而把一个短暂的、难以忍受的学习行为变成一个可以持续忍受、甚至通过习惯驱动可以持久化的行为。

所以我们在「价值主张」这一栏上写上两个关键字,一个叫「无痛学习」,一个叫「持久化的学习」,这是这个产品最核心的两个「价值主张」。

有了这个价值,我们就能帮助客户完成很多以前想学、但是因为各种原因没有办法学下去的东西,从而实现其个人成长和提升。

客户细分

picture 4

如果要具体化价值主张,就要来看客户细分。

因为是单词学习软件,所以客户群体往往还是跟学习英文需求相关的。具体划分下来,我觉得可以分成三大类。

  1. 第一类是在学校要考英语四级或者六级的大学生。
  2. 第二类是有留学或者移民需求,需要考雅思、托福的群体。
  3. 第三类是需要专业英语来提升自己在职场的业务能力的上班族。

前两类群体是要备考应试的,后一类则更注重实用能力的提升。从学习的内容上来讲,只是题库的不同。所以如果我们的软件支持了「词库切换」或者「自定义词库」功能,就可以比较容易地覆盖他们的学习需求了。

价值主张的细化

picture 5

光是「有词库,你来背」这个主张和其他背单词软件并没有什么不同,所以我们需要在「价值主张」里再加上「糖」。

但是,对于不同的群体来讲,「糖」是不一样的。如果只是放一些二次元的萌妹子,只有喜欢动漫的人会觉得这是他们的「糖」,可以吸引着他们,每天都来看一看。对于其他一些二次元无感的人群来讲,这些图就毫无吸引力,于是我们需要增加「糖」的种类。

比方说有的妹子就喜欢看帅哥、有的粉丝就喜欢看偶像、有的铲屎官就喜欢看猫猫狗狗、有的吃货就喜欢看肉和甜点。这一部分,我们可以用多图库的方式来满足。

于是,针对不同的客户细分,我们提出三个更为细化的价值主张:

  1. 「每天看40分钟妹子,一个月记住四六级词汇」
  2. 「看着帅哥,把雅思托福词汇搞定」
  3. 「一边云吸猫一边升职加薪」

现在听起来是不是就有吸引力多了?

渠道通路

picture 6

在「渠道通路」的这个方格里面呢,我们的种子用户主要由微博带过来的流量构成。

通过种子用户进行测试,一旦转化率达标,我们就可以开始对外去做一些合作,以及以微博为起点投放广告,观察广告投放的成本和其带来的流量的关系,以此判断下一步操作。

客户关系

picture 7

在「客户关系」这里,我们会通过腾讯提供的「兔小巢」这个产品来提供售后支持。它是类似于反馈板的免费工具。用户在上面提交问题,我们会收到微信或者QQ的通知,可以通过网页在电脑上或者手机上进行答复。

关键活动

picture 8

接下来我们来看一下「关键活动」。

用来验证需求的最小可行产品(MVP),是一个简单网页,只包含 100 个单词、100 张图片和简单的输入文字切换图片功能即可。我们还需要一个统计数据,看看每一个访客到底背了多少个单词。这关系到我们价值主张里的「无痛」和「持久」。

当这个价值被验证后,就可以进入第一期开发。

虽然是一个全平台应用,我们第一期却只做网页版。具体业务包括:背单词的界面,以及选择词库的界面。这是最核心的业务功能。如果我们第一期想要有收入,那么就需要支付和订单系统。

为了对转化过程进行分析、更好地挣钱,我们还需要开发一个2A3R漏斗的统计,让用户从获客层顺利滑入付费层。如果需要通过分享裂变获取更多流量,我们也需要统计发起分享的用户数据。如果要允许用户自定义词库,我们就要提供对应的制作工具。

以上这些,构成了我们的关键活动。关键活动可以采用不同颜色的文字来标记不同的分期,也可以一期一期追加。

关键资源

picture 9

在关键资源上,除了需要具备人、钱和时间以外,我们这个项目还有特有的资源需要考虑,那就是背单词所用的图片,这是一个非常值得注意的问题。

在最小可用产品中,因为不涉及到收费,我们可以使用的图片很多。一旦开始收费,如果还是不加识别地从网上下载各种版权不明的图片,放到自己软件里并以收费的方式进行售卖,很可能会出现侵权。

所以,我们就需要思考图片资源的解决方案。粗略分析后,有以下几种思路:

  1. 作者授权
  2. 换用无版权图片
  3. 用户自行提供图片

作者授权

直接找作者把图片买下来,然后作为付费词库卖给用户,这是最直接的方式。但有问题,那就是价格,光是大一点的词库就有超过一万个单词,也就是说我们要买一万多张图。如果按一张图 50 元计算,需要 50 万的投入。

在一分钱都还没挣之前就做出这么大的投入,风险还是很高的。这种方式更适合我们挣到钱以后,在扩大规模时使用。

换用无版权图片

当然,我们也可以寻找无版权的图片来做图库。这样即使我们打包在软件里进行商业销售也不会有任何问题。互联网上已经有比较庞大的无版权高清图库了,比如 Unsplash 等。不过这些图库主要是风景和动物,人物类非常少。

用户自行提供图片

本质而言,我们卖的是「看图背词」的工具,而不是图片本身。现在之所以在版权上有风险,是因为打包导致的。所以我们可以尝试着将付费的服务和免费的图片分离开。

比如我们可以给用户提供自定义图库的制作工具,让他们把自己收藏的图片导入进去。这样既能达到目的,又没有版权上的风险。

类似需要考虑的,还有背单词时用到的音频。最简单粗暴的方式是使用云平台的TTS(文字转语音)接口直接生成。

成本收益

picture 10

在填好这几个格子以后,我们就可以开始对成本和收益进行相应的预估,算出预期利润区间。

由于我们开发的项目相对比较小,用到的资源也不是特别的多,所以商业模式画布做得还不算细致。不过通常来讲,第一版的商业模式,画布本身也不会特别细。它是随着项目的进展不断被细化的。

最后我们来看看完整的商业模式画布:

picture 11

================================================ FILE: docs/040304.html ================================================ 通过用户画像细化客户 - 精益副业

通过用户画像细化客户

什么是用户画像

在商业模式画布里面,我们对客户进行了细分,把客户分成了不同的组,每一组代表一个独立的需求。

用户画像(persona)呢,就是给这些已经分好的组,每一组搞一个人设、建一个虚拟形象,让其变得有血有肉、有姓名有年龄有性别、有自己的身份有自己的爱好、有使用产品的场景。

这样当我们聊到这个用户画像的时候,就像在讲自己的朋友、同事一般熟悉的人一样。

把抽象的需求变成活灵活现的人,这样我们在进行产品设计的时候,就更容易还原到场景,带着画面去想象这个人的需求和行动,这就是用户画像的意义。

福利单词的用户画像

接下来,我们就在福利单词的客户细分基础上,为每一类客户建立用户画像。

四六级备考生

首先是备考四六级的大学生这个细分客户群。我们叫他王小康,设定为一个大三的男生。他现在有一个迫切的任务,就是一定要通过四级考试。这位同学是一个动漫宅,他喜欢看的图就是二次元的萌妹子。

留学移民预备军

然后我们来给有留学移民需求、需要考雅思和托福的人群做一个用户画像。我们叫她章小留,她是一个大学刚毕业一年的女生,现在有出国留学的想法,正在准备雅思考试。这位同学是追星族,喜欢看的图片是韩国帅哥。

专业提升小白领

第三个细分人群的用户画像,我们叫她卢小白,是一个毕业两年左右的女生。在生物公司从事技术相关的工作,她需要尽快熟悉大量的生物专业方向的英文单词,方便她更好地了解公司业务。她家里有猫,喜欢看的图片是萌宠和美食。

确定了这三个用户画像的基本资料以后,我们会给他们配上头像,写上他们的需求关键字,把它整理到一页A4纸上。

这样我们就可以把它打印出来,贴到墙上,在做产品设计的时候可以随时去看他们,就像看着我们身边的熟人一样。

画像的头像制作

很多书里面都强调说,用户画像的头像要尽可能真实,最好用真人头像。但需要注意在网上乱找真人头像容易导致肖像权问题,这里给大家推荐一个通过AI生成真人头像的网站,叫做 thispersondoesnotexist.com。

picture 12

不过这个网站生成的多是欧美人,对国内的产品来讲,反而各种违和。我更喜欢使用日系的动漫捏脸网站来做,比如 charat.me 这个网站。

picture 13

最终的用户画像

有了头像,再配上角色的说明和需求关键字,我们就有了一个简单好用的用户画像。下边是我们制作好的三个画像:

picture 14

picture 15

picture 16

================================================ FILE: docs/040305.html ================================================ 画像→场景→功能和分期 - 精益副业

画像→场景→功能和分期

使用场景分析

有了栩栩如生的用户画像,我们就可以从画像想象出场景,再由场景梳理出功能列表并进行分期。下边我们就具体来看下怎么分析使用场景。

王小康的使用场景分析

首先是王小康的使用场景,包括在学生宿舍、在图书馆以及在课堂上。

在宿舍,他每天晚上八点到九点使用台式机。因为宿舍比较吵,他会戴着耳机学习。这时候他使用的是外接键盘。

晚上睡觉之前,他还会窝在被窝里玩一会儿手机,时间大概是晚上十一点半到十二点,也就是睡觉前的半个小时,这时候的使用场景就是用手机背单词。

图书馆也是一个典型场景,因为在这个环境里边,需要保持安静。所以你要么戴耳机,要么将设备调成静音。王小康一般是下午三点到五点去图书馆自习,这个时候他使用的是笔记本电脑和 iPad 。

需要注意的是使用 iPad 的时候是没有键盘的,所以在输入上面没有使用外接键盘方便,整体输入速度会下降很多。

图书馆和学生宿舍是两个相当不同的场景。宿舍里很可能有室友在玩游戏或者聊天,很容易分心,甚至连背单词这件事都很容易忘掉,所以我们需要有提醒。

相对而言,图书馆就是安静的沉浸式环境,没有人来打扰你,大家都在忙着学自己的东西。

章小留的使用场景分析

下面我们来做章小留的场景分析。

她现在辞职在家,完全是备考的状态。每天上午会在家学网课、或者去线下的培训班学习,下午会在家学词汇。晚上的话,可能要看韩剧。

主要场景在学词汇的下午。因为是在家里边,她使用的是台式机,鼠标和键盘都是外接的。每天早上起床的时候可能也需要复习一下。

所以她的两个主要使用场景是使用电脑学习,以及早上起床时用手机进行复习。

实际上,这个场景和王小康在晚上用手机复习的场景非常类似,可以都写上,最后进行功能合并时,重复的内容会被合并掉。

同时,因为这两个用户都是在备考,所以他们其实还有「考试复习」这个特殊场景。

在这个场景里,它的词库是有范围的,不一定是整个词库。而背单词的时候,需要有一个考试模式,限时答题,并给出得分。这些需求我们不一定都要通过福利单词这个产品来满足,但可以先写下来。

卢小白的使用场景分析

小白是上班族,所以学习时间是非常有限的,主要是在上下班通勤的时候学习,以及在周末的时候有一点空余时间。

通勤场景一般会在地铁上。运气好的时候就有座位,运气不好的时候还需要站立着。这时候她会使用手机和耳机来学习。

因为她的词汇学习主要是为了工作需要,所以在工作的时候可能还会有查词的需求,可以通过词典软件解决,但是她可能会想把生词加入到福利单词来记忆。

大部分时间地铁里是很挤的,有时候需要一个手扶住上面的吊环或者旁边的柱子,所以小白可能需要单手操作。

另外要意识到小白只是一个典型代表,她需要的是生物类的词汇,但是其他的上班族需要的词汇可能会覆盖各行各业,这部分的词库需要通过自定义词库来解决。

同时,小白很喜欢宠物,当她看见可爱的喵星人时,很可能希望将这个图片保存到相册。这里如果再结合到我们上面的考试模式的话,其实可以做得更游戏化一些。比如说我们可以加入一个图鉴,就是一个画册,里边有每一个单词对应的图。只有你对这个单词达到一定的熟练度以后,才能在里边看见。大体上这就是小白的使用场景。

从场景到功能

现在我们三个用户画像的使用场景已经分析完了。接下来,我们就可以根据场景来确定功能了。也就是说,为了满足这些场景下的需求,我们在产品上需要提供哪些功能来支撑。

在确定功能的时候,有两类需要特别注意。一类是核心功能,没有它,所有画像都没法使用我们的产品。另一类是边界功能,没有它,某一个画像就没法使用我们的产品。核心功能是交集、边界功能是并集。

我们会根据画像的设定,将一些边界功能分配给他们。比如说,为什么卢小白她就会想保存图片到相册,章小留就不会呢?事实上章小留也会,但我们不需要把一个边界功能重复分配,因为最终都会覆盖到。

画像需要注意的是它特有的场景,比如考试模式是备考生的特有场景。对于不考试的同学来说有没有都无所谓,但是对考试的同学是非常有用的。

我们把边界功能标记出来以后,就可以框定一个大体的功能范围。

比如说,章小留使用的是苹果台式机,这就要PC版需要同时支持 Windows 和 Mac 两个操作系统。路小白上下班通勤的时候是单手操作,我们在手机上设计浮动键盘时,就要考虑到小屏幕手机上26键的全键盘单手时容易按错的问题。

对于卢小白来讲,她的空余时间不多,所以可能还会利用家务和健身的时间,这个时候如果她想复习单词,可能还有一个语音播报的需求。

章小留是追星族,那她在网上看韩剧的时候,会顺便把喜欢的偶像的图片给保存下来,制作成词库,甚至还会分享给同好。

这些都是边界功能。在早期设计的时候,可以先不考虑工期、开发量这些很现实的问题,我们可以先把它放进来思考,至于做不做、什么时候做,那是以后的事情。

我们要做的东西在早期应该尽可能的少,但是思考的范围却应该尽可能的广。我们是把很多东西都想明白了以后,选其中最核心的、最重要的来做。而不是说很多东西我压根就不想,只做眼前看到的那一丁点就开始做了。这样到项目中期,就会出现很多思考上的盲点,这些盲点甚至会导致我们的项目重做,所以需要尽可能避免。

通过思维导图梳理功能

我们可以通过思维导图软件来梳理功能。

想象一下新用户从什么地方开始使用我们的软件,跟着他的使用流程来同步构建功能。

比如说,首先会需要有一个用户系统,这样我们才能识别用户。接着我们肯定需要有词库,不然就没有单词可以背了。我们肯定也需要有单词的背诵、管理,如果我们要收费的话,肯定还需要有支付。

用户系统里边,我们考虑使用微信登入,这是目前最简单的办法,不用做用户系统、也不用做密码找回。有了登入肯定也得有退出。

有了用户系统以后我们就可以保存用户背单词的进度了。在词库这边呢,既然我们要做一个可切换和自定义的词库,那肯定会有一个列表。

这个列表,首先是会有一个官方的或者叫内置的,然后我们在建立一个本地的列表,给自定义词库用的。

自定义词库这边,我们可能还需要给提供一个工具来制作词库。我们需要有一个单词表、需要生成对应的音频、需要有对应的解释,以及我们背单词的时候看的图片。这是词库的大体功能。

如果我们要做图鉴的话,就需要有词库的完成度数据。就是用户背了词库里面百分之多少的单词、以及对每一个单词的熟练度。在这个基础上我们还需要有一个相册,用来欣赏高清图片。

自定义词库制作完成以后,它还需要有一个分享方式。我们可以允许用户通过二维码分享,其他的用户通过二维码扫码导入。

接下来,我们来看背单词的功能。

首先它需要有一个地方来输入字母,我们会根据输入的字母动态地进行遮罩的调整。然后我们需要把用户输入的时间或者错误的次数统计起来,这代表着对这个单词的熟练程度。我们也还需要有一些辅助按钮,用来显示单词的意思、以及跳过不会的单词。

在最后,当正确地输入了单词以后,我们需要显示一个高清图片,让用户可以很完整地看见这张图片,这是对其的奖励。

另外我们也需要把用户的背单词成绩记录下来,为了能更清楚地看见这个成绩,可能还需要提供一个进度统计,告诉用户背了词库里面的百分之多少,各自的熟练度是多少。

还有支付部分别忘了。首先我们要显示可以付费的商品,当点击购买按钮以后,要把微信支付给呼叫起来。在微信支付完成以后,要进行确认。同时我们也需要维护一个订单列表来进行售后和退款。

分期

确定好功能表以后,接下来就可以进行分期了。

功能分期

因为我们现在的功能实际上已经非常多了,必须要把它分成不同的阶段来做。最小可行产品不太典型,这里我们以 PMF 验证完成后的第一个版本为例,来选择第一期的内容。第二期就是「以后再做」的功能,第三期就是「不知道啥时候做」的功能。

来看我们的功能列表:

  • 推送提醒:可以放到第一期。但为了实现推送,需要有消息系统。如果要做定时提醒的话,还需要做设置界面。因为用户设置过提醒以后,可能有一天不需要了,要能及时取消,不然天天推送还挺烦人的。
  • 考试模式:放到第二期。虽然对备考生很重要,但是因为整个开发量比较大,在挣钱之前可以先不做。
  • 虚拟键盘:放到第一期。为了支持单手操作,我们需要给背单词的界面添加在移动设备上的键盘界面。不同输入法的键盘可能会导致兼容性问题,所以我们直接通过一个虚拟键盘来解决它。
  • 自定义词库分享:放到第二期。
  • 图鉴模式:放到第二期,也可能是第三期。
  • 语音回放:放到第二期。

picture 17

确定分期的时候,也要同时检查功能点是否都对应上了。比如支付里面,我们需要把「微信支付的对接」加上。

功能归类到界面

确定好某一期的功能列表后,可以把各个功能归类到界面里。新建一个思维导图,写上显而易见的各个界面,然后把功能放到界面下去。

如果发现有功能没有界面放,恭喜你提前发现了做丢的界面,赶紧把这个界面也加进去吧。

picture 18

这一步完成以后,我们就可以开始进入设计阶段了。

================================================ FILE: docs/040306.html ================================================ 什么是好的商业设计 - 精益副业

什么是好的商业设计

这一节开始我们会讲一些设计方面的东西。和专业的设计课不同,我们主要着眼于如何让非专业设计人员也能做出七十到八十分的设计。

首先我们来和大家聊一聊,什么是好的商业设计。

好设计的标准

要做好一件事,首先要弄明白好的标准是什么,而这恰恰是讨论设计时的一个难点。

为什么呢?

我们写程序做软件,好不好是有一个相对可以量化的指标的。比如:用了多少行代码,执行了多久时间,占用了多少内存、在一秒以内可以承受的并发请求数是多少。这些都可以很精确地衡量出一个程序是否写得好。

但是,对于设计来讲,它是一个很个人化的东西。同样一个设计,有的人会觉得它好,有的人会觉得它不好,还没法说谁对谁错。甚至有一些艺术家,他的作品可能在当时就没有人能够理解,隔了很多年大家又把它拿出来,才发现惊为天人。

这就造成了一个问题,设计到底应该按什么样的标准去衡量?不光是设计师本身需要思考这个问题,设计需求的提供方其实也需要去思考。

商业设计

但是后来我们发现,如果把设计的范围给缩小一些,就可能得出一个部分适用的答案。

艺术这个东西它确实是千人千面的,因个人的感受而异。但是我们为商业产品做的设计它并不等价于艺术,大部分情况下它是为商业服务的,我们就叫它「商业设计」吧。

一个好的商业设计,其实就是要让尽可能多的客户喜欢它。因为,喜欢上我们设计的人,很可能也会喜欢上我们的品牌和产品,最终转变成商业价值。

至于这个设计在艺术上深刻不深刻,完全是另外一个领域的事情。

这里有一个比较极端、但大家也很熟悉的例子,那就是椰树椰汁的产品设计。它基本上是把美感给扔了,但换取了很好的识别度,这就是一种商业上的权衡。

我们写程序的时候,要从代码思维上走出来,回到商业思维的角度上来;我们做设计的时候也要从设计本身走出来,从整个商业链条的角度去思考。

通常来讲,我们会面临的抉择,往往是在两类截然不同的设计之间。一类剑走偏锋、足够深刻,能理解它的一类人特别地喜欢,而不理解的又特别讨厌它;另一类设计,看似中庸,然而平中见奇,不同层次的人都可以看到自己喜欢的点。

如果这个设计要拿去参加艺术大赛,可能前者更合适。但如果用于商业产品,那我觉得应该选择后者。因为归根结底,它是用来承载功能、向客户传递品牌质感的,而不是要体现它自身有多深刻,那样反而喧宾夺主了。

简洁即美

每个人的兴趣和爱好都是不同的,要做一个设计或者塑造一种风格,让绝大部分人都喜欢上是很难的。但我们幸运的发现,设计如果足够简洁的话,就不容易包含太多触发各种反感的点,更容易获得绝大部分人的喜爱。

而对于副业来讲,简洁风格的方案所需要的设计和开发资源都相对较少,配合起来又比较容易协调,所以简洁风格是我们的首选。

================================================ FILE: docs/040307.html ================================================ 人人能用的四大原则 - 精益副业

人人能用的四大原则

界面设计是很多尝试自己开发完整产品的程序员非常痛苦的事情。很多时候,如果我们去问设计师,很多人虽然会设计,却讲不出背后的道理。只会说,「这样做感觉上更好一些」,「这就是经验/灵感」。

我以前也是这么认为的,直到读了一本书才明白,原来界面设计背后一样是有规律的。

界面的表层结构展现的正是它内部的逻辑。

一个界面上应该摆放哪些控件,哪几个应该离得近,哪几个应该离得远,哪些应该用同样的风格,哪些又应该区别开来,这些都源于它背后严密的逻辑关系,而不是因为设计师的一时兴起。

那本书就是《写给大家看的设计书》。在书里,作者提出了界面排版的四个基本原则,通过活用这四个原则,我们就能够把界面设计得美观大方。

这四个原则分别是「重复」,「对比」,「对齐」和「亲密性」。

  • 「重复」原则强调「一致性」,它说的是「在逻辑上一致的物件,在视觉上也应该一致」。
  • 「对比」原则强调「层次感],它说的是「逻辑上不同的物件,在视觉上也应该不同」。所以我们要想办法拉出距离来。
  • 「对齐」原则强调的是「安定感」。均匀的留白能够营造出一种稳定的感觉。这正是产品质感的一种潜意识渗透。对齐虽然是很小的细节,但是如果处理不好,很容易会破坏产品整体质感,而且会给有强迫症的朋友带来莫大的压力。
  • 「亲密性」原则,强调区块的关系,它说的是「逻辑上存在很近的关系,那么这个关系也应该表现在视觉上」。相关的项应该彼此靠近,不相关的项应该彼此远离。

书里有非常详尽的介绍和让人顿悟的例子,建议大家都去阅读下原书。

picture 19

四大原则回答了常见的一些界面问题。比如说,上图中,白色方块之间的间距为什么不能比第一个方块和页面边界的距离大。

如果从纯感性的角度来讲,可能会说「这样放不好看」。但是如果通过亲密性原则来思考的话,我们会发现在逻辑上,相对于页面边框,白色方块是一个整体。一个白色方块和另一个方块的关系,显然比它和页面边框近。所以这种深层关系表现在视觉上,就是它们之间的边距差异。

如果视觉关系和逻辑关系不一致,我们就会觉得「别扭」、「不直观」。这些原则为我们通过逻辑理解设计推开了一扇门,让之前仅存于「感觉」和「经验」的设计技巧变得有章可循。熟悉它们以后,只要多加练习,再配合上一些简洁、清爽风格的设计细节,我们就可以在大部分场景下做出七十到八十分的界面来。

picture 20

================================================ FILE: docs/040308.html ================================================ 独特Logo解决方案 - 精益副业

独特Logo解决方案

接下来讲下,如何设计产品的 Logo 。

最简单的方式当然是请设计师来设计,我们只需要像产品经理那样在背后指指点点,改需求、当甲方就好了。但是,在做副业时,我们很可能没有足够的预算去雇佣专业的设计师。尤其是在软件还没有获得收益之前,如果花很多钱去请设计师设计,而产品本身又运营不起来的话,钱就白花了。

所以,学会自己做一些比较简单能用的 Logo 还是很重要的。等以后挣钱了,可以再花大钱请高手来重新设计。

Logo 的设计还是有些考验绘画能力的,即使是相对简单的简笔画,对于很多没画过图的程序员来讲,也挺难绘制一个像样的出来。

如果你有一定的绘画基础,或者想发掘自己隐藏的天赋,那么我特别建议大家用矢量软件来绘制,对于像我这样手残的同学来讲特别有用。

我最开始画 Logo ,是给自己的开源项目。刚开始使用的是像素绘图软件。由于缺乏练习,即使使用数位屏,也很难绘制出光滑的线条。即使偶尔画出来了,要调整它时,又会花费大量的时间。

后来我发现了矢量绘图软件,在它里边,我们绘制的其实不是线条,而是一个个形状。线条是我们指定的形状的边界,可以通过描边自动生成。最棒的一点是,当我们改变形状时,线条就自动随之变动,无需再重新绘制。

只要熟悉了形状的画法,我们就可以通过矢量绘图软件来绘制一些简单的、线条光滑饱满的图案了。

picture 21

作为对比,上图左边是我用像素绘图软件绘制的头像,右边是后来我用一个周末学习完矢量绘图软件后花一天时间重新绘制的。真的是好用太多了。

免费和开放的矢量资源

当然,不是所有同学都有时间和精力去学习绘图的,所以我们还是回到适合更多人的方案上来。首先,我们可以使用网上的开源矢量资源。最近两年开始出现一些视觉效果非常不错的矢量插图网站。

picture 22

比如 unDraw,它就提供大量的适合互联网和软件场景的开源矢量插图。更贴心的是,在网站右上角还提供了颜色按钮,通过调整颜色,我们可以得到和自己产品风格更为统一的矢量图。

一个需要注意的地方是,如果使用免费素材,一定要留意不要从国内那些没有注明作者和授权的网站上下载。因为这些来历不明的素材很可能给你带来版权风险,说不定哪天巨额索赔就找上你了。

购买付费素材

如果没有好的免费备选,或者没有太多时间去各个网站上挑,我们还可以通过购买的方式来获取素材。

picture 23

在购买素材的时候,要注意使用的限制。有的网站的素材是会限制使用的项目数、域名、甚至媒体类型的。我推荐大家优先购买采用「royalty-free」许可的网站。这种许可非常开放,往往只要付费就可以永久使用。

提供付费矢量图标的网站比较多,比如 flaticon.com ,thenounproject.com 都是比较有名的。我个人一直订阅的是后者,提供的图标够多,价格也比较便宜。它还提供了一个电脑客户端,可以很方便的搜索、复制粘贴图标文件。

这个网站目前提供的图标都是没有颜色的。当然这一点可能对我们来讲,并没有太大的影响。为什么呢,因为直接使用这些网站上的图标做 Logo ,会带来一个潜在的问题。

将付费素材变成独有的

这种买断式授权的素材非常好用,但是既然我们可以花很少的钱来买这个设计,那同样的,其他人也可以来买这个设计拿去使用。正如许可中指出的,这种许可是非排他的。

如果这些图标只是用到界面上,多个应用之间相似甚至相同,可能还是好事,因为这降低了用户的学习成本。但如果用在 Logo 这种代表品牌的场景,就会出现多个应用 Logo 一样的尴尬场面。

只是从这种买断式素材网站上直接买一个素材就拿过来把它作为 Logo,那人家也可以从这个素材网站上买同样的素材作为它的 Logo。这种行为可能是无意的,也可能是有意的。这种情况下我们还不能说人家抄袭侵权,因为都是从同一个地方买的,你可以买,人家当然也可以买。除非你把这个图案拿去抢先注册了商标,否则就会存在潜在风险。

不过,我们可以通过混搭组合的方式,将 Logo 变得独一无二、且更贴近我们产品的本质。

你看,thenounproject.com 上有上百万的图标。我们单独使用,总有其他的用户和我们一样喜欢上某一个图标,并把它作为 Logo,这个时候我们两个产品就冲突了。

但是如果我们把这几百万的图标混搭组合起来,就会产生出上亿种组合,再要想重复,就变得非常困难了。而「从一个图案里边截取一部分,跟其他的地方拼合起来,构成一个新图案」的这种操作,即使对于一个没有绘画功底的同学来讲,只要能熟练地使用软件,也可以轻易完成。

另外,在增加识别度方面,除了混搭,还可以通过上色来实现。单色图标因为使用的颜色数少,往往比较单薄,看起来缺乏层次感。当我们把它作为产品 Logo 的时候,可能就不是那么耐看。这时候我们可以自己来给它上色。因为是矢量图标,所以调色和上色都非常简单。调色只要选中后改变线或者形状的颜色就可以。

================================================ FILE: docs/040309.html ================================================ 使用AdobeXD设计界面 - 精益副业

使用AdobeXD设计界面

什么是 Adobe XD

picture 24

Adobe XD是由 Adobe 开发的矢量设计工具,它和 Sketch 类似,既可以用来绘制矢量界面,又包含原型设计功能,还可以在手机上预览设计好的界面。XD 支持 Windows 和 Mac,是 Adobe 为数不多的可以免费使用的软件(当然你可以付费升级 pro 版本)。

使用 Adobe XD 设计简单界面

软件的使用主要还是靠大家勤学多练,这里我们和大家演示下如何用它来设计背单词界面。

理解画板

首先,我们在 XD 里新建一个画板(art board)。

画板是什么?它相当于 Word 里边的页面。一般的纯设计工具没有画板这个概念,但 XD 也包含了原型功能,有时候我们需要在多个界面之间来回切换,而一个画板往往就是一个界面。

点击左侧的菜单里面倒数第2个画板的按钮 picture 25
,这时候在屏幕最右边就会出来一系列预置的画板尺寸。

picture 26

它已经帮我们准备好了常用的规格,比如苹果的iPhone、iPad,谷歌的安卓机型,以及网页常见的尺寸。

我们只要从里边选择对应的尺寸就好了,当然也可以不选择它给你预置的,直接手工拖拽来画或者在属性里面调整画板的宽和高。那我们就新建一个iPhone Xs尺寸的画板好了。

然后按住 CTRL或者CMD + D,就可以直接复制画板。我们把第一个画板叫做背单词界面,然后开始设计。

picture 27

遮罩的制作

先来制作背单词时,字母没有输入完时显示的遮罩效果。选择左侧工具栏中的矩形 picture 29
工具,画出一个覆盖全部画板的长方形。然后调节填充颜色为黑色,透明度为 30%。

picture 30

然后我们到 unsplash.com 这个无版权网站上,找一只猫的图片,把它也放进来。

picture 28

这时候猫是在遮罩上方的,所以它挡住了遮罩。

picture 31

点击右键,选择「Send to back」将它放到遮罩后,我们就可以看到被半透明遮罩挡住的猫了。

单词释义和输入框

接下来,在遮罩上边,我们来放上单词释义和输入框。点击最左侧工具栏中的 picture 33
图标,切换到文字工具。

然后输入文字释义。

picture 32

在右侧的属性面板里,我们可以调节文字的字体、大小、颜色和对齐。

然后我们放上之前设计好的 Logo,加上单词输入框。

picture 34

注意这个输入框不一定非要是「框」,比如我们这里也可以把它做成下划线。

虚拟键盘

picture 35

虚拟键盘的制作在 XD 中也很简单,直接用矩形工具绘制就行。需要注意的是圆角的做法。

picture 36

其实很简单,在右侧的属性设置里边,把圆角从0 改为 5 就可以了。在做好一个按钮后,我们可以按住 Shift 同时选中按钮和上边的文字,在右键菜单中将其编组(Group);然后按 CTRL或者CMD + D 就可以复制按钮。

picture 37

当按钮多起来之后,要对齐它们还挺费事的。其实选中多个按钮后,可以在菜单 Object → Align 中来自动对齐;也可以在 Object → Distribute 中让它们自动均匀分布。

矢量图标

再下来,我们需要在界面中引入图标。既然是矢量界面,当然是矢量图标最好。前边我们已经介绍过 thenounproject.com 了,它还为 pro 用户提供了一个客户端。在这个客户端里边可以非常方便的复制图标。

picture 38

当我们通过关键字搜索到图标后,可以通过下载并将其拖拽到 XD 的方式引入;也可以直接在客户端中右键选择 Copy as SVG,然后直接粘贴。因为是 SVG 格式,调整完大小后可以很方便地更换颜色。

最后我们再微调一下输入框和单词释义的位置,背单词界面就做完了。其他界面的制作非常类似,就不在这里累述了。

================================================ FILE: docs/040310.html ================================================ 个人支付解决方案 - 精益副业

个人支付解决方案

略过开发环节,我们来讲讲变现。绝大部分的支付方案都是面向企业的,面向个人的正规支付方案非常少。那么对于没注册公司的个人,怎么样才能比较安全地收款呢?

常见的几种个人收款方式

个人收款码

市面上最简单粗暴的个人收款方案,就是利用微信或者支付宝的个人收款码来做。

具体的说,就是生成一张二维码,在这个二维码上面添加一个付款的备注,让用户备注中补充上特定的消息后(比如订单号)支付。当完成支付以后,我们就会通过APP或者网站,得到备注里面填的消息,通过识别,我们就能定位到订单,从而自动发货。也有不用备注,用支付金额来识别的。

这个方式淘宝店家已经用了很多年,它的问题就在于,从用户端的体验来讲,它需要填写额外的消息或者发送不确定的金额。从商家端的体验来讲,它需要有一个常驻的服务,随时去监测收款的相关消息,这就会有相当的不稳定因素在里边。

二次封装接口

另一种解决方案,就是由那些有资质的企业申请到接口权限后,二次封装后提供给个人来用。这种方案的问题在于,钱是支付给提供接口的企业的,我们只能定期找他们结算提款。万一对方跑路了,我们的钱也就没了。这种方式风险非常高,不推荐。

小微商户

「小微商户」是支付平台针对个人、也就是大量没有企业资质的用户推出的一个解决方案。最开始推出的时候,是为了帮助一些线下的店面,快捷地接入支付而存在的一个服务,然后又扩展到了网上的网店和商家。

一些银行和微信都有这个服务。但是微信并没有给它做专门的后台页面,所以我们在支付平台的后台里是看不见它的,它只有API。

微信把这一部分业务,交给了微信开放平台上的服务商。由服务商去调用这些接口来帮助个人接入到微信的支付服务里面来,同时服务商会提供后台的页面帮个人用户进行管理、也是服务商封装API供个人使用。

这种方案它的好处在于,它是完全合规的,而且这个钱是从微信直接打到小微商户的银行卡里边,不经过中间服务商,所以非常安全。

目前国内有名一点比如 xorpay.com 和 payjs.cn 。他们都是收费服务,前者的费用似乎更为便宜一些。这两个业务我们了解不多,大家使用之前请自行判断其靠谱系数。

数字内容销售平台

如果我们就是写一个软件,想简单地进行销售获得收入的话,我们还可以使用一些现成的数字内容销售平台。面向国外市场的话,可以使用Gumroad.com;如果面向国内市场的话,可以使用mianbaoduo.com。

picture 39

逻辑上讲,所有的网店都能解决我们卖软件的需求,但相对而言,面包多这类专门面向数字商品的平台提供了更低的手续费和更为全面的 API 接口。

picture 40

================================================ FILE: docs/040311.html ================================================ 使用「兔小巢」处理用户反馈 - 精益副业

使用「兔小巢」处理用户反馈

市面上管理用户反馈的产品很多,不过大部分都是收费的;这里我们介绍下自己在用的、腾讯出品的免费工具「兔小巢」。

picture 41

这个产品最大的用户就是腾讯自己,原来叫「吐个槽」,最近才升级并更名为「兔小巢」。我们已经使用了几个月,用下来感受很不错。

从用户端来讲,它支持微信和QQ登入,能及时地推送回复通知;从运营端来讲,用起来明显可以感受到这是一款看似简单,功能却相当强大的产品。比如它可以设置移动端的展示方式;可以适配大型产品和通用产品;默认发帖可以隐藏,也就可以当做工单使用;甚至还配备了团队博客和知识库。

不足的地方是提供的 API 比较少,但也够在自己产品中展示用户反馈了。有了它,我觉得大部分情况下,就不用再去购买同类的付费产品了。

整合说明

下边分享一些整合细节,供大家参考。

链接跳转

兔小巢提供的是非常浅的整合,不管是在 Web 还是 APP 中,都是通过网页转向的方式来进行。通过设置,在反馈区上方可以显示一个链接,供用户返回到产品中。

状态登入

但是通过链接跳转会遇到一个问题,就是在我们的产品和兔小巢之间,用户的登录状态会丢失,这样我们就不知道那个反馈是哪一个用户提交的了。

为此,兔小巢提供了一个tucao.js,让我们可以在跳转时传递用户的登录态,从而实现用户的统一。

反馈数据整合

在默认的模式下,我们只能点击链接后,在单独的页面上才能看到反馈信息。但通过兔小巢提供的 API,我们可以直接在产品中显示反馈内容。

================================================ FILE: docs/040312.html ================================================ 2A3R漏斗和增长优化 - 精益副业

2A3R漏斗和增长优化

什么是 2A3R 漏斗

2A3R 漏斗,又叫 AARRR 漏斗,是一个用来描述用户转化的结构。

picture 42

它是一个五层结构,分别是:

  1. 获客层
  2. 激活层
  3. 留存层
  4. 推荐层
  5. 付费层

用户由上至下逐步转化,直至完成付费。其中,留存层、推荐层和付费层可以是并列的,因为用户激活以后,立刻就可以付费、推荐好友。

使用 2A3R 漏斗进行业务优化

2A3R 漏斗的现实意义在于,它促使我们从结果出发,去反向优化前边各个环节的转化率。比如说,如果我们福利单词的销售额定为 1000 套,那么就是说最终到达付费层的用户有 1000 人。而在付费层上至少还有获客层、激活层。

这里我们把获客指标定义为「访问网站」;把激活指标定义为「用户登入」。假设每一层的转化率是 10%,那么访问我们产品的用户数需要达到 1000 乘以 100 等于 10 万人。

优化方向包括:

  1. 我们可以加大推广力度,让访问人数从十万变成一百万,这样就能卖掉一万套软件了。
  2. 我们可以优化「用户登入」环节,在微信里边做成自动登录,这样把原来 10% 的激活转化提高为 30%,这样即使依然是 10 万访客,销售额也会变为 3000 套。
  3. 我们可以强化「付费转化」环节,给第一次访问的用户一个限时折扣,比如 1 个小时内购买,买一送一。如果能拉升 10% 的支付转化,我们的销售也会上升。

留存层优化

留存层优化主要用于一些基于高粘度增长引擎的业务,或者免费+付费模式的产品。在这些模式下,用户需要经过很长时间的使用,才会付费。如果留存做不好,用户熬不到付费那天。

对于福利单词而言,留存层优化可以通过推送通知、定时提醒等功能来做。因为背单词本来就是一个周期性行为,所以我们有足够的理由去召回用户。

推荐层优化

现在的流量已经是非常贵的了,所以我们必须珍惜每一滴流量。通过旧用户带来新用户,可以为我们提供免费流量;如果做得足够好,流量甚至能像滚雪球一样不断变大。这就是推荐层优化要做的事情。

在我们的应用中,我们可以选择几个用户情绪高涨的点来做分享触发:

  1. 完成当天的背单词目标,比如背了 100 个单词
  2. 完成有挑战的任务,比如连续 30 个单词不出错
  3. 看到赏心悦目的图片,比如看到超级呆萌的猫

在这些时刻,我们都可以引导用户通过海报来分享他们的激动心情,同时为我们带来新的用户。

推荐阅读

关于增长优化,这里给大家推荐两本书。一本是肖恩·埃利斯的《增长黑客》,系统化地讲述了如果建立增长实验机制并从中受益;另一本是《病毒循环》,记录了众多流量传奇。它们中很多细节和技巧,都可以用到我们的副业当中。

================================================ FILE: docs/0404.html ================================================ 进一步提升副业的鲁棒性 - 精益副业
================================================ FILE: docs/040401.html ================================================ 网课+独立开发的双引擎副业模式 - 精益副业

网课+独立开发的双引擎副业模式

前面我们通过两个大章节的实践课程,为大家详细讲解了怎么通过独立开发和网络课程制作来发展副业。之所以会选择这两个方向,除了它们非常典型、有很高的投入产出比,还有一个原因 —— 它们之间可以形成非常好的互补。

目前看来,在国内要通过独立开发赚到一流企业程序员的年收入(大致三十到五十万),还是比较困难的。免费加收费模式虽然后期收益巨大,但前期需要长时间的投入。

相对而言,网络课程的售卖更容易带来现金收益。如果我们把独立开发的整个过程完整的录制下来,并加工成网络课程进行销售,那么即使独立开发项目最终难以通过销售软件和服务来赚取足够多的收益,我们还可以通过网络课程获得收入。

而且,不管对于课程学员还是独立软件/服务使用者来讲,都更有益。课程的学员可以学到更为真实、更贴近一线、且经过事实验证的开发技巧;软件/服务使用者则可以获得详尽的文档、架构说明,更有机会进一步深入了解整个规划、设计、开发过程,充分理解业务,甚至因此变成代码贡献者。

从流量上讲,软件/服务可以给课程带来学员;课程可以给软件/服务带来用户。两者互相促进,为我们的副业更添了一层保障。

picture 25

最终,我们就可以实现一个多次利用「副产品优势」的三级收入模式。在这个模式下,我们首先通过主业赚取最核心的收益,以供日常生活和基本发展。然后,我们在主业工作中积累的知识、经验、人脉基础上,开发我们的副业,比如独立软件或服务。在独立开发的过程中,我们再次把它的副产品——制作过程,录制成课程进行售卖。最终,我们可以分别从主业、独立开发以及课程三个渠道获取收益。

这样即使某些收入源不是特别好,我们的整体收入还是相对高的,这就让我们有足够的时间和资源去修正这些错误,让整体发展得越来越好。

================================================ FILE: docs/404.html ================================================

Document not found (404)

This URL is invalid, sorry. Please use the navigation bar or search to continue.

================================================ FILE: docs/FontAwesome/css/font-awesome.css ================================================ /*! * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} ================================================ FILE: docs/ayu-highlight.css ================================================ /* Based off of the Ayu theme Original by Dempfi (https://github.com/dempfi/ayu) */ .hljs { display: block; overflow-x: auto; background: #191f26; color: #e6e1cf; padding: 0.5em; } .hljs-comment, .hljs-quote { color: #5c6773; font-style: italic; } .hljs-variable, .hljs-template-variable, .hljs-attribute, .hljs-attr, .hljs-regexp, .hljs-link, .hljs-selector-id, .hljs-selector-class { color: #ff7733; } .hljs-number, .hljs-meta, .hljs-builtin-name, .hljs-literal, .hljs-type, .hljs-params { color: #ffee99; } .hljs-string, .hljs-bullet { color: #b8cc52; } .hljs-title, .hljs-built_in, .hljs-section { color: #ffb454; } .hljs-keyword, .hljs-selector-tag, .hljs-symbol { color: #ff7733; } .hljs-name { color: #36a3d9; } .hljs-tag { color: #00568d; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } .hljs-addition { color: #91b362; } .hljs-deletion { color: #d96c75; } ================================================ FILE: docs/book.js ================================================ "use strict"; // Fix back button cache problem window.onunload = function () { }; // Global variable, shared between modules function playground_text(playground) { let code_block = playground.querySelector("code"); if (window.ace && code_block.classList.contains("editable")) { let editor = window.ace.edit(code_block); return editor.getValue(); } else { return code_block.textContent; } } (function codeSnippets() { function fetch_with_timeout(url, options, timeout = 6000) { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)) ]); } var playgrounds = Array.from(document.querySelectorAll(".playground")); if (playgrounds.length > 0) { fetch_with_timeout("https://play.rust-lang.org/meta/crates", { headers: { 'Content-Type': "application/json", }, method: 'POST', mode: 'cors', }) .then(response => response.json()) .then(response => { // get list of crates available in the rust playground let playground_crates = response.crates.map(item => item["id"]); playgrounds.forEach(block => handle_crate_list_update(block, playground_crates)); }); } function handle_crate_list_update(playground_block, playground_crates) { // update the play buttons after receiving the response update_play_button(playground_block, playground_crates); // and install on change listener to dynamically update ACE editors if (window.ace) { let code_block = playground_block.querySelector("code"); if (code_block.classList.contains("editable")) { let editor = window.ace.edit(code_block); editor.addEventListener("change", function (e) { update_play_button(playground_block, playground_crates); }); // add Ctrl-Enter command to execute rust code editor.commands.addCommand({ name: "run", bindKey: { win: "Ctrl-Enter", mac: "Ctrl-Enter" }, exec: _editor => run_rust_code(playground_block) }); } } } // updates the visibility of play button based on `no_run` class and // used crates vs ones available on http://play.rust-lang.org function update_play_button(pre_block, playground_crates) { var play_button = pre_block.querySelector(".play-button"); // skip if code is `no_run` if (pre_block.querySelector('code').classList.contains("no_run")) { play_button.classList.add("hidden"); return; } // get list of `extern crate`'s from snippet var txt = playground_text(pre_block); var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; var snippet_crates = []; var item; while (item = re.exec(txt)) { snippet_crates.push(item[1]); } // check if all used crates are available on play.rust-lang.org var all_available = snippet_crates.every(function (elem) { return playground_crates.indexOf(elem) > -1; }); if (all_available) { play_button.classList.remove("hidden"); } else { play_button.classList.add("hidden"); } } function run_rust_code(code_block) { var result_block = code_block.querySelector(".result"); if (!result_block) { result_block = document.createElement('code'); result_block.className = 'result hljs language-bash'; code_block.append(result_block); } let text = playground_text(code_block); let classes = code_block.querySelector('code').classList; let edition = "2015"; if(classes.contains("edition2018")) { edition = "2018"; } else if(classes.contains("edition2021")) { edition = "2021"; } var params = { version: "stable", optimize: "0", code: text, edition: edition }; if (text.indexOf("#![feature") !== -1) { params.version = "nightly"; } result_block.innerText = "Running..."; fetch_with_timeout("https://play.rust-lang.org/evaluate.json", { headers: { 'Content-Type': "application/json", }, method: 'POST', mode: 'cors', body: JSON.stringify(params) }) .then(response => response.json()) .then(response => { if (response.result.trim() === '') { result_block.innerText = "No output"; result_block.classList.add("result-no-output"); } else { result_block.innerText = response.result; result_block.classList.remove("result-no-output"); } }) .catch(error => result_block.innerText = "Playground Communication: " + error.message); } // Syntax highlighting Configuration hljs.configure({ tabReplace: ' ', // 4 spaces languages: [], // Languages used for auto-detection }); let code_nodes = Array .from(document.querySelectorAll('code')) // Don't highlight `inline code` blocks in headers. .filter(function (node) {return !node.parentElement.classList.contains("header"); }); if (window.ace) { // language-rust class needs to be removed for editable // blocks or highlightjs will capture events code_nodes .filter(function (node) {return node.classList.contains("editable"); }) .forEach(function (block) { block.classList.remove('language-rust'); }); Array code_nodes .filter(function (node) {return !node.classList.contains("editable"); }) .forEach(function (block) { hljs.highlightElement(block); }); } else { code_nodes.forEach(function (block) { hljs.highlightElement(block); }); } // Adding the hljs class gives code blocks the color css // even if highlighting doesn't apply code_nodes.forEach(function (block) { block.classList.add('hljs'); }); Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) { var lines = Array.from(block.querySelectorAll('.boring')); // If no lines were hidden, return if (!lines.length) { return; } block.classList.add("hide-boring"); var buttons = document.createElement('div'); buttons.className = 'buttons'; buttons.innerHTML = ""; // add expand button var pre_block = block.parentNode; pre_block.insertBefore(buttons, pre_block.firstChild); pre_block.querySelector('.buttons').addEventListener('click', function (e) { if (e.target.classList.contains('fa-eye')) { e.target.classList.remove('fa-eye'); e.target.classList.add('fa-eye-slash'); e.target.title = 'Hide lines'; e.target.setAttribute('aria-label', e.target.title); block.classList.remove('hide-boring'); } else if (e.target.classList.contains('fa-eye-slash')) { e.target.classList.remove('fa-eye-slash'); e.target.classList.add('fa-eye'); e.target.title = 'Show hidden lines'; e.target.setAttribute('aria-label', e.target.title); block.classList.add('hide-boring'); } }); }); if (window.playground_copyable) { Array.from(document.querySelectorAll('pre code')).forEach(function (block) { var pre_block = block.parentNode; if (!pre_block.classList.contains('playground')) { var buttons = pre_block.querySelector(".buttons"); if (!buttons) { buttons = document.createElement('div'); buttons.className = 'buttons'; pre_block.insertBefore(buttons, pre_block.firstChild); } var clipButton = document.createElement('button'); clipButton.className = 'fa fa-copy clip-button'; clipButton.title = 'Copy to clipboard'; clipButton.setAttribute('aria-label', clipButton.title); clipButton.innerHTML = ''; buttons.insertBefore(clipButton, buttons.firstChild); } }); } // Process playground code blocks Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) { // Add play button var buttons = pre_block.querySelector(".buttons"); if (!buttons) { buttons = document.createElement('div'); buttons.className = 'buttons'; pre_block.insertBefore(buttons, pre_block.firstChild); } var runCodeButton = document.createElement('button'); runCodeButton.className = 'fa fa-play play-button'; runCodeButton.hidden = true; runCodeButton.title = 'Run this code'; runCodeButton.setAttribute('aria-label', runCodeButton.title); buttons.insertBefore(runCodeButton, buttons.firstChild); runCodeButton.addEventListener('click', function (e) { run_rust_code(pre_block); }); if (window.playground_copyable) { var copyCodeClipboardButton = document.createElement('button'); copyCodeClipboardButton.className = 'fa fa-copy clip-button'; copyCodeClipboardButton.innerHTML = ''; copyCodeClipboardButton.title = 'Copy to clipboard'; copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title); buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); } let code_block = pre_block.querySelector("code"); if (window.ace && code_block.classList.contains("editable")) { var undoChangesButton = document.createElement('button'); undoChangesButton.className = 'fa fa-history reset-button'; undoChangesButton.title = 'Undo changes'; undoChangesButton.setAttribute('aria-label', undoChangesButton.title); buttons.insertBefore(undoChangesButton, buttons.firstChild); undoChangesButton.addEventListener('click', function () { let editor = window.ace.edit(code_block); editor.setValue(editor.originalCode); editor.clearSelection(); }); } }); })(); (function themes() { var html = document.querySelector('html'); var themeToggleButton = document.getElementById('theme-toggle'); var themePopup = document.getElementById('theme-list'); var themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); var stylesheets = { ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"), tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"), highlight: document.querySelector("[href$='highlight.css']"), }; function showThemes() { themePopup.style.display = 'block'; themeToggleButton.setAttribute('aria-expanded', true); themePopup.querySelector("button#" + get_theme()).focus(); } function hideThemes() { themePopup.style.display = 'none'; themeToggleButton.setAttribute('aria-expanded', false); themeToggleButton.focus(); } function get_theme() { var theme; try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { } if (theme === null || theme === undefined) { return default_theme; } else { return theme; } } function set_theme(theme, store = true) { let ace_theme; if (theme == 'coal' || theme == 'navy') { stylesheets.ayuHighlight.disabled = true; stylesheets.tomorrowNight.disabled = false; stylesheets.highlight.disabled = true; ace_theme = "ace/theme/tomorrow_night"; } else if (theme == 'ayu') { stylesheets.ayuHighlight.disabled = false; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = true; ace_theme = "ace/theme/tomorrow_night"; } else { stylesheets.ayuHighlight.disabled = true; stylesheets.tomorrowNight.disabled = true; stylesheets.highlight.disabled = false; ace_theme = "ace/theme/dawn"; } setTimeout(function () { themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor; }, 1); if (window.ace && window.editors) { window.editors.forEach(function (editor) { editor.setTheme(ace_theme); }); } var previousTheme = get_theme(); if (store) { try { localStorage.setItem('mdbook-theme', theme); } catch (e) { } } html.classList.remove(previousTheme); html.classList.add(theme); } // Set theme var theme = get_theme(); set_theme(theme, false); themeToggleButton.addEventListener('click', function () { if (themePopup.style.display === 'block') { hideThemes(); } else { showThemes(); } }); themePopup.addEventListener('click', function (e) { var theme = e.target.id || e.target.parentElement.id; set_theme(theme); }); themePopup.addEventListener('focusout', function(e) { // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) { hideThemes(); } }); // Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628 document.addEventListener('click', function(e) { if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) { hideThemes(); } }); document.addEventListener('keydown', function (e) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } if (!themePopup.contains(e.target)) { return; } switch (e.key) { case 'Escape': e.preventDefault(); hideThemes(); break; case 'ArrowUp': e.preventDefault(); var li = document.activeElement.parentElement; if (li && li.previousElementSibling) { li.previousElementSibling.querySelector('button').focus(); } break; case 'ArrowDown': e.preventDefault(); var li = document.activeElement.parentElement; if (li && li.nextElementSibling) { li.nextElementSibling.querySelector('button').focus(); } break; case 'Home': e.preventDefault(); themePopup.querySelector('li:first-child button').focus(); break; case 'End': e.preventDefault(); themePopup.querySelector('li:last-child button').focus(); break; } }); })(); (function sidebar() { var html = document.querySelector("html"); var sidebar = document.getElementById("sidebar"); var sidebarLinks = document.querySelectorAll('#sidebar a'); var sidebarToggleButton = document.getElementById("sidebar-toggle"); var sidebarResizeHandle = document.getElementById("sidebar-resize-handle"); var firstContact = null; function showSidebar() { html.classList.remove('sidebar-hidden') html.classList.add('sidebar-visible'); Array.from(sidebarLinks).forEach(function (link) { link.setAttribute('tabIndex', 0); }); sidebarToggleButton.setAttribute('aria-expanded', true); sidebar.setAttribute('aria-hidden', false); try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { } } var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle'); function toggleSection(ev) { ev.currentTarget.parentElement.classList.toggle('expanded'); } Array.from(sidebarAnchorToggles).forEach(function (el) { el.addEventListener('click', toggleSection); }); function hideSidebar() { html.classList.remove('sidebar-visible') html.classList.add('sidebar-hidden'); Array.from(sidebarLinks).forEach(function (link) { link.setAttribute('tabIndex', -1); }); sidebarToggleButton.setAttribute('aria-expanded', false); sidebar.setAttribute('aria-hidden', true); try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { } } // Toggle sidebar sidebarToggleButton.addEventListener('click', function sidebarToggle() { if (html.classList.contains("sidebar-hidden")) { var current_width = parseInt( document.documentElement.style.getPropertyValue('--sidebar-width'), 10); if (current_width < 150) { document.documentElement.style.setProperty('--sidebar-width', '150px'); } showSidebar(); } else if (html.classList.contains("sidebar-visible")) { hideSidebar(); } else { if (getComputedStyle(sidebar)['transform'] === 'none') { hideSidebar(); } else { showSidebar(); } } }); sidebarResizeHandle.addEventListener('mousedown', initResize, false); function initResize(e) { window.addEventListener('mousemove', resize, false); window.addEventListener('mouseup', stopResize, false); html.classList.add('sidebar-resizing'); } function resize(e) { var pos = (e.clientX - sidebar.offsetLeft); if (pos < 20) { hideSidebar(); } else { if (html.classList.contains("sidebar-hidden")) { showSidebar(); } pos = Math.min(pos, window.innerWidth - 100); document.documentElement.style.setProperty('--sidebar-width', pos + 'px'); } } //on mouseup remove windows functions mousemove & mouseup function stopResize(e) { html.classList.remove('sidebar-resizing'); window.removeEventListener('mousemove', resize, false); window.removeEventListener('mouseup', stopResize, false); } document.addEventListener('touchstart', function (e) { firstContact = { x: e.touches[0].clientX, time: Date.now() }; }, { passive: true }); document.addEventListener('touchmove', function (e) { if (!firstContact) return; var curX = e.touches[0].clientX; var xDiff = curX - firstContact.x, tDiff = Date.now() - firstContact.time; if (tDiff < 250 && Math.abs(xDiff) >= 150) { if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) showSidebar(); else if (xDiff < 0 && curX < 300) hideSidebar(); firstContact = null; } }, { passive: true }); // Scroll sidebar to current active section var activeSection = document.getElementById("sidebar").querySelector(".active"); if (activeSection) { // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView activeSection.scrollIntoView({ block: 'center' }); } })(); (function chapterNavigation() { document.addEventListener('keydown', function (e) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } if (window.search && window.search.hasFocus()) { return; } switch (e.key) { case 'ArrowRight': e.preventDefault(); var nextButton = document.querySelector('.nav-chapters.next'); if (nextButton) { window.location.href = nextButton.href; } break; case 'ArrowLeft': e.preventDefault(); var previousButton = document.querySelector('.nav-chapters.previous'); if (previousButton) { window.location.href = previousButton.href; } break; } }); })(); (function clipboard() { var clipButtons = document.querySelectorAll('.clip-button'); function hideTooltip(elem) { elem.firstChild.innerText = ""; elem.className = 'fa fa-copy clip-button'; } function showTooltip(elem, msg) { elem.firstChild.innerText = msg; elem.className = 'fa fa-copy tooltipped'; } var clipboardSnippets = new ClipboardJS('.clip-button', { text: function (trigger) { hideTooltip(trigger); let playground = trigger.closest("pre"); return playground_text(playground); } }); Array.from(clipButtons).forEach(function (clipButton) { clipButton.addEventListener('mouseout', function (e) { hideTooltip(e.currentTarget); }); }); clipboardSnippets.on('success', function (e) { e.clearSelection(); showTooltip(e.trigger, "Copied!"); }); clipboardSnippets.on('error', function (e) { showTooltip(e.trigger, "Clipboard error!"); }); })(); (function scrollToTop () { var menuTitle = document.querySelector('.menu-title'); menuTitle.addEventListener('click', function () { document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' }); }); })(); (function controllMenu() { var menu = document.getElementById('menu-bar'); (function controllPosition() { var scrollTop = document.scrollingElement.scrollTop; var prevScrollTop = scrollTop; var minMenuY = -menu.clientHeight - 50; // When the script loads, the page can be at any scroll (e.g. if you reforesh it). menu.style.top = scrollTop + 'px'; // Same as parseInt(menu.style.top.slice(0, -2), but faster var topCache = menu.style.top.slice(0, -2); menu.classList.remove('sticky'); var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster document.addEventListener('scroll', function () { scrollTop = Math.max(document.scrollingElement.scrollTop, 0); // `null` means that it doesn't need to be updated var nextSticky = null; var nextTop = null; var scrollDown = scrollTop > prevScrollTop; var menuPosAbsoluteY = topCache - scrollTop; if (scrollDown) { nextSticky = false; if (menuPosAbsoluteY > 0) { nextTop = prevScrollTop; } } else { if (menuPosAbsoluteY > 0) { nextSticky = true; } else if (menuPosAbsoluteY < minMenuY) { nextTop = prevScrollTop + minMenuY; } } if (nextSticky === true && stickyCache === false) { menu.classList.add('sticky'); stickyCache = true; } else if (nextSticky === false && stickyCache === true) { menu.classList.remove('sticky'); stickyCache = false; } if (nextTop !== null) { menu.style.top = nextTop + 'px'; topCache = nextTop; } prevScrollTop = scrollTop; }, { passive: true }); })(); (function controllBorder() { menu.classList.remove('bordered'); document.addEventListener('scroll', function () { if (menu.offsetTop === 0) { menu.classList.remove('bordered'); } else { menu.classList.add('bordered'); } }, { passive: true }); })(); })(); ================================================ FILE: docs/css/chrome.css ================================================ /* CSS for UI elements (a.k.a. chrome) */ @import 'variables.css'; ::-webkit-scrollbar { background: var(--bg); } ::-webkit-scrollbar-thumb { background: var(--scrollbar); } html { scrollbar-color: var(--scrollbar) var(--bg); } #searchresults a, .content a:link, a:visited, a > .hljs { color: var(--links); } /* Menu Bar */ #menu-bar, #menu-bar-hover-placeholder { z-index: 101; margin: auto calc(0px - var(--page-padding)); } #menu-bar { position: relative; display: flex; flex-wrap: wrap; background-color: var(--bg); border-bottom-color: var(--bg); border-bottom-width: 1px; border-bottom-style: solid; } #menu-bar.sticky, .js #menu-bar-hover-placeholder:hover + #menu-bar, .js #menu-bar:hover, .js.sidebar-visible #menu-bar { position: -webkit-sticky; position: sticky; top: 0 !important; } #menu-bar-hover-placeholder { position: sticky; position: -webkit-sticky; top: 0; height: var(--menu-bar-height); } #menu-bar.bordered { border-bottom-color: var(--table-border-color); } #menu-bar i, #menu-bar .icon-button { position: relative; padding: 0 8px; z-index: 10; line-height: var(--menu-bar-height); cursor: pointer; transition: color 0.5s; } @media only screen and (max-width: 420px) { #menu-bar i, #menu-bar .icon-button { padding: 0 5px; } } .icon-button { border: none; background: none; padding: 0; color: inherit; } .icon-button i { margin: 0; } .right-buttons { margin: 0 15px; } .right-buttons a { text-decoration: none; } .left-buttons { display: flex; margin: 0 5px; } .no-js .left-buttons { display: none; } .menu-title { display: inline-block; font-weight: 200; font-size: 2.4rem; line-height: var(--menu-bar-height); text-align: center; margin: 0; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .js .menu-title { cursor: pointer; } .menu-bar, .menu-bar:visited, .nav-chapters, .nav-chapters:visited, .mobile-nav-chapters, .mobile-nav-chapters:visited, .menu-bar .icon-button, .menu-bar a i { color: var(--icons); } .menu-bar i:hover, .menu-bar .icon-button:hover, .nav-chapters:hover, .mobile-nav-chapters i:hover { color: var(--icons-hover); } /* Nav Icons */ .nav-chapters { font-size: 2.5em; text-align: center; text-decoration: none; position: fixed; top: 0; bottom: 0; margin: 0; max-width: 150px; min-width: 90px; display: flex; justify-content: center; align-content: center; flex-direction: column; transition: color 0.5s, background-color 0.5s; } .nav-chapters:hover { text-decoration: none; background-color: var(--theme-hover); transition: background-color 0.15s, color 0.15s; } .nav-wrapper { margin-top: 50px; display: none; } .mobile-nav-chapters { font-size: 2.5em; text-align: center; text-decoration: none; width: 90px; border-radius: 5px; background-color: var(--sidebar-bg); } .previous { float: left; } .next { float: right; right: var(--page-padding); } @media only screen and (max-width: 1080px) { .nav-wide-wrapper { display: none; } .nav-wrapper { display: block; } } @media only screen and (max-width: 1380px) { .sidebar-visible .nav-wide-wrapper { display: none; } .sidebar-visible .nav-wrapper { display: block; } } /* Inline code */ :not(pre) > .hljs { display: inline; padding: 0.1em 0.3em; border-radius: 3px; } :not(pre):not(a) > .hljs { color: var(--inline-code-color); overflow-x: initial; } a:hover > .hljs { text-decoration: underline; } pre { position: relative; } pre > .buttons { position: absolute; z-index: 100; right: 5px; top: 5px; color: var(--sidebar-fg); cursor: pointer; } pre > .buttons :hover { color: var(--sidebar-active); } pre > .buttons i { margin-left: 8px; } pre > .buttons button { color: inherit; background: transparent; border: none; cursor: inherit; } pre > .result { margin-top: 10px; } /* Search */ #searchresults a { text-decoration: none; } mark { border-radius: 2px; padding: 0 3px 1px 3px; margin: 0 -3px -1px -3px; background-color: var(--search-mark-bg); transition: background-color 300ms linear; cursor: pointer; } mark.fade-out { background-color: rgba(0,0,0,0) !important; cursor: auto; } .searchbar-outer { margin-left: auto; margin-right: auto; max-width: var(--content-max-width); } #searchbar { width: 100%; margin: 5px auto 0px auto; padding: 10px 16px; transition: box-shadow 300ms ease-in-out; border: 1px solid var(--searchbar-border-color); border-radius: 3px; background-color: var(--searchbar-bg); color: var(--searchbar-fg); } #searchbar:focus, #searchbar.active { box-shadow: 0 0 3px var(--searchbar-shadow-color); } .searchresults-header { font-weight: bold; font-size: 1em; padding: 18px 0 0 5px; color: var(--searchresults-header-fg); } .searchresults-outer { margin-left: auto; margin-right: auto; max-width: var(--content-max-width); border-bottom: 1px dashed var(--searchresults-border-color); } ul#searchresults { list-style: none; padding-left: 20px; } ul#searchresults li { margin: 10px 0px; padding: 2px; border-radius: 2px; } ul#searchresults li.focus { background-color: var(--searchresults-li-bg); } ul#searchresults span.teaser { display: block; clear: both; margin: 5px 0 0 20px; font-size: 0.8em; } ul#searchresults span.teaser em { font-weight: bold; font-style: normal; } /* Sidebar */ .sidebar { position: fixed; left: 0; top: 0; bottom: 0; width: var(--sidebar-width); font-size: 0.875em; box-sizing: border-box; -webkit-overflow-scrolling: touch; overscroll-behavior-y: contain; background-color: var(--sidebar-bg); color: var(--sidebar-fg); } .sidebar-resizing { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; } .js:not(.sidebar-resizing) .sidebar { transition: transform 0.3s; /* Animation: slide away */ } .sidebar code { line-height: 2em; } .sidebar .sidebar-scrollbox { overflow-y: auto; position: absolute; top: 0; bottom: 0; left: 0; right: 0; padding: 10px 10px; } .sidebar .sidebar-resize-handle { position: absolute; cursor: col-resize; width: 0; right: 0; top: 0; bottom: 0; } .js .sidebar .sidebar-resize-handle { cursor: col-resize; width: 5px; } .sidebar-hidden .sidebar { transform: translateX(calc(0px - var(--sidebar-width))); } .sidebar::-webkit-scrollbar { background: var(--sidebar-bg); } .sidebar::-webkit-scrollbar-thumb { background: var(--scrollbar); } .sidebar-visible .page-wrapper { transform: translateX(var(--sidebar-width)); } @media only screen and (min-width: 620px) { .sidebar-visible .page-wrapper { transform: none; margin-left: var(--sidebar-width); } } .chapter { list-style: none outside none; padding-left: 0; line-height: 2.2em; } .chapter ol { width: 100%; } .chapter li { display: flex; color: var(--sidebar-non-existant); } .chapter li a { display: block; padding: 0; text-decoration: none; color: var(--sidebar-fg); } .chapter li a:hover { color: var(--sidebar-active); } .chapter li a.active { color: var(--sidebar-active); } .chapter li > a.toggle { cursor: pointer; display: block; margin-left: auto; padding: 0 10px; user-select: none; opacity: 0.68; } .chapter li > a.toggle div { transition: transform 0.5s; } /* collapse the section */ .chapter li:not(.expanded) + li > ol { display: none; } .chapter li.chapter-item { line-height: 1.5em; margin-top: 0.6em; } .chapter li.expanded > a.toggle div { transform: rotate(90deg); } .spacer { width: 100%; height: 3px; margin: 5px 0px; } .chapter .spacer { background-color: var(--sidebar-spacer); } @media (-moz-touch-enabled: 1), (pointer: coarse) { .chapter li a { padding: 5px 0; } .spacer { margin: 10px 0; } } .section { list-style: none outside none; padding-left: 20px; line-height: 1.9em; } /* Theme Menu Popup */ .theme-popup { position: absolute; left: 10px; top: var(--menu-bar-height); z-index: 1000; border-radius: 4px; font-size: 0.7em; color: var(--fg); background: var(--theme-popup-bg); border: 1px solid var(--theme-popup-border); margin: 0; padding: 0; list-style: none; display: none; } .theme-popup .default { color: var(--icons); } .theme-popup .theme { width: 100%; border: 0; margin: 0; padding: 2px 10px; line-height: 25px; white-space: nowrap; text-align: left; cursor: pointer; color: inherit; background: inherit; font-size: inherit; } .theme-popup .theme:hover { background-color: var(--theme-hover); } .theme-popup .theme:hover:first-child, .theme-popup .theme:hover:last-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } ================================================ FILE: docs/css/general.css ================================================ /* Base styles and content styles */ @import 'variables.css'; :root { /* Browser default font-size is 16px, this way 1 rem = 10px */ font-size: 62.5%; } html { font-family: "Open Sans", sans-serif; color: var(--fg); background-color: var(--bg); text-size-adjust: none; } body { margin: 0; font-size: 1.6rem; overflow-x: hidden; } code { font-family: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace !important; font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */ } /* Don't change font size in headers. */ h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { font-size: unset; } .left { float: left; } .right { float: right; } .boring { opacity: 0.6; } .hide-boring .boring { display: none; } .hidden { display: none !important; } h2, h3 { margin-top: 2.5em; } h4, h5 { margin-top: 2em; } .header + .header h3, .header + .header h4, .header + .header h5 { margin-top: 1em; } h1:target::before, h2:target::before, h3:target::before, h4:target::before, h5:target::before, h6:target::before { display: inline-block; content: "»"; margin-left: -30px; width: 30px; } /* This is broken on Safari as of version 14, but is fixed in Safari Technology Preview 117 which I think will be Safari 14.2. https://bugs.webkit.org/show_bug.cgi?id=218076 */ :target { scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); } .page { outline: 0; padding: 0 var(--page-padding); margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */ } .page-wrapper { box-sizing: border-box; } .js:not(.sidebar-resizing) .page-wrapper { transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ } .content { overflow-y: auto; padding: 0 15px; padding-bottom: 50px; } .content main { margin-left: auto; margin-right: auto; max-width: var(--content-max-width); } .content p { line-height: 1.45em; } .content ol { line-height: 1.45em; } .content ul { line-height: 1.45em; } .content a { text-decoration: none; } .content a:hover { text-decoration: underline; } .content img, .content video { max-width: 100%; } .content .header:link, .content .header:visited { color: var(--fg); } .content .header:link, .content .header:visited:hover { text-decoration: none; } table { margin: 0 auto; border-collapse: collapse; } table td { padding: 3px 20px; border: 1px var(--table-border-color) solid; } table thead { background: var(--table-header-bg); } table thead td { font-weight: 700; border: none; } table thead th { padding: 3px 20px; } table thead tr { border: 1px var(--table-header-bg) solid; } /* Alternate background colors for rows */ table tbody tr:nth-child(2n) { background: var(--table-alternate-bg); } blockquote { margin: 20px 0; padding: 0 20px; color: var(--fg); background-color: var(--quote-bg); border-top: .1em solid var(--quote-border); border-bottom: .1em solid var(--quote-border); } :not(.footnote-definition) + .footnote-definition, .footnote-definition + :not(.footnote-definition) { margin-top: 2em; } .footnote-definition { font-size: 0.9em; margin: 0.5em 0; } .footnote-definition p { display: inline; } .tooltiptext { position: absolute; visibility: hidden; color: #fff; background-color: #333; transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ left: -8px; /* Half of the width of the icon */ top: -35px; font-size: 0.8em; text-align: center; border-radius: 6px; padding: 5px 8px; margin: 5px; z-index: 1000; } .tooltipped .tooltiptext { visibility: visible; } .chapter li.part-title { color: var(--sidebar-fg); margin: 5px 0px; font-weight: bold; } .result-no-output { font-style: italic; } ================================================ FILE: docs/css/print.css ================================================ #sidebar, #menu-bar, .nav-chapters, .mobile-nav-chapters { display: none; } #page-wrapper.page-wrapper { transform: none; margin-left: 0px; overflow-y: initial; } #content { max-width: none; margin: 0; padding: 0; } .page { overflow-y: initial; } code { background-color: #666666; border-radius: 5px; /* Force background to be printed in Chrome */ -webkit-print-color-adjust: exact; } pre > .buttons { z-index: 2; } a, a:visited, a:active, a:hover { color: #4183c4; text-decoration: none; } h1, h2, h3, h4, h5, h6 { page-break-inside: avoid; page-break-after: avoid; } pre, code { page-break-inside: avoid; white-space: pre-wrap; } .fa { display: none !important; } ================================================ FILE: docs/css/variables.css ================================================ /* Globals */ :root { --sidebar-width: 300px; --page-padding: 15px; --content-max-width: 750px; --menu-bar-height: 50px; } /* Themes */ .ayu { --bg: hsl(210, 25%, 8%); --fg: #c5c5c5; --sidebar-bg: #14191f; --sidebar-fg: #c8c9db; --sidebar-non-existant: #5c6773; --sidebar-active: #ffb454; --sidebar-spacer: #2d334f; --scrollbar: var(--sidebar-fg); --icons: #737480; --icons-hover: #b7b9cc; --links: #0096cf; --inline-code-color: #ffb454; --theme-popup-bg: #14191f; --theme-popup-border: #5c6773; --theme-hover: #191f26; --quote-bg: hsl(226, 15%, 17%); --quote-border: hsl(226, 15%, 22%); --table-border-color: hsl(210, 25%, 13%); --table-header-bg: hsl(210, 25%, 28%); --table-alternate-bg: hsl(210, 25%, 11%); --searchbar-border-color: #848484; --searchbar-bg: #424242; --searchbar-fg: #fff; --searchbar-shadow-color: #d4c89f; --searchresults-header-fg: #666; --searchresults-border-color: #888; --searchresults-li-bg: #252932; --search-mark-bg: #e3b171; } .coal { --bg: hsl(200, 7%, 8%); --fg: #98a3ad; --sidebar-bg: #292c2f; --sidebar-fg: #a1adb8; --sidebar-non-existant: #505254; --sidebar-active: #3473ad; --sidebar-spacer: #393939; --scrollbar: var(--sidebar-fg); --icons: #43484d; --icons-hover: #b3c0cc; --links: #2b79a2; --inline-code-color: #c5c8c6;; --theme-popup-bg: #141617; --theme-popup-border: #43484d; --theme-hover: #1f2124; --quote-bg: hsl(234, 21%, 18%); --quote-border: hsl(234, 21%, 23%); --table-border-color: hsl(200, 7%, 13%); --table-header-bg: hsl(200, 7%, 28%); --table-alternate-bg: hsl(200, 7%, 11%); --searchbar-border-color: #aaa; --searchbar-bg: #b7b7b7; --searchbar-fg: #000; --searchbar-shadow-color: #aaa; --searchresults-header-fg: #666; --searchresults-border-color: #98a3ad; --searchresults-li-bg: #2b2b2f; --search-mark-bg: #355c7d; } .light { --bg: hsl(0, 0%, 100%); --fg: hsl(0, 0%, 0%); --sidebar-bg: #fafafa; --sidebar-fg: hsl(0, 0%, 0%); --sidebar-non-existant: #aaaaaa; --sidebar-active: #1f1fff; --sidebar-spacer: #f4f4f4; --scrollbar: #8F8F8F; --icons: #747474; --icons-hover: #000000; --links: #20609f; --inline-code-color: #301900; --theme-popup-bg: #fafafa; --theme-popup-border: #cccccc; --theme-hover: #e6e6e6; --quote-bg: hsl(197, 37%, 96%); --quote-border: hsl(197, 37%, 91%); --table-border-color: hsl(0, 0%, 95%); --table-header-bg: hsl(0, 0%, 80%); --table-alternate-bg: hsl(0, 0%, 97%); --searchbar-border-color: #aaa; --searchbar-bg: #fafafa; --searchbar-fg: #000; --searchbar-shadow-color: #aaa; --searchresults-header-fg: #666; --searchresults-border-color: #888; --searchresults-li-bg: #e4f2fe; --search-mark-bg: #a2cff5; } .navy { --bg: hsl(226, 23%, 11%); --fg: #bcbdd0; --sidebar-bg: #282d3f; --sidebar-fg: #c8c9db; --sidebar-non-existant: #505274; --sidebar-active: #2b79a2; --sidebar-spacer: #2d334f; --scrollbar: var(--sidebar-fg); --icons: #737480; --icons-hover: #b7b9cc; --links: #2b79a2; --inline-code-color: #c5c8c6;; --theme-popup-bg: #161923; --theme-popup-border: #737480; --theme-hover: #282e40; --quote-bg: hsl(226, 15%, 17%); --quote-border: hsl(226, 15%, 22%); --table-border-color: hsl(226, 23%, 16%); --table-header-bg: hsl(226, 23%, 31%); --table-alternate-bg: hsl(226, 23%, 14%); --searchbar-border-color: #aaa; --searchbar-bg: #aeaec6; --searchbar-fg: #000; --searchbar-shadow-color: #aaa; --searchresults-header-fg: #5f5f71; --searchresults-border-color: #5c5c68; --searchresults-li-bg: #242430; --search-mark-bg: #a2cff5; } .rust { --bg: hsl(60, 9%, 87%); --fg: #262625; --sidebar-bg: #3b2e2a; --sidebar-fg: #c8c9db; --sidebar-non-existant: #505254; --sidebar-active: #e69f67; --sidebar-spacer: #45373a; --scrollbar: var(--sidebar-fg); --icons: #737480; --icons-hover: #262625; --links: #2b79a2; --inline-code-color: #6e6b5e; --theme-popup-bg: #e1e1db; --theme-popup-border: #b38f6b; --theme-hover: #99908a; --quote-bg: hsl(60, 5%, 75%); --quote-border: hsl(60, 5%, 70%); --table-border-color: hsl(60, 9%, 82%); --table-header-bg: #b3a497; --table-alternate-bg: hsl(60, 9%, 84%); --searchbar-border-color: #aaa; --searchbar-bg: #fafafa; --searchbar-fg: #000; --searchbar-shadow-color: #aaa; --searchresults-header-fg: #666; --searchresults-border-color: #888; --searchresults-li-bg: #dec2a2; --search-mark-bg: #e69f67; } @media (prefers-color-scheme: dark) { .light.no-js { --bg: hsl(200, 7%, 8%); --fg: #98a3ad; --sidebar-bg: #292c2f; --sidebar-fg: #a1adb8; --sidebar-non-existant: #505254; --sidebar-active: #3473ad; --sidebar-spacer: #393939; --scrollbar: var(--sidebar-fg); --icons: #43484d; --icons-hover: #b3c0cc; --links: #2b79a2; --inline-code-color: #c5c8c6;; --theme-popup-bg: #141617; --theme-popup-border: #43484d; --theme-hover: #1f2124; --quote-bg: hsl(234, 21%, 18%); --quote-border: hsl(234, 21%, 23%); --table-border-color: hsl(200, 7%, 13%); --table-header-bg: hsl(200, 7%, 28%); --table-alternate-bg: hsl(200, 7%, 11%); --searchbar-border-color: #aaa; --searchbar-bg: #b7b7b7; --searchbar-fg: #000; --searchbar-shadow-color: #aaa; --searchresults-header-fg: #666; --searchresults-border-color: #98a3ad; --searchresults-li-bg: #2b2b2f; --search-mark-bg: #355c7d; } } ================================================ FILE: docs/fonts/OPEN-SANS-LICENSE.txt ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: docs/fonts/SOURCE-CODE-PRO-LICENSE.txt ================================================ Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. ================================================ FILE: docs/fonts/fonts.css ================================================ /* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ /* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ /* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url('open-sans-v17-all-charsets-300.woff2') format('woff2'); } /* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 300; src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), url('open-sans-v17-all-charsets-300italic.woff2') format('woff2'); } /* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('open-sans-v17-all-charsets-regular.woff2') format('woff2'); } /* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; src: local('Open Sans Italic'), local('OpenSans-Italic'), url('open-sans-v17-all-charsets-italic.woff2') format('woff2'); } /* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), url('open-sans-v17-all-charsets-600.woff2') format('woff2'); } /* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), url('open-sans-v17-all-charsets-600italic.woff2') format('woff2'); } /* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local('Open Sans Bold'), local('OpenSans-Bold'), url('open-sans-v17-all-charsets-700.woff2') format('woff2'); } /* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), url('open-sans-v17-all-charsets-700italic.woff2') format('woff2'); } /* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 800; src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), url('open-sans-v17-all-charsets-800.woff2') format('woff2'); } /* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 800; src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), url('open-sans-v17-all-charsets-800italic.woff2') format('woff2'); } /* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 500; src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2'); } ================================================ FILE: docs/highlight.css ================================================ /* * An increased contrast highlighting scheme loosely based on the * "Base16 Atelier Dune Light" theme by Bram de Haan * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) * Original Base16 color scheme by Chris Kempson * (https://github.com/chriskempson/base16) */ /* Comment */ .hljs-comment, .hljs-quote { color: #575757; } /* Red */ .hljs-variable, .hljs-template-variable, .hljs-attribute, .hljs-tag, .hljs-name, .hljs-regexp, .hljs-link, .hljs-name, .hljs-selector-id, .hljs-selector-class { color: #d70025; } /* Orange */ .hljs-number, .hljs-meta, .hljs-built_in, .hljs-builtin-name, .hljs-literal, .hljs-type, .hljs-params { color: #b21e00; } /* Green */ .hljs-string, .hljs-symbol, .hljs-bullet { color: #008200; } /* Blue */ .hljs-title, .hljs-section { color: #0030f2; } /* Purple */ .hljs-keyword, .hljs-selector-tag { color: #9d00ec; } .hljs { display: block; overflow-x: auto; background: #f6f7f6; color: #000; padding: 0.5em; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } .hljs-addition { color: #22863a; background-color: #f0fff4; } .hljs-deletion { color: #b31d28; background-color: #ffeef0; } ================================================ FILE: docs/highlight.js ================================================ /*! Highlight.js v11.0.0 (git: 21857218b9) (c) 2006-2021 Ivan Sagalaev and other contributors License: BSD-3-Clause */ var hljs=function(){"use strict";var e={exports:{}};function n(e){ return e instanceof Map?e.clear=e.delete=e.set=()=>{ throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ throw Error("set is read-only") }),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((s=>{var t=e[s] ;"object"!=typeof t||Object.isFrozen(t)||n(t)})),e} e.exports=n,e.exports.default=n;var s=e.exports;class t{constructor(e){ void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} ignoreMatch(){this.isMatchIgnored=!0}}function a(e){ return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") }function i(e,...n){const s=Object.create(null);for(const n in e)s[n]=e[n] ;return n.forEach((e=>{for(const n in e)s[n]=e[n]})),s}const r=e=>!!e.kind ;class o{constructor(e,n){ this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){ this.buffer+=a(e)}openNode(e){if(!r(e))return;let n=e.kind ;n=e.sublanguage?"language-"+n:((e,{prefix:n})=>{if(e.includes(".")){ const s=e.split(".") ;return[`${n}${s.shift()}`,...s.map(((e,n)=>`${e}${"_".repeat(n+1)}`))].join(" ") }return`${n}${e}`})(n,{prefix:this.classPrefix}),this.span(n)}closeNode(e){ r(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ this.buffer+=``}}class c{constructor(){this.rootNode={ children:[]},this.stack=[this.rootNode]}get top(){ return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ this.top.children.push(e)}openNode(e){const n={kind:e,children:[]} ;this.add(n),this.stack.push(n)}closeNode(){ if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){ return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n), n.children.forEach((n=>this._walk(e,n))),e.closeNode(n)),e}static _collapse(e){ "string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ c._collapse(e)})))}}class l extends c{constructor(e){super(),this.options=e} addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())} addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const s=e.root ;s.kind=n,s.sublanguage=!0,this.add(s)}toHTML(){ return new o(this,this.options).value()}finalize(){return!0}}function d(e){ return e?"string"==typeof e?e:e.source:null}function p(e){return u("(?=",e,")")} function m(e){return u("(?:",e,")?")}function u(...e){ return e.map((e=>d(e))).join("")}function b(...e){return"("+((e=>{ const n=e[e.length-1] ;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} })(e).capture?"":"?:")+e.map((e=>d(e))).join("|")+")"}function g(e){ return RegExp(e.toString()+"|").exec("").length-1} const v=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ ;function _(e,{joinWith:n}){let s=0;return e.map((e=>{s+=1;const n=s ;let t=d(e),a="";for(;t.length>0;){const e=v.exec(t);if(!e){a+=t;break} a+=t.substring(0,e.index), t=t.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?a+="\\"+(Number(e[1])+n):(a+=e[0], "("===e[0]&&s++)}return a})).map((e=>`(${e})`)).join(n)} const f="[a-zA-Z]\\w*",h="[a-zA-Z_]\\w*",E="\\b\\d+(\\.\\d+)?",w="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",N="\\b(0b[01]+)",y={ begin:"\\\\[\\s\\S]",relevance:0},x={scope:"string",begin:"'",end:"'", illegal:"\\n",contains:[y]},O={scope:"string",begin:'"',end:'"',illegal:"\\n", contains:[y]},M=(e,n,s={})=>{const t=i({scope:"comment",begin:e,end:n, contains:[]},s);t.contains.push({scope:"doctag", begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) ;const a=b("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) ;return t.contains.push({begin:u(/[ ]+/,"(",a,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),t },A=M("//","$"),k=M("/\\*","\\*/"),S=M("#","$");var C=Object.freeze({ __proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:f,UNDERSCORE_IDENT_RE:h, NUMBER_RE:E,C_NUMBER_RE:w,BINARY_NUMBER_RE:N, RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", SHEBANG:(e={})=>{const n=/^#![ ]*\// ;return e.binary&&(e.begin=u(n,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:n, end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)}, BACKSLASH_ESCAPE:y,APOS_STRING_MODE:x,QUOTE_STRING_MODE:O,PHRASAL_WORDS_MODE:{ begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ },COMMENT:M,C_LINE_COMMENT_MODE:A,C_BLOCK_COMMENT_MODE:k,HASH_COMMENT_MODE:S, NUMBER_MODE:{scope:"number",begin:E,relevance:0},C_NUMBER_MODE:{scope:"number", begin:w,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:N,relevance:0}, REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//, end:/\/[gimuy]*/,illegal:/\n/,contains:[y,{begin:/\[/,end:/\]/,relevance:0, contains:[y]}]}]},TITLE_MODE:{scope:"title",begin:f,relevance:0}, UNDERSCORE_TITLE_MODE:{scope:"title",begin:h,relevance:0},METHOD_GUARD:{ begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ "on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{ n.data._beginMatch!==e[1]&&n.ignoreMatch()}})});function q(e,n){ "."===e.input[e.index-1]&&n.ignoreMatch()}function T(e,n){ void 0!==e.className&&(e.scope=e.className,delete e.className)}function R(e,n){ n&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", e.__beforeBegin=q,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, void 0===e.relevance&&(e.relevance=0))}function D(e,n){ Array.isArray(e.illegal)&&(e.illegal=b(...e.illegal))}function I(e,n){ if(e.match){ if(e.begin||e.end)throw Error("begin & end are not supported with match") ;e.begin=e.match,delete e.match}}function L(e,n){ void 0===e.relevance&&(e.relevance=1)}const B=(e,n)=>{if(!e.beforeMatch)return ;if(e.starts)throw Error("beforeMatch cannot be used with starts") ;const s=Object.assign({},e);Object.keys(e).forEach((n=>{delete e[n] })),e.keywords=s.keywords,e.begin=u(s.beforeMatch,p(s.begin)),e.starts={ relevance:0,contains:[Object.assign(s,{endsParent:!0})] },e.relevance=0,delete s.beforeMatch },z=["of","and","for","in","not","or","if","then","parent","list","value"] ;function $(e,n,s="keyword"){const t=Object.create(null) ;return"string"==typeof e?a(s,e.split(" ")):Array.isArray(e)?a(s,e):Object.keys(e).forEach((s=>{ Object.assign(t,$(e[s],n,s))})),t;function a(e,s){ n&&(s=s.map((e=>e.toLowerCase()))),s.forEach((n=>{const s=n.split("|") ;t[s[0]]=[e,F(s[0],s[1])]}))}}function F(e,n){ return n?Number(n):(e=>z.includes(e.toLowerCase()))(e)?0:1}const U={},j=e=>{ console.error(e)},P=(e,...n)=>{console.log("WARN: "+e,...n)},K=(e,n)=>{ U[`${e}/${n}`]||(console.log(`Deprecated as of ${e}. ${n}`),U[`${e}/${n}`]=!0) },H=Error();function G(e,n,{key:s}){let t=0;const a=e[s],i={},r={} ;for(let e=1;e<=n.length;e++)r[e+t]=a[e],i[e+t]=!0,t+=g(n[e-1]) ;e[s]=r,e[s]._emit=i,e[s]._multi=!0}function Z(e){(e=>{ e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ _wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope }),(e=>{if(Array.isArray(e.begin)){ if(e.skip||e.excludeBegin||e.returnBegin)throw j("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), H ;if("object"!=typeof e.beginScope||null===e.beginScope)throw j("beginScope must be object"), H;G(e,e.begin,{key:"beginScope"}),e.begin=_(e.begin,{joinWith:""})}})(e),(e=>{ if(Array.isArray(e.end)){ if(e.skip||e.excludeEnd||e.returnEnd)throw j("skip, excludeEnd, returnEnd not compatible with endScope: {}"), H ;if("object"!=typeof e.endScope||null===e.endScope)throw j("endScope must be object"), H;G(e,e.end,{key:"endScope"}),e.end=_(e.end,{joinWith:""})}})(e)}function W(e){ function n(n,s){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(s?"g":""))} class s{constructor(){ this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} addRule(e,n){ n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]), this.matchAt+=g(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) ;const e=this.regexes.map((e=>e[1]));this.matcherRe=n(_(e,{joinWith:"|" }),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex ;const n=this.matcherRe.exec(e);if(!n)return null ;const s=n.findIndex(((e,n)=>n>0&&void 0!==e)),t=this.matchIndexes[s] ;return n.splice(0,s),Object.assign(n,t)}}class t{constructor(){ this.rules=[],this.multiRegexes=[], this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ if(this.multiRegexes[e])return this.multiRegexes[e];const n=new s ;return this.rules.slice(e).forEach((([e,s])=>n.addRule(e,s))), n.compile(),this.multiRegexes[e]=n,n}resumingScanAtSamePosition(){ return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){ this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){ const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex ;let s=n.exec(e) ;if(this.resumingScanAtSamePosition())if(s&&s.index===this.lastIndex);else{ const n=this.getMatcher(0);n.lastIndex=this.lastIndex+1,s=n.exec(e)} return s&&(this.regexIndex+=s.position+1, this.regexIndex===this.count&&this.considerAll()),s}} if(e.compilerExtensions||(e.compilerExtensions=[]), e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") ;return e.classNameAliases=i(e.classNameAliases||{}),function s(a,r){const o=a ;if(a.isCompiled)return o ;[T,I,Z,B].forEach((e=>e(a,r))),e.compilerExtensions.forEach((e=>e(a,r))), a.__beforeBegin=null,[R,D,L].forEach((e=>e(a,r))),a.isCompiled=!0;let c=null ;return"object"==typeof a.keywords&&a.keywords.$pattern&&(a.keywords=Object.assign({},a.keywords), c=a.keywords.$pattern, delete a.keywords.$pattern),c=c||/\w+/,a.keywords&&(a.keywords=$(a.keywords,e.case_insensitive)), o.keywordPatternRe=n(c,!0), r&&(a.begin||(a.begin=/\B|\b/),o.beginRe=n(a.begin),a.end||a.endsWithParent||(a.end=/\B|\b/), a.end&&(o.endRe=n(a.end)), o.terminatorEnd=d(a.end)||"",a.endsWithParent&&r.terminatorEnd&&(o.terminatorEnd+=(a.end?"|":"")+r.terminatorEnd)), a.illegal&&(o.illegalRe=n(a.illegal)), a.contains||(a.contains=[]),a.contains=[].concat(...a.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((n=>i(e,{ variants:null},n)))),e.cachedVariants?e.cachedVariants:Q(e)?i(e,{ starts:e.starts?i(e.starts):null }):Object.isFrozen(e)?i(e):e))("self"===e?a:e)))),a.contains.forEach((e=>{s(e,o) })),a.starts&&s(a.starts,r),o.matcher=(e=>{const n=new t ;return e.contains.forEach((e=>n.addRule(e.begin,{rule:e,type:"begin" }))),e.terminatorEnd&&n.addRule(e.terminatorEnd,{type:"end" }),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n})(o),o}(e)}function Q(e){ return!!e&&(e.endsWithParent||Q(e.starts))}const V=a,X=i,Y=Symbol("nomatch") ;var J=(e=>{const n=Object.create(null),a=Object.create(null),i=[];let r=!0 ;const o="Could not find the language '{}', did you forget to load/include a language module?",c={ disableAutodetect:!0,name:"Plain text",contains:[]};let d={ ignoreUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", cssSelector:"pre code",languages:null,__emitter:l};function p(e){ return d.noHighlightRe.test(e)}function m(e,n,s,t){let a="",i="" ;"object"==typeof n?(a=e, s=n.ignoreIllegals,i=n.language,t=void 0):(K("10.7.0","highlight(lang, code, ...args) has been deprecated."), K("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), i=e,a=n),void 0===s&&(s=!0);const r={code:a,language:i};w("before:highlight",r) ;const o=r.result?r.result:u(r.language,r.code,s,t) ;return o.code=r.code,w("after:highlight",o),o}function u(e,s,a,i){ const c=Object.create(null);function l(){if(!O.keywords)return void A.addText(k) ;let e=0;O.keywordPatternRe.lastIndex=0;let n=O.keywordPatternRe.exec(k),s="" ;for(;n;){s+=k.substring(e,n.index) ;const a=N.case_insensitive?n[0].toLowerCase():n[0],i=(t=a,O.keywords[t]);if(i){ const[e,t]=i ;if(A.addText(s),s="",c[a]=(c[a]||0)+1,c[a]<=7&&(S+=t),e.startsWith("_"))s+=n[0];else{ const s=N.classNameAliases[e]||e;A.addKeyword(n[0],s)}}else s+=n[0] ;e=O.keywordPatternRe.lastIndex,n=O.keywordPatternRe.exec(k)}var t ;s+=k.substr(e),A.addText(s)}function p(){null!=O.subLanguage?(()=>{ if(""===k)return;let e=null;if("string"==typeof O.subLanguage){ if(!n[O.subLanguage])return void A.addText(k) ;e=u(O.subLanguage,k,!0,M[O.subLanguage]),M[O.subLanguage]=e._top }else e=b(k,O.subLanguage.length?O.subLanguage:null) ;O.relevance>0&&(S+=e.relevance),A.addSublanguage(e._emitter,e.language) })():l(),k=""}function m(e,n){let s=1;for(;void 0!==n[s];){if(!e._emit[s]){s++ ;continue}const t=N.classNameAliases[e[s]]||e[s],a=n[s] ;t?A.addKeyword(a,t):(k=a,l(),k=""),s++}}function g(e,n){ return e.scope&&"string"==typeof e.scope&&A.openNode(N.classNameAliases[e.scope]||e.scope), e.beginScope&&(e.beginScope._wrap?(A.addKeyword(k,N.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), k=""):e.beginScope._multi&&(m(e.beginScope,n),k="")),O=Object.create(e,{parent:{ value:O}}),O}function v(e,n,s){let a=((e,n)=>{const s=e&&e.exec(n) ;return s&&0===s.index})(e.endRe,s);if(a){if(e["on:end"]){const s=new t(e) ;e["on:end"](n,s),s.isMatchIgnored&&(a=!1)}if(a){ for(;e.endsParent&&e.parent;)e=e.parent;return e}} if(e.endsWithParent)return v(e.parent,n,s)}function _(e){ return 0===O.matcher.regexIndex?(k+=e[0],1):(T=!0,0)}function h(e){ const n=e[0],t=s.substr(e.index),a=v(O,e,t);if(!a)return Y;const i=O ;O.endScope&&O.endScope._wrap?(p(), A.addKeyword(n,O.endScope._wrap)):O.endScope&&O.endScope._multi?(p(), m(O.endScope,e)):i.skip?k+=n:(i.returnEnd||i.excludeEnd||(k+=n), p(),i.excludeEnd&&(k=n));do{ O.scope&&!O.isMultiClass&&A.closeNode(),O.skip||O.subLanguage||(S+=O.relevance), O=O.parent}while(O!==a.parent) ;return a.starts&&g(a.starts,e),i.returnEnd?0:n.length}let E={};function w(n,i){ const o=i&&i[0];if(k+=n,null==o)return p(),0 ;if("begin"===E.type&&"end"===i.type&&E.index===i.index&&""===o){ if(k+=s.slice(i.index,i.index+1),!r){const n=Error(`0 width match regex (${e})`) ;throw n.languageName=e,n.badRule=E.rule,n}return 1} if(E=i,"begin"===i.type)return(e=>{ const n=e[0],s=e.rule,a=new t(s),i=[s.__beforeBegin,s["on:begin"]] ;for(const s of i)if(s&&(s(e,a),a.isMatchIgnored))return _(n) ;return s.skip?k+=n:(s.excludeBegin&&(k+=n), p(),s.returnBegin||s.excludeBegin||(k=n)),g(s,e),s.returnBegin?0:n.length})(i) ;if("illegal"===i.type&&!a){ const e=Error('Illegal lexeme "'+o+'" for mode "'+(O.scope||"")+'"') ;throw e.mode=O,e}if("end"===i.type){const e=h(i);if(e!==Y)return e} if("illegal"===i.type&&""===o)return 1 ;if(q>1e5&&q>3*i.index)throw Error("potential infinite loop, way more iterations than matches") ;return k+=o,o.length}const N=f(e) ;if(!N)throw j(o.replace("{}",e)),Error('Unknown language: "'+e+'"') ;const y=W(N);let x="",O=i||y;const M={},A=new d.__emitter(d);(()=>{const e=[] ;for(let n=O;n!==N;n=n.parent)n.scope&&e.unshift(n.scope) ;e.forEach((e=>A.openNode(e)))})();let k="",S=0,C=0,q=0,T=!1;try{ for(O.matcher.considerAll();;){ q++,T?T=!1:O.matcher.considerAll(),O.matcher.lastIndex=C ;const e=O.matcher.exec(s);if(!e)break;const n=w(s.substring(C,e.index),e) ;C=e.index+n}return w(s.substr(C)),A.closeAllNodes(),A.finalize(),x=A.toHTML(),{ language:e,value:x,relevance:S,illegal:!1,_emitter:A,_top:O}}catch(n){ if(n.message&&n.message.includes("Illegal"))return{language:e,value:V(s), illegal:!0,relevance:0,_illegalBy:{message:n.message,index:C, context:s.slice(C-100,C+100),mode:n.mode,resultSoFar:x},_emitter:A};if(r)return{ language:e,value:V(s),illegal:!1,relevance:0,errorRaised:n,_emitter:A,_top:O} ;throw n}}function b(e,s){s=s||d.languages||Object.keys(n);const t=(e=>{ const n={value:V(e),illegal:!1,relevance:0,_top:c,_emitter:new d.__emitter(d)} ;return n._emitter.addText(e),n})(e),a=s.filter(f).filter(E).map((n=>u(n,e,!1))) ;a.unshift(t);const i=a.sort(((e,n)=>{ if(e.relevance!==n.relevance)return n.relevance-e.relevance ;if(e.language&&n.language){if(f(e.language).supersetOf===n.language)return 1 ;if(f(n.language).supersetOf===e.language)return-1}return 0})),[r,o]=i,l=r ;return l.secondBest=o,l}function g(e){let n=null;const s=(e=>{ let n=e.className+" ";n+=e.parentNode?e.parentNode.className:"" ;const s=d.languageDetectRe.exec(n);if(s){const n=f(s[1]) ;return n||(P(o.replace("{}",s[1])), P("Falling back to no-highlight mode for this block.",e)),n?s[1]:"no-highlight"} return n.split(/\s+/).find((e=>p(e)||f(e)))})(e);if(p(s))return ;w("before:highlightElement",{el:e,language:s }),!d.ignoreUnescapedHTML&&e.children.length>0&&(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), console.warn("https://github.com/highlightjs/highlight.js/issues/2886"), console.warn(e)),n=e;const t=n.textContent,i=s?m(t,{language:s,ignoreIllegals:!0 }):b(t);e.innerHTML=i.value,((e,n,s)=>{const t=n&&a[n]||s ;e.classList.add("hljs"),e.classList.add("language-"+t) })(e,s,i.language),e.result={language:i.language,re:i.relevance, relevance:i.relevance},i.secondBest&&(e.secondBest={ language:i.secondBest.language,relevance:i.secondBest.relevance }),w("after:highlightElement",{el:e,result:i,text:t})}let v=!1;function _(){ "loading"!==document.readyState?document.querySelectorAll(d.cssSelector).forEach(g):v=!0 }function f(e){return e=(e||"").toLowerCase(),n[e]||n[a[e]]} function h(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ a[e.toLowerCase()]=n}))}function E(e){const n=f(e) ;return n&&!n.disableAutodetect}function w(e,n){const s=e;i.forEach((e=>{ e[s]&&e[s](n)}))} "undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ v&&_()}),!1),Object.assign(e,{highlight:m,highlightAuto:b,highlightAll:_, highlightElement:g, highlightBlock:e=>(K("10.7.0","highlightBlock will be removed entirely in v12.0"), K("10.7.0","Please use highlightElement now."),g(e)),configure:e=>{d=X(d,e)}, initHighlighting:()=>{ _(),K("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, initHighlightingOnLoad:()=>{ _(),K("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") },registerLanguage:(s,t)=>{let a=null;try{a=t(e)}catch(e){ if(j("Language definition for '{}' could not be registered.".replace("{}",s)), !r)throw e;j(e),a=c} a.name||(a.name=s),n[s]=a,a.rawDefinition=t.bind(null,e),a.aliases&&h(a.aliases,{ languageName:s})},unregisterLanguage:e=>{delete n[e] ;for(const n of Object.keys(a))a[n]===e&&delete a[n]}, listLanguages:()=>Object.keys(n),getLanguage:f,registerAliases:h, autoDetection:E,inherit:X,addPlugin:e=>{(e=>{ e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=n=>{ e["before:highlightBlock"](Object.assign({block:n.el},n)) }),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=n=>{ e["after:highlightBlock"](Object.assign({block:n.el},n))})})(e),i.push(e)} }),e.debugMode=()=>{r=!1},e.safeMode=()=>{r=!0},e.versionString="11.0.0" ;for(const e in C)"object"==typeof C[e]&&s(C[e]);return Object.assign(e,C),e })({});const ee=e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ scope:"number", begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", relevance:0} }),ne=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],se=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],te=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],ae=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],ie=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse(),re=te.concat(ae) ;var oe="\\.([0-9](_*[0-9])*)",ce="[0-9a-fA-F](_*[0-9a-fA-F])*",le={ className:"number",variants:[{ begin:`(\\b([0-9](_*[0-9])*)((${oe})|\\.)?|(${oe}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` },{begin:`\\b([0-9](_*[0-9])*)((${oe})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ begin:`(${oe})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ begin:`\\b0[xX]((${ce})\\.?|(${ce})?\\.(${ce}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` },{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${ce})[lL]?\\b`},{ begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], relevance:0};function de(e,n,s){return-1===s?"":e.replace(n,(t=>de(e,n,s-1)))} const pe="[A-Za-z$_][0-9A-Za-z$_]*",me=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],ue=["true","false","null","undefined","NaN","Infinity"],be=["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],ge=["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],ve=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],_e=["arguments","this","super","console","window","document","localStorage","module","global"],fe=[].concat(ve,be,ge) ;function he(e){const n=pe,s={begin:/<[A-Za-z0-9\\._:-]+/, end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ const s=e[0].length+e.index,t=e.input[s];"<"!==t?">"===t&&(((e,{after:n})=>{ const s="",M={ match:[/const|var|let/,/\s+/,n,/\s*/,/=\s*/,p(O)],className:{1:"keyword", 3:"title.function"},contains:[_]};return{name:"Javascript", aliases:["js","jsx","mjs","cjs"],keywords:t,exports:{PARAMS_CONTAINS:v}, illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node", relevance:5}),{label:"use_strict",className:"meta",relevance:10, begin:/^\s*['"]use (strict|asm)['"]/ },e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,c,l,d,m,r,h,{className:"attr", begin:n+p(":"),relevance:0},M,{ begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", keywords:"return throw case",relevance:0,contains:[m,e.REGEXP_MODE,{ className:"function",begin:O,returnBegin:!0,end:"\\s*=>",contains:[{ className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{ className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, excludeEnd:!0,keywords:t,contains:v}]}]},{begin:/,/,relevance:0},{match:/\s+/, relevance:0},{variants:[{begin:"<>",end:""},{begin:s.begin, "on:begin":s.isTrulyOpeningTag,end:s.end}],subLanguage:"xml",contains:[{ begin:s.begin,end:s.end,skip:!0,contains:["self"]}]}]},E,{ beginKeywords:"while if switch catch for"},{ begin:"\\b(?!function)"+e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", returnBegin:!0,label:"func.def",contains:[_,e.inherit(e.TITLE_MODE,{begin:n, className:"title.function"})]},{match:/\.\.\./,relevance:0},y,{match:"\\$"+n, relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, contains:[_]},w,{relevance:0,match:/\b[A-Z][A-Z_]+\b/, className:"variable.constant"},f,x,{match:/\$[(.]/}]}} const Ee=e=>u(/\b/,e,/\w$/.test(e)?/\b/:/\B/),we=["Protocol","Type"].map(Ee),Ne=["init","self"].map(Ee),ye=["Any","Self"],xe=["actor","associatedtype","async","await",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","lazy","let","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],Oe=["false","nil","true"],Me=["assignment","associativity","higherThan","left","lowerThan","none","right"],Ae=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],ke=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],Se=b(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),Ce=b(Se,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),qe=u(Se,Ce,"*"),Te=b(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/),Re=b(Te,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),De=u(Te,Re,"*"),Ie=u(/[A-Z]/,Re,"*"),Le=["autoclosure",u(/convention\(/,b("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",u(/objc\(/,De,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","testable","UIApplicationMain","unknown","usableFromInline"],Be=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"] ;var ze=Object.freeze({__proto__:null,grmr_bash:e=>{const n={},s={begin:/\$\{/, end:/\}/,contains:["self",{begin:/:-/,contains:[n]}]};Object.assign(n,{ className:"variable",variants:[{ begin:u(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},s]});const t={ className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},a={ begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/, end:/(\w+)/,className:"string"})]}},i={className:"string",begin:/"/,end:/"/, contains:[e.BACKSLASH_ESCAPE,n,t]};t.contains.push(i);const r={begin:/\$\(\(/, end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,n] },o=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 }),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], literal:["true","false"], built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" },contains:[o,e.SHEBANG(),c,r,e.HASH_COMMENT_MODE,a,i,{className:"",begin:/\\"/ },{className:"string",begin:/'/,end:/'/},n]}},grmr_c:e=>{ const n=e.COMMENT("//","$",{contains:[{begin:/\\\n/}] }),s="[a-zA-Z_]\\w*::",t="(decltype\\(auto\\)|"+m(s)+"[a-zA-Z_]\\w*"+m("<[^<>]+>")+")",a={ className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ match:/\batomic_[a-z]{3,6}\b/}]},i={className:"string",variants:[{ begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},r={ className:"number",variants:[{begin:"\\b(0b[01']+)"},{ begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" },{ begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" }],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" },contains:[{begin:/\\\n/,relevance:0},e.inherit(i,{className:"string"}),{ className:"string",begin:/<.*?>/},n,e.C_BLOCK_COMMENT_MODE]},c={ className:"title",begin:m(s)+e.IDENT_RE,relevance:0 },l=m(s)+e.IDENT_RE+"\\s*\\(",d={ keyword:["asm","auto","break","case","const","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","static","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","complex","bool","imaginary"], literal:"true false NULL", built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" },p=[o,a,n,e.C_BLOCK_COMMENT_MODE,r,i],u={variants:[{begin:/=/,end:/;/},{ begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], keywords:d,contains:p.concat([{begin:/\(/,end:/\)/,keywords:d, contains:p.concat(["self"]),relevance:0}]),relevance:0},b={ begin:"("+t+"[\\*&\\s]+)+"+l,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, keywords:d,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", keywords:d,relevance:0},{begin:l,returnBegin:!0,contains:[e.inherit(c,{ className:"title.function"})],relevance:0},{relevance:0,match:/,/},{ className:"params",begin:/\(/,end:/\)/,keywords:d,relevance:0, contains:[n,e.C_BLOCK_COMMENT_MODE,i,r,a,{begin:/\(/,end:/\)/,keywords:d, relevance:0,contains:["self",n,e.C_BLOCK_COMMENT_MODE,i,r,a]}] },a,n,e.C_BLOCK_COMMENT_MODE,o]};return{name:"C",aliases:["h"],keywords:d, disableAutodetect:!0,illegal:"=]/,contains:[{ beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:o, strings:i,keywords:d}}},grmr_cpp:e=>{const n=e.COMMENT("//","$",{contains:[{ begin:/\\\n/}] }),s="[a-zA-Z_]\\w*::",t="(?!struct)(decltype\\(auto\\)|"+m(s)+"[a-zA-Z_]\\w*"+m("<[^<>]+>")+")",a={ className:"type",begin:"\\b[a-z\\d_]*_t\\b"},i={className:"string",variants:[{ begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{ begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", end:"'",illegal:"."},e.END_SAME_AS_BEGIN({ begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},r={ className:"number",variants:[{begin:"\\b(0b[01']+)"},{ begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" },{ begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" }],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" },contains:[{begin:/\\\n/,relevance:0},e.inherit(i,{className:"string"}),{ className:"string",begin:/<.*?>/},n,e.C_BLOCK_COMMENT_MODE]},c={ className:"title",begin:m(s)+e.IDENT_RE,relevance:0 },l=m(s)+e.IDENT_RE+"\\s*\\(",d={ type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t"], keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","signed","sizeof","static","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","unsigned","using","virtual","volatile","while","xor","xor_eq,"], literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"], _type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"] },b={className:"function.dispatch",relevance:0,keywords:{ _hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"] }, begin:u(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!while)/,e.IDENT_RE,p(/(<[^<>]+>|)\s*\(/)) },g=[b,o,a,n,e.C_BLOCK_COMMENT_MODE,r,i],v={variants:[{begin:/=/,end:/;/},{ begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], keywords:d,contains:g.concat([{begin:/\(/,end:/\)/,keywords:d, contains:g.concat(["self"]),relevance:0}]),relevance:0},_={className:"function", begin:"("+t+"[\\*&\\s]+)+"+l,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, keywords:d,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", keywords:d,relevance:0},{begin:l,returnBegin:!0,contains:[c],relevance:0},{ begin:/::/,relevance:0},{begin:/:/,endsWithParent:!0,contains:[i,r]},{ relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:d, relevance:0,contains:[n,e.C_BLOCK_COMMENT_MODE,i,r,a,{begin:/\(/,end:/\)/, keywords:d,relevance:0,contains:["self",n,e.C_BLOCK_COMMENT_MODE,i,r,a]}] },a,n,e.C_BLOCK_COMMENT_MODE,o]};return{name:"C++", aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:d,illegal:"",keywords:d,contains:["self",a]},{begin:e.IDENT_RE+"::",keywords:d},{ match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/], className:{1:"keyword",3:"title.class"}}])}},grmr_csharp:e=>{const n={ keyword:["abstract","as","base","break","case","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]), built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"], literal:["default","false","null","true"]},s=e.inherit(e.TITLE_MODE,{ begin:"[a-zA-Z](\\.?\\w)*"}),t={className:"number",variants:[{ begin:"\\b(0b[01']+)"},{ begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{ begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" }],relevance:0},a={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}] },i=e.inherit(a,{illegal:/\n/}),r={className:"subst",begin:/\{/,end:/\}/, keywords:n},o=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/, end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/ },e.BACKSLASH_ESCAPE,o]},l={className:"string",begin:/\$@"/,end:'"',contains:[{ begin:/\{\{/},{begin:/\}\}/},{begin:'""'},r]},d=e.inherit(l,{illegal:/\n/, contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},o]}) ;r.contains=[l,c,a,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,t,e.C_BLOCK_COMMENT_MODE], o.contains=[d,c,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,t,e.inherit(e.C_BLOCK_COMMENT_MODE,{ illegal:/\n/})];const p={variants:[l,c,a,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] },m={begin:"<",end:">",contains:[{beginKeywords:"in out"},s] },u=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={ begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"], keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0, contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{ begin:"\x3c!--|--\x3e"},{begin:""}]}] }),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#", end:"$",keywords:{ keyword:"if else elif endif define undef warning error line region endregion pragma checksum" }},p,t,{beginKeywords:"class interface",relevance:0,end:/[{;=]/, illegal:/[^\s:,]/,contains:[{beginKeywords:"where class" },s,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace", relevance:0,end:/[{;=]/,illegal:/[^\s:]/, contains:[s,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/, contains:[s,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta", begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{ className:"string",begin:/"/,end:/"/}]},{ beginKeywords:"new return throw await else",relevance:0},{className:"function", begin:"("+u+"\\s+)+"+e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{ beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial", relevance:0},{begin:e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, contains:[e.TITLE_MODE,m],relevance:0},{className:"params",begin:/\(/,end:/\)/, excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0, contains:[p,t,e.C_BLOCK_COMMENT_MODE] },e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}},grmr_css:e=>{ const n=ee(e),s=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:"CSS", case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, classNameAliases:{keyframePosition:"selector-tag"}, contains:[e.C_BLOCK_COMMENT_MODE,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/ },n.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0 },{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 },n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ begin:":("+te.join("|")+")"},{begin:"::("+ae.join("|")+")"}]},{ className:"attribute",begin:"\\b("+ie.join("|")+")\\b"},{begin:":",end:"[;}]", contains:[n.HEXCOLOR,n.IMPORTANT,n.CSS_NUMBER_MODE,...s,{ begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" },contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}] },{className:"built_in",begin:/[\w-]+(?=\()/}]},{begin:p(/@/),end:"[{;]", relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/ },{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{ $pattern:/[a-z-]+/,keyword:"and or not only",attribute:se.join(" ")},contains:[{ begin:/[a-z-]+(?=:)/,className:"attribute"},...s,n.CSS_NUMBER_MODE]}]},{ className:"selector-tag",begin:"\\b("+ne.join("|")+")\\b"}]}},grmr_diff:e=>({ name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10, match:b(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/) },{className:"comment",variants:[{ begin:b(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/), end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{ className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, end:/$/}]}),grmr_go:e=>{const n={ keyword:["break","default","func","interface","select","case","map","struct","chan","else","goto","package","switch","const","fallthrough","if","range","type","continue","for","import","return","var","go","defer","bool","byte","complex64","complex128","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"], literal:["true","false","iota","nil"], built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"] };return{name:"Go",aliases:["golang"],keywords:n,illegal:"{const n={ className:"number",relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{ begin:e.NUMBER_RE}]},s=e.COMMENT();s.variants=[{begin:/;/,end:/$/},{begin:/#/, end:/$/}];const t={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{ begin:/\$\{(.*?)\}/}]},a={className:"literal", begin:/\bon|off|true|false|yes|no\b/},i={className:"string", contains:[e.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{ begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}] },r={begin:/\[/,end:/\]/,contains:[s,a,t,i,n,"self"],relevance:0 },o=b(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{name:"TOML, also INI", aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[s,{ className:"section",begin:/\[+/,end:/\]+/},{ begin:u(o,"(\\s*\\.\\s*",o,")*",p(/\s*=\s*[^#\s]/)),className:"attr",starts:{ end:/$/,contains:[s,r,a,t,i,n]}}]}},grmr_java:e=>{ const n="[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",s=n+de("(?:<"+n+"~~~(?:\\s*,\\s*"+n+"~~~)*>)?",/~~~/g,2),t={ keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do"], literal:["false","true","null"], type:["char","boolean","long","float","int","byte","short","double"], built_in:["super","this"]},a={className:"meta",begin:"@"+n,contains:[{ begin:/\(/,end:/\)/,contains:["self"]}]},i={className:"params",begin:/\(/, end:/\)/,keywords:t,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0} ;return{name:"Java",aliases:["jsp"],keywords:t,illegal:/<\/|#/, contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 },e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,n],className:{ 1:"keyword",3:"title.class"}},{begin:[n,/\s+/,n,/\s+/,/=/],className:{1:"type", 3:"variable",5:"operator"}},{begin:[/record/,/\s+/,n],className:{1:"keyword", 3:"title.class"},contains:[i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ beginKeywords:"new throw return else",relevance:0},{ begin:["(?:"+s+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{ 2:"title.function"},keywords:t,contains:[{className:"params",begin:/\(/, end:/\)/,keywords:t,relevance:0, contains:[a,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,le,e.C_BLOCK_COMMENT_MODE] },e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},le,a]}},grmr_javascript:he, grmr_json:e=>({name:"JSON",contains:[{className:"attr", begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/, className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ beginKeywords:"true false null" },e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}), grmr_kotlin:e=>{const n={ keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", literal:"true false null"},s={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" },t={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},a={ className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},i={className:"string", variants:[{begin:'"""',end:'"""(?=[^"])',contains:[a,t]},{begin:"'",end:"'", illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, contains:[e.BACKSLASH_ESCAPE,a,t]}]};t.contains.push(i);const r={ className:"meta", begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" },o={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, end:/\)/,contains:[e.inherit(i,{className:"string"})]}] },c=le,l=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),d={ variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, contains:[]}]},p=d;return p.variants[1].contains=[d],d.variants[1].contains=[p], {name:"Kotlin",aliases:["kt","kts"],keywords:n, contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag", begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,l,{className:"keyword", begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", begin:/@\w+/}]}},s,r,o,{className:"function",beginKeywords:"fun",end:"[(]|$", returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, endsWithParent:!0,contains:[d,e.C_LINE_COMMENT_MODE,l],relevance:0 },e.C_LINE_COMMENT_MODE,l,r,o,i,e.C_NUMBER_MODE]},l]},{className:"class", beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, illegal:"extends implements",contains:[{ beginKeywords:"public protected internal private constructor" },e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/, excludeBegin:!0,returnEnd:!0},r,o]},i,{className:"meta",begin:"^#!/usr/bin/env", end:"$",illegal:"\n"},c]}},grmr_less:e=>{ const n=ee(e),s=re,t="([\\w-]+|@\\{[\\w-]+\\})",a=[],i=[],r=e=>({ className:"string",begin:"~?"+e+".*?"+e}),o=(e,n,s)=>({className:e,begin:n, relevance:s}),c={$pattern:/[a-z-]+/,keyword:"and or not only", attribute:se.join(" ")},l={begin:"\\(",end:"\\)",contains:i,keywords:c, relevance:0} ;i.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,r("'"),r('"'),n.CSS_NUMBER_MODE,{ begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]", excludeEnd:!0} },n.HEXCOLOR,l,o("variable","@@?[\\w-]+",10),o("variable","@\\{[\\w-]+\\}"),o("built_in","~?`[^`]*?`"),{ className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0 },n.IMPORTANT);const d=i.concat({begin:/\{/,end:/\}/,contains:a}),p={ beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not" }].concat(i)},m={begin:t+"\\s*:",returnBegin:!0,end:/[;}]/,relevance:0, contains:[{begin:/-(webkit|moz|ms|o)-/},{className:"attribute", begin:"\\b("+ie.join("|")+")\\b",end:/(?=:)/,starts:{endsWithParent:!0, illegal:"[<=$]",relevance:0,contains:i}}]},u={className:"keyword", begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b", starts:{end:"[;{}]",keywords:c,returnEnd:!0,contains:i,relevance:0}},b={ className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{ begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:d}},g={variants:[{ begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:t,end:/\{/}],returnBegin:!0, returnEnd:!0,illegal:"[<='$\"]",relevance:0, contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,p,o("keyword","all\\b"),o("variable","@\\{[\\w-]+\\}"),{ begin:"\\b("+ne.join("|")+")\\b",className:"selector-tag" },o("selector-tag",t+"%?",0),o("selector-id","#"+t),o("selector-class","\\."+t,0),o("selector-tag","&",0),n.ATTRIBUTE_SELECTOR_MODE,{ className:"selector-pseudo",begin:":("+te.join("|")+")"},{ className:"selector-pseudo",begin:"::("+ae.join("|")+")"},{begin:/\(/,end:/\)/, relevance:0,contains:d},{begin:"!important"}]},v={ begin:`[\\w-]+:(:)?(${s.join("|")})`,returnBegin:!0,contains:[g]} ;return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,u,b,v,m,g),{ name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}},grmr_lua:e=>{ const n="\\[=*\\[",s="\\]=*\\]",t={begin:n,end:s,contains:["self"] },a=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",s,{contains:[t], relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE, literal:"true false nil", keyword:"and break do else elseif end for goto if in local not or repeat return then until while", built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove" },contains:a.concat([{className:"function",beginKeywords:"function",end:"\\)", contains:[e.inherit(e.TITLE_MODE,{ begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params", begin:"\\(",endsWithParent:!0,contains:a}].concat(a) },e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string", begin:n,end:s,contains:[t],relevance:5}])}},grmr_makefile:e=>{const n={ className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)", contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{ const n=u(/[A-Z_]/,m(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),s={className:"symbol", begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/,contains:[{ className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},a=e.inherit(t,{ begin:/\(/,end:/\)/}),i=e.inherit(e.APOS_STRING_MODE,{className:"string" }),r=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),o={endsWithParent:!0, illegal:/`]+/}]}]}]};return{name:"HTML, XML", aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], case_insensitive:!0,contains:[{className:"meta",begin://, relevance:10,contains:[t,r,i,a,{begin:/\[/,end:/\]/,contains:[{className:"meta", begin://,contains:[t,a,r,i]}]}]},e.COMMENT(//,{ relevance:10}),{begin://,relevance:10},s,{ className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", begin:/)/,end:/>/,keywords:{name:"style"},contains:[o],starts:{ end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", begin:/)/,end:/>/,keywords:{name:"script"},contains:[o],starts:{ end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ className:"tag",begin:/<>|<\/>/},{className:"tag", begin:u(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", begin:n,relevance:0,starts:o}]},{className:"tag",begin:u(/<\//,p(u(n,/>/))), contains:[{className:"name",begin:n,relevance:0},{begin:/>/,relevance:0, endsParent:!0}]}]}},grmr_markdown:e=>{const n={begin:/<\/?[A-Za-z_]/,end:">", subLanguage:"xml",relevance:0},s={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 },{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, relevance:2},{begin:u(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", end:"\\]",excludeBegin:!0,excludeEnd:!0}]},t={className:"strong",contains:[], variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},a={ className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ begin:/_(?!_)/,end:/_/,relevance:0}]};t.contains.push(a),a.contains.push(t) ;let i=[n,s] ;return t.contains=t.contains.concat(i),a.contains=a.contains.concat(i), i=i.concat(t,a),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:i},{ begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", contains:i}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", end:"\\s+",excludeEnd:!0},t,a,{className:"quote",begin:"^>\\s+",contains:i, end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ begin:"^[-\\*]{3,}",end:"$"},s,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}},grmr_objectivec:e=>{ const n=/[a-zA-Z@][a-zA-Z0-9_]*/,s={$pattern:n, keyword:["@interface","@class","@protocol","@implementation"]};return{ name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], keywords:{$pattern:n, keyword:["int","float","while","char","export","sizeof","typedef","const","struct","for","union","unsigned","long","volatile","static","bool","mutable","if","do","return","goto","void","enum","else","break","extern","asm","case","short","default","double","register","explicit","signed","typename","this","switch","continue","wchar_t","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","super","unichar","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"], literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"], built_in:["BOOL","dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"] },illegal:"/,end:/$/,illegal:"\\n" },e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class", begin:"("+s.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:s, contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE, relevance:0}]}},grmr_perl:e=>{const n=/[dualxmsipngr]{0,12}/,s={ $pattern:/[\w.]+/, keyword:"abs accept alarm and atan2 bind binmode bless break caller chdir chmod chomp chop chown chr chroot close closedir connect continue cos crypt dbmclose dbmopen defined delete die do dump each else elsif endgrent endhostent endnetent endprotoent endpwent endservent eof eval exec exists exit exp fcntl fileno flock for foreach fork format formline getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep gt hex if index int ioctl join keys kill last lc lcfirst length link listen local localtime log lstat lt ma map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct open opendir or ord our pack package pipe pop pos print printf prototype push q|0 qq quotemeta qw qx rand read readdir readline readlink readpipe recv redo ref rename require reset return reverse rewinddir rindex rmdir say scalar seek seekdir select semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat state study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unless unlink unpack unshift untie until use utime values vec wait waitpid wantarray warn when while write x|0 xor y|0" },t={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:s},a={begin:/->\{/, end:/\}/},i={variants:[{begin:/\$\d/},{ begin:u(/[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])") },{begin:/[$%@][^\s\w{]/,relevance:0}] },r=[e.BACKSLASH_ESCAPE,t,i],o=[/!/,/\//,/\|/,/\?/,/'/,/"/,/#/],c=(e,s,t="\\1")=>{ const a="\\1"===t?t:u(t,s) ;return u(u("(?:",e,")"),s,/(?:\\.|[^\\\/])*?/,a,/(?:\\.|[^\\\/])*?/,t,n) },l=(e,s,t)=>u(u("(?:",e,")"),s,/(?:\\.|[^\\\/])*?/,t,n),d=[i,e.HASH_COMMENT_MODE,e.COMMENT(/^=\w/,/=cut/,{ endsWithParent:!0}),a,{className:"string",contains:r,variants:[{ begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[", end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{ begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">", relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'", contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`", contains:[e.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,relevance:0},{ begin:"-?\\w+\\s*=>",relevance:0}]},{className:"number", begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b", relevance:0},{ begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*", keywords:"split return print reverse grep",relevance:0, contains:[e.HASH_COMMENT_MODE,{className:"regexp",variants:[{ begin:c("s|tr|y",b(...o,{capture:!0}))},{begin:c("s|tr|y","\\(","\\)")},{ begin:c("s|tr|y","\\[","\\]")},{begin:c("s|tr|y","\\{","\\}")}],relevance:2},{ className:"regexp",variants:[{begin:/(m|qr)\/\//,relevance:0},{ begin:l("(?:m|qr)?",/\//,/\//)},{begin:l("m|qr",b(...o,{capture:!0}),/\1/)},{ begin:l("m|qr",/\(/,/\)/)},{begin:l("m|qr",/\[/,/\]/)},{ begin:l("m|qr",/\{/,/\}/)}]}]},{className:"function",beginKeywords:"sub", end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{ begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$", subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}] }];return t.contains=d,a.contains=d,{name:"Perl",aliases:["pl","pm"],keywords:s, contains:d}},grmr_php:e=>{const n={className:"variable", begin:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?![A-Za-z0-9])(?![$])"},s={ className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{ begin:/\?>/}]},t={className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/, end:/\}/}]},a=e.inherit(e.APOS_STRING_MODE,{illegal:null }),i=e.inherit(e.QUOTE_STRING_MODE,{illegal:null, contains:e.QUOTE_STRING_MODE.contains.concat(t)}),r=e.END_SAME_AS_BEGIN({ begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/, contains:e.QUOTE_STRING_MODE.contains.concat(t)}),o={className:"string", contains:[e.BACKSLASH_ESCAPE,s],variants:[e.inherit(a,{begin:"b'",end:"'" }),e.inherit(i,{begin:'b"',end:'"'}),i,a,r]},c={className:"number",variants:[{ begin:"\\b0b[01]+(?:_[01]+)*\\b"},{begin:"\\b0o[0-7]+(?:_[0-7]+)*\\b"},{ begin:"\\b0x[\\da-f]+(?:_[\\da-f]+)*\\b"},{ begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:e[+-]?\\d+)?" }],relevance:0},l={ keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile enum eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list match|0 mixed new object or private protected public real return string switch throw trait try unset use var void while xor yield", literal:"false null true", built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException UnhandledMatchError ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Stringable Throwable Traversable WeakReference WeakMap Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass" };return{case_insensitive:!0,keywords:l, contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[s] }),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}] }),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0, keywords:"__halt_compiler"}),s,{className:"keyword",begin:/\$this\b/},n,{ begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function", relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0, illegal:"[$%\\[]",contains:[{beginKeywords:"use"},e.UNDERSCORE_TITLE_MODE,{ begin:"=>",endsParent:!0},{className:"params",begin:"\\(",end:"\\)", excludeBegin:!0,excludeEnd:!0,keywords:l, contains:["self",n,e.C_BLOCK_COMMENT_MODE,o,c]}]},{className:"class",variants:[{ beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait", illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{ beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{ beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/, contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",relevance:0,end:";", contains:[e.UNDERSCORE_TITLE_MODE]},o,c]}},grmr_php_template:e=>({ name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/, subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"', end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},e.inherit(e.APOS_STRING_MODE,{ illegal:null,className:null,contains:null,skip:!0 }),e.inherit(e.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null, skip:!0})]}]}),grmr_plaintext:e=>({name:"Plain text",aliases:["text","txt"], disableAutodetect:!0}),grmr_python:e=>{const n={$pattern:/[A-Za-z]\w+|__\w+__/, keyword:["and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"], built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"], literal:["__debug__","Ellipsis","False","None","NotImplemented","True"], type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"] },s={className:"meta",begin:/^(>>>|\.\.\.) /},t={className:"subst",begin:/\{/, end:/\}/,keywords:n,illegal:/#/},a={begin:/\{\{/,relevance:0},i={ className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, contains:[e.BACKSLASH_ESCAPE,s],relevance:10},{ begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, contains:[e.BACKSLASH_ESCAPE,s],relevance:10},{ begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, contains:[e.BACKSLASH_ESCAPE,s,a,t]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, end:/"""/,contains:[e.BACKSLASH_ESCAPE,s,a,t]},{begin:/([uU]|[rR])'/,end:/'/, relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, contains:[e.BACKSLASH_ESCAPE,a,t]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, contains:[e.BACKSLASH_ESCAPE,a,t]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] },r="[0-9](_?[0-9])*",o=`(\\b(${r}))?\\.(${r})|\\b(${r})\\.`,c={ className:"number",relevance:0,variants:[{ begin:`(\\b(${r})|(${o}))[eE][+-]?(${r})[jJ]?\\b`},{begin:`(${o})[jJ]?`},{ begin:"\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?\\b"},{ begin:"\\b0[bB](_?[01])+[lL]?\\b"},{begin:"\\b0[oO](_?[0-7])+[lL]?\\b"},{ begin:"\\b0[xX](_?[0-9a-fA-F])+[lL]?\\b"},{begin:`\\b(${r})[jJ]\\b`}]},l={ className:"comment",begin:p(/# type:/),end:/$/,keywords:n,contains:[{ begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},d={ className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/, end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n, contains:["self",s,c,i,e.HASH_COMMENT_MODE]}]};return t.contains=[i,c,s],{ name:"Python",aliases:["py","gyp","ipython"],keywords:n, illegal:/(<\/|->|\?)|=>/,contains:[s,c,{begin:/\bself\b/},{beginKeywords:"if", relevance:0},i,l,e.HASH_COMMENT_MODE,{match:[/def/,/\s+/,f],scope:{1:"keyword", 3:"title.function"},contains:[d]},{variants:[{ match:[/class/,/\s+/,f,/\s*/,/\(\s*/,f,/\s*\)/]},{match:[/class/,/\s+/,f]}], scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{ className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[c,d,i]}]}}, grmr_python_repl:e=>({aliases:["pycon"],contains:[{className:"meta",starts:{ end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{ begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}),grmr_r:e=>{ const n=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/,s=b(/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,/0[xX][0-9a-fA-F]+(?:[pP][+-]?\d+)?[Li]?/,/(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?[Li]?/),t=/[=!<>:]=|\|\||&&|:::?|<-|<<-|->>|->|\|>|[-+*\/?!$&|:<=>@^~]|\*\*/,a=b(/[()]/,/[{}]/,/\[\[/,/[[\]]/,/\\/,/,/) ;return{name:"R",keywords:{$pattern:n, keyword:"function if in break next repeat else for while", literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10", built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm" },contains:[e.COMMENT(/#'/,/$/,{contains:[{scope:"doctag",begin:"@examples", starts:{contains:[{begin:/\n/},{begin:/#'\s*(?=@[a-zA-Z]+)/,endsParent:!0},{ begin:/#'/,end:/$/,excludeBegin:!0}]}},{scope:"doctag",begin:"@param",end:/$/, contains:[{scope:"variable",variants:[{begin:n},{begin:/`(?:\\.|[^`\\])+`/}], endsParent:!0}]},{scope:"doctag",begin:/@[a-zA-Z]+/},{scope:"keyword", begin:/\\[a-zA-Z]+/}]}),e.HASH_COMMENT_MODE,{scope:"string", contains:[e.BACKSLASH_ESCAPE],variants:[e.END_SAME_AS_BEGIN({ begin:/[rR]"(-*)\(/,end:/\)(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/, end:/\}(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/ }),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/ }),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/ }),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"', relevance:0},{begin:"'",end:"'",relevance:0}]},{relevance:0,variants:[{scope:{ 1:"operator",2:"number"},match:[t,s]},{scope:{1:"operator",2:"number"}, match:[/%[^%]*%/,s]},{scope:{1:"punctuation",2:"number"},match:[a,s]},{scope:{ 2:"number"},match:[/[^a-zA-Z0-9._]|^/,s]}]},{scope:{3:"operator"}, match:[n,/\s+/,/<-/,/\s+/]},{scope:"operator",relevance:0,variants:[{match:t},{ match:/%[^%]*%/}]},{scope:"punctuation",relevance:0,match:a},{begin:"`",end:"`", contains:[{begin:/\\./}]}]}},grmr_ruby:e=>{ const n="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", built_in:"proc lambda",literal:"true false nil"},t={className:"doctag", begin:"@[A-Za-z]+"},a={begin:"#<",end:">"},i=[e.COMMENT("#","$",{contains:[t] }),e.COMMENT("^=begin","^=end",{contains:[t],relevance:10 }),e.COMMENT("^__END__","\\n$")],r={className:"subst",begin:/#\{/,end:/\}/, keywords:s},o={className:"string",contains:[e.BACKSLASH_ESCAPE,r],variants:[{ begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{ begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{ begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{ begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{ begin:u(/<<[-~]?'?/,p(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)), contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, contains:[e.BACKSLASH_ESCAPE,r]})]}]},c="[0-9](_?[0-9])*",l={className:"number", relevance:0,variants:[{ begin:`\\b([1-9](_?[0-9])*|0)(\\.(${c}))?([eE][+-]?(${c})|r)?i?\\b`},{ begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" },{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ begin:"\\b0(_?[0-7])+r?i?\\b"}]},d={className:"params",begin:"\\(",end:"\\)", endsParent:!0,keywords:s},m=[o,{className:"class",beginKeywords:"class module", end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{ begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE,relevance:0}]}].concat(i)},{ className:"function",begin:u(/def\s+/,p(n+"\\s*(\\(|;|$)")),relevance:0, keywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:n }),d].concat(i)},{begin:e.IDENT_RE+"::"},{className:"symbol", begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol", begin:":(?!\\s)",contains:[o,{begin:n}],relevance:0},l,{className:"variable", begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ className:"regexp",contains:[e.BACKSLASH_ESCAPE,r],illegal:/\n/,variants:[{ begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] }].concat(a,i),relevance:0}].concat(a,i);r.contains=m,d.contains=m;const b=[{ begin:/^\s*=>/,starts:{end:"$",contains:m}},{className:"meta", begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", starts:{end:"$",contains:m}}];return i.unshift(a),{name:"Ruby", aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, contains:[e.SHEBANG({binary:"ruby"})].concat(b).concat(i).concat(m)}}, grmr_rust:e=>{const n={className:"title.function.invoke",relevance:0, begin:u(/\b/,/(?!let\b)/,e.IDENT_RE,p(/\s*\(/)) },s="([ui](8|16|32|64|128|size)|f(32|64))?",t=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","panic!","file!","format!","format_args!","include_bin!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"] ;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?", type:["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"], keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","unsafe","unsized","use","virtual","where","while","yield"], literal:["true","false","Some","None","Ok","Err"],built_in:t},illegal:""},n]}}, grmr_scss:e=>{const n=ee(e),s=ae,t=te,a="@[a-z-]+",i={className:"variable", begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"};return{name:"SCSS",case_insensitive:!0, illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{ className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0 },n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag", begin:"\\b("+ne.join("|")+")\\b",relevance:0},{className:"selector-pseudo", begin:":("+t.join("|")+")"},{className:"selector-pseudo", begin:"::("+s.join("|")+")"},i,{begin:/\(/,end:/\)/,contains:[n.CSS_NUMBER_MODE] },{className:"attribute",begin:"\\b("+ie.join("|")+")\\b"},{ begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" },{begin:":",end:";", contains:[i,n.HEXCOLOR,n.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.IMPORTANT] },{begin:"@(page|font-face)",keywords:{$pattern:a,keyword:"@page @font-face"}},{ begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/, keyword:"and or not only",attribute:se.join(" ")},contains:[{begin:a, className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute" },i,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.HEXCOLOR,n.CSS_NUMBER_MODE]}]}}, grmr_shell:e=>({name:"Shell Session",aliases:["console","shellsession"], contains:[{className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{ end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}),grmr_sql:e=>{ const n=e.COMMENT("--","$"),s=["true","false","unknown"],t=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],a=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],i=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],r=a,o=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!a.includes(e))),c={ begin:u(/\b/,b(...r),/\s*\(/),relevance:0,keywords:{built_in:r}};return{ name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ $pattern:/\b[\w\.]+/,keyword:((e,{exceptions:n,when:s}={})=>{const t=s ;return n=n||[],e.map((e=>e.match(/\|\d+$/)||n.includes(e)?e:t(e)?e+"|0":e)) })(o,{when:e=>e.length<3}),literal:s,type:t, built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"] },contains:[{begin:b(...i),relevance:0,keywords:{$pattern:/[\w\.]+/, keyword:o.concat(i),literal:s,type:t}},{className:"type", begin:b("double precision","large object","with timezone","without timezone") },c,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,n,{className:"operator", begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}, grmr_swift:e=>{const n={match:/\s+/,relevance:0},s=e.COMMENT("/\\*","\\*/",{ contains:["self"]}),t=[e.C_LINE_COMMENT_MODE,s],a={match:[/\./,b(...we,...Ne)], className:{2:"keyword"}},i={match:u(/\./,b(...xe)),relevance:0 },r=xe.filter((e=>"string"==typeof e)).concat(["_|0"]),o={variants:[{ className:"keyword", match:b(...xe.filter((e=>"string"!=typeof e)).concat(ye).map(Ee),...Ne)}]},c={ $pattern:b(/\b\w+/,/#\w+/),keyword:r.concat(Ae),literal:Oe},l=[a,i,o],d=[{ match:u(/\./,b(...ke)),relevance:0},{className:"built_in", match:u(/\b/,b(...ke),/(?=\()/)}],m={match:/->/,relevance:0},g=[m,{ className:"operator",relevance:0,variants:[{match:qe},{match:`\\.(\\.|${Ce})+`}] }],v="([0-9a-fA-F]_*)+",_={className:"number",relevance:0,variants:[{ match:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{ match:`\\b0x(${v})(\\.(${v}))?([pP][+-]?(([0-9]_*)+))?\\b`},{ match:/\b0o([0-7]_*)+\b/},{match:/\b0b([01]_*)+\b/}]},f=(e="")=>({ className:"subst",variants:[{match:u(/\\/,e,/[0\\tnr"']/)},{ match:u(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),h=(e="")=>({className:"subst", match:u(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),E=(e="")=>({className:"subst", label:"interpol",begin:u(/\\/,e,/\(/),end:/\)/}),w=(e="")=>({begin:u(e,/"""/), end:u(/"""/,e),contains:[f(e),h(e),E(e)]}),N=(e="")=>({begin:u(e,/"/), end:u(/"/,e),contains:[f(e),E(e)]}),y={className:"string", variants:[w(),w("#"),w("##"),w("###"),N(),N("#"),N("##"),N("###")]},x={ match:u(/`/,De,/`/)},O=[x,{className:"variable",match:/\$\d+/},{ className:"variable",match:`\\$${Re}+`}],M=[{match:/(@|#)available/, className:"keyword",starts:{contains:[{begin:/\(/,end:/\)/,keywords:Be, contains:[...g,_,y]}]}},{className:"keyword",match:u(/@/,b(...Le))},{ className:"meta",match:u(/@/,De)}],A={match:p(/\b[A-Z]/),relevance:0,contains:[{ className:"type", match:u(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,Re,"+") },{className:"type",match:Ie,relevance:0},{match:/[?!]+/,relevance:0},{ match:/\.\.\./,relevance:0},{match:u(/\s+&\s+/,p(Ie)),relevance:0}]},k={ begin://,keywords:c,contains:[...t,...l,...M,m,A]};A.contains.push(k) ;const S={begin:/\(/,end:/\)/,relevance:0,keywords:c,contains:["self",{ match:u(De,/\s*:/),keywords:"_|0",relevance:0 },...t,...l,...d,...g,_,y,...O,...M,A]},C={begin://,contains:[...t,A] },q={begin:/\(/,end:/\)/,keywords:c,contains:[{ begin:b(p(u(De,/\s*:/)),p(u(De,/\s+/,De,/\s*:/))),end:/:/,relevance:0, contains:[{className:"keyword",match:/\b_\b/},{className:"params",match:De}] },...t,...l,...g,_,y,...M,A,S],endsParent:!0,illegal:/["']/},T={ match:[/func/,/\s+/,b(x.match,De,qe)],className:{1:"keyword",3:"title.function" },contains:[C,q,n],illegal:[/\[/,/%/]},R={ match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"}, contains:[C,q,n],illegal:/\[|%/},D={match:[/operator/,/\s+/,qe],className:{ 1:"keyword",3:"title"}},I={begin:[/precedencegroup/,/\s+/,Ie],className:{ 1:"keyword",3:"title"},contains:[A],keywords:[...Me,...Oe],end:/}/} ;for(const e of y.variants){const n=e.contains.find((e=>"interpol"===e.label)) ;n.keywords=c;const s=[...l,...d,...g,_,y,...O];n.contains=[...s,{begin:/\(/, end:/\)/,contains:["self",...s]}]}return{name:"Swift",keywords:c, contains:[...t,T,R,{beginKeywords:"struct protocol class extension enum actor", end:"\\{",excludeEnd:!0,keywords:c,contains:[e.inherit(e.TITLE_MODE,{ className:"title.class",begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...l] },D,I,{beginKeywords:"import",end:/$/,contains:[...t],relevance:0 },...l,...d,...g,_,y,...O,...M,A,S]}},grmr_typescript:e=>{const n={$pattern:pe, keyword:me.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]), literal:ue, built_in:fe.concat(["any","void","number","boolean","string","object","never","enum"]), "variable.language":_e},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*" },t=(e,n,s)=>{const t=e.contains.findIndex((e=>e.label===n)) ;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,s) },a=he(e) ;return Object.assign(a.keywords,n),a.exports.PARAMS_CONTAINS.push(s),a.contains=a.contains.concat([s,{ beginKeywords:"namespace",end:/\{/,excludeEnd:!0},{beginKeywords:"interface", end:/\{/,excludeEnd:!0,keywords:"interface extends" }]),t(a,"shebang",e.SHEBANG()),t(a,"use_strict",{className:"meta",relevance:10, begin:/^\s*['"]use strict['"]/ }),a.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(a,{ name:"TypeScript",aliases:["ts","tsx"]}),a},grmr_vbnet:e=>{ const n=/\d{1,2}\/\d{1,2}\/\d{4}/,s=/\d{4}-\d{1,2}-\d{1,2}/,t=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,a=/\d{1,2}(:\d{1,2}){1,2}/,i={ className:"literal",variants:[{begin:u(/# */,b(s,n),/ *#/)},{ begin:u(/# */,a,/ *#/)},{begin:u(/# */,t,/ *#/)},{ begin:u(/# */,b(s,n),/ +/,b(t,a),/ *#/)}]},r=e.COMMENT(/'''/,/$/,{contains:[{ className:"doctag",begin:/<\/?/,end:/>/}]}),o=e.COMMENT(null,/$/,{variants:[{ begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET", aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{ keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield", built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort", type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort", literal:"true false nothing"}, illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{ className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/, end:/"/,illegal:/\n/,contains:[{begin:/""/}]},i,{className:"number",relevance:0, variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/ },{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{ begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{ className:"label",begin:/^\w+:/},r,o,{className:"meta", begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/, end:/$/,keywords:{ keyword:"const disable else elseif enable end externalsource if region then"}, contains:[o]}]}},grmr_yaml:e=>{ const n="true false yes no null",s="[\\w#;/?:@&=+$,.~*'()[\\]]+",t={ className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ },{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},a=e.inherit(t,{ variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),i={ end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},r={begin:/\{/, end:/\}/,contains:[i],illegal:"\\n",relevance:0},o={begin:"\\[",end:"\\]", contains:[i],illegal:"\\n",relevance:0},c=[{className:"attr",variants:[{ begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{ begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$", relevance:10},{className:"string", begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, relevance:0},{className:"type",begin:"!\\w+!"+s},{className:"type", begin:"!<"+s+">"},{className:"type",begin:"!"+s},{className:"type",begin:"!!"+s },{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ className:"number", begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" },{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},r,o,t],l=[...c] ;return l.pop(),l.push(a),i.contains=l,{name:"YAML",case_insensitive:!0, aliases:["yml"],contains:c}},grmr_apache:e=>{const n={className:"number", begin:/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?/};return{ name:"Apache config",aliases:["apacheconf"],case_insensitive:!0, contains:[e.HASH_COMMENT_MODE,{className:"section",begin:/<\/?/,end:/>/, contains:[n,{className:"number",begin:/:\d{1,5}/ },e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute", begin:/\w+/,relevance:0,keywords:{ _:["order","deny","allow","setenv","rewriterule","rewriteengine","rewritecond","documentroot","sethandler","errordocument","loadmodule","options","header","listen","serverroot","servername"] },starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"}, contains:[{className:"meta",begin:/\s\[/,end:/\]$/},{className:"variable", begin:/[\$%]\{/,end:/\}/,contains:["self",{className:"number",begin:/[$%]\d+/}] },n,{className:"number",begin:/\b\d+/},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}, grmr_armasm:e=>{const n={variants:[e.COMMENT("^[ \\t]*(?=#)","$",{relevance:0, excludeBegin:!0}),e.COMMENT("[;@]","$",{relevance:0 }),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]};return{name:"ARM Assembly", case_insensitive:!0,aliases:["arm"],keywords:{$pattern:"\\.?"+e.IDENT_RE, meta:".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND ", built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @" },contains:[{className:"keyword", begin:"\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?(?=\\s)" },n,e.QUOTE_STRING_MODE,{className:"string",begin:"'",end:"[^\\\\]'",relevance:0 },{className:"title",begin:"\\|",end:"\\|",illegal:"\\n",relevance:0},{ className:"number",variants:[{begin:"[#$=]?0x[0-9a-f]+"},{begin:"[#$=]?0b[01]+" },{begin:"[#$=]\\d+"},{begin:"\\b\\d+"}],relevance:0},{className:"symbol", variants:[{begin:"^[ \\t]*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{ begin:"^[a-z_\\.\\$][a-z0-9_\\.\\$]+"},{begin:"[=#]\\w+"}],relevance:0}]}}, grmr_coffeescript:e=>{const n={ keyword:me.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((s=["var","const","let","function","static"], e=>!s.includes(e))),literal:ue.concat(["yes","no","on","off"]), built_in:fe.concat(["npm","print"])};var s ;const t="[A-Za-z$_][0-9A-Za-z$_]*",a={className:"subst",begin:/#\{/,end:/\}/, keywords:n},i=[e.BINARY_NUMBER_MODE,e.inherit(e.C_NUMBER_MODE,{starts:{ end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/, end:/'''/,contains:[e.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/, contains:[e.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/, contains:[e.BACKSLASH_ESCAPE,a]},{begin:/"/,end:/"/, contains:[e.BACKSLASH_ESCAPE,a]}]},{className:"regexp",variants:[{begin:"///", end:"///",contains:[a,e.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)", relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+t },{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{ begin:"```",end:"```"},{begin:"`",end:"`"}]}];a.contains=i ;const r=e.inherit(e.TITLE_MODE,{begin:t}),o="(\\(.*\\)\\s*)?\\B[-=]>",c={ className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/, end:/\)/,keywords:n,contains:["self"].concat(i)}]};return{name:"CoffeeScript", aliases:["coffee","cson","iced"],keywords:n,illegal:/\/\*/, contains:[...i,e.COMMENT("###","###"),e.HASH_COMMENT_MODE,{className:"function", begin:"^\\s*"+t+"\\s*=\\s*"+o,end:"[-=]>",returnBegin:!0,contains:[r,c]},{ begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function",begin:o, end:"[-=]>",returnBegin:!0,contains:[c]}]},{className:"class", beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{ beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[r]},r] },{begin:t+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}]}},grmr_d:e=>{ const n={$pattern:e.UNDERSCORE_IDENT_RE, keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__", built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring", literal:"false null true" },s="((0|[1-9][\\d_]*)|0[bB][01_]+|0[xX]([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))",t="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};",a={ className:"number",begin:"\\b"+s+"(L|u|U|Lu|LU|uL|UL)?",relevance:0},i={ className:"number", begin:"\\b(((0[xX](([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)\\.([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)|\\.?([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))[pP][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))|((0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(\\.\\d*|([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)))|\\d+\\.(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)|\\.(0|[1-9][\\d_]*)([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))?))([fF]|L|i|[fF]i|Li)?|"+s+"(i|[fF]i|Li))", relevance:0},r={className:"string",begin:"'("+t+"|.)",end:"'",illegal:"."},o={ className:"string",begin:'"',contains:[{begin:t,relevance:0}],end:'"[cwd]?' },c=e.COMMENT("\\/\\+","\\+\\/",{contains:["self"],relevance:10});return{ name:"D",keywords:n,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,c,{ className:"string",begin:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',relevance:10},o,{ className:"string",begin:'[rq]"',end:'"[cwd]?',relevance:5},{className:"string", begin:"`",end:"`[cwd]?"},{className:"string",begin:'q"\\{',end:'\\}"'},i,a,r,{ className:"meta",begin:"^#!",end:"$",relevance:5},{className:"meta", begin:"#(line)",end:"$",relevance:5},{className:"keyword", begin:"@[a-zA-Z_][a-zA-Z_\\d]*"}]}},grmr_handlebars:e=>{const n={ $pattern:/[\w.\/]+/, built_in:["action","bindattr","collection","component","concat","debugger","each","each-in","get","hash","if","in","input","link-to","loc","log","lookup","mut","outlet","partial","query-params","render","template","textarea","unbound","unless","view","with","yield"] },s=/\[\]|\[[^\]]+\]/,t=/[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+/,a=b(/""|"[^"]+"/,/''|'[^']+'/,s,t),i=u(m(/\.|\.\/|\//),a,(r=u(/(\.|\/)/,a), u("(?:",r,")*")));var r;const o=u("(",s,"|",t,")(?==)"),c={begin:i },l=e.inherit(c,{keywords:{$pattern:/[\w.\/]+/, literal:["true","false","undefined","null"]}}),d={begin:/\(/,end:/\)/},p={ className:"attr",begin:o,relevance:0,starts:{begin:/=/,end:/=/,starts:{ contains:[e.NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,l,d]}}},g={ contains:[e.NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{begin:/as\s+\|/, keywords:{keyword:"as"},end:/\|/,contains:[{begin:/\w+/}]},p,l,d],returnEnd:!0 },v=e.inherit(c,{className:"name",keywords:n,starts:e.inherit(g,{end:/\)/})}) ;d.contains=[v];const _=e.inherit(c,{keywords:n,className:"name", starts:e.inherit(g,{end:/\}\}/})}),f=e.inherit(c,{keywords:n,className:"name" }),h=e.inherit(c,{className:"name",keywords:n,starts:e.inherit(g,{end:/\}\}/})}) ;return{name:"Handlebars", aliases:["hbs","html.hbs","html.handlebars","htmlbars"],case_insensitive:!0, subLanguage:"xml",contains:[{begin:/\\\{\{/,skip:!0},{begin:/\\\\(?=\{\{)/, skip:!0},e.COMMENT(/\{\{!--/,/--\}\}/),e.COMMENT(/\{\{!/,/\}\}/),{ className:"template-tag",begin:/\{\{\{\{(?!\/)/,end:/\}\}\}\}/,contains:[_], starts:{end:/\{\{\{\{\//,returnEnd:!0,subLanguage:"xml"}},{ className:"template-tag",begin:/\{\{\{\{\//,end:/\}\}\}\}/,contains:[f]},{ className:"template-tag",begin:/\{\{#/,end:/\}\}/,contains:[_]},{ className:"template-tag",begin:/\{\{(?=else\}\})/,end:/\}\}/,keywords:"else"},{ className:"template-tag",begin:/\{\{(?=else if)/,end:/\}\}/,keywords:"else if" },{className:"template-tag",begin:/\{\{\//,end:/\}\}/,contains:[f]},{ className:"template-variable",begin:/\{\{\{/,end:/\}\}\}/,contains:[h]},{ className:"template-variable",begin:/\{\{/,end:/\}\}/,contains:[h]}]}}, grmr_haskell:e=>{const n={variants:[e.COMMENT("--","$"),e.COMMENT(/\{-/,/-\}/,{ contains:["self"]})]},s={className:"meta",begin:/\{-#/,end:/#-\}/},t={ className:"meta",begin:"^#",end:"$"},a={className:"type", begin:"\\b[A-Z][\\w']*",relevance:0},i={begin:"\\(",end:"\\)",illegal:'"', contains:[s,t,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?" },e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),n]},r="([0-9a-fA-F]_*)+",o={ className:"number",relevance:0,variants:[{ match:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{ match:`\\b0[xX]_*(${r})(\\.(${r}))?([pP][+-]?(([0-9]_*)+))?\\b`},{ match:"\\b0[oO](([0-7]_*)+)\\b"},{match:"\\b0[bB](([01]_*)+)\\b"}]};return{ name:"Haskell",aliases:["hs"], keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec", contains:[{beginKeywords:"module",end:"where",keywords:"module where", contains:[i,n],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$", keywords:"import qualified as hiding",contains:[i,n],illegal:"\\W\\.|;"},{ className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where", keywords:"class family instance where",contains:[a,i,n]},{className:"class", begin:"\\b(data|(new)?type)\\b",end:"$", keywords:"data family type newtype deriving",contains:[s,a,i,{begin:/\{/, end:/\}/,contains:i.contains},n]},{beginKeywords:"default",end:"$", contains:[a,i,n]},{beginKeywords:"infix infixl infixr",end:"$", contains:[e.C_NUMBER_MODE,n]},{begin:"\\bforeign\\b",end:"$", keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe", contains:[a,e.QUOTE_STRING_MODE,n]},{className:"meta", begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$" },s,t,e.QUOTE_STRING_MODE,o,a,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*" }),n,{begin:"->|<-"}]}},grmr_http:e=>{const n="HTTP/(2|1\\.[01])",s={ className:"attribute",begin:u("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{ contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$", relevance:0}}]}},t=[s,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0} }];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{ begin:"^(?="+n+" \\d{3})",end:/$/,contains:[{className:"meta",begin:n},{ className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/, contains:t}},{begin:"(?=^[A-Z]+ (.*?) "+n+"$)",end:/$/,contains:[{ className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{ className:"meta",begin:n},{className:"keyword",begin:"[A-Z]+"}],starts:{ end:/\b\B/,illegal:/\S/,contains:t}},e.inherit(s,{relevance:0})]}}, grmr_julia:e=>{var n="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",s={ $pattern:n, keyword:["baremodule","begin","break","catch","ccall","const","continue","do","else","elseif","end","export","false","finally","for","function","global","if","import","in","isa","let","local","macro","module","quote","return","true","try","using","where","while"], literal:["ARGS","C_NULL","DEPOT_PATH","ENDIAN_BOM","ENV","Inf","Inf16","Inf32","Inf64","InsertionSort","LOAD_PATH","MergeSort","NaN","NaN16","NaN32","NaN64","PROGRAM_FILE","QuickSort","RoundDown","RoundFromZero","RoundNearest","RoundNearestTiesAway","RoundNearestTiesUp","RoundToZero","RoundUp","VERSION|0","devnull","false","im","missing","nothing","pi","stderr","stdin","stdout","true","undef","\u03c0","\u212f"], built_in:["AbstractArray","AbstractChannel","AbstractChar","AbstractDict","AbstractDisplay","AbstractFloat","AbstractIrrational","AbstractMatrix","AbstractRange","AbstractSet","AbstractString","AbstractUnitRange","AbstractVecOrMat","AbstractVector","Any","ArgumentError","Array","AssertionError","BigFloat","BigInt","BitArray","BitMatrix","BitSet","BitVector","Bool","BoundsError","CapturedException","CartesianIndex","CartesianIndices","Cchar","Cdouble","Cfloat","Channel","Char","Cint","Cintmax_t","Clong","Clonglong","Cmd","Colon","Complex","ComplexF16","ComplexF32","ComplexF64","CompositeException","Condition","Cptrdiff_t","Cshort","Csize_t","Cssize_t","Cstring","Cuchar","Cuint","Cuintmax_t","Culong","Culonglong","Cushort","Cvoid","Cwchar_t","Cwstring","DataType","DenseArray","DenseMatrix","DenseVecOrMat","DenseVector","Dict","DimensionMismatch","Dims","DivideError","DomainError","EOFError","Enum","ErrorException","Exception","ExponentialBackOff","Expr","Float16","Float32","Float64","Function","GlobalRef","HTML","IO","IOBuffer","IOContext","IOStream","IdDict","IndexCartesian","IndexLinear","IndexStyle","InexactError","InitError","Int","Int128","Int16","Int32","Int64","Int8","Integer","InterruptException","InvalidStateException","Irrational","KeyError","LinRange","LineNumberNode","LinearIndices","LoadError","MIME","Matrix","Method","MethodError","Missing","MissingException","Module","NTuple","NamedTuple","Nothing","Number","OrdinalRange","OutOfMemoryError","OverflowError","Pair","PartialQuickSort","PermutedDimsArray","Pipe","ProcessFailedException","Ptr","QuoteNode","Rational","RawFD","ReadOnlyMemoryError","Real","ReentrantLock","Ref","Regex","RegexMatch","RoundingMode","SegmentationFault","Set","Signed","Some","StackOverflowError","StepRange","StepRangeLen","StridedArray","StridedMatrix","StridedVecOrMat","StridedVector","String","StringIndexError","SubArray","SubString","SubstitutionString","Symbol","SystemError","Task","TaskFailedException","Text","TextDisplay","Timer","Tuple","Type","TypeError","TypeVar","UInt","UInt128","UInt16","UInt32","UInt64","UInt8","UndefInitializer","UndefKeywordError","UndefRefError","UndefVarError","Union","UnionAll","UnitRange","Unsigned","Val","Vararg","VecElement","VecOrMat","Vector","VersionNumber","WeakKeyDict","WeakRef"] },t={keywords:s,illegal:/<\//},a={className:"subst",begin:/\$\(/,end:/\)/, keywords:s},i={className:"variable",begin:"\\$"+n},r={className:"string", contains:[e.BACKSLASH_ESCAPE,a,i],variants:[{begin:/\w*"""/,end:/"""\w*/, relevance:10},{begin:/\w*"/,end:/"\w*/}]},o={className:"string", contains:[e.BACKSLASH_ESCAPE,a,i],begin:"`",end:"`"},c={className:"meta", begin:"@"+n};return t.name="Julia",t.contains=[{className:"number", begin:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/, relevance:0},{className:"string",begin:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},r,o,c,{ className:"comment",variants:[{begin:"#=",end:"=#",relevance:10},{begin:"#", end:"$"}]},e.HASH_COMMENT_MODE,{className:"keyword", begin:"\\b(((abstract|primitive)\\s+)type|(mutable\\s+)?struct)\\b"},{begin:/<:/ }],a.contains=t.contains,t},grmr_nginx:e=>{const n={className:"variable", variants:[{begin:/\$\d+/},{begin:/\$\{\w+\}/},{ begin:u(/[$@]/,e.UNDERSCORE_IDENT_RE)}]},s={endsWithParent:!0,keywords:{ $pattern:/[a-z_]{2,}|\/dev\/poll/, literal:["on","off","yes","no","true","false","none","blocked","debug","info","notice","warn","error","crit","select","break","last","permanent","redirect","kqueue","rtsig","epoll","poll","/dev/poll"] },relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string", contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/ }]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n] },{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^", end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{ begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number", begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{ className:"number",begin:"\\b\\d+[kKmMgGdshdwy]?\\b",relevance:0},n]};return{ name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{ beginKeywords:"upstream location",end:/;|\{/,contains:s.contains,keywords:{ section:"upstream location"}},{className:"section", begin:u(e.UNDERSCORE_IDENT_RE+p(/\s+\{/)),relevance:0},{ begin:p(e.UNDERSCORE_IDENT_RE+"\\s"),end:";|\\{",contains:[{ className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:s}],relevance:0}], illegal:"[^\\s\\}\\{]"}},grmr_properties:e=>{ const n="[ \\t\\f]*",s="([^\\\\:= \\t\\f\\n]|\\\\.)+";return{name:".properties", disableAutodetect:!0,case_insensitive:!0,illegal:/\S/, contains:[e.COMMENT("^\\s*[!#]","$"),{returnBegin:!0,variants:[{ begin:s+"[ \\t\\f]*[:=][ \\t\\f]*"},{begin:s+"[ \\t\\f]+"}],contains:[{ className:"attr",begin:s,endsParent:!0}],starts:{ end:"([ \\t\\f]*[:=][ \\t\\f]*|[ \\t\\f]+)",relevance:0,starts:{ className:"string",end:/$/,relevance:0,contains:[{begin:"\\\\\\\\"},{ begin:"\\\\\\n"}]}}},{className:"attr",begin:s+n+"$"}]}},grmr_scala:e=>{ const n={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:/\$\{/, end:/\}/}]},s={className:"string",variants:[{begin:'"""',end:'"""'},{begin:'"', end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:'[a-z]+"',end:'"', illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,n]},{className:"string", begin:'[a-z]+"""',end:'"""',contains:[n],relevance:10}]},t={className:"type", begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},a={className:"title", begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/, relevance:0},i={className:"class",beginKeywords:"class object trait type", end:/[:={\[\n;]/,excludeEnd:!0, contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0, excludeEnd:!0,relevance:0,contains:[t]},{className:"params",begin:/\(/,end:/\)/, excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[t]},a]},r={ className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0, contains:[a]};return{name:"Scala",keywords:{literal:"true false null", keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit" },contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,{className:"symbol", begin:"'\\w[\\w\\d_]*(?!')"},t,r,i,e.C_NUMBER_MODE,{className:"meta", begin:"@[A-Za-z]+"}]}},grmr_x86asm:e=>({name:"Intel x86 Assembly", case_insensitive:!0,keywords:{$pattern:"[.%]?"+e.IDENT_RE, keyword:"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63", built_in:"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0 ymm1 ymm2 ymm3 ymm4 ymm5 ymm6 ymm7 ymm8 ymm9 ymm10 ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0 zmm1 zmm2 zmm3 zmm4 zmm5 zmm6 zmm7 zmm8 zmm9 zmm10 zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr", meta:"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %if %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist __FILE__ __LINE__ __SECT__ __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__ __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__" },contains:[e.COMMENT(";","$",{relevance:0}),{className:"number",variants:[{ begin:"\\b(?:([0-9][0-9_]*)?\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*(\\.[0-9_]*)?(?:[pP](?:[+-]?[0-9_]+)?)?)\\b", relevance:0},{begin:"\\$[0-9][0-9A-Fa-f]*",relevance:0},{ begin:"\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\b" },{ begin:"\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\b" }]},e.QUOTE_STRING_MODE,{className:"string",variants:[{begin:"'",end:"[^\\\\]'" },{begin:"`",end:"[^\\\\]`"}],relevance:0},{className:"symbol",variants:[{ begin:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)"},{ begin:"^\\s*%%[A-Za-z0-9_$#@~.?]*:"}],relevance:0},{className:"subst", begin:"%[0-9]+",relevance:0},{className:"subst",begin:"%!S+",relevance:0},{ className:"meta",begin:/^\s*\.[\w_-]+/}]})});const $e=J ;for(const e of Object.keys(ze)){const n=e.replace("grmr_","") ;$e.registerLanguage(n,ze[e])}return $e}() ;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); ================================================ FILE: docs/index.html ================================================ 精益副业 - 精益副业
================================================ FILE: docs/print.html ================================================ 精益副业

精益副业

为什么副业特别重要

在很多人的印象中,副业也许只是挣点零花钱补贴家用的小打小闹。但实际上,它对于我们的整个职业有非常大的影响,甚至会改变我们的人生。

本章我们将从「职业可能性」、「职业自由度」以及「职业成长性」三个方面来进行说明。

职业可能性

职业的四大象限

2014年的时候,我做过一个「程序员拍卖」的项目。听起来很神奇,其实就是将我们遴选过的优质程序员推送给各家在招聘的公司,让他们来竞价,从而帮程序员们找到一份满意的工作。

那两年,我们为上千名程序员找到了工作。后来我把从中学到的对于程序员职业的理解写成了一本小书,叫做《程序员跳槽全攻略》

书里我创造了一个用来分析程序员职业的工具,叫做「方糖职业路线图」。它根据现金流将程序员的职业空间分布到了E、S、B、I 四个象限中,我们依次来说说。

E象限(雇员象限)、帮别人挣钱

E象限是雇员象限。别人给我们发工资,我们帮别人挣钱。这是风险最小的象限,我们的工作任务是别人分配的,只要认真完成,每个月都能得到预期中的收益。

在从开发走向高级开发后,往往就可以开始选择发展路线。E象限的典型的发展路线有两种,专家线和管理线。

E象限的优点是稳定,缺点是天花板非常明显。

S象限(自雇象限)、为自己挣钱

S象限是自雇象限,自己挣钱自己花,一般不雇用别人。比如做独立开发、组建工作室做外包和建站,甚至也可能做一些和编程没有关系的事情。

S象限最大的优点是,自己的业务自己做主,挣的钱也都是自己的。一个三五十万的外包做下来,一年的基本生活保障就有了。

S象限的缺点是,收益未必能比E象限多多少,而风险却高很多。光靠单纯的编程技能往往搞不定,还需要把接活拉活的能力、协调沟通的能力都培养起来。这些能力往往在程序员的舒适区外,需要花精力和时间去培养。因为收入是业务驱动的,所以行业的风险也会直接转嫁到我们这里。

B象限(创业象限)、让雇员挣钱

B象限是创业象限,和S象限最大的不同是我们不是自己干活,而是雇用其他人来帮我们干活挣钱。

它的优点在于,可以让我们从S象限的天花板中解脱出来,拥有规模化成长的可能性。

而缺点在于,它有一个比较大的固定成本。即使是对于轻资产的互联网公司来说,也是如此。比如人力成本。招聘、组建、培养一个团队是非常耗费时间和精力的,所以即使当业务不好的时候,我们还是需要支付大量的工资来维持团队,以便之后能快速恢复业务。

I象限(投资象限)、让钱挣钱

I象限是投资象限,是在我们有了一定的资本之后的一种让钱挣钱的方式。在B象限里,我们需要创办企业来挣钱,这需要大量的精力。即使你的精力异常充沛,同时运营三五家公司也就到上限了。I象限让我们以投资的方式参与到大量的公司中去,共享这些公司的增长,从而实现资产的增值。

在了解了四大象限以后,我们可以发现,如果赶不上公司上市这种可遇不可求的事情、或者能一路升迁做到大公司高层,先不说财务自由,光是要想在北上深买房安家,只留在E象限都是非常困难的 —— 我们必须向其他象限发展。

没有副业的职业

然而在没有副业的情况下,我们的职业就是单进程、只能做单选题。

我们在象限之间的移动,往往只能是突发式的。前一天还在E象限做雇员,第二天突然就辞职创业或者做外包去了。然而贸然进入一个新象限,将面临非常大的风险。因为每一个象限,它背后的商业模式是不同的,对人的能力、思维、精力的要求也都完全不一样。

E→B,辞职创业

先来说说「辞职创业」。

媒体很喜欢把创业宣传得一蹴而就,仿佛只要有一个独特的想法,就可以一夜暴富、咸鱼翻身。

程序员群体的理想主义趋向又比较明显,加上有无数包装出来的成功案例,所以这是程序员从E象限移动到B象限最常见的途径。

有激进派的,拿着自己的一点积蓄就英勇地加入的创业的队伍;有稳健点的,在搞定了天使投资以后再离职的。

但创业的光环在市场的面前毫无用处,要找到一个真正有商业价值的需求非常困难,往往要花很长的时间试错。而后,还要针对这个需求做出比现有方案至少好十倍的新方案。同时,还有大量公司管理、人力招聘、融资沟通方面的事务,这些都会让创业新手难以招架。

不少程序员朋友找我聊他们的创业想法,我发现他们真的只有想法 —— 完全没有进行过验证,他们并不了解B象限的生存法则。

E→S,回老家开工作室

S象限,在这里可以看成是 Easy 难度的B象限,因为自雇没有员工,可以不处理公司管理相关事务。

最熟悉的讨论就是回老家结婚,不,开工作室。我有不少北漂朋友都选择了这条路。本质上来说,这其实是一个好选择,但问题在于,如果没有做好前期准备,失败率也是非常高的。

在大公司工作的人容易产生一种幻觉,那就是把平台的能力当做自己的能力。以大公司的身份去和别人谈合作的时候,感觉都很容易。等到自己离完职才发现,同样的客户,你根本都见不到人。

我知道不少朋友都是因为高估了自己拉业务的能力,最后不得不又重返北上深。

加上全球经济放缓、美元投资减少,这种单线切换的方式又包含巨大的风险,所以很多程序员都选择了被锁死在E象限,成为永久的打工人。

我并不是说打工不好,但如果你不能较快地晋升到高级职位的话,就要仔细考虑如何应对正在形成的35岁新门槛。

副业带来的可能性

当我们有了副业,情况就完全不一样了。

因为我们从单进程变成了多进程,可以并行地进行尝试。最重要的是,这种尝试并不会影响我们的主业,不会降低我们的生活质量。

我们还是以上一节的两个例子来看。

E→S,回老家开工作室

采用副业的方式操作,我们在离开北上深之前就可以创立自己的工作室,并开始接活。一方面拓展客户,累积口碑,另一方面,我们还可以从客户的案例中提取重复需求,将其产品化、服务化。等到有了自己的客户和产品,我们在哪个城市已经不那么重要了,甚至可以在全国一个城市住上那么一两个月,一边旅行一边工作。

E→B,创业

有了副业,B象限等于完全开放了。不要纠结于是否成立了公司,那只是一个形式。真正驱动公司的是业务能力和运营公司的能力,而这些我们都可以通过副业练出来。

把创业想法以 Side Project 的方式来运作,以最简单的产品直扑最核心的需求。没有经验和所谓的产品感都不要紧,因为副业我们是输得起的。这个项目找不到需求,那么复盘以后开始下一个。那些创业公司花大价钱验证的认知,我们通过 Side Project 同样能获得,只是时间可能更长一些而已。

这种低风险的创业模式,也是非常契合当下的创业环境的。创新工场的汪华在2020年4月的一场分享中提到,移动互联网信息、交易等纯界面层的战争已经基本结束,那种靠想法和快速扩张的打法,已经很难奏效了。

所以通过副业的方式,扎扎实实地经营一家企业,靠对市场的理解、优质的产品、良好的管理和持续发展取胜,才是新时代更好的选择。

可以看到,引入副业后,我们可以以低风险、并行的方式在职业象限中移动,为职业的发展带来了无穷的可能性。

职业自由度

从中指备用金说起

前面说了副业给我们的职业带来了更多的可能性,接下来我们就来看,副业给我们的职业带来的更大的自由度。

首先是职业选择的自由。

这里我们先来讲一个比较有意思的概念,它叫做 F*** you money。这是国外的一个词,我们把它翻译成「中指备用金」。

它指的是一笔钱,数量大概是这个样子:突然有一天你跟老板闹翻了,你可以竖起中指,跟他讲说老子不干了,然后辞职回家。在这种情况下,你的生活质量也不会受到影响。

标准意义上的「中指备用金」,其实是和财务自由差不多额度的一笔钱,是以「不工作」为前提的。如果大家在北上深,要做到财务自由还是很难的。

我们这里要讲的是以「换工作」为前提的一个低配版本。也就是说,你可以随意裸辞,在找到下一份满意的工作之前,这段可能会长达半年甚至一年的时间里,没有任何收入,但你的生活品质不会受到太大影响。

很多年轻一点的同学可能觉得根本不需要这种备用金,因为现在的 90 后 00 后正是这么干的。但是当你的年龄稍微大一些,还着房贷车贷、养着老人小孩的时候,要是突然没有收入来源,压力实际上是非常大的。

而副业,恰恰可以为我们提供这么一笔钱。可能总额不大,但可以持续不断的提供。

比如我现在的课程放到网易云课堂上,即使自己不在微博去做主动的营销推广,通过网易平台上的自然流量进行的课程转化,也会有几千块钱。

我现在在重庆生活,这边房租非常的便宜,一个近七十平的小两居,房租每月不到两千。加上日常花销,也就几千块钱。所以现在即使不去上班挣钱,副业也可以在相当长的一段时间里保证我的基本生活不受影响。

这种情况下,我们就可以花更多的时间去思考自己的职业、未来和人生。去做一些短期内收入不明显,但长期收益巨大的决定。

这也就是副业带来的选择自由。

PlanB和反脆弱

除了可以给我们的职业带来自由度,副业更可以为我们的职业引入反脆弱结构。

「反脆弱」这个概念,它来自塔勒布的书《反脆弱——从不确定性中获益》。

picture 1

在书里边,塔勒布说,他之所以要专门造一个词,是因为大家往往对脆弱的反面有所误解,以为是「坚强」,也就是类似软件的「鲁棒性」。但事实上,反脆弱性比鲁棒性更棒。

什么意思呢?鲁棒性是说在风险来临的时候我们要做到不受影响。而反脆弱性更上一层楼,它说的是,当风险来临的时候,我们不但不受负面影响,还能从风险中受益,变得比原来更好。

具体到职业上,鲁棒性是说,万一现在公司发展不好,我们可以很容易地跳到平级的其他公司,继续我们之前的职业路线图。

而反脆弱性是说,当现在公司发展不好,我们可以很轻松的切换到另一个职业象限,实现跨越式的职业发展。

如果我们精心选择并发展合适的副业,它能带给我们的,正是后者。为什么这么说呢?这是由副业的天然特性决定的。因为它是我们用业余时间、在资源紧缺的情况下发展出来的。如果我们能把它转为主业,而它依然保留了对时间、资源需求不多的特性,那么这份工作就会极为舒适。

全新的工作自由度

接着上一节,我们来看看副业带来的、全新的工作自由度。这里我们多展望一下未来,主要是给大家鼓气。副业是很累的,要把别人用来休息的时间用到额外的工作上,多想想它的好处可以鼓励我们坚持下去。

当然,就像前边提过的,工作自由度最高当然是财务自由,上不上班都行,完全没有压力。我们这一节要讨论的是,在暂时还必须上班的情况下,我们可以取得的一些自由——我们就叫它「工作自由」吧。

我一般从三点上来看工作自由度:

  1. 工作地点的自由
  2. 工作时间的自由
  3. 工作内容的自由。

不同的工作方式,有着不同的自由度。

远程办公

比如最近新冠流行,很多公司都开始搞远程办公了,有些大公司甚至宣布员工可以永久远程办公。远程办公这种工作方式,就实现了工作地点自由。你可以去公司的办公室、也可以在自己的家里,甚至是在旅游的路上办公。

但是,远程办公并没有实现工作时间和工作内容的自由,你依然要和其他人同时办公,区别只是以前面对面,现在改成视频了而已。

freelancer

freelancer,就是那种在网上接单并收取报酬的工作者。这种工作方式在工作地点上同样是自由的,而且经常全部内容都是自己做,需要和别人沟通协调的内容不多,客户主要卡交工时间,只要能赶上进度,时间是可以自己安排的。所以它还实现了工作时间自由。

但freelancer没有实现工作内容自由,因为工作内容都是由客户指定的,绝大部分情况下,都不是你自己想要开发的东西。

独立开发

再来看独立开发这种工作方式。它通过售卖独立的软件、游戏或者在线服务来赚取收益。所以在工作地点、工作时间上都是自由的。

由于是自主售卖产品,它在工作内容上,也是自由的。

这里是举个例子,实际上还有很多在地点、时间和内容上都很自由的工作。比如网课讲师。

picture 2

有意思的是,正是因为这些工作自由度高,所以适合作为副业来操作。反过来,一旦实际成熟,我们可以让副业反客为主,变成主业,从而随心所欲的掌控我们的日常工作。

职业成长性

新技术练兵场

前边说的都是当职业需要跨象限的时候,副业能提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,它也能提供非常大的帮助。

首先,副业可以成为新技术的练兵场。

现在社区里边吐槽得很多的一个现象是「面试造火箭,上班拧螺丝」。去面试一个前端岗位,问一些前端框架的最新版细节、底层原理,这是合理的,属于前端的业务范围。但如果把深度学习、大数据、云原生、容器编排、区块链甚至量子计算都拿来面试,就有点装了。

picture 1

但是面试本质上就不是合格考试,而是竞争考试 —— 是要在一群人中选择最好的,所以这也还可以理解。但最不好理解的是,当我们过五关斩六将入职以后,发现这家公司还在用十年前的技术栈,代码管理用的还是 SVN。

不光是小公司、也不光是传统行业;甚至在一些互联网行业的大公司的某些部门里,也会出现这种情况。吐槽规吐槽,但为什么这种情况相当普遍呢?这其实是由于「技术债务驱动的架构更新」导致的。

什么是「技术债务驱动的架构更新」?

把时间拉回五年前,现在有一个业务需要上线,于是我们用当下(也就是五年前)最新的技术构建了这套系统。然后,随着时间慢慢过去,新技术不断涌出,但是线上系统依然能用,业务团队要求稳定;产品团队需要的是不断添加新功能;根本没有机会对技术栈本身进行大幅更新。虽然技术栈逐渐变得陈旧,但是「又不是不能用,理解万岁」嘛。在这种想法下,技术债务不断累积,直到有一天,技术债务快把整个架构压垮了,甚至业务被迫中止一两天后,公司终于决定了 —— 要重新整套系统。于是,又会选用当前时间点最先进的技术来重新开发一套全新的系统。所以你会发现很多公司的系统,它并不是持续不断地更新、不是随时保持最新;而是在新旧之间反复横跳。

由于五年中,业务变动的可能性和幅度都非常大,所以对公司来讲,重写系统是可能比维护系统更合理的。但对于那些在五年里一直用原来技术栈持续不断地维护旧系统的同学来讲,他们的技术栈被迫变旧了。

而当决定开发新系统的时候,公司又希望使用当下最新的技术栈。这就要求原系统的程序员在一瞬间学会新技术,并开发出一套稳定的系统来。大部分人是做不到的,但从公司的角度讲没有关系,淘汰掉,招聘新人组建新团队就好了,说不定成本还能更低点呢。

picture 2

所以在这种结构的架构更新里边,如果程序员自己不想办法去学新技术,不去找地方去应用新技术,那么就像温水里的青蛙,最后终会用后即弃。

我很喜欢一句话,它听起来有些残酷,但真实,也时时推动着我去学习最新的技术。

一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。 —— Stewart Brand

副业给了我们一个坐上压路机,避免被碾压的机会。程序员这个行业跟其他行业还不一样,它对新技术的要求并不只是认知,光知道新知识、了解新思路是不够的,还需要一个实打实的练手环境,花上相当长时间去踩坑,才能稳妥地做出一个稳定的方案。副业提供了一个真实业务,让我们可以把最新的技术用到上面,随时保持技术栈最新,增强主业的职业竞争力。

业务敏感度

除了技术,副业也可以帮助我们在业务上获得新认知,保持敏感性。

之前我们在做程序员职业成长服务的时候,发现了一个问题。很多初阶的程序员没法升到中高阶,有两个很大的非技术影响因素,一个是管理能力、另一个是业务理解能力。

管理能力比较好理解。每一个程序员即使把自己的潜力发挥到极致,成为十倍开发者( 10x developer),他可以处理的事情也是有限的。

但是如果管理能力好,他就可以培养出很多拥有和自己同等技能的人,这样就不只是十倍、而是可以成百上千倍地复制能力,为公司增加更多的生产力。

业务理解能力这一块,是因为在绝大部分的公司里,技术都是为业务服务的。所以需要针对业务的各种需求、各种流程来做解决方案。

如果对业务不了解,那么即使技术很不错,因为不知道某些业务细节,最后设计出来的方案可能也不是最优的。这就像我们小学时做应用题,有一个隐藏条件包含在业务逻辑中,如果忽视了它,即使数学再好,做出来的答案也是错的。

所以,程序员应该需要培养自己对业务的理解能力。但比较讽刺的是,很多公司的初阶程序员,恰恰没有机会去了解业务。尤其是一些比较大的公司,很多业务相关的问题都是在中高阶的技术决策层就已经解决掉了,分配到初阶程序员这里,就只剩下一些规划好的、待实现的技术方案了。

这就会形成职业上的一个断层,让初阶程序员无法变成行业专家。很多公司是无意的,也有极少数公司是有意为之。因为高阶的岗位是有限的,如果你成长起来后没有位置,就会跳槽了。所以,公司不培养我们的时候,我们就只能自己培养自己。

而副业正是磨练自己的好方法。我们可以做一个跟我们主业相关的副业,通过自己的项目来了解需求、理解业务,从而弄明白公司在做什么样的事情,怎样才能做得更好。将自己从一个纯粹的螺丝钉,变成独当一面的解决方案高手。

如何优雅地做副业

想明白核心资源和核心优势

在通过大量章节充分了解了副业的重要意义之后,相信大家已经明白了「为什么」。下边我们开始来讲「是什么」和「怎么做」。

在做一件事情之前,我的习惯是要想明白它的本质,弄清楚它的核心资源,了解它的核心优势。

副业的核心资源

来看我们这本书的副标题 —— 「程序员如何优雅地做副业」。它有两个重点,一个是「优雅」、一个是「副业」。

既然是「副业」,就表明我们还有一份作为「主业」的正职工作。副业只是我们从本来已经很繁忙的工作、生活时间里面活活挤出来的一点时间精力去做的业务。

所以对于副业来讲,最核心、最宝贵的资源,就是我们的时间片。

为什么这么说呢?

因为对于一家企业来讲,它有足够多的资源可以调配。它可以通过雇人的方式,批量增加可用的时间片。但是对于我们处于「副业」状态的业务来讲,精力和资源都是非常有限的。

副业本来挣得就很少,如果还要去雇人的话,每一个人分下来就会更少,会有入不敷出的风险。另外,人多了以后,在沟通上、管理上的成本也会飙升。所以副业的人应该尽可能少。

于是,时间片就成为了整个副业中,最为有限、最难拓展的资源。我们应该围绕紧缺的核心资源来规划副业。

副业的核心优势

我们的目标读者是程序员。大部分的程序员要么是在写软件、要么是在写网站、要么是在写APP,通常属于软件或者互联网行业。

软件行业和互联网行业的竞争是非常激烈的。而我们在上一节里面说过,副业它有一个先天的特点,或者说是不足,也就是我们能在这个业务上可以投入的时间和精力是非常有限的。

市场是非常残酷的,它并不会管你这个产品的制作方是个人还是公司,开发它的程序员是全职还是兼职。最终用户会以同样的标准来看评判产品,优胜劣汰。

那在一个竞争如此激烈的市场里面,一个先天投入不足的业务,凭什么可以战胜其他的项目,获得成功呢?这是我们开始之前就要想明白的问题。只有想明白了这个问题,我们在做副业的时候才是有的放矢,而不是随波逐流。

这个问题困扰了我挺久,后来在读《创业就是要细分垄断》时,里边一段话让我觉得非常有启发。

它大概意思是说,所谓的「快鱼吃慢鱼」,并不是说人家加班到晚上12点,你就天天逼着员工加班看凌晨四点的中关村。快鱼的快不是这种意义上的快,而是策略上的快。

书里还举了 AirBnb 的例子。它通过共享的方式来创造供应,AirBnb 增加一个民宿只需要几天,而连锁酒店可能要花上半年。就算连锁酒店的员工每天工作85 个小时,也赶不上 AirBnb 的速度。这就是策略上的快。

所以,回到副业上面来,如果想要我们的副业具备很强的竞争力,我们就必须根据其独有的特点,为其制定一个有竞争力的策略。

比如说,我们的副业项目往往规模不用做到特别大。因为如果我们想做到财务自由,那么1000万左右的人民币基本上也就够了。1000万这个数字对个人来讲可能很多,但是对于企业来讲,其实是一个非常小的市场。尤其对于一些以融资方式发展的创业公司和上市公司来讲,这种规模的市场根本就没有办法生存。所以,如果我们选择的目标市场足够好的话,是可以避免很大一部分公司的竞争的。

当然,即使是在一两千万的市场里边,仍然会有不少的竞争对手。我们仍然需要结合副业的特点来构造自己的优势。这里给大家介绍其中一种,叫做「副产品优势」。我们本身是有正职工作的,通过日常工作,会积累很多的经验知识和其他资源。如果我们把这些东西利用起来,把它做成副业的产品的话,它的成本是非常低的,而在深度上,往往又会有很高的门槛。

举一个实际的例子。

比如,我一个朋友是云平台的架构师,他的工作是专门为传统企业往云平台上做业务迁移提供解决方案,方便这些企业购买他所在公司的云计算产品。

但是在这个过程中,他接触了大量的、各行各业的公司的迁移需求,并为他们做了架构方案。这让他的架构能力突飞猛进,架构经验也远超旁人。

这个时候,如果他以副业的形式,开设讲授架构技巧的课程,对他来讲成本是非常低的。因为无论他做不做这个副业,都要投同样多的精力在这件事情上。

作为对比,如果一位全职网课讲师想要来做同样主题的课程,那么就需要从头开始学习完整的架构知识,并花足够长的时间,比如说几个月甚至几年,去接触大量的实际案例,最终才可能做出同样品质的课程。

而对专职讲师来讲,他的收益仅仅是课程收益,并不包含主业的薪资,所以最终收益甚至可能还赶不上他为了制作课程进行的投入。在这种情况下,全职反而成为了一种劣势,这就是我们所谓的副产品优势。

当然,我们还可以根据副业的其他特点,发掘出各种独特的竞争力。但只有围绕核心的稀缺资源进行规划,并从策略上建立我们的核心优势,才能真正做到优雅地做副业。

时间片

这一节开始,我们就来讲讲副业的核心资源——时间片。

时间片的销售

前边说过,时间片是我们副业的核心资源,所以直接把它以一个比较低的价格销售出去,是不划算的。这种方式和「优雅」这两个字不太匹配,但我们这里还是会简单介绍一下。

它不会作为我们这本书的重点,但大家有一个简单的了解也是好的,至少可以作为其他副业方式的对比。

私单

不经任何加工直接销售时间片,最主要是以「私单」的方式来进行的。

外包

传统的私单主要是外包模式。也就是说,一家公司有一个项目要做,它把这个独立项目完整的包给你。双方约定完成的时间、验收的标准和价格。大一点的项目,还会有阶段性的交付和付款。

除了这种完全线下的外包,还有基于网络的 freelancer 方式。大体上是基于网络接单,然后按发包方的要求进行开发。因为没有地域的制约,可以承接国外的业务。

目前的情况看,中国程序员在海外外包市场上并不占据优势,尤其是个人。因为现在海外接单平台上有大量的印度、巴基斯坦等国家的程序员,他们要价非常的低,而且平均而言,英文沟通能力比中国程序员要强一点。接这些单子会比较累。

做起来比较舒服、利润比较多、沟通上比较容易的私单,往往是通过行业人脉和开源项目来的。

外包的坑

大部分的外包在我看来都是很痛苦的,因为它其实和程序员的技术栈不对应。

沟通问题

我们平时在公司开发时,都是产品经理把需求梳理好,然后和程序员进行沟通,好一点的还有高保真原型。即使在这样的情况下,进行需求调整的时候,我们还是会很难受。大量的代码需要改动,如果上线时间表比较紧,我们就会被逼着加班。

而外包模式下,需求方往往就变成了外部的人群。因为个人的工作量有限,所以通常不会是特别大的单子,这就有可能遇到大量不靠谱的发包方。他们很可能并不了解开发的流程,也表达不清自己的需求。

这就要求我们有相当的沟通技巧。如果是基于网络的沟通,效率会进一步降低,问一句得等半天才能有响应。

甚至,很多时候我们会被迫去做需求分析工作,因为整个环节中缺失了产品经理 —— 很多发包方觉得根本不需要这个中间角色。

尾款问题

即使熬过了开发阶段,还有一个尾款收取问题。新手容易因为太过信任对方先交工再收钱;老手也逃不掉那种开发完了对方的创业公司倒闭了的情况。

比较大的项目或者面向特定行业的项目,在签单之前可能会有招投标,然后可能会有层层的审批。在款项的时间预期上要有心理准备,经常会有项目都做完了审批还没有走完的情况。

项目全部由自己开发还好,如果需要其他人的配合,那我们就需要自己垫付资金。这些风险需要合理的控制。

开票问题

个人做私单还有一个烦心的事情,就是大部分的单子都是需要开具发票的。这时候就只能去找一些公司代开。这种代开是有费用的,所以在定价的时候要把这些也考虑进去。

按需雇用

正是因为这种整单外包的方式会带来各种麻烦,最近开始出现一个更加「简单粗暴」的私单方式,叫做「按需雇用」。这是面向发包方的说法,对于程序员来讲其实应该叫做「驻场开发」。

我们平时都有正职工作,但是如果不是去了黑心企业的话,周末的时间还是空出来的。这时候我们就可以到其他公司去上一两天班。通常是一些创业公司,去解决一些他们的开发没有能力或者精力解决的问题。

在这种模式下,费用是按时薪结算,沟通也更为顺畅。只要像平时一样多上一天班就可以获得好几倍的回报。而且当天晚上就可以获得收入,也没有尾款的烦恼。

所以如果非要销售时间片的话,我觉得这种方式更高效一些。

更优雅的方式

但是正如我们前面所说的,你的时间片是非常有限的。像按需雇用这种方式,虽然收益看起来高一点,但它的天花板也是非常明显的。

我们可以很容易地算出来。假设我们每周末拿出一天,一个月也就只有四天而已。就算一天能挣2000块钱,一个月也就是8000块钱。

这是最理想的情况下,因为只能周末工作,所以往往并不是每周都会有活;同时,如果遇到开发内容不是特别熟悉的情况,可能还要花一点时间去学习相关的资料。

整体来讲,我们认为私单,尤其是按需雇用,属于一个中高收益、中低风险、但是也有明显的收入天花板的一个副业。

时间片的优化

时间片的优化有两个思路。

提升单位时间的收益

提升单位时间的收益其实就是提升时薪(但并不一定局限于按时薪支付的副业,其他形式可以折算成时薪),有几个简单的思路。

切换地域

「切换地域」就是说,我们同样是干活,但如果服务对象所在的位置不同的话,单位时间的收益也是不同的。

比如你在重庆,给本地公司去做一些外包,那整个项目的基础价格就是参照当地程序员的人工成本来进行比价的。但如果是在重庆可以给北京的公司做外包,那发包方就会更多地参照北京的各种成本来进行相应的股价,这样我们就可以把自己单位时间的收益提升上去。当然,需要考虑沟通的效率和成本。

把这个思路扩大一点,就变成在国内做国外的业务了。

因为和国内相比,国外的人力成本通常会贵很多,如果你在二三线城市,那么成本又更低。这样就出现了一个价格差,如果能控制好这个价格差,我们就能挣到更多的钱。

当然前边也说过,这里边有竞争和外语沟通的问题,需要根据自己的实际情况来选择。

从外包到二次开发

在没有建立起自己的知名度之前,非常单纯地去做外包,面对的往往是价格战的红海。地球那么大,总有人的时间比你不值钱。

而且外包它是一个开放性的需求,如果真要把很多雇主的需求细细做好的话,对技术栈的广度要求还挺高的。因为每一个项目它要求的技术栈可能不一样。项目做的越多,用到的偏门技术就可能越多。

所以我们要想办法解决竞争的问题。细分市场就是一个很好的思路,比如说我们可以给一些标准化的开源产品做二次开发来挣钱。

这其实不是什么特别新的思路,早在个人站长时代就有人专门给 Discuz!这个开源论坛软件写插件和定制功能挣钱,而且还真养活了不少小公司。

现在我们可以把这个思路更扩展开一些,比如说我们把从「支持国内项目」变成「支持国际知名的项目」。

这样的话,我们就能解决掉出海接活面临的大部分起步问题。

你看:

  • 我们从什么地方来获得客户?直接从开源社区获取客户。
  • 如何证明我们的开发能力? 可以写一些高质量的开源插件,给大家免费使用,并作为我们的demo。
  • 如何来获取比较高的收益?专门给一个项目写插件的团队并不是太多,选择够好的话,就可以成为这个细分领域的No.1,获得一些品牌上的溢价。

提升单位时间的效率

提升单位时间的效率对于按工作量支付的副业来说特别重要。

比如说我们现在有一个项目,交付后的收益是10万块钱。以原来的方式完成它,可能需要花100个小时。现在我们想到了一种新办法,把效率提升了10倍,那么原来100个小时才能完成的活,现在10个小时就能做完了,这就是效率的提升。

多出来的90个小时我们可以用到其他项目上,哪怕是用来休息,也是很好的。

打鸡血难以奏效

当然,通过增强意志力来强迫自己去提升生产效率,其实是很难奏效的。

因为我们本来就是在利用工作之余的时间。在这个时间上,很难保证精力非常充沛。别说提升工作效率,能保证在做这些事情的时候尽可能的不被干扰,不让自己的生产效率降下去,已经是非常不错了。

自动化

但是非常幸运的是,我们是程序员。我们从事的工作,它本身就有一部分是由机器来完成的,所以我们可以引入自动化来提升效率。机器是使用电来工作,它的效率提升空间是非常大的,而且它也不需要休息,可以7×24小时地进行工作。

代码生成器

对于程序员的日常工作来说,最主要的自动化方式就是代码生成器。

但一说到代码生成器,就会听到很多反对声音。如果你用过一些比较早期的代码生成器产品,很可能你也会会有一些负面印象。

在大概十多年前吧,我当时所在的公司也就购买了一套代码生成工具。根据说明书,配置好业务逻辑,然后就可以同时生成ASP、PHP和JSP的代码。

公司买来以后就强制性行推广,但在硬推了两个月以后,发现推不动,只好放弃了。

最主要的原因是因为它没有办法处理我们特有的一些逻辑,加上每一个部门有自己独立的规范和周边库,在那个工具里边没法用上。之后很长的时间里,我们整个部门的人都对代码生成器非常反感。

但是后来还是经不住偷懒的诱惑,我自己一直在偷偷地不断尝试。渐渐地发现,其实要做一套全世界通用的代码生成系统可能会特别难;但是如果只是给自己做一个专用的代码生成工具却非常简单,只要遵循以下两个原则。

只为自己设计

第一个原则是「只为自己设计」。

因为每一个公司,每一个部门甚至每一个岗位它所面临的需求是千差万别的,很难通过一个通用工具来解决,所以我们也很难买到为自己量身定制的工具。

但如果自己来开发工具的话,就完全不同了。我们可以完全按照自己的工作流程、按照每天写代码的需求来进行设计。我们非常清楚写代码的时候,元数据是存放到什么地方的、通过什么样的方式进行加工、以及最终要生成怎样的代码。所以可以开发出非常好用的自用代码生成工具。

能自动化的自动化,不能自动化的半自动化

第二个原则是「能自动化的自动化,不能自动化的半自动化」,后半句特别重要。

很多程序员在设计代码生成工具的时候,往往太过完美主义,老想着要做一个系统把所有的工作都做完,最好点一下按钮后,什么事情都不用去做了。

这当然是最理想的方式,但是我们的开发环境和其他的办公软件之间不一定存在交互接口,很多软件只有图形界面,不支持通过 API 进行数据交换。所以,很多时候我们就没法做成全自动。完美主义或者叫强迫症的同学就会说,既然这个东西不能完全自动化,那就直接手动来处理吧。

但我们开发代码生成器的根本目标并不是要做一个完整的自动化产品,而是要提升我们的生产效率。所以,即使有一些地方不能做到完全的自动化,我们也可以把它做成半自动化。

半自动化有两个思路。第一个思路是,我们可以通过交互方式来解决一些不能自动化,或者需要花很多时间去处理的细节问题。

举一个例子,这个例子发生的年代比较久远,现在可能已经不适用了。

我们当初在做网站的时候,有很多的资料都是编辑给的。那个年代还没有产品经理,都是由网站编辑给我们资料。他们都使用 office 软件来存放数据。

当时是没有比较好的 office 格式解析包的,所以很多同学都放弃了数据的解析,改为手工输入。我给了一个解决方案,就是直接在 office 里复制数据表格,然后再粘贴到一个 textarea 里,最后用 PHP 分析 tab 和换行符号,把数据分离出来。为了防止分析错误,还做了一个界面来进行确认和手动修正。虽然没能实现全自动,但是比起手工输入数据,这个方案效率的提升是几十倍的。所以不要过分纠结于全自动化,有的解决方案不完美,但也可以很精彩。

另外一个思路是,只对小操作做自动化,用来生成代码片段。比如说,我们在写输入处理的时候,往往需要根据数据表字段来对输入进行验证,这往往是一个重复劳动。所以,我就写了一个命令行的小工具,它可以直接读取数据表里边的字段和对应的注释,根据注释里的标记来判断对应的字段的验证信息,最后会自动生成验证部分的代码。我把这些代码粘贴到编辑器后,再进行相应的修改,就可以很快的完成验证工作。这没有什么技术含量,但是它可以切实提高我们的生产效率。

这些只是我想到的思路,当然还有很多其他的。比如有的同学是通过工具链,通过命令行交互,来实现自动化。

人工智能

代码模板呢,只能解决相对比较死板的规则。但最近随着人工智能的进步,在某些特定的场景下,原来很多低效率的人工操作其实可以交给 AI 了。

现在,AI 的正确率确实达不到和人类同等水平。但是,还是前边那句话,「不能完全自动化的,可以考虑做成半自动化」。针对 AI 正确率不高的场景,我们可以通过人机结合的方式来处理。

比如说,我们要进行图片分类,之前可能需要花上十几个小时的人工。现在使用 AI 进行分类,只需要十几秒。但是它可能有20%的图片分类是错的。

我们就可以先让 AI 来进行分类,然后再人工确认一遍。确认花的时间可能是两个小时,但即使这样,比起之前的十个小时来讲,效率也提升到了五倍。

最近很多人工智能接口的品质已经不错了。比如说,熟悉我微博的同学都知道,我经常会用语音的合成和识别服务来提升内容生产效率。

比如我经常会发一些技术视频,但是又不想自己录音,于是就会使用人工智能来生成语音。而大家正在看的这本书里,至少有一半的内容我是通过语音识别APP,以每分钟100多字的速度记录下来,然后再二次进行修改、校正完成的。

所以不管你对 AI 有什么看法,它现在已经在实实在在地改变着我们的生活。我们要思考的是,如何更好地利用它。

如果服务足够可靠,我们就可以做成自动化服务,直接提供给最终用户;如果服务还不够可靠,我们可以把它放到中间流程里来提升效率。

比如,同样是代码生成技术,如果我们把它做成面向不懂技术的人群的产品,服务不是很可靠的话,最终效果就会很惨;但同样品质的接口,如果我们把它做成面向开发者的服务,而且是在编辑器里面实时地进行代码补全和建议的工具,它就会显得非常好用,可以极大地提升生产效率。

突破时间片限制

前面我们讲了时间片的优化,敏锐的同学可能已经感受到了,时间片的限制其实是有办法突破的。下边我们就专门来讲一下怎么突破时间片限制。

倍增

第一个思路叫「倍增」,就是让时间片的数量成倍的增加。但这里有一个前提,就是不能过多的增加我们的精力消耗和风险。

因为不考虑这个前提的时间片倍增非常容易,只需要增加雇员就可以了。但我们随时都要提醒自己,这是在做副业。

如果我们雇用全职人员,就需要有办公场地、还需要到现场进行人员管理。这对于有正职工作的同学来说,是很难分身的。除非你把办公场地放到正职工作的公司附近,用空闲时间去管理。但这依然有精力上的风险,搞不好既没做好副业,又影响了正职工作,这就本末倒置了。

既然雇用全职的路子走不通,我们就只能考虑雇用兼职。

外包

主要的方式就是将部分业务外包。前边我们其实刚聊过外包,只不过在这里,我们从接单方变成了发包方。

外包的方式,可以将大块的业务交给别人去做,自己只需要花少量的时间片来做沟通和管理。等于接单方的时间片也为我们所用了,所以整体来看,时间片是倍增了。

外包还会带来一些潜在的风险。

我们的时间片是倍增了,但我们的成本也在成倍地增加,也就是说本身我们的项目需要有足够的利润空间才适合使用这种方式。如果控制不好,很可能最后整个项目做下来不挣钱甚至亏本。

另外,外包方式下,沟通和项目管理也是比较大的挑战。因为它不是那种每天在一起的沟通环境、也不是直接的上下级关系。只能以合同的形式来进行约束,很多时候甚至连合同都没有。这种情况下,其中某些环节出现问题,我们就需要为整个项目承担风险。

众包

其实还存在其他的雇用兼职的方式,比如众包。众包和外包类似,但粒度更细,接单方更多,甚至我们都不知道接单方是谁。

一个典型的例子是 Facebook 的多语言翻译工作,他们提供了一个在线翻译工具,让懂该语言的用户每人来翻译几句,因为用户数量庞大,很快就能完成整个翻译工作。

众包的收益非常不错,一方面是成本上的,因为接单方多,所以会产生竞价。如果分摊的工作量非常小,甚至可以是免费的。另一方面是时间上的,同样因为接单方多,完成的速度会非常惊人。

不过,为了支持大量的接单方,我们的业务结构需要进行相应的调整。

比如说,通常我们可以把一个系统分成平台部分和扩展部分。平台部分,我们可以自己制作;扩展部分就可以把它设计成插件、扩展、中间件,将这些东西以众包的方式分出去。即使其中的组件出问题,对我们核心平台的影响也是小的。

这样对接单方来讲还有一个突出的好处,就是这种组件本身的逻辑和它的相关资源是闭合的,只需要知道输入输出,内部实现完全可以自己决定。组件开发者之间也不需要沟通,只需要跟平台以文档、API的形式来进行沟通,在使用细节上以工单的方式来进行反馈就可以了。这可以大幅度降低我们的管理成本。更进一步,我们可以开发工具来对众包进行支持,进一步提高效率。

所以,如果能培养起好的众包生态,我们是可以实现低投入的时间片倍增的。对于不想开公司、对时间片又需求大的业务来说,是非常值得尝试的。

超卖

另外一个突破时间片限制的方式我叫它「超卖」,就是把一份时间片卖给多个人。

在很多非常个性化的业务里边,我们是为对方专门定制的服务和内容,所以一份时间片只能卖给一个人。但是,当我们业务做得足够久了之后,就会聚集起来很多有相同需求的人。

这时候我们就可以把他们的公共需求抽取出来,做一份面向这个公共需求的产品或者服务。这样的话,我们只需要花一份时间来做产品,就可以把它卖给多个人,也就间接地实现了时间片的超卖。

比较典型的例子是建站。这曾经是很多小公司赖以生存的业务。在最开始的时候呢,建站公司都是去跟客户谈,想建一个什么样的网站,然后找设计师进行界面设计,完了以后再进行开发。这种服务就是一对一的时间片售卖。

但后来很多公司发现其中重复的需求太多,于是就把建站的需求做成了一个系统。在这个系统上,客户可以自行选择模板,添加功能模块,输入内容,通过浏览器就可以很快地生成自己想要的网站。整个过程甚至不需要其他人参与。

从个性化服务到标准化服务,是实现时间片超卖的主要思路。

再举一个更明显一点的例子。熟悉我的同学都知道,网课是我一个很重要的业务。但和其他的机构不同,我从来不做直播课。所谓直播课是说,我提前准备好教学内容,等大家都上线了,然后我们在一个直播房间里边,一边讲课一边学习。相对的是录播课,是说我提前把这个内容录好,然后大家自己找时间去看视频就好了。

从讲师的角度来看呢,直播课就是一对一的时间片消耗模式,每讲一次,都要消耗一次我的时间片。而录播课则是一对多的时间片消耗模式,不管有多少学员,他们只需要去看录制好的视频就行,我付出的时间片不会增加。这也实现了时间片的超卖。

从上边的两个例子可以看出,时间片的超卖背后,实际上是商业模式的调整。

最理想的情况下,我们只需要付出一份时间片,然后即使我们什么都不做,它都可以持续不断地进行售卖。不管我们是在吃饭睡觉、看电影逛街、还是在旅行休假,这个产品都会持续不断地给我们带来收入。这种收入我们称为被动收入,能带来被动收入的东西,我们叫它资产。

资产和被动收入

什么是资产

资产的定义见仁见智了,我比较习惯用罗伯特·清崎在《穷爸爸富爸爸》里的定义,那就是「能把钱放进你口袋的东西」就是资产。换句话说,能产生被动收入的东西,其实就是资产。

《穷爸爸富爸爸》这本书很多人都读过,罗伯特·清崎后来还写了一个系列,核心是富人不为钱工作,而是让钱为自己工作

在书里边,主要通过「购买」的方式来获得资产。这里是书中列出来的资产类型:

  • 股票
  • 债券
  • 能够产生收入的房地产
  • 票据(借据)
  • 版税,如音乐、手稿、专利
  • 其他任何有价值、可产生收入或者增值潜力且有很好销路的东西

这个系列后来就跑去教人投资和理财了。

其实投资也可以视为一种副业。优点很多,比如占用精力相对较少、没有收入天花板等;但也有两个明显的缺点。

最主要的缺点是风险高,且不易评估。还有一个缺点是,投资你得先有资理财你得先有财。在风险可控的范围内,大部分投资理财的回报率差异不会特别大。如果你手上一百万都不到,可能折腾一年、背着挺大的风险也就是多挣了几万块钱。

投资理财是一门深奥的学问,我们不在本书中展开,大家可以阅读相关的专门书籍。

在罗伯特的资产清单中,还有一个可以无成本获得类别 —— 版税。但其实在中国因为书卖得特别便宜,而版权又普遍不受重视,一些大公司都堂而皇之地侵权,其实很难获得高收益。

如果没有初步的积累、或者不想背负过大的风险,怎样才能获得资产?

资产的获得方式

资产最简单粗暴的获得方式当然是通过购买。但好的资产未必人家愿意卖,当然更可能的是,我们未必买得起。

但是除了购买,其实还有一个逐渐被遗忘的方式 —— 直接「创造资产」。对于很多传统行业的人来说,创造资产会大量的消耗精力,最后成本可能并不会比购买资产低多少。

但现在软件吞噬了世界,数字化业务已经茁壮成长,数字资产的生产资料日益廉价。而我们是程序员,正是那个可以通过自己的技能栈低成本、低风险的创造数字资产的群体。

并不是每个人都有我们这么幸运,其实大部分的程序员,离完整地做出一个商业产品,缺的可能只是一点美感和设计能力。

资产的量化评估

当然,并不是所有的数字资产都适合我们以副业的方式去创造。不过就像前面不断重复的,副业是一个资源和精力都非常缺乏的状态,我们也只能从庞大的可能性中,选择那些适合的产品和服务。

适合副业的几个特征

说到底有哪些产品和服务适合副业呢?下边是我觉得值得留意的几个特征。

自传播

首先是「自传播」,就是说这个东西做出来了以后,它本身有很强的感染力,它的用户会主动地去推荐给其他用户,这样的话我们就不用花很大的成本去做营销。

对于大部分程序员来讲,把程序写出来只是时间和精力问题。写不出来程序的程序员很少,但卖不出去程序的程序员非常多。所以,如果我们做的东西本身就能传播,那么我们就可以在零市场预算的情况下获得成长。

UGC

第二类叫做「UGC」,用户贡献内容,它其实可以理解为一种更广意义上的众包。核心也是突破时间片限制。比如说我现在经营一个原创博客,天天都是自己写,就会觉得自己累得都不行了。

但如果我们去做一个访谈类的博客,弄一个相对固定的问题列表,然后拿着这个列表去采访各行各业的人,把结果做成一期一期的内容。这样用户就贡献了至少一半的内容了。

如果我们再改成办一个杂志,每一期大家根据主题投稿,你就从主创变身成编辑了。虽然投稿里有好有坏,良莠不齐,但我们的主要任务已经变成去筛选了,只要贡献内容的用户足够的多,那整体质量还是有保证的。最主要是内容的量就上来了。一个人的话,不管你多么努力,总是有一个上限的,因为你毕竟是人类。

自动化

自动化」前边有提过。

就是说应用做起来以后,它所有的环节全部都可以由机器完成,我们什么都不用管,只需要把它扔到云平台上,然后定期给云平台打钱。当然这是一个理想的情况,意外总是会出现的,而且各种意外会约好在同一天出来逛街,别问我为啥知道。但是在绝大部分情况下,我们都可以不去管它,它都可以自动化运行。这种被动资产是非常适合副业来做的。

量化评估标准

我们也可以更为量化地给资产定一个评估标准,确定好要考察的几个方面,每个方面做一个满分为5分的评分,对每一项评分就可以得到一个多边形,从而一目了然的看到各类资产的状况。

这个标准每个人的想法可能不同,这里分享的是我自己用得比较多的标准。

投入

项目的一般投入都是三项:「人」、「钱」、「时间」。

「人」和「时间」不多说,通常就是我们自己和挤出来的那点时间了。

「钱」方面,我们也需要一点启动资金,但不用花大钱去购买各种固定资产。这也是我们这个行业能自己动手创造资产的一个重要原因。尤其是现在,云计算已经普及了。即使是很大访问量的网站,我们直接租用云服务,按用量付费,省钱又省心。我大学刚毕业的时候,要是做大点的网站,还要自己去买服务器,自己扛去机房托管。现在只需要点点鼠标就能买到一堆 vps ,其实是蛮幸福的。

要提醒大家的是,一定不要忘记维护成本。我们卖时间片的时候,活干完就完了,钱就拿到手了。 但是在自己创造资产的时候,资产的每个细节基本都得自己来 cover 的,所以维护成本一定要算进去

维护成本往往不是那么显而易见。比如说吧,网课也是有维护成本的,尤其是技术类的,它的更新成本其实相当高。

产出

在评估产出的时候,可以分为「一次性的回报」和「周期性的回报」。

一次性回报,比如我们给人家做技术顾问。可能就是在周三拿到一个邮件介绍说是什么样的一个需求,有什么问题要解答。我们花上2~3个小时来准备,在周末约一个时间,面谈一个小时,把之前准备的内容聊清楚,聊完了以后,回报就拿到手了。这就是一次性回报。

周期性回报,比如说我们在掘金上写了一个小册,那只要有人在购买,我们就会不停的有收益,这种收入一般按月结,所以每次看起来没多少,但加起来还是挺多的。我之前算了一下,发现在我创造的各种资产中,掘金小册的投入产出比是最高的

可持续性

持续性是以前忽略掉的评分项,后来被我追加上来。这其实是一个非常浅显的道理,一个资产放在那个地方,它不可能一直就持续地挣钱。就像电池光用不充电的话,总会有用光的一天(别和我提太阳能电池)。

这是因为我们创造这个资产的时候,它是面对一个市场需求的,而需求本身它会随时间变动。绝大部分的情况下,需求和我们提供的解决方案之间的契合度,会随着时间越来越差。最后就会变成,要么我们就不去管它,让它慢慢地随着时间去消亡;要么我们又要花成本去维护它,把它从偏差的地方给拉回来,重新覆盖到需求上面。把用户的满意度、用户的体验、市场的趋势给重新考虑进去,让我们资产的生命期变得更长。

对于不同的资产,只是过程的快慢会不一样,但整体来讲,都是会有这么一个过程的。

风险

程序员创造产品最大的风险是「没人用」,因为虽然大部分科班出身的程序员都学过需求分析,但仍然各种喜欢拿着锤子找钉子。

当然,这对于没有做过独立开发或者自己产品的同学来讲,是一个必经的阶段。所以早期项目的风险都会非常高,但并不是说风险高我们就不做了,我们可以相对的调低投入,原来要投入三个月上线的产品,可以花三天做个最小可行产品(MVP,后文会说明)上线,测试到需求以后,再继续加码。这样也能慢慢的获取到一个平衡点。

门槛

最后我加了一个评估标准叫做门槛。因为「副业」的关系,我们的各项资源都是受限的,这个评估标准体现了受限情况下创造资产的难度。

优选资产

在这一部分,我们整理了大量的副业,并从中拿出适合程序员的来进行评估和讨论。

知识和人脉的变现

付费视频课

picture 2

总体来讲,付费视频课是一个中等投入,然后产出极高的副业。

低投入 ★

前期需要做一些课程内容的准备;后期你需要对视频进行剪辑;录音还需要购买硬件。大部分的程序员并没有视频剪辑技能,所以这里有学习成本。硬件的话倒不算贵,便宜点的不到一千就能搞定。但是这是在我们赚到钱之前就要投入进去的。

高产出 ★★★★★

从产出上来讲,课程是一个非常好的品类。中国人有良好的为教育花钱的传统,大部分的用户都愿意为好的课程花钱。一些优质的、上百节的大课可以卖到几千甚至几万。相比其他的副业,它的产出是非常高的。

可持续性 ★★

我们是做技术类的课程。技术内容本身的变更是非常快的,除非我们做一些非常经典的基础课,比如说计算机原理、算法等等。

如果是跟语言、框架、实战相关的各种前沿课程,大概半年到一年就需要更新一次。如果我们使用屏幕录制方式来制作课程,在修改的时候,很可能需要重录相当部分,修改起来成本很高。

低风险 ★★

风险不低。如果做的课程比较长,比如几十上百集的大课,用业余时间来做可能会花上几个月甚至一两年,有时候做完技术都更新了。如果最终卖不出去的话,损失是很大的。

低门槛 ★★★

门槛不算高也不算低。如果经常在公司里面给团队做分享的话,那对你来讲这个门槛就很低。如果一直都是默默无闻地在做技术的话,可能就需要去练习一下怎么讲课。

因为我们最终是可以通过剪辑来进行调整的,所以也只是一个时间投入上的问题。讲得不好,你就多讲几遍;哪一句讲错了,就重新再讲。所以它本身的硬性门槛并不高。

关于风险和维护成本这两点,其实是有办法可以解决的,我们会在后续用专门的章节来讨论,这里就不展开了。

付费专栏

picture 3

付费专栏就是付费的系列文章,绝大部分是技术教程,也有一些面向程序员的「心灵鸡汤」。我们可以简单地把它看成是传统出版的网络化。

对于技术内容来说,传统的纸书出版方式有一些明显的缺点。比如,不是彩页的话代码不能高亮,彩页的话书又特别贵。书里的代码也不能边看边调试。纸书的出品周期也较长,更新也慢,一些最新的技术会有一个较长的空白期。

而在线的付费专栏恰恰可以解决掉这些问题:它基于浏览器,自然可以通过 JS 来进行代码高亮;内容可以在线修改,几乎可以实时生效;做得细的技术专栏往往还内嵌了基于浏览器的调试环境,可以做到边学边练。

再加上原来技术博客的群众基础很好,于是技术平台和社区纷纷添加了付费专栏功能。这其中,做得比较好的应该算掘金的小册

picture 6

下面我们来看一下付费专栏作为副业资产的各项评分。

低投入 ★★★

从投入上来讲,文字专栏比视频课程投入要低很多。但是技术内容比起其他文章的写作来讲,需要有技术实践作为基础,经常还要嵌入代码,调整格式,投入相对要高些。

高产出 ★★★

文字专栏的售价普遍比视频课程要低,像掘金小册的话,一般就在20~30块钱之间,还经常打折促销。

可持续性 ★★★

前面已经说过,技术内容一般更新频次高。但是图文专栏的更新成本很低,只需要编辑文字、加入新的内容就好,不需要像视频那样重新录制和剪辑。

低风险 ★★★★

文章的创作成本很低,而且我们可以通过发布短文来测试主题是否受欢迎,在确认后再开始系列文章的书写。

低门槛 ★★★★★

只要会写文章,就可以做付费专栏。

付费社群

picture 4

所谓付费社群就是指一些收费的微信群,QQ群或者付费可见的信息流、圈子类产品。

之所以把付费社群单独拿出来讲,是因为它更偏重于销售的不是内容本身,而是一种人脉关系、社区氛围或者互动型的服务。

像付费课程,通常是类似于出版。我提供内容,你来进行学习。通过文章评论和回复进行互动,时效性和效率比较低。

而在付费社群里边,大家互动起来会比较方便。比如在群里,你一句我一语很快就可以讨论起来。所以,付费课程和付费社群其实是有互补关系的两个产品。

我们可以把付费课程放到课程平台,然后把实时的学员答疑或者其他服务,再做成付费社群。

低投入 ★★★★

付费社群的投入是非常低的。如果我们要做课程的话,需要累积相当多的内容。但是付费社群它卖的不是内容本身,所以即使它没有内容,也可以立刻进行销售。

而且因为社群的互动环境在形式上比较随意,有个什么想法随时发一段文字或者几张照片都可以,内容创作的成本很低。

高产出 ★★★

产出方面就要看具体销售的是什么东西。氛围和讨论环境本身,通常不会特别值钱。但是如果能利用起来,价值就会非常高。比如用付费社群来做中高端猎头服务。

可持续性 ★

需要持续不断的有内容更新。当然也可以引导其他用户贡献内容。如果一段时间没有内容和话题,就很难维持社群的活跃,氛围会随着时间慢慢变冷,严重影响第二年的续费。

低风险 ★★★★★

没什么特别的风险。

低门槛 ★★★★★

会建群会聊天就可以开始。

图书出版

picture 5

如果把电子书也算进来,目前可以分发图书的方式大概有三类。

第一类是自己独立撰写图书,并生成 PDF 等电子书格式通过自己的渠道进行销售。这种更类似于数字商品售卖,所以并不包含在本节图书出版中。

第二类是通过出版商单独发行电子版。因为电子书不需要印刷,所以比起纸版图书门槛更低一些。我之前用 BookDNA 出版过电子书,只需要将书提交给他们,就可以上架到亚马逊、苹果、京东、多看等多个平台。收入他们会代收,按分成结算回来。

第三类就是通过出版社出纸书,有时候也会同时把电子书版权签下来。一般纸版的门槛会高一些,需要有一定的影响力或者完成度已经较高的书稿作为参考。

低投入 ★

图书出版的投入非常大。一般至少需要花费3到6个月来编写初稿,加上审校印刷等环节,最后出版可能还需要花上半年,整个周期很长。

基于现有的内容,比如课程、文章整理创作书稿投入会相对较低,但仍有大量的工作要做。

高产出 ★★★

产出要把物质回报和非物质回报分开来看。

通过 BookDNA 等出版社专门出版电子书,可以按图书销售收入获得分成,大概在 70% ,还算不错。如果是纸版书,一般版税就只有 8%~15%,整体收入相当有限。

但纸版书对个人品牌提升的效果明显,而且可以通过线下书店等渠道获得读者,所以在非物质回报上比较高。

可持续性 ★★★★

图书的更新频次都很低,一般只有销售得不错,才会在再版时进行修订。所以我们可以认为它的可持续性还算不错。

低风险 ★★★★

主要还是时间投入,没有太多额外的风险。因为我们主要是出版技术书籍,内容方面的风险也非常小。

低门槛 ★

不管是电子版还是纸版,都要经过图书编辑审核,通过以后才能出版。尤其是纸书,要考虑至少收回印刷成本,所以门槛还是很高的。

如果在 GitHub 或者其他地方有发布电子书,且有较好的反馈,那么纸版的出版谈起来门槛就会低很多。

自有产品和服务

那接下来我们就来聊聊程序员的专业领域 —— 通过开发自有的产品和服务、作为 side project 运营来变现。

需求的发现

首先要说的是很多同学都很困扰的问题。

我以前以为最困扰的问题应该是如何抽出时间和精力来做一个项目,但后来发现还有一个同样甚至更为困扰大家的问题,那就是有了时间以后,不知道做什么。

通常来讲,解决方案有两种。

一种是通过日常的工作和生活发现原生需求;另一种是通过观察分析和阅读报告来发现。

原生需求

最靠谱的方式就是,留意那些我们自己在日常的生活和工作中遇到的困扰,然后为它去做解决方案,最后把这个解决方案做成产品,出售给有同样需求的人。

这种需求叫做原生需求,不是我们因为有了某个技术而幻想出来的应用场景。原生需求不是等我我们去寻找,而是它会主动找到我们。这种需求非常真实可靠。

但有一个问题,我们程序员相对于整个大众来讲,其实是一个非常小众的人群。这个人群有一些独特的文化、行为和思考方式。所以程序员遇到的原生需求,很可能只适合程序员人群,而不适合其他更为大众的市场。这就让它的目标市场比较小。

而程序员又是一个动手能力非常强、开源文化深入骨髓的群体,绝大部分的解决方案都能找到开源项目,或者改几行代码就能实现了。一些大公司还时不时的开源一堆非常强悍的工具,所以面向这个群体的免费或开源工具很受欢迎,但收费工具却是非常难做的。

反而是如果你在非专业领域有一些更为大众的兴趣爱好,从那些方面来发现需求的话,难度就会下降很多。

需求的验证

另外要重复强调的就是,需求的验证不能以口头承诺甚至免费用户来验。做需求分析的时候你去问,很多都会说我觉得这个东西挺好的。但你让他们付钱的时候情况就完全不同了。

大家可以回想下自己在过去一年里边,为哪些软件或服务支付超过 100 元人民币。我之前发过一篇微博问我的粉丝(大部分是程序员),后来发现绝大部分都是一些资源型的服务,比如视频会员、云主机、网课、网盘;软件就非常少了。所以我们还是要尽可能的从更广泛的人群里去发掘更值钱的需求来做。

降低起始难度

上边并不是说程序员人群的需求不能做,而是说难度比较高。

作为副业,我们投入的精力是有限的,如果一上来就是玩 Hard 模式,失败的概率会非常高。如果经常失败的话,最后就变成一种习惯了,渐渐的,也就会不再想去做副业,甚至连创业的冲动也跟着没有了,这就非常可惜。

观察分析和阅读报告

另一个路径是观察分析那些已经在挣钱的应用,阅读它的用户评论,发现可以改良的点,制作更好的产品。这个工作量还是很大的,所以也可以考虑直接购买一些分析报告。

这里的分析报告不是那种行业的通用报告,那是针对创业公司和大公司的,需要投入很多资源,以爆发式增长的方式去推动,并不适合副业。

最近在国外开始有一些专门针对副业和 Side project 的分析报告。他们收集整个市场的信息,然后针对大致一亿美金以下的细分市场做趋势分析。这种市场一般冲着上市去的创业公司看不上,所以留下了比较大的市场空间。

我最近读过报告的有两家,一家是 Trends.vc,另一家是 SoftwareIdeas.io。不过这两家本身也是初创或副业业务,不知道各位读到这本书的时候是否还在运营。这里最主要的还是给大家提供一种思路。

我们在做副业的时候,也需要慢慢来改变我们的一些习惯。比如说对于程序员来讲,绝大部分的东西都是可以自力更生的。所有能自己做的就自己做,不能自己做的,我们会找开源项目。这样我们会更有安全感,做的事情也会更加靠谱。但是我们在做商业的时候,尤其是在做副业的时候,遇到的问题就在于我们的精力是非常有限的,在价格适中、又有购买能力的情况下,更好的方式是通过购买而不是自己开发。

应用市场卖 APP

picture 5

对于我们绝大部分程序员来讲,开发是自己的本职工作,所以都比较擅长。但是在做副业的时候,我们还不可避免地需要把自己的软件卖出去。而销售往往是我们的弱项,有没有一个办法让我们可以避免它呢?

答案就是应用商店。早期的应用商店是一个非常好的入口,它会分门别类的将软件陈列在上面,有需求的用户会通过分类浏览或者搜索查询的方式来安装或者购买。

但经过一段时间的发展,应用商店里边的软件已经越来越多,各种需求被满足得也越来越充分。

现在大部分的应用商店已经是红海市场,也就意味着说,即使你在应用商店上架了软件,也不等于其他的用户有机会看见它,因为软件实在是太太太多了。

所以,我们需要想办法在应用市场的应用海洋中获取流量。一般来讲免费获得流量的途径有两个。

关键字搜索

一个是通过关键字搜索。一般应用商店都会有搜索入口,用户输入关键字,商店则会列出匹配的应用列表。如果我们指定的关键字被搜得更多,那就更容易覆盖到更多的人群。

编辑推荐

另外一个途径是编辑推荐。一些看起来有创意、格调比较高的APP更容易被推荐。而同样功能但是界面不好看的应用,则很难被推荐。所以界面设计不光是用户体验的问题,甚至还直接影响我们的获客。

虽然现在应用市场很多,但是有强用户付费习惯的国内市场,其实也就是苹果商店,所以我们如果以挣钱为主要目标的话,就应该优先考虑苹果商店这个市场。Google 在国内没有商店业务,如果是面向全球市场的业务,可以上 Google Play。

下边来看看评分项。

低投入 ★★★

从投入上来说,如果你本身不是 iOS 开发者,又没有苹果电脑,那么可能需要为 iOS APP 开发购买一些硬件,同时苹果开发者还有一个至少 699 的开发者年费。

高产出 ★★★★

一旦进入市场某个分类排行前列,可以获得的流量还是很多的。

可持续性 ★★★

需要跟上操作系统的更新升级。应用市场会定期下架一些 SDK 版本过低的APP。大部分时候只重新编译就好了,但如果使用的一些库出现了兼容性问题,那么就需要有大量的维护工作了。

低风险 ★★★★

软件应用商店托管,数据同步可以用 iCloud 等,没什么特别风险。

低门槛 ★★★

对移动客户端的开发者来讲,基本上没有门槛。其他开发者要进入这个市场,需要学习移动开发技能。当然也有桌面应用市场,但数据比移动市场差很多。

精益副业

精益副业流程

商业模式画布

前边我们说到,在精益创业方法论里,有两个非常重要的假设,第一个就是「价值创建假设」。

因为不管是向用户销售软件还是在线服务,它本质上来讲其实是一种价值交换。也就是我们「给什么样的客户」「提供什么样的服务」,然后「收多少钱」的一个简单逻辑。

而围绕着价值的定义、创造和传播,我们可以使用一个非常棒的工具来描述它,这个工具叫做商业模式画布。商业模式听起来是一个很高大上的名词,但它具体化以后就很容易理解。

商业模式画布是以价值为中心的一张图,让我们把所有和价值相关的内容都放到上面,从而可以一目了然地纵观全局。

那下面,我们就来看一下商业模式画布是怎么围绕核心价值,一层一层建立起来的。

价值的定义

商业模式的核心,就是「价值主张」。也就是刚刚提过的,对谁,提供什么样的服务,收多少钱。 picture 6

创造价值

定义好价值以后,我们会从两方面来考虑它。首先是如何把这个价值给创造出来;然后是如何把这个价值给销售出去。

在价值创造这边,我们可以把它细化为三个方面。

picture 7

包括:

  • 我们需要进行什么样的活动?这里的「活动」是「activity」,其实也可以叫做动作。
  • 我们需要什么样的资源?
  • 我们需要进行哪些合作?

销售价值

在价值销售这边呢,我们就要思考:

picture 8

  • 我们的价值主张定义得够不够好?
  • 我们的渠道通路是不是足够的通畅,到达是不是有效?
  • 我们的客户关系要怎么来建立和维系?

其实价值主张应该放到价值定义里边,但因为价值主张它直接涉及到了客户细分,又直接影响到了销售,所以我暂时把它放到销售这一边。

分层结构

按前面的描述,我们比较容易把商业模式画布当成一张图。但事实上,它其实更类似于Photoshop 软件中 的 PSD 文件,是分层的。其中每一层针对一个细分人群。

这主要是因为我们提出的价值主张,很难同时覆盖多个人群。同样的价值主张对一类人来讲可能是非常棒的东西;而对于另一类人来讲可能就毫无用处。

所以,我们提出价值主张之前,就需要进行客户细分,把我们的客户分成几类典型的角色,再针对每一类角色来提出更为具体、更有针对性的价值主张。

画布结构

下面我们就实际来看一下商业模式画布的布局。

picture 9

在表格的最中间,就是我们的价值主张。在最右边,是客户细分。我们可以用不同颜色的文字,来代表不同的细分客户和针对他们的价值主张。

在价值主张表格的左边,是关于价值创造的区域,有「关键活动」、「关键资源」、「关键合作伙伴」;在价值主张表格的右边,是关于价值销售的区域,除了我们刚才已经说过的「客户细分」,还包含了「客户关系」和「渠道通路」。

表格的最下边一行,分成了两部分,左边是「成本构成」,右边是「收入来源」,它们都是根据我们上面的表格来进行计算的。一旦计算完,我们就可以预先知道这个项目做下来能不能挣钱,或者说挣钱的可能性有多大。

价值主张画布

在整个商业模式画布里边,「价值主张」和「客户细分」是最为基础、也最为关键的地方。如果价值主张没定义好,其他的做得再好也没有用。

所以,为了更好地进行价值主张设计,我们还有一张专门针对这两个部分的、更为详尽的「价值主张画布」。

picture 10

上边这张图就是「价值主张画布」。它左边是「价值主张」,右边是「客户细分」。

客户细分

在「客户细分」这里,它更为详尽地描述了客户的情况。

这个圆分为三部分,最右侧描述了客户想要进行的工作、要完成的业务;下方是他在完成这些工作的时候所感受到的痛苦;上方是在完成工作后可以得到的收益。

价值主张

图左边的正方形就是我们的价值主张。可以看到,价值主张是针对需求提供的解决方案。比如:针对痛点,我们会提供「痛点缓释方案」,让客户在完成工作的过程中,没有那么痛苦;针对收益,提出「收益创造方案」,让收益变得更多。

在这两个方案的基础上,我们通过产品和服务的形式来将其落地,也就是正方形的左侧部分。

契合

大家可以注意到,在「客户细分」的圆形和「价值主张」的方形中间,有两个正对着的箭头,它表示「价值主张」和「客户细分」之间要达成契合。

因为我们会把整个客户群体分成多个细分群体,所以价值主张画布,它其实也是多份的。针对每一个细分的客户群体,都会有一张自己的价值主张画布。

最小可行产品和产品市场契合

上一节讲了如何通过商业模式画布来规划商业逻辑,但是「所有的战略和规划都是假设」,只有被验证以后的认知才是可靠、可信的。所以接下来,我们就需要用实验的方式来对它们进行验证。

通常,我们会采用「最小可行产品」(Minimum Viable Product,缩写为 MVP)来进行验证。

「最小可行产品」有两个关键词。一个是「可行」,它其实并不是指用户拿过去能用,而是指它可以很好地验证我们的假设。

另一个关键词是「最小」。它是说,除了验证所必需的功能以外,其他的功能都应该先不做。那些功能应该在验证完成之后再去添加,不然如果我们验证失败的话,功能就白做了。在我们的精力非常有限的情况下,这种浪费是非常可惜的。

严格意义上来讲,我们可以针对整个商业规划里边的每一个假设来做一个最小可行产品对其进行验证。但是我们的精力是有限的,所以通常只对核心假设通过MVP来验证。这个核心假设就是我们之前提到过的「价值创建假设」。

一旦这个假设被证实了,我们就认为我们找到了「产品和市场之间的契合」(Product-Market Fit,缩写为 PMF)。

具体而言,我们会在验证假设之前,定下一些量化的指标。在我们验证的时候,进行相应的衡量。最后根据指标的数据,来判断是否达到了 PMF。如果是,就可以进一步的增加功能,往前推进;如果不是,则需要调整,甚至需要通过战略转型来重新找到 PMF。

这种转型可以是针对原有市场的细分市场重新提出价值主张;也可能是扩大需求,让它支持更广泛的人群。但无论如何,在找到 PMF 之前,我们都应该专注于价值假设的验证,而不是功能的丰富和市场的推广。

精益独立开发实践

前面我们给大家介绍了精益副业的基本概念,因为只有理论,所以看起来可能比较抽象。

从这一章开始,我们就以实际的副业实践为例,看看如何使用精益副业流程贯穿始终,多快好省地发展副业。我们安排了两个深度实践,一个是独立开发、一个是网课。下边我们开始第一部分。

独立开发的精益流程

picture 1

前面我们了解了精益创业的一些核心理念,接下来我们就在「独立开发」这个更为具体的副业活动中来看看如何应用精益流程。

这个流程和很多硅谷公司的产品流程很像,但是针对副业做了一些调整和优化。经过三年多时间的使用,我们自己用起来已经很顺手。

  1. 首先定义价值主张,然后围绕着价值来设计商业模式画布。
  2. 完成画布以后,我们把画布里的「客户细分」部分拿出来,做成「用户画像」。这是一个将细分客户具体化、变得有血有肉的工具
  3. 有了画像,再据此还原用户使用产品的各个场景,他们是用电脑还是用手机、是在家里还是在车上使用等等。
  4. 想象为了在上述场景下向用户传递价值,我们需要什么样的功能,这样就会得到一个功能列表
  5. 功能列表会很长,不同功能的优先级也不同。所以我们会对功能进行分期,其中最重要也是最靠前的一个功能分期,就是用来开发「最小可行产品」的分期。
  6. 当「最小可行产品」开发完成后,进行「产品市场契合」的验证,如果达不到设定的验证目标,就需要调整功能,甚至重新设计价值主张。
  7. 当通过「产品市场契合」后,我们就可以按照分期迭代开发产品的其他功能了。
  8. 在迭代过程中,我们会持续对新上线的部分功能进行增长优化,保证每一部分功能达到预定的目标。

以上就是我们为独立开发优化的精益流程,虽然讲起来比较多,但实际操作起来还是比较简单的。而且我们其实省略了不少大公司流程中的环节,比如用户访谈、焦点小组等。

下一节开始,我们将用一个具体的例子来讲解。

福利单词项目简介

先来介绍一下我们的实战项目 —— 福利单词。

它来自于我在学习过程中的一个原生需求。最开始我是使用 Anki 这个软件来背单词,软件很好用,但是每次都有一种逼着自己去背的感觉,背完以后如释重负。为了提醒自己不要逃避,我还定了一个闹钟每天催自己。

有一天,我又因为上Pixiv(一个二次元内容创作社区)看图忘记了时间。突然间我想到,能不能把背单词和看图片这两个行为绑定到一起呢?

你看,背单词虽然有用,但让我痛苦,度日如年;看图片很欢乐,流连忘返,但似乎不是很「有用」。如果我们把两者结合到一起,一边看图一边背单词,是不是就可以让背单词不那么难受,可以持续不断地背下去了?

这就是福利单词的出发点。

接下来,我们就来看看,怎么从这个还有些模糊的想法中提出一个明确的价值主张,然后围绕它进行商业模式规划、功能和界面设计、验证和迭代开发,最终使其成为一个商业产品。

picture 2

需要说明的是,开发过程很难在有限的篇幅中讲解清楚,也偏离了本书的主题,所以我们只会简略地提及一些需要注意的地方,并不会进行开发的教学。

福利单词的商业模式画布

前边我们已经讲解过商业模式画布,这一节我们就以「福利单词」为例,来看看怎么使用。

价值主张

picture 3

首先来看一下价值主张。它的核心价值就是,让那些觉得学习起来很痛苦的人不那么痛苦,给一点糖,让其可以持续地、无痛地学习下去。它试图给学习过程添加一些乐趣来综合不是那么爱学习的人的痛苦,从而把一个短暂的、难以忍受的学习行为变成一个可以持续忍受、甚至通过习惯驱动可以持久化的行为。

所以我们在「价值主张」这一栏上写上两个关键字,一个叫「无痛学习」,一个叫「持久化的学习」,这是这个产品最核心的两个「价值主张」。

有了这个价值,我们就能帮助客户完成很多以前想学、但是因为各种原因没有办法学下去的东西,从而实现其个人成长和提升。

客户细分

picture 4

如果要具体化价值主张,就要来看客户细分。

因为是单词学习软件,所以客户群体往往还是跟学习英文需求相关的。具体划分下来,我觉得可以分成三大类。

  1. 第一类是在学校要考英语四级或者六级的大学生。
  2. 第二类是有留学或者移民需求,需要考雅思、托福的群体。
  3. 第三类是需要专业英语来提升自己在职场的业务能力的上班族。

前两类群体是要备考应试的,后一类则更注重实用能力的提升。从学习的内容上来讲,只是题库的不同。所以如果我们的软件支持了「词库切换」或者「自定义词库」功能,就可以比较容易地覆盖他们的学习需求了。

价值主张的细化

picture 5

光是「有词库,你来背」这个主张和其他背单词软件并没有什么不同,所以我们需要在「价值主张」里再加上「糖」。

但是,对于不同的群体来讲,「糖」是不一样的。如果只是放一些二次元的萌妹子,只有喜欢动漫的人会觉得这是他们的「糖」,可以吸引着他们,每天都来看一看。对于其他一些二次元无感的人群来讲,这些图就毫无吸引力,于是我们需要增加「糖」的种类。

比方说有的妹子就喜欢看帅哥、有的粉丝就喜欢看偶像、有的铲屎官就喜欢看猫猫狗狗、有的吃货就喜欢看肉和甜点。这一部分,我们可以用多图库的方式来满足。

于是,针对不同的客户细分,我们提出三个更为细化的价值主张:

  1. 「每天看40分钟妹子,一个月记住四六级词汇」
  2. 「看着帅哥,把雅思托福词汇搞定」
  3. 「一边云吸猫一边升职加薪」

现在听起来是不是就有吸引力多了?

渠道通路

picture 6

在「渠道通路」的这个方格里面呢,我们的种子用户主要由微博带过来的流量构成。

通过种子用户进行测试,一旦转化率达标,我们就可以开始对外去做一些合作,以及以微博为起点投放广告,观察广告投放的成本和其带来的流量的关系,以此判断下一步操作。

客户关系

picture 7

在「客户关系」这里,我们会通过腾讯提供的「兔小巢」这个产品来提供售后支持。它是类似于反馈板的免费工具。用户在上面提交问题,我们会收到微信或者QQ的通知,可以通过网页在电脑上或者手机上进行答复。

关键活动

picture 8

接下来我们来看一下「关键活动」。

用来验证需求的最小可行产品(MVP),是一个简单网页,只包含 100 个单词、100 张图片和简单的输入文字切换图片功能即可。我们还需要一个统计数据,看看每一个访客到底背了多少个单词。这关系到我们价值主张里的「无痛」和「持久」。

当这个价值被验证后,就可以进入第一期开发。

虽然是一个全平台应用,我们第一期却只做网页版。具体业务包括:背单词的界面,以及选择词库的界面。这是最核心的业务功能。如果我们第一期想要有收入,那么就需要支付和订单系统。

为了对转化过程进行分析、更好地挣钱,我们还需要开发一个2A3R漏斗的统计,让用户从获客层顺利滑入付费层。如果需要通过分享裂变获取更多流量,我们也需要统计发起分享的用户数据。如果要允许用户自定义词库,我们就要提供对应的制作工具。

以上这些,构成了我们的关键活动。关键活动可以采用不同颜色的文字来标记不同的分期,也可以一期一期追加。

关键资源

picture 9

在关键资源上,除了需要具备人、钱和时间以外,我们这个项目还有特有的资源需要考虑,那就是背单词所用的图片,这是一个非常值得注意的问题。

在最小可用产品中,因为不涉及到收费,我们可以使用的图片很多。一旦开始收费,如果还是不加识别地从网上下载各种版权不明的图片,放到自己软件里并以收费的方式进行售卖,很可能会出现侵权。

所以,我们就需要思考图片资源的解决方案。粗略分析后,有以下几种思路:

  1. 作者授权
  2. 换用无版权图片
  3. 用户自行提供图片

作者授权

直接找作者把图片买下来,然后作为付费词库卖给用户,这是最直接的方式。但有问题,那就是价格,光是大一点的词库就有超过一万个单词,也就是说我们要买一万多张图。如果按一张图 50 元计算,需要 50 万的投入。

在一分钱都还没挣之前就做出这么大的投入,风险还是很高的。这种方式更适合我们挣到钱以后,在扩大规模时使用。

换用无版权图片

当然,我们也可以寻找无版权的图片来做图库。这样即使我们打包在软件里进行商业销售也不会有任何问题。互联网上已经有比较庞大的无版权高清图库了,比如 Unsplash 等。不过这些图库主要是风景和动物,人物类非常少。

用户自行提供图片

本质而言,我们卖的是「看图背词」的工具,而不是图片本身。现在之所以在版权上有风险,是因为打包导致的。所以我们可以尝试着将付费的服务和免费的图片分离开。

比如我们可以给用户提供自定义图库的制作工具,让他们把自己收藏的图片导入进去。这样既能达到目的,又没有版权上的风险。

类似需要考虑的,还有背单词时用到的音频。最简单粗暴的方式是使用云平台的TTS(文字转语音)接口直接生成。

成本收益

picture 10

在填好这几个格子以后,我们就可以开始对成本和收益进行相应的预估,算出预期利润区间。

由于我们开发的项目相对比较小,用到的资源也不是特别的多,所以商业模式画布做得还不算细致。不过通常来讲,第一版的商业模式,画布本身也不会特别细。它是随着项目的进展不断被细化的。

最后我们来看看完整的商业模式画布:

picture 11

通过用户画像细化客户

什么是用户画像

在商业模式画布里面,我们对客户进行了细分,把客户分成了不同的组,每一组代表一个独立的需求。

用户画像(persona)呢,就是给这些已经分好的组,每一组搞一个人设、建一个虚拟形象,让其变得有血有肉、有姓名有年龄有性别、有自己的身份有自己的爱好、有使用产品的场景。

这样当我们聊到这个用户画像的时候,就像在讲自己的朋友、同事一般熟悉的人一样。

把抽象的需求变成活灵活现的人,这样我们在进行产品设计的时候,就更容易还原到场景,带着画面去想象这个人的需求和行动,这就是用户画像的意义。

福利单词的用户画像

接下来,我们就在福利单词的客户细分基础上,为每一类客户建立用户画像。

四六级备考生

首先是备考四六级的大学生这个细分客户群。我们叫他王小康,设定为一个大三的男生。他现在有一个迫切的任务,就是一定要通过四级考试。这位同学是一个动漫宅,他喜欢看的图就是二次元的萌妹子。

留学移民预备军

然后我们来给有留学移民需求、需要考雅思和托福的人群做一个用户画像。我们叫她章小留,她是一个大学刚毕业一年的女生,现在有出国留学的想法,正在准备雅思考试。这位同学是追星族,喜欢看的图片是韩国帅哥。

专业提升小白领

第三个细分人群的用户画像,我们叫她卢小白,是一个毕业两年左右的女生。在生物公司从事技术相关的工作,她需要尽快熟悉大量的生物专业方向的英文单词,方便她更好地了解公司业务。她家里有猫,喜欢看的图片是萌宠和美食。

确定了这三个用户画像的基本资料以后,我们会给他们配上头像,写上他们的需求关键字,把它整理到一页A4纸上。

这样我们就可以把它打印出来,贴到墙上,在做产品设计的时候可以随时去看他们,就像看着我们身边的熟人一样。

画像的头像制作

很多书里面都强调说,用户画像的头像要尽可能真实,最好用真人头像。但需要注意在网上乱找真人头像容易导致肖像权问题,这里给大家推荐一个通过AI生成真人头像的网站,叫做 thispersondoesnotexist.com。

picture 12

不过这个网站生成的多是欧美人,对国内的产品来讲,反而各种违和。我更喜欢使用日系的动漫捏脸网站来做,比如 charat.me 这个网站。

picture 13

最终的用户画像

有了头像,再配上角色的说明和需求关键字,我们就有了一个简单好用的用户画像。下边是我们制作好的三个画像:

picture 14

picture 15

picture 16

画像→场景→功能和分期

使用场景分析

有了栩栩如生的用户画像,我们就可以从画像想象出场景,再由场景梳理出功能列表并进行分期。下边我们就具体来看下怎么分析使用场景。

王小康的使用场景分析

首先是王小康的使用场景,包括在学生宿舍、在图书馆以及在课堂上。

在宿舍,他每天晚上八点到九点使用台式机。因为宿舍比较吵,他会戴着耳机学习。这时候他使用的是外接键盘。

晚上睡觉之前,他还会窝在被窝里玩一会儿手机,时间大概是晚上十一点半到十二点,也就是睡觉前的半个小时,这时候的使用场景就是用手机背单词。

图书馆也是一个典型场景,因为在这个环境里边,需要保持安静。所以你要么戴耳机,要么将设备调成静音。王小康一般是下午三点到五点去图书馆自习,这个时候他使用的是笔记本电脑和 iPad 。

需要注意的是使用 iPad 的时候是没有键盘的,所以在输入上面没有使用外接键盘方便,整体输入速度会下降很多。

图书馆和学生宿舍是两个相当不同的场景。宿舍里很可能有室友在玩游戏或者聊天,很容易分心,甚至连背单词这件事都很容易忘掉,所以我们需要有提醒。

相对而言,图书馆就是安静的沉浸式环境,没有人来打扰你,大家都在忙着学自己的东西。

章小留的使用场景分析

下面我们来做章小留的场景分析。

她现在辞职在家,完全是备考的状态。每天上午会在家学网课、或者去线下的培训班学习,下午会在家学词汇。晚上的话,可能要看韩剧。

主要场景在学词汇的下午。因为是在家里边,她使用的是台式机,鼠标和键盘都是外接的。每天早上起床的时候可能也需要复习一下。

所以她的两个主要使用场景是使用电脑学习,以及早上起床时用手机进行复习。

实际上,这个场景和王小康在晚上用手机复习的场景非常类似,可以都写上,最后进行功能合并时,重复的内容会被合并掉。

同时,因为这两个用户都是在备考,所以他们其实还有「考试复习」这个特殊场景。

在这个场景里,它的词库是有范围的,不一定是整个词库。而背单词的时候,需要有一个考试模式,限时答题,并给出得分。这些需求我们不一定都要通过福利单词这个产品来满足,但可以先写下来。

卢小白的使用场景分析

小白是上班族,所以学习时间是非常有限的,主要是在上下班通勤的时候学习,以及在周末的时候有一点空余时间。

通勤场景一般会在地铁上。运气好的时候就有座位,运气不好的时候还需要站立着。这时候她会使用手机和耳机来学习。

因为她的词汇学习主要是为了工作需要,所以在工作的时候可能还会有查词的需求,可以通过词典软件解决,但是她可能会想把生词加入到福利单词来记忆。

大部分时间地铁里是很挤的,有时候需要一个手扶住上面的吊环或者旁边的柱子,所以小白可能需要单手操作。

另外要意识到小白只是一个典型代表,她需要的是生物类的词汇,但是其他的上班族需要的词汇可能会覆盖各行各业,这部分的词库需要通过自定义词库来解决。

同时,小白很喜欢宠物,当她看见可爱的喵星人时,很可能希望将这个图片保存到相册。这里如果再结合到我们上面的考试模式的话,其实可以做得更游戏化一些。比如说我们可以加入一个图鉴,就是一个画册,里边有每一个单词对应的图。只有你对这个单词达到一定的熟练度以后,才能在里边看见。大体上这就是小白的使用场景。

从场景到功能

现在我们三个用户画像的使用场景已经分析完了。接下来,我们就可以根据场景来确定功能了。也就是说,为了满足这些场景下的需求,我们在产品上需要提供哪些功能来支撑。

在确定功能的时候,有两类需要特别注意。一类是核心功能,没有它,所有画像都没法使用我们的产品。另一类是边界功能,没有它,某一个画像就没法使用我们的产品。核心功能是交集、边界功能是并集。

我们会根据画像的设定,将一些边界功能分配给他们。比如说,为什么卢小白她就会想保存图片到相册,章小留就不会呢?事实上章小留也会,但我们不需要把一个边界功能重复分配,因为最终都会覆盖到。

画像需要注意的是它特有的场景,比如考试模式是备考生的特有场景。对于不考试的同学来说有没有都无所谓,但是对考试的同学是非常有用的。

我们把边界功能标记出来以后,就可以框定一个大体的功能范围。

比如说,章小留使用的是苹果台式机,这就要PC版需要同时支持 Windows 和 Mac 两个操作系统。路小白上下班通勤的时候是单手操作,我们在手机上设计浮动键盘时,就要考虑到小屏幕手机上26键的全键盘单手时容易按错的问题。

对于卢小白来讲,她的空余时间不多,所以可能还会利用家务和健身的时间,这个时候如果她想复习单词,可能还有一个语音播报的需求。

章小留是追星族,那她在网上看韩剧的时候,会顺便把喜欢的偶像的图片给保存下来,制作成词库,甚至还会分享给同好。

这些都是边界功能。在早期设计的时候,可以先不考虑工期、开发量这些很现实的问题,我们可以先把它放进来思考,至于做不做、什么时候做,那是以后的事情。

我们要做的东西在早期应该尽可能的少,但是思考的范围却应该尽可能的广。我们是把很多东西都想明白了以后,选其中最核心的、最重要的来做。而不是说很多东西我压根就不想,只做眼前看到的那一丁点就开始做了。这样到项目中期,就会出现很多思考上的盲点,这些盲点甚至会导致我们的项目重做,所以需要尽可能避免。

通过思维导图梳理功能

我们可以通过思维导图软件来梳理功能。

想象一下新用户从什么地方开始使用我们的软件,跟着他的使用流程来同步构建功能。

比如说,首先会需要有一个用户系统,这样我们才能识别用户。接着我们肯定需要有词库,不然就没有单词可以背了。我们肯定也需要有单词的背诵、管理,如果我们要收费的话,肯定还需要有支付。

用户系统里边,我们考虑使用微信登入,这是目前最简单的办法,不用做用户系统、也不用做密码找回。有了登入肯定也得有退出。

有了用户系统以后我们就可以保存用户背单词的进度了。在词库这边呢,既然我们要做一个可切换和自定义的词库,那肯定会有一个列表。

这个列表,首先是会有一个官方的或者叫内置的,然后我们在建立一个本地的列表,给自定义词库用的。

自定义词库这边,我们可能还需要给提供一个工具来制作词库。我们需要有一个单词表、需要生成对应的音频、需要有对应的解释,以及我们背单词的时候看的图片。这是词库的大体功能。

如果我们要做图鉴的话,就需要有词库的完成度数据。就是用户背了词库里面百分之多少的单词、以及对每一个单词的熟练度。在这个基础上我们还需要有一个相册,用来欣赏高清图片。

自定义词库制作完成以后,它还需要有一个分享方式。我们可以允许用户通过二维码分享,其他的用户通过二维码扫码导入。

接下来,我们来看背单词的功能。

首先它需要有一个地方来输入字母,我们会根据输入的字母动态地进行遮罩的调整。然后我们需要把用户输入的时间或者错误的次数统计起来,这代表着对这个单词的熟练程度。我们也还需要有一些辅助按钮,用来显示单词的意思、以及跳过不会的单词。

在最后,当正确地输入了单词以后,我们需要显示一个高清图片,让用户可以很完整地看见这张图片,这是对其的奖励。

另外我们也需要把用户的背单词成绩记录下来,为了能更清楚地看见这个成绩,可能还需要提供一个进度统计,告诉用户背了词库里面的百分之多少,各自的熟练度是多少。

还有支付部分别忘了。首先我们要显示可以付费的商品,当点击购买按钮以后,要把微信支付给呼叫起来。在微信支付完成以后,要进行确认。同时我们也需要维护一个订单列表来进行售后和退款。

分期

确定好功能表以后,接下来就可以进行分期了。

功能分期

因为我们现在的功能实际上已经非常多了,必须要把它分成不同的阶段来做。最小可行产品不太典型,这里我们以 PMF 验证完成后的第一个版本为例,来选择第一期的内容。第二期就是「以后再做」的功能,第三期就是「不知道啥时候做」的功能。

来看我们的功能列表:

  • 推送提醒:可以放到第一期。但为了实现推送,需要有消息系统。如果要做定时提醒的话,还需要做设置界面。因为用户设置过提醒以后,可能有一天不需要了,要能及时取消,不然天天推送还挺烦人的。
  • 考试模式:放到第二期。虽然对备考生很重要,但是因为整个开发量比较大,在挣钱之前可以先不做。
  • 虚拟键盘:放到第一期。为了支持单手操作,我们需要给背单词的界面添加在移动设备上的键盘界面。不同输入法的键盘可能会导致兼容性问题,所以我们直接通过一个虚拟键盘来解决它。
  • 自定义词库分享:放到第二期。
  • 图鉴模式:放到第二期,也可能是第三期。
  • 语音回放:放到第二期。

picture 17

确定分期的时候,也要同时检查功能点是否都对应上了。比如支付里面,我们需要把「微信支付的对接」加上。

功能归类到界面

确定好某一期的功能列表后,可以把各个功能归类到界面里。新建一个思维导图,写上显而易见的各个界面,然后把功能放到界面下去。

如果发现有功能没有界面放,恭喜你提前发现了做丢的界面,赶紧把这个界面也加进去吧。

picture 18

这一步完成以后,我们就可以开始进入设计阶段了。

什么是好的商业设计

这一节开始我们会讲一些设计方面的东西。和专业的设计课不同,我们主要着眼于如何让非专业设计人员也能做出七十到八十分的设计。

首先我们来和大家聊一聊,什么是好的商业设计。

好设计的标准

要做好一件事,首先要弄明白好的标准是什么,而这恰恰是讨论设计时的一个难点。

为什么呢?

我们写程序做软件,好不好是有一个相对可以量化的指标的。比如:用了多少行代码,执行了多久时间,占用了多少内存、在一秒以内可以承受的并发请求数是多少。这些都可以很精确地衡量出一个程序是否写得好。

但是,对于设计来讲,它是一个很个人化的东西。同样一个设计,有的人会觉得它好,有的人会觉得它不好,还没法说谁对谁错。甚至有一些艺术家,他的作品可能在当时就没有人能够理解,隔了很多年大家又把它拿出来,才发现惊为天人。

这就造成了一个问题,设计到底应该按什么样的标准去衡量?不光是设计师本身需要思考这个问题,设计需求的提供方其实也需要去思考。

商业设计

但是后来我们发现,如果把设计的范围给缩小一些,就可能得出一个部分适用的答案。

艺术这个东西它确实是千人千面的,因个人的感受而异。但是我们为商业产品做的设计它并不等价于艺术,大部分情况下它是为商业服务的,我们就叫它「商业设计」吧。

一个好的商业设计,其实就是要让尽可能多的客户喜欢它。因为,喜欢上我们设计的人,很可能也会喜欢上我们的品牌和产品,最终转变成商业价值。

至于这个设计在艺术上深刻不深刻,完全是另外一个领域的事情。

这里有一个比较极端、但大家也很熟悉的例子,那就是椰树椰汁的产品设计。它基本上是把美感给扔了,但换取了很好的识别度,这就是一种商业上的权衡。

我们写程序的时候,要从代码思维上走出来,回到商业思维的角度上来;我们做设计的时候也要从设计本身走出来,从整个商业链条的角度去思考。

通常来讲,我们会面临的抉择,往往是在两类截然不同的设计之间。一类剑走偏锋、足够深刻,能理解它的一类人特别地喜欢,而不理解的又特别讨厌它;另一类设计,看似中庸,然而平中见奇,不同层次的人都可以看到自己喜欢的点。

如果这个设计要拿去参加艺术大赛,可能前者更合适。但如果用于商业产品,那我觉得应该选择后者。因为归根结底,它是用来承载功能、向客户传递品牌质感的,而不是要体现它自身有多深刻,那样反而喧宾夺主了。

简洁即美

每个人的兴趣和爱好都是不同的,要做一个设计或者塑造一种风格,让绝大部分人都喜欢上是很难的。但我们幸运的发现,设计如果足够简洁的话,就不容易包含太多触发各种反感的点,更容易获得绝大部分人的喜爱。

而对于副业来讲,简洁风格的方案所需要的设计和开发资源都相对较少,配合起来又比较容易协调,所以简洁风格是我们的首选。

人人能用的四大原则

界面设计是很多尝试自己开发完整产品的程序员非常痛苦的事情。很多时候,如果我们去问设计师,很多人虽然会设计,却讲不出背后的道理。只会说,「这样做感觉上更好一些」,「这就是经验/灵感」。

我以前也是这么认为的,直到读了一本书才明白,原来界面设计背后一样是有规律的。

界面的表层结构展现的正是它内部的逻辑。

一个界面上应该摆放哪些控件,哪几个应该离得近,哪几个应该离得远,哪些应该用同样的风格,哪些又应该区别开来,这些都源于它背后严密的逻辑关系,而不是因为设计师的一时兴起。

那本书就是《写给大家看的设计书》。在书里,作者提出了界面排版的四个基本原则,通过活用这四个原则,我们就能够把界面设计得美观大方。

这四个原则分别是「重复」,「对比」,「对齐」和「亲密性」。

  • 「重复」原则强调「一致性」,它说的是「在逻辑上一致的物件,在视觉上也应该一致」。
  • 「对比」原则强调「层次感],它说的是「逻辑上不同的物件,在视觉上也应该不同」。所以我们要想办法拉出距离来。
  • 「对齐」原则强调的是「安定感」。均匀的留白能够营造出一种稳定的感觉。这正是产品质感的一种潜意识渗透。对齐虽然是很小的细节,但是如果处理不好,很容易会破坏产品整体质感,而且会给有强迫症的朋友带来莫大的压力。
  • 「亲密性」原则,强调区块的关系,它说的是「逻辑上存在很近的关系,那么这个关系也应该表现在视觉上」。相关的项应该彼此靠近,不相关的项应该彼此远离。

书里有非常详尽的介绍和让人顿悟的例子,建议大家都去阅读下原书。

picture 19

四大原则回答了常见的一些界面问题。比如说,上图中,白色方块之间的间距为什么不能比第一个方块和页面边界的距离大。

如果从纯感性的角度来讲,可能会说「这样放不好看」。但是如果通过亲密性原则来思考的话,我们会发现在逻辑上,相对于页面边框,白色方块是一个整体。一个白色方块和另一个方块的关系,显然比它和页面边框近。所以这种深层关系表现在视觉上,就是它们之间的边距差异。

如果视觉关系和逻辑关系不一致,我们就会觉得「别扭」、「不直观」。这些原则为我们通过逻辑理解设计推开了一扇门,让之前仅存于「感觉」和「经验」的设计技巧变得有章可循。熟悉它们以后,只要多加练习,再配合上一些简洁、清爽风格的设计细节,我们就可以在大部分场景下做出七十到八十分的界面来。

picture 20

独特Logo解决方案

接下来讲下,如何设计产品的 Logo 。

最简单的方式当然是请设计师来设计,我们只需要像产品经理那样在背后指指点点,改需求、当甲方就好了。但是,在做副业时,我们很可能没有足够的预算去雇佣专业的设计师。尤其是在软件还没有获得收益之前,如果花很多钱去请设计师设计,而产品本身又运营不起来的话,钱就白花了。

所以,学会自己做一些比较简单能用的 Logo 还是很重要的。等以后挣钱了,可以再花大钱请高手来重新设计。

Logo 的设计还是有些考验绘画能力的,即使是相对简单的简笔画,对于很多没画过图的程序员来讲,也挺难绘制一个像样的出来。

如果你有一定的绘画基础,或者想发掘自己隐藏的天赋,那么我特别建议大家用矢量软件来绘制,对于像我这样手残的同学来讲特别有用。

我最开始画 Logo ,是给自己的开源项目。刚开始使用的是像素绘图软件。由于缺乏练习,即使使用数位屏,也很难绘制出光滑的线条。即使偶尔画出来了,要调整它时,又会花费大量的时间。

后来我发现了矢量绘图软件,在它里边,我们绘制的其实不是线条,而是一个个形状。线条是我们指定的形状的边界,可以通过描边自动生成。最棒的一点是,当我们改变形状时,线条就自动随之变动,无需再重新绘制。

只要熟悉了形状的画法,我们就可以通过矢量绘图软件来绘制一些简单的、线条光滑饱满的图案了。

picture 21

作为对比,上图左边是我用像素绘图软件绘制的头像,右边是后来我用一个周末学习完矢量绘图软件后花一天时间重新绘制的。真的是好用太多了。

免费和开放的矢量资源

当然,不是所有同学都有时间和精力去学习绘图的,所以我们还是回到适合更多人的方案上来。首先,我们可以使用网上的开源矢量资源。最近两年开始出现一些视觉效果非常不错的矢量插图网站。

picture 22

比如 unDraw,它就提供大量的适合互联网和软件场景的开源矢量插图。更贴心的是,在网站右上角还提供了颜色按钮,通过调整颜色,我们可以得到和自己产品风格更为统一的矢量图。

一个需要注意的地方是,如果使用免费素材,一定要留意不要从国内那些没有注明作者和授权的网站上下载。因为这些来历不明的素材很可能给你带来版权风险,说不定哪天巨额索赔就找上你了。

购买付费素材

如果没有好的免费备选,或者没有太多时间去各个网站上挑,我们还可以通过购买的方式来获取素材。

picture 23

在购买素材的时候,要注意使用的限制。有的网站的素材是会限制使用的项目数、域名、甚至媒体类型的。我推荐大家优先购买采用「royalty-free」许可的网站。这种许可非常开放,往往只要付费就可以永久使用。

提供付费矢量图标的网站比较多,比如 flaticon.com ,thenounproject.com 都是比较有名的。我个人一直订阅的是后者,提供的图标够多,价格也比较便宜。它还提供了一个电脑客户端,可以很方便的搜索、复制粘贴图标文件。

这个网站目前提供的图标都是没有颜色的。当然这一点可能对我们来讲,并没有太大的影响。为什么呢,因为直接使用这些网站上的图标做 Logo ,会带来一个潜在的问题。

将付费素材变成独有的

这种买断式授权的素材非常好用,但是既然我们可以花很少的钱来买这个设计,那同样的,其他人也可以来买这个设计拿去使用。正如许可中指出的,这种许可是非排他的。

如果这些图标只是用到界面上,多个应用之间相似甚至相同,可能还是好事,因为这降低了用户的学习成本。但如果用在 Logo 这种代表品牌的场景,就会出现多个应用 Logo 一样的尴尬场面。

只是从这种买断式素材网站上直接买一个素材就拿过来把它作为 Logo,那人家也可以从这个素材网站上买同样的素材作为它的 Logo。这种行为可能是无意的,也可能是有意的。这种情况下我们还不能说人家抄袭侵权,因为都是从同一个地方买的,你可以买,人家当然也可以买。除非你把这个图案拿去抢先注册了商标,否则就会存在潜在风险。

不过,我们可以通过混搭组合的方式,将 Logo 变得独一无二、且更贴近我们产品的本质。

你看,thenounproject.com 上有上百万的图标。我们单独使用,总有其他的用户和我们一样喜欢上某一个图标,并把它作为 Logo,这个时候我们两个产品就冲突了。

但是如果我们把这几百万的图标混搭组合起来,就会产生出上亿种组合,再要想重复,就变得非常困难了。而「从一个图案里边截取一部分,跟其他的地方拼合起来,构成一个新图案」的这种操作,即使对于一个没有绘画功底的同学来讲,只要能熟练地使用软件,也可以轻易完成。

另外,在增加识别度方面,除了混搭,还可以通过上色来实现。单色图标因为使用的颜色数少,往往比较单薄,看起来缺乏层次感。当我们把它作为产品 Logo 的时候,可能就不是那么耐看。这时候我们可以自己来给它上色。因为是矢量图标,所以调色和上色都非常简单。调色只要选中后改变线或者形状的颜色就可以。

使用AdobeXD设计界面

什么是 Adobe XD

picture 24

Adobe XD是由 Adobe 开发的矢量设计工具,它和 Sketch 类似,既可以用来绘制矢量界面,又包含原型设计功能,还可以在手机上预览设计好的界面。XD 支持 Windows 和 Mac,是 Adobe 为数不多的可以免费使用的软件(当然你可以付费升级 pro 版本)。

使用 Adobe XD 设计简单界面

软件的使用主要还是靠大家勤学多练,这里我们和大家演示下如何用它来设计背单词界面。

理解画板

首先,我们在 XD 里新建一个画板(art board)。

画板是什么?它相当于 Word 里边的页面。一般的纯设计工具没有画板这个概念,但 XD 也包含了原型功能,有时候我们需要在多个界面之间来回切换,而一个画板往往就是一个界面。

点击左侧的菜单里面倒数第2个画板的按钮 picture 25
,这时候在屏幕最右边就会出来一系列预置的画板尺寸。

picture 26

它已经帮我们准备好了常用的规格,比如苹果的iPhone、iPad,谷歌的安卓机型,以及网页常见的尺寸。

我们只要从里边选择对应的尺寸就好了,当然也可以不选择它给你预置的,直接手工拖拽来画或者在属性里面调整画板的宽和高。那我们就新建一个iPhone Xs尺寸的画板好了。

然后按住 CTRL或者CMD + D,就可以直接复制画板。我们把第一个画板叫做背单词界面,然后开始设计。

picture 27

遮罩的制作

先来制作背单词时,字母没有输入完时显示的遮罩效果。选择左侧工具栏中的矩形 picture 29
工具,画出一个覆盖全部画板的长方形。然后调节填充颜色为黑色,透明度为 30%。

picture 30

然后我们到 unsplash.com 这个无版权网站上,找一只猫的图片,把它也放进来。

picture 28

这时候猫是在遮罩上方的,所以它挡住了遮罩。

picture 31

点击右键,选择「Send to back」将它放到遮罩后,我们就可以看到被半透明遮罩挡住的猫了。

单词释义和输入框

接下来,在遮罩上边,我们来放上单词释义和输入框。点击最左侧工具栏中的 picture 33
图标,切换到文字工具。

然后输入文字释义。

picture 32

在右侧的属性面板里,我们可以调节文字的字体、大小、颜色和对齐。

然后我们放上之前设计好的 Logo,加上单词输入框。

picture 34

注意这个输入框不一定非要是「框」,比如我们这里也可以把它做成下划线。

虚拟键盘

picture 35

虚拟键盘的制作在 XD 中也很简单,直接用矩形工具绘制就行。需要注意的是圆角的做法。

picture 36

其实很简单,在右侧的属性设置里边,把圆角从0 改为 5 就可以了。在做好一个按钮后,我们可以按住 Shift 同时选中按钮和上边的文字,在右键菜单中将其编组(Group);然后按 CTRL或者CMD + D 就可以复制按钮。

picture 37

当按钮多起来之后,要对齐它们还挺费事的。其实选中多个按钮后,可以在菜单 Object → Align 中来自动对齐;也可以在 Object → Distribute 中让它们自动均匀分布。

矢量图标

再下来,我们需要在界面中引入图标。既然是矢量界面,当然是矢量图标最好。前边我们已经介绍过 thenounproject.com 了,它还为 pro 用户提供了一个客户端。在这个客户端里边可以非常方便的复制图标。

picture 38

当我们通过关键字搜索到图标后,可以通过下载并将其拖拽到 XD 的方式引入;也可以直接在客户端中右键选择 Copy as SVG,然后直接粘贴。因为是 SVG 格式,调整完大小后可以很方便地更换颜色。

最后我们再微调一下输入框和单词释义的位置,背单词界面就做完了。其他界面的制作非常类似,就不在这里累述了。

个人支付解决方案

略过开发环节,我们来讲讲变现。绝大部分的支付方案都是面向企业的,面向个人的正规支付方案非常少。那么对于没注册公司的个人,怎么样才能比较安全地收款呢?

常见的几种个人收款方式

个人收款码

市面上最简单粗暴的个人收款方案,就是利用微信或者支付宝的个人收款码来做。

具体的说,就是生成一张二维码,在这个二维码上面添加一个付款的备注,让用户备注中补充上特定的消息后(比如订单号)支付。当完成支付以后,我们就会通过APP或者网站,得到备注里面填的消息,通过识别,我们就能定位到订单,从而自动发货。也有不用备注,用支付金额来识别的。

这个方式淘宝店家已经用了很多年,它的问题就在于,从用户端的体验来讲,它需要填写额外的消息或者发送不确定的金额。从商家端的体验来讲,它需要有一个常驻的服务,随时去监测收款的相关消息,这就会有相当的不稳定因素在里边。

二次封装接口

另一种解决方案,就是由那些有资质的企业申请到接口权限后,二次封装后提供给个人来用。这种方案的问题在于,钱是支付给提供接口的企业的,我们只能定期找他们结算提款。万一对方跑路了,我们的钱也就没了。这种方式风险非常高,不推荐。

小微商户

「小微商户」是支付平台针对个人、也就是大量没有企业资质的用户推出的一个解决方案。最开始推出的时候,是为了帮助一些线下的店面,快捷地接入支付而存在的一个服务,然后又扩展到了网上的网店和商家。

一些银行和微信都有这个服务。但是微信并没有给它做专门的后台页面,所以我们在支付平台的后台里是看不见它的,它只有API。

微信把这一部分业务,交给了微信开放平台上的服务商。由服务商去调用这些接口来帮助个人接入到微信的支付服务里面来,同时服务商会提供后台的页面帮个人用户进行管理、也是服务商封装API供个人使用。

这种方案它的好处在于,它是完全合规的,而且这个钱是从微信直接打到小微商户的银行卡里边,不经过中间服务商,所以非常安全。

目前国内有名一点比如 xorpay.com 和 payjs.cn 。他们都是收费服务,前者的费用似乎更为便宜一些。这两个业务我们了解不多,大家使用之前请自行判断其靠谱系数。

数字内容销售平台

如果我们就是写一个软件,想简单地进行销售获得收入的话,我们还可以使用一些现成的数字内容销售平台。面向国外市场的话,可以使用Gumroad.com;如果面向国内市场的话,可以使用mianbaoduo.com。

picture 39

逻辑上讲,所有的网店都能解决我们卖软件的需求,但相对而言,面包多这类专门面向数字商品的平台提供了更低的手续费和更为全面的 API 接口。

picture 40

使用「兔小巢」处理用户反馈

市面上管理用户反馈的产品很多,不过大部分都是收费的;这里我们介绍下自己在用的、腾讯出品的免费工具「兔小巢」。

picture 41

这个产品最大的用户就是腾讯自己,原来叫「吐个槽」,最近才升级并更名为「兔小巢」。我们已经使用了几个月,用下来感受很不错。

从用户端来讲,它支持微信和QQ登入,能及时地推送回复通知;从运营端来讲,用起来明显可以感受到这是一款看似简单,功能却相当强大的产品。比如它可以设置移动端的展示方式;可以适配大型产品和通用产品;默认发帖可以隐藏,也就可以当做工单使用;甚至还配备了团队博客和知识库。

不足的地方是提供的 API 比较少,但也够在自己产品中展示用户反馈了。有了它,我觉得大部分情况下,就不用再去购买同类的付费产品了。

整合说明

下边分享一些整合细节,供大家参考。

链接跳转

兔小巢提供的是非常浅的整合,不管是在 Web 还是 APP 中,都是通过网页转向的方式来进行。通过设置,在反馈区上方可以显示一个链接,供用户返回到产品中。

状态登入

但是通过链接跳转会遇到一个问题,就是在我们的产品和兔小巢之间,用户的登录状态会丢失,这样我们就不知道那个反馈是哪一个用户提交的了。

为此,兔小巢提供了一个tucao.js,让我们可以在跳转时传递用户的登录态,从而实现用户的统一。

反馈数据整合

在默认的模式下,我们只能点击链接后,在单独的页面上才能看到反馈信息。但通过兔小巢提供的 API,我们可以直接在产品中显示反馈内容。

2A3R漏斗和增长优化

什么是 2A3R 漏斗

2A3R 漏斗,又叫 AARRR 漏斗,是一个用来描述用户转化的结构。

picture 42

它是一个五层结构,分别是:

  1. 获客层
  2. 激活层
  3. 留存层
  4. 推荐层
  5. 付费层

用户由上至下逐步转化,直至完成付费。其中,留存层、推荐层和付费层可以是并列的,因为用户激活以后,立刻就可以付费、推荐好友。

使用 2A3R 漏斗进行业务优化

2A3R 漏斗的现实意义在于,它促使我们从结果出发,去反向优化前边各个环节的转化率。比如说,如果我们福利单词的销售额定为 1000 套,那么就是说最终到达付费层的用户有 1000 人。而在付费层上至少还有获客层、激活层。

这里我们把获客指标定义为「访问网站」;把激活指标定义为「用户登入」。假设每一层的转化率是 10%,那么访问我们产品的用户数需要达到 1000 乘以 100 等于 10 万人。

优化方向包括:

  1. 我们可以加大推广力度,让访问人数从十万变成一百万,这样就能卖掉一万套软件了。
  2. 我们可以优化「用户登入」环节,在微信里边做成自动登录,这样把原来 10% 的激活转化提高为 30%,这样即使依然是 10 万访客,销售额也会变为 3000 套。
  3. 我们可以强化「付费转化」环节,给第一次访问的用户一个限时折扣,比如 1 个小时内购买,买一送一。如果能拉升 10% 的支付转化,我们的销售也会上升。

留存层优化

留存层优化主要用于一些基于高粘度增长引擎的业务,或者免费+付费模式的产品。在这些模式下,用户需要经过很长时间的使用,才会付费。如果留存做不好,用户熬不到付费那天。

对于福利单词而言,留存层优化可以通过推送通知、定时提醒等功能来做。因为背单词本来就是一个周期性行为,所以我们有足够的理由去召回用户。

推荐层优化

现在的流量已经是非常贵的了,所以我们必须珍惜每一滴流量。通过旧用户带来新用户,可以为我们提供免费流量;如果做得足够好,流量甚至能像滚雪球一样不断变大。这就是推荐层优化要做的事情。

在我们的应用中,我们可以选择几个用户情绪高涨的点来做分享触发:

  1. 完成当天的背单词目标,比如背了 100 个单词
  2. 完成有挑战的任务,比如连续 30 个单词不出错
  3. 看到赏心悦目的图片,比如看到超级呆萌的猫

在这些时刻,我们都可以引导用户通过海报来分享他们的激动心情,同时为我们带来新的用户。

推荐阅读

关于增长优化,这里给大家推荐两本书。一本是肖恩·埃利斯的《增长黑客》,系统化地讲述了如果建立增长实验机制并从中受益;另一本是《病毒循环》,记录了众多流量传奇。它们中很多细节和技巧,都可以用到我们的副业当中。

精益网课变现实践

大纲的注意点

这一节我们来讲大纲。大纲大家都会做,所以我们不全面的展开,只挑其中一些需要注意的点和大家交流。

条理性

最重要的一点,就是大纲一定要有条理性。如果在条例性上做得不够好,其他细节做得再好,这个课做出来在逻辑上也是乱的,最后学起来就会很别扭。

具体来说,我们要保证大纲的层次足够清楚,逻辑足够严密。有一个比较常用的结构推荐给大家,尤其适合知识性为课程。

三段式

这个结构分成三段,是一个总、分、总的结构。

在课程的最开始,我们会简明扼要地讲明白整个课程包含哪些内容;课程中的一些基础、原理也会放到这里。

之后呢,我们就可以按照章节进行展开,对每一个部分进行详细地讲解。

在最后我们会进行一个总结,同时放入一个大的实践章节。这样不但可以复习内容,还可以学以致用。当然在每一章结尾也可以安排小实践内容。

绝大部分以知识讲授为主的课程都可以采用这种总分总的结构,非常好用。

提问式

我们也可以用问问题的方式来引出我们的每一部分结构。比如「是什么」——「为什么」——「怎么做」。这种结构可以是全局的,也可以是针对每一部分的。它会让我们的逻辑和层次更清晰。

覆盖面

第二个需要注意的点是覆盖面。因为我们的课程往往是出于自己的实践经验,有时候会局限于我们所在的公司和所在的行业节点,它的覆盖不一定特别的全。所以我们的视角不一定能覆盖到所有的需求方。

有时候我们的课程是为了一类人做的,但另外一类人,实际上也可以学习我们的课程,就差一点点的周边知识。在这种情况下,如果我们可以注意到大纲的覆盖面,把缺少的那点知识补上,就可以扩大受众,让我们的销售变得更为容易。

那具体怎么保证大纲的覆盖面呢?

那首先大纲应该覆盖该领域的主要内容,这些内容通常来源于以下几个地方:

  1. 官方文档:官方会处理几乎所有来自社区和其他客户的需求,即使一些边缘的需求,因为囤积的时间比较长,也会慢慢地累积起来,所以一般来讲官方资料的覆盖度是最为全面的
  2. 行业的权威文档:虽然不是官方出品的,但因为日积月累它最后可能变成了事实标准,也是我们作为参考的一个主要来源
  3. 图书:这也是大参考源,对于经典知识来讲,一些销量比较好的图书,会经过多次的再版,并会加入一些之前没有覆盖的内容。使用微信读书的无限卡,无需购买就可以直接搜索大量计算机图书,对查资料来讲非常好用
  4. 同类课程:国外的同类课程往往也是非常好的参考,尤其是面向新技术的课程

然后呢,我们的大纲应该覆盖该领域最频繁出现的问题,那我们到什么地方找问题呢?

  1. 搜索关键词
  2. 专业问答网站,比如 stackoverflow.com
  3. GitHub 的 issue 区
  4. 课程平台的答疑区

粒度

除了条例性和覆盖面,那我们最后,而且其实也是非常想强调的一个问题,就是大家一定要注意我们大纲的粒度。

大纲这名字听起来就像一个目录,很具备误导性。很多同学做大纲的时候,通常做两个层次就算是做得细的了。事实上,大纲的粒度越细,课程的品质就越可控,后期制作起来速度就越快。而且我们要拿大纲去做预售来验证需求,它越细,验证的效果就越好。

所以呢,建议大家把大纲至少细化到段落这个级别,同时把段落以下的一些知识点所涉及到的素材和资料,全部都整理到这个节点上去。

这里推荐大家使用 Dynalist 这种无限分级的树状笔记软件来做大纲,会特别方便。

通过预售验证销量

为什么要验证

随机抽样了某云课堂上近 500 门付费课程(通过搜索「课」字),其中销售不到 30 的有 24%,销售小于等于 1 的 10%

这是我之前分析某课程平台时的抽样数据,有十分之一的课程销量小于等于一,这个一还很可能是作者;而销售不到 30 套的课程约四分之一。

这些失败的课程背后,每一个都可能有几十几百个小时的制作时间,既然我们把宝贵的副业时间投入其中,就应该尽量避免重蹈覆辙。

如何验证

回到我们这一节课的标题上来,「通过预售验证销量」。两个关键词「预售」,「销量」。

  1. 预售,我们用什么来做预售?简单一点可以用「课程介绍」,复杂一些则可以提供「试学章节」,但我们测试下来最合适的是「课程大纲」。它能非常清楚的描述内容范围。
  2. 销量,如何来评估?我们需要给自己设定一个达标的销售额,一般设定为比成本略高,预售结束时如果销售不达标,我们就退款,不制作这个课程了。

抓住这两个关键,就可以做好验证。在此基础上,可以扩展出一个完整的流程:

  1. 准备课程介绍资料,主要是大纲和试学章节
  2. 设定验证的目标,设定预售达标值
  3. 开始预售
  4. 每天统计销售量,并根据反馈调整介绍
  5. 预售达标则进入课程制作
  6. 预售不达标则进行退款,并反思价值主张

要支撑这个流程,我们大致有三种方案:

  1. 通过众筹/预售平台来完成
  2. 自建众筹/预售平台
  3. 通过付费群简单解决下

下边我们分别来说:

众筹/预售平台

使用现成的众筹/预售平台是最省心的。其实最方便的是微博提供的众筹功能,集传播和销售于一体,很适合在微博有影响力的同学。

picture 49

之前我用的时候还挺好找,现在这个功能藏得有点深,在微博的钱包二级菜单里。当然,其他的平台也是可以的。大体来讲,这类平台的问题在于操作相对麻烦,对个人的话,除了收取服务费,往往还会代扣 20% 左右的税。

另一方面,课程还不是实物商品,众筹完了可以直接寄送;我们众筹完以后,可能还要提供在线观看课程的功能。如果放到其他平台,还有一个账号统一的问题要解决。

自建众筹/预售平台

对于我们程序员来讲,自建众筹/预售平台是很容易的事情。找不到满意的平台,当然是自己动手丰衣足食。功能开发上很简单,但这里有一个非技术因素,那就是支付接口往往需要公司资质来申请,个人很难申请下来。所以还没有搞定支付的同学们在动手前要留意,不要花几周写完系统要上线时才想起来。

付费群

付费群就不需要任何的开发,交易完全走一对一支付,只要自己在年终走个税申报就行。它的缺点在于维护成本有点高,需要手工跟进整个众筹的流程;群功能也相对有限,甚至出现过仿冒老师的账号进行收款的事情。

这里也分享一个微信批量退款的小技巧:将要退款的同学拉到一个微信群中,然后发一个人数乘以金额的普通红包就可以了。注意是普通红包,不是拼手气红包。

综合以上,我们的建议是,早期通过付费群或者一对一付费就可以了。等到付费用户多了以后,再专门开发一个系统来做预售/众筹。

我们也做了一个众筹+课程托管的一体化平台自用,等成熟以后会考虑开放出来,感兴趣的同学可以关注下我的微博。

常见的课程片段类型

这一节开始我们来讲课程的制作。

我们将常见的课程分成四种片段:

  1. 文稿讲义类:这是我们最熟悉的PPT+语音的形式
  2. 屏幕录制类:在实战和演示时用得最多的形式
  3. 真人出镜类:技术类课程用得较少,一般在右下角放一个小窗显示真人
  4. 虚拟形象类:不想真人出镜时,可以用虚拟形象来代替

几乎所有的课程都是由以上四类课程片段组合而成,所以一旦学会了每种片段的制作,也就学会了几乎所有课程的制作。

文稿讲义类课程片段的制作

这里的文稿讲义,主要指使用幻灯片软件来进行播放的资料。如果是使用PDF这类材料,其实是属于「屏幕录制」类,我们会在下一节里详细讲解。

对于文稿讲义类课程片段,我们的画面、图文内容都已经做到了幻灯片里面,要录制的主要是声音。但我们有三种截然不同的方式来录制声音:

  1. 第一种是最通用的,通过全局录屏来完成。不管是使用什么软件,只要在电脑里,都会被录下来。
  2. 第二种是使用幻灯片软件自带的「演讲录制」功能来完成。
  3. 第三种是最不为人知的,通过幻灯片软件的「导出为视频」来完成,这种方式有一个非常大的优点,可以极大地降低修改成本,在后文中会详细说明

下边我们分别说明。

全局录屏

下一节会详细讲,这里就略过了。

使用幻灯片软件自带的「演讲录制」功能

picture 50

目前用得最多的幻灯片软件,分别是苹果公司的 Keynote 和微软的 PowerPoint。下边我们就以它们为例进行讲解。

首先,我们需要使用幻灯片软件将内容制作完成。课程完成度越高,修改起来成本就越高,所以要仔细检查有无错别字或其他疏漏,然后再进入音频录制阶段。

如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程

我们先来看在 Keynote 中如何录制。

在 Keynote 菜单「播放」里选择「录制幻灯片放映」

picture 52

然后我们就会进入一个深色背景的幻灯片录制的环境,在这个界面的最下方有一个红色的录制按钮。

picture 53

点击它就可以开始进行录音,可以随时暂停和停止。需要注意的是,这里录制的音频不是仅仅当前这页幻灯片的,而是整个幻灯片的。你可以来回切换幻灯片来录制音频,如果界面看到的有些不一样,可以通过调整预览界面的配置来修改。

当我们在录制环境中完成了整个课程的音频录制后,就可以回到主界面。从菜单中选择「文件」→「导出为」→「影片」。

picture 54

这样,Keynote 就会为刚才的录制生成视频。有一个需要特别注意的地方,就是导出窗口中,「播放」选项要选择为「幻灯片放映录制」。

picture 55

如果觉得导出的视频文件过大,可以使用HandBrake来进行压缩。这是一款开源的视频压缩软件,默认的预置(比如 fast1080p )就很好用。

picture 56

如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程

下边我们来看 PowerPoint 中如何操作,其实很类似,只是菜单名称和个别细节不同。选择菜单「幻灯片放映」→「录制幻灯片演示」。

picture 57

同样会进入一个暗色的录制界面。

picture 58

在左上角有一个时间正在走,在旁边有控制按钮,可以暂停。默认已经开始录制了,我们可以选择幻灯片进行讲解。全部讲解完成后,一样是导出视频。

picture 59

在顶部菜单中选择「文件」→「导出」。

picture 60

也有一个需要特别注意的地方,就是在导出窗口中要选中「使用录制时的计时和旁白」。

幻灯片导出为视频

单从录制来讲,前一种方法就非常方便了,可以说是一气呵成。但如果录制完成后我们发现有几句话讲错了需要修改,那么就相当麻烦了。究其原因,主要在于虽然幻灯片是一页一页的,但音频却是整体录制的,所以音频出问题就只能重录。

那么我们能不能让音频也变成一段一段的,对应到每一页呢?这样我们以后再修改的时候,只需要重新录制那一页的音频。

picture 62

这就是我们第三种方案的思路。Keynote 和 PowerPoint 虽然没有提供分页录制的功能,但它们都能往幻灯片上添加音频,并将其合并到视频中统一输出。

所以我们要做的,就是在每一页幻灯片上,添加上语音讲解的音频。比较方便的地方是,这两个软件都支持直接录制语音讲解,而且一页幻灯片上可以录制多段,还能手工调整顺序。

下边我们来看具体如何操作。

如何使用 Keynote 以「导出为视频」的方式生成视频课程

还是先来看 Keynote。第一步依然是制作好图文部分的内容,最好把要讲的文稿放到演讲者注释区域,这样录制的时候可以参考。

然后先选中要添加语音讲解的幻灯片,从菜单中选择「插入」→「录制音频」。

picture 63

在弹出的小窗口中点击录音按钮就可以开始录音。

picture 64

录制完成可以试听,没问题后再插入到当前幻灯片。当一张幻灯片有多个音频时,可以选择右上角的「动画效果」菜单,再点击右下角的「构建顺序」就可以看到当前幻灯片中的音频列表了。被选中的时候,会有蓝色描边,通过拖拽可以很方便地调整顺序。

picture 65

导出和之前类似,还是通过「文件」→「导出为」→「影片」。 picture 66

但需要注意的是,这次在导出窗口中,播放选项要选为「自动播放」。

picture 67

同时,我们还要把下边两个等待时间设置为「0」秒钟。

picture 68

如何使用 PowerPoint 以「导出为视频」的方式生成视频课程

再来看看 PowerPoint 里边的做法。给幻灯片添加语音讲义也在菜单「插入」→「音频」中。

picture 69

选择「录制音频」可以直接录制。

picture 70

下边我们看看怎么调整多个音频的顺序。点击「动画」菜单,在右边会出现一个「动画窗格」,再点击它,在最右边就可以看到当前幻灯片上所有的音频的列表。

音频前边还有编号,可以一一对应到幻灯片上的音频。通过调节它们的上下顺序就可以手动的指定最终的音频播放顺序。

细心的同学可能会留意到这些音频都会被放到一个叫做动画的菜单里面,其实这个菜单的功能是指定动画播放的顺序,音频被当做动画的一种,所以也在里边了。通过同样的方式还可以控制插入的视频的播放顺序。

picture 71

最后依然是通过「文件」→「导出」来生成视频,但是记得去掉「使用录制的计时和旁白」前的小勾,同时把「没有设置时间的每张幻灯片所用的秒数」设置为「0」。

picture 72

屏幕录制类课程片段的制作

屏幕录制的原理

屏幕录制软件的原理,是不停地截取屏幕画面,然后和音频合成为最终视频。屏幕录制的优点是可以把电脑屏幕上显示的所有东西都录下来,不管你在哪个应用里边,不受应用本身功能的限制。所以可以非常直观地向学员展示完整的操作。

屏幕录制的软件

在试用了很多屏幕录制软件以后,我们选择了 OBS 。它的优点主要有:

  1. 功能强大
  2. 开源免费
  3. 跨平台

功能强大

OBS 不但可以录制屏幕,还有一个非常强大的功能就是直播。现在很多视频网站的直播都支持用 OBS 来进行推流。所以学会了它,不但可以录制屏幕,而且可以进行直播,一箭双雕、非常划算。

然后,OBS 可以非常容易地进行屏幕之间的叠加,比如画中画模式,这就非常适合我们马上要讲到的「真人出镜」和「虚拟形象」类型的课程片段。

同时呢,OBS 还支持通过快捷键在各个场景之间来回切换,在录制课程的时候可以非常方便的进行转场,这个功能不少收费软件都没有。

开源免费

和那些昂贵的收费软件不同,OBS 是开源而且免费的,这意味着使用它没有任何版权风险。我们在制作付费课程的时候,需要特别留意版权方面的问题。因为平时以个人身份在免费文章和视频中用一些字体、图片是没问题的;但在收费的商业课程中,就可能面临被起诉索赔的风险。

跨平台

再来说一下,为什么跨平台的特性非常重要。在课程中,尤其是编程类课程中,我们经常会遇到需要讲解某个工具软件在各个操作系统上的安装和使用的情况,这时候就需要在多个平台上录屏。

如果使用一个特有平台上的录屏软件,在录制其他平台上的课程内容时,就不能使用了。只能重新购买和学习一个新的录屏软件。这不但浪费钱,更浪费时间和精力。

而使用 OBS 就没有这种困扰,它不但支持 Windows 和 Mac 系统,连主流 Linux 系统都是支持的。

所以,在我们后续课程中,将以 OBS 为例进行讲解。

OBS 的层次逻辑

OBS 的功能非常强大,还有包含了直播相关的功能,所以需要理解它特有的一些概念后,用起来才会更加顺手。

像一般的屏幕录制软件,只需要启动后点击录制按钮,进行录制就完了。但 OBS 中,它有自己的层次逻辑。

picture 73

场景

OBS 的第一个层次叫做「场景」,你可以把它理解为一种预设。

为什么需要场景?比如我们一个讲师,他每天上午要进行直播,这个时候视频的来源是摄像头和电脑屏幕;然后他每天下午要录制课程,这时视频的来源就只需要电脑屏幕,但他有两块屏幕,他希望都录进去。

如果没有场景这个概念,那我们每天上午到下午的时候,就需要不停的修改配置,非常麻烦。而有了场景以后,我们只需要把上午和下午定义成两个场景,使用的时候切换下就OK了。

你可能会想为什么要叫「场景」而不是直接叫「预设」呢?因为 OBS 中场景比预设更为常用和强大,它是可以实时切换的。

也就是说,如果我们有三个显示器ABC,可以在场景一里显示A;在场景二中显示BC;然后根据需求通过键盘快捷键来切换,甚至还能给它添加转场特效。

来源

picture 74

在定义好「场景」以后,就可以往里面添加「来源」。最常用的来源其实就两类,也就是视频和音频。视频最主要的是显示器,也就是电脑屏幕,偶尔还有摄像头。音频的话主要就是麦克风。

picture 75

来看一下 OBS 的来源菜单。

首先它提供了「图像」和「图像幻灯片放映」,如果我们想在视频上面显示一张固定的图片或者图片轮播可以用它。

比较有意思的是,我们还可以把一个场景指定为来源,这样就可以非常容易地实现场景嵌套。也可以把媒体作为一个来源,这样就会在画面上面播放另外一个视频。

文本来源这里可以输入一些文字,指定它的颜色、字号和字体,然后它就会显示到屏幕上方。可用来显示我们机构的品牌名称之类的。可以看到,一些本来是后期才进行处理的功能,在 OBS 里都可以通过来源来实现。

显示器采集也就是我们的屏幕;视频采集设备通常就是指摄像头;音频输入采集这里通常就是耳机、麦克风或者外接的USB声卡之类。

这里还有一个音频输出采集,可以用来做多层次的音频加工。比如说我们电脑上有一个软件,就像柯南的蝴蝶结一样,可以对输入的声音进行变声,那我们就可以把这个软件的输出作为来源接入到 OBS 里边,录制下来的声音就是变声后的效果。

来源的层次

在多个来源之间,其实是有上下层级的概念的。打开 OBS 的来源小窗口,我们可以看见当前已经添加的所有来源。

来源是从上至下进行覆盖的。也就是说来源窗口的最上边一层,在最终视频中也会显示到最上面,上一层的内容会压住下边各层的内容。

picture 77

这个对于我们制作真人出镜类型的课程片段很重要,因为它通常是通过摄像头和显示器两个来源叠加得到的。摄像头的画面小、通常显示在右下角;显示器的画面大,往往覆盖整个视频画面。在来源窗口里,摄像头需要在显示器上层才看得见,不然会被显示器画面完全挡住。

滤镜

picture 78

如果通过来源采集的信息不是百分之百符合我们的需求,还可以通过滤镜来进行进一步加工。OBS带有两类滤镜,一类叫做「音视频滤镜」,可以对音视频进行处理,比如进行噪音的抑制或者把音量放大;另一类叫「效果滤镜」,包括各种各样的特效,比如「色度键」可以用来抠背景。

真人出镜类课程片段的制作

虽然前面其实已经陆续讲到了真人出镜类课程片段的基本原理,这里还是再明确下。

什么是真人出镜类课程片段

「真人出镜」类的视频非常简单,只需要使用摄像头、手机或者摄影机直接录制就好了。而「真人出镜」类的课程反而要复杂一些。这是因为在课程中,讲师其实并不是主体,课程内容才是。所以我们往往会采用「画中画」的模式,将讲师的头像部分做成一个小方块放到画面中。

picture 79

但这有一个小问题,就是这个方块会带背景。如果它的背景和作为主体的课程不搭,看起来就会比较别扭。要是能把背景变成透明的,它就能更好地融入到课程中。

抠图

那么,怎么才能让背景变成透明的呢?答案是「抠图」。对于计算机来讲,将数字内容的一部分变成透明是非常简单的,真正的麻烦在于它不知道哪一些像素是背景、哪一些像素是讲师,所以我们需要一个方式来告诉计算机。

现在最常用的,也是最简单有效的一个办法,叫做「绿幕抠图」。就是在讲师身后放上绿色的背景布,再告诉计算机,绿色的部分都是背景,把它抠掉。这样就实现了背景的透明。

有同学可能会问说,为什么非要绿色,其他的颜色行不行?答案是可以的,但如果把背景设置成黑色,很多人的眼睛和头发都是黑色的,这些部分也会被透明,看起来会很灵异。

而绿色在日常生活中出现的频次比较低,所以一般默认用绿色来作为背景。但如果有天你穿了个绿色的衣裳,那就可以考虑换用蓝色的背景了。

picture 80

这一部分的具体操作是这样:

  1. 在场景中添加一个「显示器采集」来源,选为我们想要录制的电脑屏幕,放到来源窗口最底层。
  2. 在场景中再添加一个「视频采集设备」来源,选为摄像头,将其放置到屏幕右下方,在来源窗口中位于显示器之上。
  3. 在摄像头来源的右键菜单中,选择「滤镜」,在「效果滤镜」中添加一个「色度键」滤镜,背景为默认的绿色。
  4. 调整「相似度」和「平滑」的值,让背景消失得更为柔和。

picture 82

picture 83

关掉滤镜窗口,这时候在 OBS 的预览界面上我们看到的摄像头画面背景就应该已经透明了。

picture 84

真人出镜的其他细节

如果你是使用笔记本电脑,通常自带一个摄像头;如果是台式机,就需要自己装一个。摄像头需要对着讲师的脸,因为摄像头看到的,就是学员最后在课程里面看到的角度。

然后我们在讲师背后竖一个比较大的绿幕,充满整个摄像头的背景区域。一般两米宽高就够了,不够的话可以调整摄像头。

绿幕可以在电商网站输入「绿幕布」关键词搜索购买。有一些专业的幕布会比较贵,但我们早期可以买便宜的幕布来试水,一般几十块钱就能搞定。

为了让讲师和背景之间分离得更清晰一些,可以再通过光源进行补光。这里我们用手办做了个示意图给大家。这个灯的色温不能调,所以看起来稍微有点偏黄。实际录制的时候,可以用白色的灯来补光。

picture 81

虚拟形象类课程片段的制作

虚拟形象的原理

最后,我们再来看一下虚拟形象类课程片段的制作。虚拟形象实际上跟真人出镜差不多,但因为可以用卡通的形象来代表真人,所以形式上看起来会更加有意思,更适合年轻的同学。

在上一节里面,摄像头里拍到的是真实的画面,现在我们要想将真实的变成虚拟的,就要使用虚拟摄像头。

所谓的虚拟摄像头,就是其实并不存在这么一个物理上的摄像头,这个摄像头是用软件来模拟的。但是其他软件并不知道,它们会以为这个摄像头是真实的,于是它们之间就可以无缝地进行整合。

FaceRig

我们使用的是 FaceRig 这个虚拟摄像头软件,它提供了很多的3D模型,还支持导入 Live2D 这个游戏和动画用得较多的模型格式。如果是通过 Steam 购买的 FaceRig,那么在创意工坊里边可以看到全球玩家上传的各种模型,喜欢的可以直接订阅,它就会出现在我们的 FaceRig 里边。

当然,我们也可以制作自己的卡通形象,生成模型并导入。顺便说一下,对于多人参与的课程来讲,虚拟IP是非常有用的。如果我们将大量的精力和推广资源放到真人讲师的IP上面,万一这个讲师离开团队,之前的投入就废掉了,甚至会变成竞争对手的资源。但是如果我们采用虚拟IP,就完全没有这个问题。

步骤

为了模拟摄像头,FaceRig 构造了一个 3D 空间。这个空间由「模型」和「背景」两部分组成。选好模型、配好背景,打开跟踪器让模型和我们的表情同步,就实现了用虚拟形象代替真人形象。

下边我们更为详细地讲述下步骤:

  1. 购买和安装
  2. 选择模型
  3. 选择背景
  4. 打开追踪器
  5. 打开广播

购买和安装

最方便的方式是在 Steam 这个平台上进行购买,它会帮你自动安装各种依赖,确保能运行起来。如果想用 Live2D 的模型,还需要购买对应的插件。

picture 85

选择模型

启动完成以后,点击顶部菜单最右边的UI按钮就可以切换右侧的面板;这个面板的第一格就是我们的模型。

点开以后可以选择喜欢的模型。

picture 86

选择背景

还是在右侧的面板,第二个图标就是。点开它可以看见预置的各种背景。如果想要最终背景透明,可以选择绿色背景方便下一步抠图。

picture 87

打开追踪器

现在虽然模型都有了,但它跟我们真人说话的表情语气没有关联起来,所以要打开追踪器。点击顶部导航,「切换追踪」按钮(图上画红圈的),摄像头就会通过人脸识别来捕捉我们的表情。这个时候我们摇脑袋和做出各种表情的话,就会同步到模型上。

picture 88

打开广播

这些都做完了以后,一定要记得还有最后一步就是要打开广播。所谓广播就是 FaceRig 把画面虚拟成一个摄像头,并同步到整个系统里,其他的软件就会把它当做一个真实的摄像头。

picture 89

打开广播也非常简单,就是点击顶部的这个像电台一样的按钮。点击打开,再点一下关闭。

当广播打开后,在 OBS 里去添加一个新的视频捕捉设备的时候,就会发现有一个名字包含 FaceRig 的摄像头,把它作为来源,就可以引入和真人表情同步的虚拟形象了。

picture 90

最常用的视频剪辑操作

视频剪辑是我们做课时用得非常多的技巧。剪辑是一门细节很多的技术,幸运的是,做课所需的只是非常基础的一些功能,所以我们才有可能花很少的时间学会。这也是我们这一节的内容。

剪辑软件

视频剪辑的软件非常多,但整体功能上大同小异。经过一系列的试用,我个人用得最多的是这两个软件:

  1. 苹果公司出品的 iMovie
  2. Adobe 公司出品的 Premiere(一般简称PR)

iMovie 是 Mac 专有的免费软件,完全可以胜任大部分的常规剪辑工作。后来苹果公司还开发了 iOS 版本,这样我们在 iPhone 和 iPad 上也能使用它。

如果我们只是想简单地调整下视频片段的顺序、删除某个片段、或者对某部分进行速度调整的话,iMovie 是个不错的选择。

PR 则是系统复杂、功能强大的专业剪辑软件,很多专业人士都在使用它。PR 是一个付费软件,但同时支持 Mac 和 Windows。

我们后续以 PR 为例进行讲解,在其他的剪辑软件里相关的操作也是非常类似的,往往只是菜单位置不同,大家可以自行摸索。

视频片段的调整

视频片段的调整是最常遇到的需求。因为我们在录课的时候很可能其中有一段讲错了,会想把它去掉,再把后边的内容给接上去;或者讲课时有一部分内容讲丢了,在后边补讲的,想把它给挪到前面去。这些情况时常发生。

比如说我们现在有一段视频,希望删除其中红色的部分,应该怎么操作呢?

picture 3

直观来讲,应该是选中一个片段然后按删除键。有一些编辑软件就是这样做的。但在 PR 中,这个操作通常被分两步:先分段、再删除。

picture 2

所以我们会先用剃刀工具将视频给切割成三段,切割的位置正好在红色部分的开始和结束,这样它就会变成一个独立的片段。

然后切换到选择工具,选择这个片段,再按删除键,片段就会被删除。

picture 4

但我们会发现,视频中间空出来了一段空白。

picture 1

这是因为在 PR 里边,连续视频并不是一种常态,所以它没有自动去掉两个视频片段之间的空白。可以在这段空白上点右键,选择「波纹删除」,这样后边的视频就会自动补上来了。

picture 5

当然,在删除视频的时候,如果不是直接按删除键,而是点击右键,选择「波纹删除」会更加方便一些。

柔软的视频片段

这里有一个需要特别注意的概念。在我最初的想象中,视频片段应该是很「硬」的,当两个视频片段有重合时,后一个片段会自动后移并紧跟前一个视频对齐。但在 PR 中,视频片段是很「软」的,当两个片段重合的时候,重叠部分会被覆盖掉,再也分不开了。可以把它们想象成两个透明胶带,一旦粘上,就很难无损分开了。

picture 6

所以,对于不熟悉 PR 的新手来讲,想要两个片段紧密连接,最简单的方式还是分开放,然后「波纹删除」中间的空白来自动对齐。

视频片段顺序的调整

正因为这些片段很「软」,当我们在进行顺序调整时,也要倍加小心。这里我们可以利用 PR 的多轨道。我们可以暂时把要移动的片段放到另一个轨道上,然后调整原来轨道上片段的顺序,挪出一个新的位置,再从外轨上把片段给挪回来。

picture 7

视频片段速度的调整

速度调整在做课时也很常见,比如说我们通过网络安装软件的时候可能就很慢,得操作二三十分钟,但我们不可能让学员一直等二三十分钟。一个方式是直接减掉这个过程,但如果其中又包含了一些操作细节,我们可能就需要把这一段视频加速。

picture 8

在需要调整速度的视频片段上边点击右键,选择「速度/持续时间」选项,会弹出设定窗口。 窗口上默认的速度是100,如果想加速,就改为大于100;想减速,就小于100。

有一个需要注意的问题,就是如果减速,视频片段会变长。如果前后有其他片段,就可能造成覆盖,所以这种情况下,最好放到另一个轨道上再调整速度。

另外,在加速的时候,原来的声音会变调,如果想要保持正常,记得选中「保持音频音调」。

视频中的音频处理

这个操作也是很常见的,比如讲课中有几句讲错了,但是不方便删除视频,可以只删除这一部分的音频。

但是,默认情况下,音频和视频是绑定的。所以我们需要将要处理音频的部分切割成独立的片段,然后在右键菜单→「音频增益」中把它的音量调到听不到(比如-100dB)。

picture 9

当然我们也可以通过选中片段后点右键菜单,选择「取消连接」来解除音频和视频的绑定。这样就可以随意编辑音频了。

除了像视频一样分段、调整顺序等,我们可能还需要对音频进行去噪、调音等更进一步的操作,这时候我们可以在对应的片段上点击右键,选择「在 Adobe Audition 中编辑剪辑」在另一个软件中来处理。具体的操作我们将放到下一节讲解。

picture 10

最常用的音频处理操作

音频的后期处理和视频类似,也是非常专业的领域,所以我们这里也只讲最简单的处理。在我们做课时,经常会用到的技巧主要包括:

  1. 去噪
  2. 标准化
  3. 混响
  4. 去齿音和嘶声

下边我们依次来看看。

去噪

「去噪」就是「去除噪音」。一般分为两个步骤:

  1. 定义噪音
  2. 去除噪音

为什么会有「定义噪音」这个步骤呢?因为对于计算机来讲,它并不知道哪一部分声音叫做噪音。 比如我们在录一首歌的时候,邻居家的猫在旁边叫,这个声音就算是噪音。但如果是想录一个宠物视频,猫在里面就不是噪音,它可能是主角。所以是否是噪音,是需要根据场景来进行定义的,计算机理解不了这点。

当然,这个例子比较特殊。通常来讲,要去掉的噪音叫做「底噪」。就是声音很小的背景噪音,比如电流声,远处汽车和行人的声音。这种时候,只需要选取一段只有这些背景音的音频,将其定义为噪音,那么软件就可以把和它类似的声音去掉。

音频处理也有很多软件能做,但因为我们视频剪辑用 PR,所以音频用 Audition(简称 AU )来做会更为方便。它在我们修改音频后,会自动更新 PR 里边的片段。

下边我们来看 AU 中具体怎么操作。首先选中一段只有背景噪音的音频,在顶部菜单中选择「效果」→「降噪/恢复」→「捕捉噪音样本」,就可以把它定义为噪音。

picture 11

然后,在顶部菜单中选择「效果」→「降噪/恢复」→「降噪(处理)」,开始去噪。

picture 12

记得在弹出的窗口中点击「选择完整文件」,再点「应用」就会开始处理。

picture 13

标准化

标准化也是一个很有用的功能。我们录音的时候,尤其是换了场地和设备录音的时候,可能声音的范围(最高音和最低音)就不一致。这种时候,就需要通过「标准化」来将这个范围统一,这样听起来音量差异才不至于太大。

picture 14

在 AU 中的具体操作如下:

在顶部菜单中选择「效果」→ 「振幅与压限」→「标准化(处理)」。

picture 15

然后在弹出的窗口中,可以将其标准化到 0 dB (如果觉得音量过大,也可以试试 -6 dB)。

picture 16

混响

我不知道大家有没有这种感受,就是有时候听一些电脑生成的音频时,会觉得声音非常纯粹,很好听,但听起来不像是真的。而一些现场录制的音频,音质可能没那么好,但听起来却会有种非常强的空间感。

这是因为我们日常在说话的时候,声音会分成两个层次到达我们的耳朵。

picture 17

一个层次是直接从发声处传到了耳朵里,另一个层次是声波打到周围的环境上,比如墙面、地面、桌椅上,被反射后,有一些很弱的声音以稍微延迟一点的时间进入我们的耳朵。我们日常听到的多是这种叠加后的声音。

在电脑中生成的音频如果不特意处理,是没有这种叠加的。这就让声音有点「平」或者「干」。为了增强声音的空间感,很多编辑软件提供了叫做「混响」的功能。其原理就是模拟现实中的声音叠加,将一部分声音强制延迟后混音,这样的声音更有立体感。

下边我们看看在 AU 中怎么具体操作。

在顶部菜单中选择「效果」→ 「混响」→「混响」。

picture 18

在弹出窗口中,可以调节各项参数。点击播放按钮可以试听。

picture 19

选择好以后,点「应用」进行处理。

齿音和嘶声

齿音是指我们说话时,呼入呼出的气流和嘴唇、牙齿之间摩擦产生的声音;嘶声则有些类似于广播电台中常听见的嘶嘶嘶的声音。这些声音混在音频中,可能听起来不那么舒服,所以 AU 也提供了工具来清除它们。这部分的操作很简单,这里就不详细说明了,这两个功能的菜单分别在:

  • 齿音:「效果」→「振幅与压限」→「消除齿音」
  • 嘶声:「效果」→「降噪/恢复」→「降低嘶声」

建议顺序

其实顺序并不是强制的,怎么都行。但考虑到标准化时有可能把底噪放大,所以我一般会按下图的顺序来进行各项音频处理操作。

picture 20

整个过程中,去噪和标准化才是最重要的,其他的三项时间紧张时可以偷懒不做。

字幕的制作和自动生成

对于技术类课程来讲,字幕是非常有用的。一些技术名词光是读出来,有时候很难明白它是什么意思。而如果有字幕,就可以一目了然了。

字幕及其格式

所谓字幕呢,是指我们在播放视频的时候,显示在屏幕下方的、和语音同步的文字。为了让计算机正确地显示出字幕,我们需要告诉它两个信息:

  1. 这个字幕的文本是什么
  2. 这个文本应该在什么时间开始显示,在什么时间结束

也就是说,最基本的字幕信息应该包含「文字本身」以及「文字显示的时间段」。

当我们把多条字幕的信息合并放到一起,就有了字幕文件。字幕文件可以是单独的文件,在播放视频时载入并显示,这种方式称为「外挂」;也可以在压制视频时直接压制到视频里,这样即使播放器不支持字幕功能,也可以正常显示。

字幕的格式有很多种,srt 格式是最简单的格式之一。

picture 21

它由多段文本组成,每段文本分为三行:

  1. 第一行是序号,一般从 0 开始递增
  2. 第二行是显示时间段,中间用箭头分隔
  3. 第三行是这个时间段应该显示的文字

字幕编辑软件

我们使用的字幕编辑软件是 ArcTime,它是一款跨平台的免费软件。启动以后的界面是这样的:

picture 22

左上部分区域是视频的预览区,可以从顶部菜单的「文件」→「导入音视频文件」载入要编辑字幕的视频。然后它就会显示预览区。

预览区下方就是字幕区,有根据音频生成的波形在上边。在这个区域点击右键,选择「插入空白字幕」,就会插入一个空白的字幕条,双击可以输入字幕,拖拽可以调整显示的时长和起止时间。

添加好字幕以后,点击预览区的播放按钮,可以实时地看到新添加的字幕效果。需要注意的是,目前的版本中,删除某条字幕的操作是不能撤销的。这可能是这个软件为数不多的缺点了。

整个视频的全部字幕添加完以后,点击顶部菜单中的「导出」→「字幕文件」就会将刚才编辑的字幕生成一个字幕文件了。

picture 23

如果想要把字幕直接压制到视频里边,则可以选择「快速压制视频」选项。

字幕的自动生成

ArcTime 还内置了一个为视频生成字幕的功能,放置在「语音识别」菜单中,但这些功能是收费的。

对于程序员来讲,有一个更为廉价的方式获得同样的效果,那就是直接写代码去调用云服务商提供的 API。比如阿里云、腾讯云和百度翻译平台就提供了相关接口。

更有开发者已经在 GitHub 上开源了基于这些接口的命令行和客户端软件。大家可以在 GitHub 搜索「VideoSrt」,自行安装试用。

picture 24

流量池和二次购买

课程制作完成上线以后,并没有结束。长征才刚刚开始,我们需要不断得去运营它。这一节就来聊一聊流量池和二次购买。

没有流量池的情况

先来看一下在没有流量池的情况下,课程转化是什么样子的。

picture 26

首先,我们将自有的或者购买的流量引导到课程页面,以触发销售转化。但如果我们没有采取更多措施,之后这个流量就走掉了。当上架新课时,又需要重新寻找或购买流量。

这种方式优点是简单,但今天操作起来问题很大,因为我们已经错过了之前流量爆炸的时代,现在流量已经很贵了,这么浪费太可惜。那么,能不能把流量囤起来,供以后使用呢?

学员池

picture 27

最简单的操作就是,把购买过课程的学员放到「学员池」里。当上架新课程以后,可以直接给他们发通知进行销售。这样就实现了流量的二次使用。很多同学觉得这是显而易见的,但事实上在操作的时候却很容易出问题。

比如说,很多讲师只是直接使用课程平台进行学员管理,而很多的平台不允许讲师给学员批量发送私信,甚至还会做关键字过滤。这种情况下,我们对学员的触达能力是非常弱的,需要建立更可控的流量池来替代。

访客池

picture 28

学员池重用了已经购买过课程的流量,但更多的没有购买课程的访客流量还是流失了。所以我们还可以更进一步,来做访客池。

把我们课程中有意思、有传播点的内容做成免费的素材,进行多渠道分发,把用户吸引过来并放到这个池子里,以备以后发送通知、触发销售。

常用的渠道包括:

  1. 搜索引擎
  2. 社交网络
  3. 媒体平台
  4. 课程平台
  5. 行业网站

学员池和访客池是我们最主要的两种流量池。

构造流量池的工具

互联网发展到现在,各种产品已经极大的丰富,所以有大量的工具可以用来构造流量池。因为课程销售有非常明确的商业诉求,所以我们对流量池也有相对明确的评判标准。这里分享下我常用的三个标准:

  1. 进入门槛低:最好能免除用户注册,尽快获得用户的基本信息和触达权限
  2. 可触达率高:这样我们的销售信息才能被更多人看到
  3. 触达免费或廉价:太贵了用不起

如果想要获取种子用户用来验证大纲,还需要考虑互动性。

针对微博、公众号、企业信号、微信群、自建 APP 这几种最常用的方案,我们整理了一个对比表格以供大家参考:

picture 30

多级流量池

各种流量池都有自己的优缺点,我们应该选取当前阶段最适合的来进行流量的存储。我们也可以分阶段、渐进式地建立多级流量池,以在投入和收益上获得平衡。

比如早期我们可以直接使用微博的关注、哔哩哔哩的订阅来做流量池;然后将一部分核心用户引导到微信群和企业微信一对一服务中。这样把微博的获客门槛低和微信的触达率高这两个优点结合起来了。

在用户规模大一些以后,我们再去开发自己的App,实现对用户流量更高级别的控制。

picture 31

如何有效地反盗版

树立反盗版的正确思路

虽然几乎所有讲师都认为反盗版是必须做的,但未必都明白反盗版的意义,觉得就是少挣了钱。实际上并不是这么简单,盗版最大的问题,是对正版用户带来的不公平。同样的课程,有人花了几千块钱买过来,有人却一分钱不付就可以得到,这让正版用户显得很傻。

其次,很多讲师以为把课程放到课程平台上,平台就会帮着进行反盗版,自己就不用管了。事实上,大部分平台的反盗版措施都非常有限,通常只能由讲师提交盗版链接,他们投诉下架。如果对方将课程放到境外网站,连下架都做不到。而且有些平台每周定时收集处理一次盗版信息,还不如自己直接投诉效率高。所以我们不能把反盗版推给平台去做,他们只能起到辅助作用,我们自己还是要足够重视。

还有一个普遍的错误想法,就是很多程序员觉得盗版是不可能完全杜绝的,所以干脆就不防范了。我们的确没有办法从技术上来完全杜绝视频课的盗版,但却可以采取各种措施来降低被盗版的概率。

要从做盗版的人的经济收益的角度来思考盗版这件事情,如果我们的课盗版门槛很低,就可能导致大量盗版,因为不需要付出太多的代价。相反,如果我们课的盗版门槛很高,那就要花很多功夫才能盗版。

很多盗版手段是针对平台的,当我们课程的盗版门槛变高以后,盗版狗有两个选择,一个是投入时间和金钱去升级盗版手段,另一个选择是用原来的盗版方法继续盗版其他门槛低的课程。绝大部分情况下,它们会选择后者。

有同学可能会说,这样其实并没有解决盗版的问题。是的,从宏观上来讲,确实没有解决盗版问题;但从个体的角度来看,我们又的确避免了自己的课程被盗版。

要从宏观层面上去解决知识产权问题,需要国家、法律、以及社会各方面一起持续不断地推动,我们作为个体,积极响应国家的政策,并保护好自己的知识产权,就是在为这事添砖加瓦。

picture 32

如何有效地反盗版

所以反盗版其实就是要不断提升盗版的门槛,降低盗版狗的收益,让它们无利可图。我们自己实践过的方法中,最有效的可以归纳成四个字、两个词:卖空和卖多。

卖空

卖空其实就是预售,还没有课程,就开始销售。你很难盗版一个还不存在的课程。而且在我们精益网课流程中,本来就是通过预售来验证需求的,所以做起来很顺手。

这个思路再扩展一下,比起一次性提供课程,连载课程的反盗版门槛更高。因为它每周只更新一到两节课程,持续时间很长。这样盗版的成本一下被提升了 N 倍。

卖空的思路很简单,但效果却非常明显,强烈推荐大家尝试。

卖多

卖多是说,现在大家课程放到平台上,盗版门槛是一样高的。但是我们可以多提供一些平台没有的、盗版不了的服务来反盗版。这些服务可以包括:

  1. 答疑
  2. 督学
  3. 社群
  4. 线下服务

在进行这些服务的时候,我们可以先进行身份确认,无法提供购买证明的人就不能享受这些服务了。

更进一步,如果我们把课程中不可或缺的部分挪到这些服务中来,那么看盗版视频的人甚至不能完整的学完课程,这就让盗版课程失去了意义。

有一个不错的实践可以分享给大家。我们的主要课程是全栈课,既有前端又有后端。为了反盗版,我们开发了一个云端的编程环境,将后端课程放在其中,然后限制只有正版学员才能登录这个系统,采用这个系统的课程后来就再也没有被盗版过。

这个系统的开发很简单,只需要在云平台上启动一个基于容器的、带有桌面的系统,然后再运行一个基于 Web 的 VNC 去连接它,就可以实现在浏览器中远程操作桌面系统了。感兴趣的同学可以去了解下NoVNC这个开源项目。

进一步提升副业的鲁棒性

网课+独立开发的双引擎副业模式

前面我们通过两个大章节的实践课程,为大家详细讲解了怎么通过独立开发和网络课程制作来发展副业。之所以会选择这两个方向,除了它们非常典型、有很高的投入产出比,还有一个原因 —— 它们之间可以形成非常好的互补。

目前看来,在国内要通过独立开发赚到一流企业程序员的年收入(大致三十到五十万),还是比较困难的。免费加收费模式虽然后期收益巨大,但前期需要长时间的投入。

相对而言,网络课程的售卖更容易带来现金收益。如果我们把独立开发的整个过程完整的录制下来,并加工成网络课程进行销售,那么即使独立开发项目最终难以通过销售软件和服务来赚取足够多的收益,我们还可以通过网络课程获得收入。

而且,不管对于课程学员还是独立软件/服务使用者来讲,都更有益。课程的学员可以学到更为真实、更贴近一线、且经过事实验证的开发技巧;软件/服务使用者则可以获得详尽的文档、架构说明,更有机会进一步深入了解整个规划、设计、开发过程,充分理解业务,甚至因此变成代码贡献者。

从流量上讲,软件/服务可以给课程带来学员;课程可以给软件/服务带来用户。两者互相促进,为我们的副业更添了一层保障。

picture 25

最终,我们就可以实现一个多次利用「副产品优势」的三级收入模式。在这个模式下,我们首先通过主业赚取最核心的收益,以供日常生活和基本发展。然后,我们在主业工作中积累的知识、经验、人脉基础上,开发我们的副业,比如独立软件或服务。在独立开发的过程中,我们再次把它的副产品——制作过程,录制成课程进行售卖。最终,我们可以分别从主业、独立开发以及课程三个渠道获取收益。

这样即使某些收入源不是特别好,我们的整体收入还是相对高的,这就让我们有足够的时间和资源去修正这些错误,让整体发展得越来越好。

================================================ FILE: docs/searcher.js ================================================ "use strict"; window.search = window.search || {}; (function search(search) { // Search functionality // // You can use !hasFocus() to prevent keyhandling in your key // event handlers while the user is typing their search. if (!Mark || !elasticlunr) { return; } //IE 11 Compatibility from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith if (!String.prototype.startsWith) { String.prototype.startsWith = function(search, pos) { return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; }; } var search_wrap = document.getElementById('search-wrapper'), searchbar = document.getElementById('searchbar'), searchbar_outer = document.getElementById('searchbar-outer'), searchresults = document.getElementById('searchresults'), searchresults_outer = document.getElementById('searchresults-outer'), searchresults_header = document.getElementById('searchresults-header'), searchicon = document.getElementById('search-toggle'), content = document.getElementById('content'), searchindex = null, doc_urls = [], results_options = { teaser_word_count: 30, limit_results: 30, }, search_options = { bool: "AND", expand: true, fields: { title: {boost: 1}, body: {boost: 1}, breadcrumbs: {boost: 0} } }, mark_exclude = [], marker = new Mark(content), current_searchterm = "", URL_SEARCH_PARAM = 'search', URL_MARK_PARAM = 'highlight', teaser_count = 0, SEARCH_HOTKEY_KEYCODE = 83, ESCAPE_KEYCODE = 27, DOWN_KEYCODE = 40, UP_KEYCODE = 38, SELECT_KEYCODE = 13; function hasFocus() { return searchbar === document.activeElement; } function removeChildren(elem) { while (elem.firstChild) { elem.removeChild(elem.firstChild); } } // Helper to parse a url into its building blocks. function parseURL(url) { var a = document.createElement('a'); a.href = url; return { source: url, protocol: a.protocol.replace(':',''), host: a.hostname, port: a.port, params: (function(){ var ret = {}; var seg = a.search.replace(/^\?/,'').split('&'); var len = seg.length, i = 0, s; for (;i': '>', '"': '"', "'": ''' }; var repl = function(c) { return MAP[c]; }; return function(s) { return s.replace(/[&<>'"]/g, repl); }; })(); function formatSearchMetric(count, searchterm) { if (count == 1) { return count + " search result for '" + searchterm + "':"; } else if (count == 0) { return "No search results for '" + searchterm + "'."; } else { return count + " search results for '" + searchterm + "':"; } } function formatSearchResult(result, searchterms) { var teaser = makeTeaser(escapeHTML(result.doc.body), searchterms); teaser_count++; // The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor var url = doc_urls[result.ref].split("#"); if (url.length == 1) { // no anchor found url.push(""); } // encodeURIComponent escapes all chars that could allow an XSS except // for '. Due to that we also manually replace ' with its url-encoded // representation (%27). var searchterms = encodeURIComponent(searchterms.join(" ")).replace(/\'/g, "%27"); return '' + result.doc.breadcrumbs + '' + '' + teaser + ''; } function makeTeaser(body, searchterms) { // The strategy is as follows: // First, assign a value to each word in the document: // Words that correspond to search terms (stemmer aware): 40 // Normal words: 2 // First word in a sentence: 8 // Then use a sliding window with a constant number of words and count the // sum of the values of the words within the window. Then use the window that got the // maximum sum. If there are multiple maximas, then get the last one. // Enclose the terms in . var stemmed_searchterms = searchterms.map(function(w) { return elasticlunr.stemmer(w.toLowerCase()); }); var searchterm_weight = 40; var weighted = []; // contains elements of ["word", weight, index_in_document] // split in sentences, then words var sentences = body.toLowerCase().split('. '); var index = 0; var value = 0; var searchterm_found = false; for (var sentenceindex in sentences) { var words = sentences[sentenceindex].split(' '); value = 8; for (var wordindex in words) { var word = words[wordindex]; if (word.length > 0) { for (var searchtermindex in stemmed_searchterms) { if (elasticlunr.stemmer(word).startsWith(stemmed_searchterms[searchtermindex])) { value = searchterm_weight; searchterm_found = true; } }; weighted.push([word, value, index]); value = 2; } index += word.length; index += 1; // ' ' or '.' if last word in sentence }; index += 1; // because we split at a two-char boundary '. ' }; if (weighted.length == 0) { return body; } var window_weight = []; var window_size = Math.min(weighted.length, results_options.teaser_word_count); var cur_sum = 0; for (var wordindex = 0; wordindex < window_size; wordindex++) { cur_sum += weighted[wordindex][1]; }; window_weight.push(cur_sum); for (var wordindex = 0; wordindex < weighted.length - window_size; wordindex++) { cur_sum -= weighted[wordindex][1]; cur_sum += weighted[wordindex + window_size][1]; window_weight.push(cur_sum); }; if (searchterm_found) { var max_sum = 0; var max_sum_window_index = 0; // backwards for (var i = window_weight.length - 1; i >= 0; i--) { if (window_weight[i] > max_sum) { max_sum = window_weight[i]; max_sum_window_index = i; } }; } else { max_sum_window_index = 0; } // add around searchterms var teaser_split = []; var index = weighted[max_sum_window_index][2]; for (var i = max_sum_window_index; i < max_sum_window_index+window_size; i++) { var word = weighted[i]; if (index < word[2]) { // missing text from index to start of `word` teaser_split.push(body.substring(index, word[2])); index = word[2]; } if (word[1] == searchterm_weight) { teaser_split.push("") } index = word[2] + word[0].length; teaser_split.push(body.substring(word[2], index)); if (word[1] == searchterm_weight) { teaser_split.push("") } }; return teaser_split.join(''); } function init(config) { results_options = config.results_options; search_options = config.search_options; searchbar_outer = config.searchbar_outer; doc_urls = config.doc_urls; searchindex = elasticlunr.Index.load(config.index); // Set up events searchicon.addEventListener('click', function(e) { searchIconClickHandler(); }, false); searchbar.addEventListener('keyup', function(e) { searchbarKeyUpHandler(); }, false); document.addEventListener('keydown', function(e) { globalKeyHandler(e); }, false); // If the user uses the browser buttons, do the same as if a reload happened window.onpopstate = function(e) { doSearchOrMarkFromUrl(); }; // Suppress "submit" events so the page doesn't reload when the user presses Enter document.addEventListener('submit', function(e) { e.preventDefault(); }, false); // If reloaded, do the search or mark again, depending on the current url parameters doSearchOrMarkFromUrl(); } function unfocusSearchbar() { // hacky, but just focusing a div only works once var tmp = document.createElement('input'); tmp.setAttribute('style', 'position: absolute; opacity: 0;'); searchicon.appendChild(tmp); tmp.focus(); tmp.remove(); } // On reload or browser history backwards/forwards events, parse the url and do search or mark function doSearchOrMarkFromUrl() { // Check current URL for search request var url = parseURL(window.location.href); if (url.params.hasOwnProperty(URL_SEARCH_PARAM) && url.params[URL_SEARCH_PARAM] != "") { showSearch(true); searchbar.value = decodeURIComponent( (url.params[URL_SEARCH_PARAM]+'').replace(/\+/g, '%20')); searchbarKeyUpHandler(); // -> doSearch() } else { showSearch(false); } if (url.params.hasOwnProperty(URL_MARK_PARAM)) { var words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' '); marker.mark(words, { exclude: mark_exclude }); var markers = document.querySelectorAll("mark"); function hide() { for (var i = 0; i < markers.length; i++) { markers[i].classList.add("fade-out"); window.setTimeout(function(e) { marker.unmark(); }, 300); } } for (var i = 0; i < markers.length; i++) { markers[i].addEventListener('click', hide); } } } // Eventhandler for keyevents on `document` function globalKeyHandler(e) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea' || e.target.type === 'text') { return; } if (e.keyCode === ESCAPE_KEYCODE) { e.preventDefault(); searchbar.classList.remove("active"); setSearchUrlParameters("", (searchbar.value.trim() !== "") ? "push" : "replace"); if (hasFocus()) { unfocusSearchbar(); } showSearch(false); marker.unmark(); } else if (!hasFocus() && e.keyCode === SEARCH_HOTKEY_KEYCODE) { e.preventDefault(); showSearch(true); window.scrollTo(0, 0); searchbar.select(); } else if (hasFocus() && e.keyCode === DOWN_KEYCODE) { e.preventDefault(); unfocusSearchbar(); searchresults.firstElementChild.classList.add("focus"); } else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE || e.keyCode === UP_KEYCODE || e.keyCode === SELECT_KEYCODE)) { // not `:focus` because browser does annoying scrolling var focused = searchresults.querySelector("li.focus"); if (!focused) return; e.preventDefault(); if (e.keyCode === DOWN_KEYCODE) { var next = focused.nextElementSibling; if (next) { focused.classList.remove("focus"); next.classList.add("focus"); } } else if (e.keyCode === UP_KEYCODE) { focused.classList.remove("focus"); var prev = focused.previousElementSibling; if (prev) { prev.classList.add("focus"); } else { searchbar.select(); } } else { // SELECT_KEYCODE window.location.assign(focused.querySelector('a')); } } } function showSearch(yes) { if (yes) { search_wrap.classList.remove('hidden'); searchicon.setAttribute('aria-expanded', 'true'); } else { search_wrap.classList.add('hidden'); searchicon.setAttribute('aria-expanded', 'false'); var results = searchresults.children; for (var i = 0; i < results.length; i++) { results[i].classList.remove("focus"); } } } function showResults(yes) { if (yes) { searchresults_outer.classList.remove('hidden'); } else { searchresults_outer.classList.add('hidden'); } } // Eventhandler for search icon function searchIconClickHandler() { if (search_wrap.classList.contains('hidden')) { showSearch(true); window.scrollTo(0, 0); searchbar.select(); } else { showSearch(false); } } // Eventhandler for keyevents while the searchbar is focused function searchbarKeyUpHandler() { var searchterm = searchbar.value.trim(); if (searchterm != "") { searchbar.classList.add("active"); doSearch(searchterm); } else { searchbar.classList.remove("active"); showResults(false); removeChildren(searchresults); } setSearchUrlParameters(searchterm, "push_if_new_search_else_replace"); // Remove marks marker.unmark(); } // Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and #heading-anchor . // `action` can be one of "push", "replace", "push_if_new_search_else_replace" // and replaces or pushes a new browser history item. // "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet. function setSearchUrlParameters(searchterm, action) { var url = parseURL(window.location.href); var first_search = ! url.params.hasOwnProperty(URL_SEARCH_PARAM); if (searchterm != "" || action == "push_if_new_search_else_replace") { url.params[URL_SEARCH_PARAM] = searchterm; delete url.params[URL_MARK_PARAM]; url.hash = ""; } else { delete url.params[URL_MARK_PARAM]; delete url.params[URL_SEARCH_PARAM]; } // A new search will also add a new history item, so the user can go back // to the page prior to searching. A updated search term will only replace // the url. if (action == "push" || (action == "push_if_new_search_else_replace" && first_search) ) { history.pushState({}, document.title, renderURL(url)); } else if (action == "replace" || (action == "push_if_new_search_else_replace" && !first_search) ) { history.replaceState({}, document.title, renderURL(url)); } } function doSearch(searchterm) { // Don't search the same twice if (current_searchterm == searchterm) { return; } else { current_searchterm = searchterm; } if (searchindex == null) { return; } // Do the actual search var results = searchindex.search(searchterm, search_options); var resultcount = Math.min(results.length, results_options.limit_results); // Display search metrics searchresults_header.innerText = formatSearchMetric(resultcount, searchterm); // Clear and insert results var searchterms = searchterm.split(' '); removeChildren(searchresults); for(var i = 0; i < resultcount ; i++){ var resultElem = document.createElement('li'); resultElem.innerHTML = formatSearchResult(results[i], searchterms); searchresults.appendChild(resultElem); } // Display results showResults(true); } fetch(path_to_root + 'searchindex.json') .then(response => response.json()) .then(json => init(json)) .catch(error => { // Try to load searchindex.js if fetch failed var script = document.createElement('script'); script.src = path_to_root + 'searchindex.js'; script.onload = () => init(window.search); document.head.appendChild(script); }); // Exported functions search.hasFocus = hasFocus; })(window.search); ================================================ FILE: docs/searchindex.js ================================================ Object.assign(window.search, {"doc_urls":["index.html#精益副业","01.html#为什么副业特别重要","0101.html#职业可能性","010101.html#职业的四大象限","010101.html#e象限雇员象限帮别人挣钱","010101.html#s象限自雇象限为自己挣钱","010101.html#b象限创业象限让雇员挣钱","010101.html#i象限投资象限让钱挣钱","010102.html#没有副业的职业","010102.html#eb辞职创业","010102.html#es回老家开工作室","010103.html#副业带来的可能性","010103.html#es回老家开工作室","010103.html#eb创业","0102.html#职业自由度","010201.html#从中指备用金说起","010202.html#planb和反脆弱","010203.html#全新的工作自由度","010203.html#远程办公","010203.html#freelancer","010203.html#独立开发","0103.html#职业成长性","010301A.html#新技术练兵场","010302.html#业务敏感度","02.html#如何优雅地做副业","0201.html#想明白核心资源和核心优势","020101.html#副业的核心资源","020102.html#副业的核心优势","0202.html#时间片","020201.html#时间片的销售","020201.html#私单","020201.html#外包","020201.html#外包的坑","020201.html#按需雇用","020201.html#更优雅的方式","020202.html#时间片的优化","020202.html#提升单位时间的收益","020202.html#切换地域","020202.html#从外包到二次开发","020202.html#提升单位时间的效率","020202.html#打鸡血难以奏效","020202.html#自动化","020203.html#突破时间片限制","020203.html#倍增","020203.html#外包","020203.html#众包","020203.html#超卖","0203.html#资产和被动收入","020301.html#什么是资产","020302.html#资产的获得方式","020303.html#资产的量化评估","020303.html#适合副业的几个特征","020303.html#自传播","020303.html#ugc","020303.html#自动化","020303.html#量化评估标准","020303.html#投入","020303.html#产出","020303.html#可持续性","020303.html#风险","020303.html#门槛","03.html#优选资产","0301.html#知识和人脉的变现","030101.html#付费视频课","030101.html#低投入-","030101.html#高产出-","030101.html#可持续性-","030101.html#低风险-","030101.html#低门槛-","030102.html#付费专栏","030102.html#低投入-","030102.html#高产出-","030102.html#可持续性-","030102.html#低风险-","030102.html#低门槛-","030103.html#付费社群","030103.html#低投入-","030103.html#高产出-","030103.html#可持续性-","030103.html#低风险-","030103.html#低门槛-","030104.html#图书出版","030104.html#低投入-","030104.html#高产出-","030104.html#可持续性-","030104.html#低风险-","030104.html#低门槛-","0302.html#自有产品和服务","0302.html#需求的发现","0302.html#原生需求","0302.html#观察分析和阅读报告","030201.html#应用市场卖-app","030201.html#关键字搜索","030201.html#编辑推荐","030201.html#低投入-","030201.html#高产出-","030201.html#可持续性-","030201.html#低风险-","030201.html#低门槛-","04.html#精益副业","0401.html#精益副业流程","040104.html#商业模式画布","040104.html#价值的定义","040104.html#创造价值","040104.html#销售价值","040104.html#分层结构","040104.html#画布结构","040104.html#价值主张画布","040104.html#客户细分","040104.html#价值主张","040104.html#契合","040105.html#最小可行产品和产品市场契合","0403.html#精益独立开发实践","040301.html#独立开发的精益流程","040302.html#福利单词项目简介","040303.html#福利单词的商业模式画布","040303.html#价值主张","040303.html#客户细分","040303.html#价值主张的细化","040303.html#渠道通路","040303.html#客户关系","040303.html#关键活动","040303.html#关键资源","040303.html#作者授权","040303.html#换用无版权图片","040303.html#用户自行提供图片","040303.html#成本收益","040304.html#通过用户画像细化客户","040304.html#什么是用户画像","040304.html#福利单词的用户画像","040304.html#四六级备考生","040304.html#留学移民预备军","040304.html#专业提升小白领","040304.html#画像的头像制作","040304.html#最终的用户画像","040305.html#画像场景功能和分期","040305.html#使用场景分析","040305.html#王小康的使用场景分析","040305.html#章小留的使用场景分析","040305.html#卢小白的使用场景分析","040305.html#从场景到功能","040305.html#通过思维导图梳理功能","040305.html#分期","040305.html#功能分期","040305.html#功能归类到界面","040306.html#什么是好的商业设计","040306.html#好设计的标准","040306.html#商业设计","040306.html#简洁即美","040307.html#人人能用的四大原则","040308.html#独特logo解决方案","040308.html#为什么要自己设计-logo","040308.html#通过矢量软件绘制-logo","040308.html#免费和开放的矢量资源","040308.html#购买付费素材","040308.html#将付费素材变成独有的","040309.html#使用adobexd设计界面","040309.html#什么是-adobe-xd","040309.html#使用-adobe-xd-设计简单界面","040309.html#理解画板","040309.html#遮罩的制作","040309.html#单词释义和输入框","040309.html#虚拟键盘","040309.html#矢量图标","040310.html#个人支付解决方案","040310.html#常见的几种个人收款方式","040310.html#个人收款码","040310.html#二次封装接口","040310.html#小微商户","040310.html#数字内容销售平台","040311.html#使用兔小巢处理用户反馈","040311.html#整合说明","040311.html#链接跳转","040311.html#状态登入","040311.html#反馈数据整合","040312.html#2a3r漏斗和增长优化","040312.html#什么是-2a3r-漏斗","040312.html#使用-2a3r-漏斗进行业务优化","040312.html#留存层优化","040312.html#推荐层优化","040312.html#推荐阅读","0402.html#精益网课变现实践","040207.html#大纲的注意点","040207.html#条理性","040207.html#三段式","040207.html#提问式","040207.html#覆盖面","040207.html#粒度","040209.html#通过预售验证销量","040209.html#为什么要验证","040209.html#如何验证","040209.html#众筹预售平台","040209.html#自建众筹预售平台","040209.html#付费群","040210.html#常见的课程片段类型","040211.html#文稿讲义类课程片段的制作","040211.html#全局录屏","040211.html#使用幻灯片软件自带的演讲录制功能","040211.html#如何使用-keynote-的录制幻灯片放映功能生成视频课程","040211.html#如何使用-powerpoint的录制幻灯片演示功能生成视频课程","040211.html#幻灯片导出为视频","040211.html#如何使用-keynote-以导出为视频的方式生成视频课程","040211.html#如何使用-powerpoint-以导出为视频的方式生成视频课程","040212.html#屏幕录制类课程片段的制作","040212.html#屏幕录制的原理","040212.html#屏幕录制的软件","040212.html#功能强大","040212.html#开源免费","040212.html#跨平台","040212.html#obs-的层次逻辑","040212.html#场景","040212.html#来源","040212.html#来源的层次","040212.html#滤镜","040213.html#真人出镜类课程片段的制作","040213.html#什么是真人出镜类课程片段","040213.html#抠图","040213.html#真人出镜的其他细节","040214.html#虚拟形象类课程片段的制作","040214.html#虚拟形象的原理","040214.html#facerig","040214.html#步骤","040215.html#最常用的视频剪辑操作","040215.html#剪辑软件","040215.html#视频片段的调整","040215.html#柔软的视频片段","040215.html#视频片段顺序的调整","040215.html#视频片段速度的调整","040215.html#视频中的音频处理","040216.html#最常用的音频处理操作","040216.html#去噪","040216.html#标准化","040216.html#混响","040216.html#齿音和嘶声","040216.html#建议顺序","040217.html#字幕的制作和自动生成","040217.html#字幕及其格式","040217.html#字幕编辑软件","040217.html#字幕的自动生成","040218.html#流量池和二次购买","040218.html#没有流量池的情况","040218.html#学员池","040218.html#访客池","040218.html#构造流量池的工具","040218.html#多级流量池","040219.html#如何有效地反盗版","040219.html#树立反盗版的正确思路","040219.html#如何有效地反盗版","040219.html#卖空","040219.html#卖多","0404.html#进一步提升副业的鲁棒性","040401.html#网课独立开发的双引擎副业模式"],"index":{"documentStore":{"docInfo":{"0":{"body":0,"breadcrumbs":0,"title":0},"1":{"body":0,"breadcrumbs":0,"title":0},"10":{"body":5,"breadcrumbs":1,"title":1},"100":{"body":0,"breadcrumbs":0,"title":0},"101":{"body":0,"breadcrumbs":0,"title":0},"102":{"body":2,"breadcrumbs":0,"title":0},"103":{"body":3,"breadcrumbs":0,"title":0},"104":{"body":2,"breadcrumbs":0,"title":0},"105":{"body":2,"breadcrumbs":0,"title":0},"106":{"body":2,"breadcrumbs":0,"title":0},"107":{"body":2,"breadcrumbs":0,"title":0},"108":{"body":0,"breadcrumbs":0,"title":0},"109":{"body":0,"breadcrumbs":0,"title":0},"11":{"body":0,"breadcrumbs":0,"title":0},"110":{"body":0,"breadcrumbs":0,"title":0},"111":{"body":12,"breadcrumbs":0,"title":0},"112":{"body":0,"breadcrumbs":0,"title":0},"113":{"body":2,"breadcrumbs":0,"title":0},"114":{"body":4,"breadcrumbs":0,"title":0},"115":{"body":0,"breadcrumbs":0,"title":0},"116":{"body":2,"breadcrumbs":0,"title":0},"117":{"body":2,"breadcrumbs":0,"title":0},"118":{"body":3,"breadcrumbs":0,"title":0},"119":{"body":2,"breadcrumbs":0,"title":0},"12":{"body":0,"breadcrumbs":1,"title":1},"120":{"body":3,"breadcrumbs":0,"title":0},"121":{"body":6,"breadcrumbs":0,"title":0},"122":{"body":2,"breadcrumbs":0,"title":0},"123":{"body":2,"breadcrumbs":0,"title":0},"124":{"body":1,"breadcrumbs":0,"title":0},"125":{"body":1,"breadcrumbs":0,"title":0},"126":{"body":4,"breadcrumbs":0,"title":0},"127":{"body":0,"breadcrumbs":0,"title":0},"128":{"body":1,"breadcrumbs":0,"title":0},"129":{"body":0,"breadcrumbs":0,"title":0},"13":{"body":6,"breadcrumbs":1,"title":1},"130":{"body":0,"breadcrumbs":0,"title":0},"131":{"body":0,"breadcrumbs":0,"title":0},"132":{"body":1,"breadcrumbs":0,"title":0},"133":{"body":7,"breadcrumbs":0,"title":0},"134":{"body":6,"breadcrumbs":0,"title":0},"135":{"body":0,"breadcrumbs":0,"title":0},"136":{"body":0,"breadcrumbs":0,"title":0},"137":{"body":2,"breadcrumbs":0,"title":0},"138":{"body":0,"breadcrumbs":0,"title":0},"139":{"body":0,"breadcrumbs":0,"title":0},"14":{"body":0,"breadcrumbs":0,"title":0},"140":{"body":4,"breadcrumbs":0,"title":0},"141":{"body":0,"breadcrumbs":0,"title":0},"142":{"body":0,"breadcrumbs":0,"title":0},"143":{"body":3,"breadcrumbs":0,"title":0},"144":{"body":2,"breadcrumbs":0,"title":0},"145":{"body":0,"breadcrumbs":0,"title":0},"146":{"body":0,"breadcrumbs":0,"title":0},"147":{"body":0,"breadcrumbs":0,"title":0},"148":{"body":0,"breadcrumbs":0,"title":0},"149":{"body":4,"breadcrumbs":0,"title":0},"15":{"body":4,"breadcrumbs":0,"title":0},"150":{"body":1,"breadcrumbs":2,"title":1},"151":{"body":1,"breadcrumbs":2,"title":1},"152":{"body":4,"breadcrumbs":2,"title":1},"153":{"body":3,"breadcrumbs":1,"title":0},"154":{"body":7,"breadcrumbs":1,"title":0},"155":{"body":8,"breadcrumbs":1,"title":0},"156":{"body":0,"breadcrumbs":2,"title":1},"157":{"body":11,"breadcrumbs":3,"title":2},"158":{"body":0,"breadcrumbs":3,"title":2},"159":{"body":17,"breadcrumbs":1,"title":0},"16":{"body":2,"breadcrumbs":2,"title":1},"160":{"body":12,"breadcrumbs":1,"title":0},"161":{"body":7,"breadcrumbs":1,"title":0},"162":{"body":17,"breadcrumbs":1,"title":0},"163":{"body":8,"breadcrumbs":1,"title":0},"164":{"body":0,"breadcrumbs":0,"title":0},"165":{"body":0,"breadcrumbs":0,"title":0},"166":{"body":1,"breadcrumbs":0,"title":0},"167":{"body":0,"breadcrumbs":0,"title":0},"168":{"body":4,"breadcrumbs":0,"title":0},"169":{"body":6,"breadcrumbs":0,"title":0},"17":{"body":0,"breadcrumbs":0,"title":0},"170":{"body":4,"breadcrumbs":0,"title":0},"171":{"body":0,"breadcrumbs":0,"title":0},"172":{"body":2,"breadcrumbs":0,"title":0},"173":{"body":1,"breadcrumbs":0,"title":0},"174":{"body":1,"breadcrumbs":0,"title":0},"175":{"body":0,"breadcrumbs":2,"title":1},"176":{"body":4,"breadcrumbs":2,"title":1},"177":{"body":13,"breadcrumbs":2,"title":1},"178":{"body":0,"breadcrumbs":1,"title":0},"179":{"body":2,"breadcrumbs":1,"title":0},"18":{"body":0,"breadcrumbs":0,"title":0},"180":{"body":0,"breadcrumbs":1,"title":0},"181":{"body":0,"breadcrumbs":0,"title":0},"182":{"body":0,"breadcrumbs":0,"title":0},"183":{"body":0,"breadcrumbs":0,"title":0},"184":{"body":0,"breadcrumbs":0,"title":0},"185":{"body":0,"breadcrumbs":0,"title":0},"186":{"body":3,"breadcrumbs":0,"title":0},"187":{"body":1,"breadcrumbs":0,"title":0},"188":{"body":0,"breadcrumbs":0,"title":0},"189":{"body":6,"breadcrumbs":0,"title":0},"19":{"body":2,"breadcrumbs":1,"title":1},"190":{"body":0,"breadcrumbs":0,"title":0},"191":{"body":3,"breadcrumbs":0,"title":0},"192":{"body":0,"breadcrumbs":0,"title":0},"193":{"body":0,"breadcrumbs":0,"title":0},"194":{"body":1,"breadcrumbs":0,"title":0},"195":{"body":1,"breadcrumbs":0,"title":0},"196":{"body":0,"breadcrumbs":0,"title":0},"197":{"body":4,"breadcrumbs":0,"title":0},"198":{"body":15,"breadcrumbs":1,"title":1},"199":{"body":9,"breadcrumbs":1,"title":1},"2":{"body":0,"breadcrumbs":0,"title":0},"20":{"body":2,"breadcrumbs":0,"title":0},"200":{"body":4,"breadcrumbs":0,"title":0},"201":{"body":14,"breadcrumbs":1,"title":1},"202":{"body":10,"breadcrumbs":1,"title":1},"203":{"body":0,"breadcrumbs":0,"title":0},"204":{"body":0,"breadcrumbs":0,"title":0},"205":{"body":1,"breadcrumbs":0,"title":0},"206":{"body":4,"breadcrumbs":0,"title":0},"207":{"body":1,"breadcrumbs":0,"title":0},"208":{"body":5,"breadcrumbs":0,"title":0},"209":{"body":4,"breadcrumbs":1,"title":1},"21":{"body":0,"breadcrumbs":0,"title":0},"210":{"body":4,"breadcrumbs":0,"title":0},"211":{"body":8,"breadcrumbs":0,"title":0},"212":{"body":3,"breadcrumbs":0,"title":0},"213":{"body":3,"breadcrumbs":0,"title":0},"214":{"body":0,"breadcrumbs":0,"title":0},"215":{"body":2,"breadcrumbs":0,"title":0},"216":{"body":9,"breadcrumbs":0,"title":0},"217":{"body":2,"breadcrumbs":0,"title":0},"218":{"body":0,"breadcrumbs":0,"title":0},"219":{"body":0,"breadcrumbs":0,"title":0},"22":{"body":7,"breadcrumbs":0,"title":0},"220":{"body":7,"breadcrumbs":1,"title":1},"221":{"body":20,"breadcrumbs":0,"title":0},"222":{"body":0,"breadcrumbs":0,"title":0},"223":{"body":14,"breadcrumbs":0,"title":0},"224":{"body":12,"breadcrumbs":0,"title":0},"225":{"body":4,"breadcrumbs":0,"title":0},"226":{"body":3,"breadcrumbs":0,"title":0},"227":{"body":3,"breadcrumbs":0,"title":0},"228":{"body":7,"breadcrumbs":0,"title":0},"229":{"body":0,"breadcrumbs":0,"title":0},"23":{"body":2,"breadcrumbs":0,"title":0},"230":{"body":11,"breadcrumbs":0,"title":0},"231":{"body":11,"breadcrumbs":0,"title":0},"232":{"body":7,"breadcrumbs":0,"title":0},"233":{"body":1,"breadcrumbs":0,"title":0},"234":{"body":2,"breadcrumbs":0,"title":0},"235":{"body":0,"breadcrumbs":0,"title":0},"236":{"body":4,"breadcrumbs":0,"title":0},"237":{"body":5,"breadcrumbs":0,"title":0},"238":{"body":7,"breadcrumbs":0,"title":0},"239":{"body":0,"breadcrumbs":0,"title":0},"24":{"body":0,"breadcrumbs":0,"title":0},"240":{"body":2,"breadcrumbs":0,"title":0},"241":{"body":2,"breadcrumbs":0,"title":0},"242":{"body":2,"breadcrumbs":0,"title":0},"243":{"body":3,"breadcrumbs":0,"title":0},"244":{"body":3,"breadcrumbs":0,"title":0},"245":{"body":0,"breadcrumbs":0,"title":0},"246":{"body":2,"breadcrumbs":0,"title":0},"247":{"body":0,"breadcrumbs":0,"title":0},"248":{"body":1,"breadcrumbs":0,"title":0},"249":{"body":3,"breadcrumbs":0,"title":0},"25":{"body":0,"breadcrumbs":0,"title":0},"250":{"body":0,"breadcrumbs":0,"title":0},"251":{"body":2,"breadcrumbs":0,"title":0},"26":{"body":0,"breadcrumbs":0,"title":0},"27":{"body":7,"breadcrumbs":0,"title":0},"28":{"body":0,"breadcrumbs":0,"title":0},"29":{"body":0,"breadcrumbs":0,"title":0},"3":{"body":2,"breadcrumbs":0,"title":0},"30":{"body":0,"breadcrumbs":0,"title":0},"31":{"body":1,"breadcrumbs":0,"title":0},"32":{"body":0,"breadcrumbs":0,"title":0},"33":{"body":0,"breadcrumbs":0,"title":0},"34":{"body":1,"breadcrumbs":0,"title":0},"35":{"body":0,"breadcrumbs":0,"title":0},"36":{"body":0,"breadcrumbs":0,"title":0},"37":{"body":0,"breadcrumbs":0,"title":0},"38":{"body":3,"breadcrumbs":0,"title":0},"39":{"body":2,"breadcrumbs":0,"title":0},"4":{"body":3,"breadcrumbs":1,"title":1},"40":{"body":0,"breadcrumbs":0,"title":0},"41":{"body":17,"breadcrumbs":0,"title":0},"42":{"body":0,"breadcrumbs":0,"title":0},"43":{"body":0,"breadcrumbs":0,"title":0},"44":{"body":0,"breadcrumbs":0,"title":0},"45":{"body":2,"breadcrumbs":0,"title":0},"46":{"body":0,"breadcrumbs":0,"title":0},"47":{"body":0,"breadcrumbs":0,"title":0},"48":{"body":0,"breadcrumbs":0,"title":0},"49":{"body":0,"breadcrumbs":0,"title":0},"5":{"body":3,"breadcrumbs":1,"title":1},"50":{"body":0,"breadcrumbs":0,"title":0},"51":{"body":0,"breadcrumbs":0,"title":0},"52":{"body":0,"breadcrumbs":0,"title":0},"53":{"body":1,"breadcrumbs":1,"title":1},"54":{"body":0,"breadcrumbs":0,"title":0},"55":{"body":1,"breadcrumbs":0,"title":0},"56":{"body":2,"breadcrumbs":0,"title":0},"57":{"body":1,"breadcrumbs":0,"title":0},"58":{"body":0,"breadcrumbs":0,"title":0},"59":{"body":1,"breadcrumbs":0,"title":0},"6":{"body":2,"breadcrumbs":1,"title":1},"60":{"body":0,"breadcrumbs":0,"title":0},"61":{"body":0,"breadcrumbs":0,"title":0},"62":{"body":0,"breadcrumbs":0,"title":0},"63":{"body":2,"breadcrumbs":0,"title":0},"64":{"body":0,"breadcrumbs":0,"title":0},"65":{"body":0,"breadcrumbs":0,"title":0},"66":{"body":0,"breadcrumbs":0,"title":0},"67":{"body":0,"breadcrumbs":0,"title":0},"68":{"body":0,"breadcrumbs":0,"title":0},"69":{"body":5,"breadcrumbs":0,"title":0},"7":{"body":2,"breadcrumbs":0,"title":0},"70":{"body":0,"breadcrumbs":0,"title":0},"71":{"body":1,"breadcrumbs":0,"title":0},"72":{"body":0,"breadcrumbs":0,"title":0},"73":{"body":0,"breadcrumbs":0,"title":0},"74":{"body":0,"breadcrumbs":0,"title":0},"75":{"body":3,"breadcrumbs":0,"title":0},"76":{"body":0,"breadcrumbs":0,"title":0},"77":{"body":0,"breadcrumbs":0,"title":0},"78":{"body":0,"breadcrumbs":0,"title":0},"79":{"body":0,"breadcrumbs":0,"title":0},"8":{"body":1,"breadcrumbs":0,"title":0},"80":{"body":0,"breadcrumbs":0,"title":0},"81":{"body":4,"breadcrumbs":0,"title":0},"82":{"body":1,"breadcrumbs":0,"title":0},"83":{"body":3,"breadcrumbs":0,"title":0},"84":{"body":0,"breadcrumbs":0,"title":0},"85":{"body":0,"breadcrumbs":0,"title":0},"86":{"body":1,"breadcrumbs":0,"title":0},"87":{"body":2,"breadcrumbs":0,"title":0},"88":{"body":0,"breadcrumbs":0,"title":0},"89":{"body":2,"breadcrumbs":0,"title":0},"9":{"body":2,"breadcrumbs":1,"title":1},"90":{"body":4,"breadcrumbs":0,"title":0},"91":{"body":2,"breadcrumbs":2,"title":1},"92":{"body":0,"breadcrumbs":1,"title":0},"93":{"body":4,"breadcrumbs":1,"title":0},"94":{"body":4,"breadcrumbs":1,"title":0},"95":{"body":0,"breadcrumbs":1,"title":0},"96":{"body":2,"breadcrumbs":1,"title":0},"97":{"body":1,"breadcrumbs":1,"title":0},"98":{"body":0,"breadcrumbs":1,"title":0},"99":{"body":0,"breadcrumbs":0,"title":0}},"docs":{"0":{"body":"","breadcrumbs":"精益副业 » 精益副业","id":"0","title":"精益副业"},"1":{"body":"在很多人的印象中,副业也许只是挣点零花钱补贴家用的小打小闹。但实际上,它对于我们的整个职业有非常大的影响,甚至会改变我们的人生。 本章我们将从「职业可能性」、「职业自由度」以及「职业成长性」三个方面来进行说明。","breadcrumbs":"为什么副业特别重要 » 为什么副业特别重要","id":"1","title":"为什么副业特别重要"},"10":{"body":"S象限,在这里可以看成是 Easy 难度的B象限,因为自雇没有员工,可以不处理公司管理相关事务。 最熟悉的讨论就是回老家结婚,不,开工作室。我有不少北漂朋友都选择了这条路。本质上来说,这其实是一个好选择,但问题在于,如果没有做好前期准备,失败率也是非常高的。 在大公司工作的人容易产生一种幻觉,那就是把平台的能力当做自己的能力。以大公司的身份去和别人谈合作的时候,感觉都很容易。等到自己离完职才发现,同样的客户,你根本都见不到人。 我知道不少朋友都是因为高估了自己拉业务的能力,最后不得不又重返北上深。 加上全球经济放缓、美元投资减少,这种单线切换的方式又包含巨大的风险,所以很多程序员都选择了被锁死在E象限,成为永久的打工人。 我并不是说打工不好,但如果你不能较快地晋升到高级职位的话,就要仔细考虑如何应对正在形成的35岁新门槛。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » E→S,回老家开工作室","id":"10","title":"E→S,回老家开工作室"},"100":{"body":"","breadcrumbs":"精益副业 » 精益副业流程 » 精益副业流程","id":"100","title":"精益副业流程"},"101":{"body":"前边我们说到,在精益创业方法论里,有两个非常重要的假设,第一个就是「价值创建假设」。 因为不管是向用户销售软件还是在线服务,它本质上来讲其实是一种价值交换。也就是我们「给什么样的客户」「提供什么样的服务」,然后「收多少钱」的一个简单逻辑。 而围绕着价值的定义、创造和传播,我们可以使用一个非常棒的工具来描述它,这个工具叫做商业模式画布。商业模式听起来是一个很高大上的名词,但它具体化以后就很容易理解。 商业模式画布是以价值为中心的一张图,让我们把所有和价值相关的内容都放到上面,从而可以一目了然地纵观全局。 那下面,我们就来看一下商业模式画布是怎么围绕核心价值,一层一层建立起来的。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 商业模式画布","id":"101","title":"商业模式画布"},"102":{"body":"商业模式的核心,就是「价值主张」。也就是刚刚提过的,对谁,提供什么样的服务,收多少钱。 picture 6","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值的定义","id":"102","title":"价值的定义"},"103":{"body":"定义好价值以后,我们会从两方面来考虑它。首先是如何把这个价值给创造出来;然后是如何把这个价值给销售出去。 在价值创造这边,我们可以把它细化为三个方面。 picture 7 包括: 我们需要进行什么样的活动?这里的「活动」是「activity」,其实也可以叫做动作。 我们需要什么样的资源? 我们需要进行哪些合作?","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 创造价值","id":"103","title":"创造价值"},"104":{"body":"在价值销售这边呢,我们就要思考: picture 8 我们的价值主张定义得够不够好? 我们的渠道通路是不是足够的通畅,到达是不是有效? 我们的客户关系要怎么来建立和维系? 其实价值主张应该放到价值定义里边,但因为价值主张它直接涉及到了客户细分,又直接影响到了销售,所以我暂时把它放到销售这一边。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 销售价值","id":"104","title":"销售价值"},"105":{"body":"按前面的描述,我们比较容易把商业模式画布当成一张图。但事实上,它其实更类似于Photoshop 软件中 的 PSD 文件,是分层的。其中每一层针对一个细分人群。 这主要是因为我们提出的价值主张,很难同时覆盖多个人群。同样的价值主张对一类人来讲可能是非常棒的东西;而对于另一类人来讲可能就毫无用处。 所以,我们提出价值主张之前,就需要进行客户细分,把我们的客户分成几类典型的角色,再针对每一类角色来提出更为具体、更有针对性的价值主张。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 分层结构","id":"105","title":"分层结构"},"106":{"body":"下面我们就实际来看一下商业模式画布的布局。 picture 9 在表格的最中间,就是我们的价值主张。在最右边,是客户细分。我们可以用不同颜色的文字,来代表不同的细分客户和针对他们的价值主张。 在价值主张表格的左边,是关于价值创造的区域,有「关键活动」、「关键资源」、「关键合作伙伴」;在价值主张表格的右边,是关于价值销售的区域,除了我们刚才已经说过的「客户细分」,还包含了「客户关系」和「渠道通路」。 表格的最下边一行,分成了两部分,左边是「成本构成」,右边是「收入来源」,它们都是根据我们上面的表格来进行计算的。一旦计算完,我们就可以预先知道这个项目做下来能不能挣钱,或者说挣钱的可能性有多大。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 画布结构","id":"106","title":"画布结构"},"107":{"body":"在整个商业模式画布里边,「价值主张」和「客户细分」是最为基础、也最为关键的地方。如果价值主张没定义好,其他的做得再好也没有用。 所以,为了更好地进行价值主张设计,我们还有一张专门针对这两个部分的、更为详尽的「价值主张画布」。 picture 10 上边这张图就是「价值主张画布」。它左边是「价值主张」,右边是「客户细分」。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值主张画布","id":"107","title":"价值主张画布"},"108":{"body":"在「客户细分」这里,它更为详尽地描述了客户的情况。 这个圆分为三部分,最右侧描述了客户想要进行的工作、要完成的业务;下方是他在完成这些工作的时候所感受到的痛苦;上方是在完成工作后可以得到的收益。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 客户细分","id":"108","title":"客户细分"},"109":{"body":"图左边的正方形就是我们的价值主张。可以看到,价值主张是针对需求提供的解决方案。比如:针对痛点,我们会提供「痛点缓释方案」,让客户在完成工作的过程中,没有那么痛苦;针对收益,提出「收益创造方案」,让收益变得更多。 在这两个方案的基础上,我们通过产品和服务的形式来将其落地,也就是正方形的左侧部分。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值主张","id":"109","title":"价值主张"},"11":{"body":"当我们有了副业,情况就完全不一样了。 因为我们从单进程变成了多进程,可以并行地进行尝试。最重要的是,这种尝试并不会影响我们的主业,不会降低我们的生活质量。 我们还是以上一节的两个例子来看。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » 副业带来的可能性","id":"11","title":"副业带来的可能性"},"110":{"body":"大家可以注意到,在「客户细分」的圆形和「价值主张」的方形中间,有两个正对着的箭头,它表示「价值主张」和「客户细分」之间要达成契合。 因为我们会把整个客户群体分成多个细分群体,所以价值主张画布,它其实也是多份的。针对每一个细分的客户群体,都会有一张自己的价值主张画布。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 契合","id":"110","title":"契合"},"111":{"body":"上一节讲了如何通过商业模式画布来规划商业逻辑,但是「所有的战略和规划都是假设」,只有被验证以后的认知才是可靠、可信的。所以接下来,我们就需要用实验的方式来对它们进行验证。 通常,我们会采用「最小可行产品」(Minimum Viable Product,缩写为 MVP)来进行验证。 「最小可行产品」有两个关键词。一个是「可行」,它其实并不是指用户拿过去能用,而是指它可以很好地验证我们的假设。 另一个关键词是「最小」。它是说,除了验证所必需的功能以外,其他的功能都应该先不做。那些功能应该在验证完成之后再去添加,不然如果我们验证失败的话,功能就白做了。在我们的精力非常有限的情况下,这种浪费是非常可惜的。 严格意义上来讲,我们可以针对整个商业规划里边的每一个假设来做一个最小可行产品对其进行验证。但是我们的精力是有限的,所以通常只对核心假设通过MVP来验证。这个核心假设就是我们之前提到过的「价值创建假设」。 一旦这个假设被证实了,我们就认为我们找到了「产品和市场之间的契合」(Product-Market Fit,缩写为 PMF)。 具体而言,我们会在验证假设之前,定下一些量化的指标。在我们验证的时候,进行相应的衡量。最后根据指标的数据,来判断是否达到了 PMF。如果是,就可以进一步的增加功能,往前推进;如果不是,则需要调整,甚至需要通过战略转型来重新找到 PMF。 这种转型可以是针对原有市场的细分市场重新提出价值主张;也可能是扩大需求,让它支持更广泛的人群。但无论如何,在找到 PMF 之前,我们都应该专注于价值假设的验证,而不是功能的丰富和市场的推广。","breadcrumbs":"精益副业 » 精益副业流程 » 最小可行产品和产品市场契合 » 最小可行产品和产品市场契合","id":"111","title":"最小可行产品和产品市场契合"},"112":{"body":"前面我们给大家介绍了精益副业的基本概念,因为只有理论,所以看起来可能比较抽象。 从这一章开始,我们就以实际的副业实践为例,看看如何使用精益副业流程贯穿始终,多快好省地发展副业。我们安排了两个深度实践,一个是独立开发、一个是网课。下边我们开始第一部分。","breadcrumbs":"精益副业 » 精益独立开发实践 » 精益独立开发实践","id":"112","title":"精益独立开发实践"},"113":{"body":"picture 1 前面我们了解了精益创业的一些核心理念,接下来我们就在「独立开发」这个更为具体的副业活动中来看看如何应用精益流程。 这个流程和很多硅谷公司的产品流程很像,但是针对副业做了一些调整和优化。经过三年多时间的使用,我们自己用起来已经很顺手。 首先定义价值主张,然后围绕着价值来设计商业模式画布。 完成画布以后,我们把画布里的「客户细分」部分拿出来,做成「用户画像」。这是一个将细分客户具体化、变得有血有肉的工具 有了画像,再据此还原用户使用产品的各个场景,他们是用电脑还是用手机、是在家里还是在车上使用等等。 想象为了在上述场景下向用户传递价值,我们需要什么样的功能,这样就会得到一个功能列表 功能列表会很长,不同功能的优先级也不同。所以我们会对功能进行分期,其中最重要也是最靠前的一个功能分期,就是用来开发「最小可行产品」的分期。 当「最小可行产品」开发完成后,进行「产品市场契合」的验证,如果达不到设定的验证目标,就需要调整功能,甚至重新设计价值主张。 当通过「产品市场契合」后,我们就可以按照分期迭代开发产品的其他功能了。 在迭代过程中,我们会持续对新上线的部分功能进行增长优化,保证每一部分功能达到预定的目标。 以上就是我们为独立开发优化的精益流程,虽然讲起来比较多,但实际操作起来还是比较简单的。而且我们其实省略了不少大公司流程中的环节,比如用户访谈、焦点小组等。 下一节开始,我们将用一个具体的例子来讲解。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独立开发的精益流程 » 独立开发的精益流程","id":"113","title":"独立开发的精益流程"},"114":{"body":"先来介绍一下我们的实战项目 —— 福利单词。 它来自于我在学习过程中的一个原生需求。最开始我是使用 Anki 这个软件来背单词,软件很好用,但是每次都有一种逼着自己去背的感觉,背完以后如释重负。为了提醒自己不要逃避,我还定了一个闹钟每天催自己。 有一天,我又因为上 Pixiv (一个二次元内容创作社区)看图忘记了时间。突然间我想到,能不能把背单词和看图片这两个行为绑定到一起呢? 你看,背单词虽然有用,但让我痛苦,度日如年;看图片很欢乐,流连忘返,但似乎不是很「有用」。如果我们把两者结合到一起,一边看图一边背单词,是不是就可以让背单词不那么难受,可以持续不断地背下去了? 这就是福利单词的出发点。 接下来,我们就来看看,怎么从这个还有些模糊的想法中提出一个明确的价值主张,然后围绕它进行商业模式规划、功能和界面设计、验证和迭代开发,最终使其成为一个商业产品。 picture 2 需要说明的是,开发过程很难在有限的篇幅中讲解清楚,也偏离了本书的主题,所以我们只会简略地提及一些需要注意的地方,并不会进行开发的教学。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词项目简介 » 福利单词项目简介","id":"114","title":"福利单词项目简介"},"115":{"body":"前边我们已经讲解过商业模式画布,这一节我们就以「福利单词」为例,来看看怎么使用。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 福利单词的商业模式画布","id":"115","title":"福利单词的商业模式画布"},"116":{"body":"picture 3 首先来看一下价值主张。它的核心价值就是,让那些觉得学习起来很痛苦的人不那么痛苦,给一点糖,让其可以持续地、无痛地学习下去。它试图给学习过程添加一些乐趣来综合不是那么爱学习的人的痛苦,从而把一个短暂的、难以忍受的学习行为变成一个可以持续忍受、甚至通过习惯驱动可以持久化的行为。 所以我们在「价值主张」这一栏上写上两个关键字,一个叫「无痛学习」,一个叫「持久化的学习」,这是这个产品最核心的两个「价值主张」。 有了这个价值,我们就能帮助客户完成很多以前想学、但是因为各种原因没有办法学下去的东西,从而实现其个人成长和提升。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 价值主张","id":"116","title":"价值主张"},"117":{"body":"picture 4 如果要具体化价值主张,就要来看客户细分。 因为是单词学习软件,所以客户群体往往还是跟学习英文需求相关的。具体划分下来,我觉得可以分成三大类。 第一类是在学校要考英语四级或者六级的大学生。 第二类是有留学或者移民需求,需要考雅思、托福的群体。 第三类是需要专业英语来提升自己在职场的业务能力的上班族。 前两类群体是要备考应试的,后一类则更注重实用能力的提升。从学习的内容上来讲,只是题库的不同。所以如果我们的软件支持了「词库切换」或者「自定义词库」功能,就可以比较容易地覆盖他们的学习需求了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 客户细分","id":"117","title":"客户细分"},"118":{"body":"picture 5 光是「有词库,你来背」这个主张和其他背单词软件并没有什么不同,所以我们需要在「价值主张」里再加上「糖」。 但是,对于不同的群体来讲,「糖」是不一样的。如果只是放一些二次元的萌妹子,只有喜欢动漫的人会觉得这是他们的「糖」,可以吸引着他们,每天都来看一看。对于其他一些二次元无感的人群来讲,这些图就毫无吸引力,于是我们需要增加「糖」的种类。 比方说有的妹子就喜欢看帅哥、有的粉丝就喜欢看偶像、有的铲屎官就喜欢看猫猫狗狗、有的吃货就喜欢看肉和甜点。这一部分,我们可以用多图库的方式来满足。 于是,针对不同的客户细分,我们提出三个更为细化的价值主张: 「每天看40分钟妹子,一个月记住四六级词汇」 「看着帅哥,把雅思托福词汇搞定」 「一边云吸猫一边升职加薪」 现在听起来是不是就有吸引力多了?","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 价值主张的细化","id":"118","title":"价值主张的细化"},"119":{"body":"picture 6 在「渠道通路」的这个方格里面呢,我们的种子用户主要由微博带过来的流量构成。 通过种子用户进行测试,一旦转化率达标,我们就可以开始对外去做一些合作,以及以微博为起点投放广告,观察广告投放的成本和其带来的流量的关系,以此判断下一步操作。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 渠道通路","id":"119","title":"渠道通路"},"12":{"body":"采用副业的方式操作,我们在离开北上深之前就可以创立自己的工作室,并开始接活。一方面拓展客户,累积口碑,另一方面,我们还可以从客户的案例中提取重复需求,将其产品化、服务化。等到有了自己的客户和产品,我们在哪个城市已经不那么重要了,甚至可以在全国一个城市住上那么一两个月,一边旅行一边工作。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » E→S,回老家开工作室","id":"12","title":"E→S,回老家开工作室"},"120":{"body":"picture 7 在「客户关系」这里,我们会通过腾讯提供的「兔小巢」这个产品来提供售后支持。它是类似于反馈板的免费工具。用户在上面提交问题,我们会收到微信或者QQ的通知,可以通过网页在电脑上或者手机上进行答复。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 客户关系","id":"120","title":"客户关系"},"121":{"body":"picture 8 接下来我们来看一下「关键活动」。 用来验证需求的最小可行产品(MVP),是一个简单网页,只包含 100 个单词、100 张图片和简单的输入文字切换图片功能即可。我们还需要一个统计数据,看看每一个访客到底背了多少个单词。这关系到我们价值主张里的「无痛」和「持久」。 当这个价值被验证后,就可以进入第一期开发。 虽然是一个全平台应用,我们第一期却只做网页版。具体业务包括:背单词的界面,以及选择词库的界面。这是最核心的业务功能。如果我们第一期想要有收入,那么就需要支付和订单系统。 为了对转化过程进行分析、更好地挣钱,我们还需要开发一个2A3R漏斗的统计,让用户从获客层顺利滑入付费层。如果需要通过分享裂变获取更多流量,我们也需要统计发起分享的用户数据。如果要允许用户自定义词库,我们就要提供对应的制作工具。 以上这些,构成了我们的关键活动。关键活动可以采用不同颜色的文字来标记不同的分期,也可以一期一期追加。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 关键活动","id":"121","title":"关键活动"},"122":{"body":"picture 9 在关键资源上,除了需要具备人、钱和时间以外,我们这个项目还有特有的资源需要考虑,那就是背单词所用的图片,这是一个非常值得注意的问题。 在最小可用产品中,因为不涉及到收费,我们可以使用的图片很多。一旦开始收费,如果还是不加识别地从网上下载各种版权不明的图片,放到自己软件里并以收费的方式进行售卖,很可能会出现侵权。 所以,我们就需要思考图片资源的解决方案。粗略分析后,有以下几种思路: 作者授权 换用无版权图片 用户自行提供图片","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 关键资源","id":"122","title":"关键资源"},"123":{"body":"直接找作者把图片买下来,然后作为付费词库卖给用户,这是最直接的方式。但有问题,那就是价格,光是大一点的词库就有超过一万个单词,也就是说我们要买一万多张图。如果按一张图 50 元计算,需要 50 万的投入。 在一分钱都还没挣之前就做出这么大的投入,风险还是很高的。这种方式更适合我们挣到钱以后,在扩大规模时使用。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 作者授权","id":"123","title":"作者授权"},"124":{"body":"当然,我们也可以寻找无版权的图片来做图库。这样即使我们打包在软件里进行商业销售也不会有任何问题。互联网上已经有比较庞大的无版权高清图库了,比如 Unsplash 等。不过这些图库主要是风景和动物,人物类非常少。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 换用无版权图片","id":"124","title":"换用无版权图片"},"125":{"body":"本质而言,我们卖的是「看图背词」的工具,而不是图片本身。现在之所以在版权上有风险,是因为打包导致的。所以我们可以尝试着将付费的服务和免费的图片分离开。 比如我们可以给用户提供自定义图库的制作工具,让他们把自己收藏的图片导入进去。这样既能达到目的,又没有版权上的风险。 类似需要考虑的,还有背单词时用到的音频。最简单粗暴的方式是使用云平台的TTS(文字转语音)接口直接生成。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 用户自行提供图片","id":"125","title":"用户自行提供图片"},"126":{"body":"picture 10 在填好这几个格子以后,我们就可以开始对成本和收益进行相应的预估,算出预期利润区间。 由于我们开发的项目相对比较小,用到的资源也不是特别的多,所以商业模式画布做得还不算细致。不过通常来讲,第一版的商业模式,画布本身也不会特别细。它是随着项目的进展不断被细化的。 最后我们来看看完整的商业模式画布: picture 11","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 成本收益","id":"126","title":"成本收益"},"127":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 通过用户画像细化客户","id":"127","title":"通过用户画像细化客户"},"128":{"body":"在商业模式画布里面,我们对客户进行了细分,把客户分成了不同的组,每一组代表一个独立的需求。 用户画像(persona)呢,就是给这些已经分好的组,每一组搞一个人设、建一个虚拟形象,让其变得有血有肉、有姓名有年龄有性别、有自己的身份有自己的爱好、有使用产品的场景。 这样当我们聊到这个用户画像的时候,就像在讲自己的朋友、同事一般熟悉的人一样。 把抽象的需求变成活灵活现的人,这样我们在进行产品设计的时候,就更容易还原到场景,带着画面去想象这个人的需求和行动,这就是用户画像的意义。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 什么是用户画像","id":"128","title":"什么是用户画像"},"129":{"body":"接下来,我们就在福利单词的客户细分基础上,为每一类客户建立用户画像。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 福利单词的用户画像","id":"129","title":"福利单词的用户画像"},"13":{"body":"有了副业,B象限等于完全开放了。不要纠结于是否成立了公司,那只是一个形式。真正驱动公司的是业务能力和运营公司的能力,而这些我们都可以通过副业练出来。 把创业想法以 Side Project 的方式来运作,以最简单的产品直扑最核心的需求。没有经验和所谓的产品感都不要紧,因为副业我们是输得起的。这个项目找不到需求,那么复盘以后开始下一个。那些创业公司花大价钱验证的认知,我们通过 Side Project 同样能获得,只是时间可能更长一些而已。 这种低风险的创业模式,也是非常契合当下的创业环境的。创新工场的汪华 在2020年4月的一场分享 中提到,移动互联网信息、交易等纯界面层的战争已经基本结束,那种靠想法和快速扩张的打法,已经很难奏效了。 所以通过副业的方式,扎扎实实地经营一家企业,靠对市场的理解、优质的产品、良好的管理和持续发展取胜,才是新时代更好的选择。 可以看到,引入副业后,我们可以以低风险、并行的方式在职业象限中移动,为职业的发展带来了无穷的可能性。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » E→B,创业","id":"13","title":"E→B,创业"},"130":{"body":"首先是备考四六级的大学生这个细分客户群。我们叫他王小康,设定为一个大三的男生。他现在有一个迫切的任务,就是一定要通过四级考试。这位同学是一个动漫宅,他喜欢看的图就是二次元的萌妹子。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 四六级备考生","id":"130","title":"四六级备考生"},"131":{"body":"然后我们来给有留学移民需求、需要考雅思和托福的人群做一个用户画像。我们叫她章小留,她是一个大学刚毕业一年的女生,现在有出国留学的想法,正在准备雅思考试。这位同学是追星族,喜欢看的图片是韩国帅哥。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 留学移民预备军","id":"131","title":"留学移民预备军"},"132":{"body":"第三个细分人群的用户画像,我们叫她卢小白,是一个毕业两年左右的女生。在生物公司从事技术相关的工作,她需要尽快熟悉大量的生物专业方向的英文单词,方便她更好地了解公司业务。她家里有猫,喜欢看的图片是萌宠和美食。 确定了这三个用户画像的基本资料以后,我们会给他们配上头像,写上他们的需求关键字,把它整理到一页A4纸上。 这样我们就可以把它打印出来,贴到墙上,在做产品设计的时候可以随时去看他们,就像看着我们身边的熟人一样。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 专业提升小白领","id":"132","title":"专业提升小白领"},"133":{"body":"很多书里面都强调说,用户画像的头像要尽可能真实,最好用真人头像。但需要注意在网上乱找真人头像容易导致肖像权问题,这里给大家推荐一个通过AI生成真人头像的网站,叫做 thispersondoesnotexist.com。 picture 12 不过这个网站生成的多是欧美人,对国内的产品来讲,反而各种违和。我更喜欢使用日系的动漫捏脸网站来做,比如 charat.me 这个网站。 picture 13","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 画像的头像制作","id":"133","title":"画像的头像制作"},"134":{"body":"有了头像,再配上角色的说明和需求关键字,我们就有了一个简单好用的用户画像。下边是我们制作好的三个画像: picture 14 picture 15 picture 16","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 最终的用户画像","id":"134","title":"最终的用户画像"},"135":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 画像→场景→功能和分期","id":"135","title":"画像→场景→功能和分期"},"136":{"body":"有了栩栩如生的用户画像,我们就可以从画像想象出场景,再由场景梳理出功能列表并进行分期。下边我们就具体来看下怎么分析使用场景。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 使用场景分析","id":"136","title":"使用场景分析"},"137":{"body":"首先是王小康的使用场景,包括在学生宿舍、在图书馆以及在课堂上。 在宿舍,他每天晚上八点到九点使用台式机。因为宿舍比较吵,他会戴着耳机学习。这时候他使用的是外接键盘。 晚上睡觉之前,他还会窝在被窝里玩一会儿手机,时间大概是晚上十一点半到十二点,也就是睡觉前的半个小时,这时候的使用场景就是用手机背单词。 图书馆也是一个典型场景,因为在这个环境里边,需要保持安静。所以你要么戴耳机,要么将设备调成静音。王小康一般是下午三点到五点去图书馆自习,这个时候他使用的是笔记本电脑和 iPad 。 需要注意的是使用 iPad 的时候是没有键盘的,所以在输入上面没有使用外接键盘方便,整体输入速度会下降很多。 图书馆和学生宿舍是两个相当不同的场景。宿舍里很可能有室友在玩游戏或者聊天,很容易分心,甚至连背单词这件事都很容易忘掉,所以我们需要有提醒。 相对而言,图书馆就是安静的沉浸式环境,没有人来打扰你,大家都在忙着学自己的东西。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 王小康的使用场景分析","id":"137","title":"王小康的使用场景分析"},"138":{"body":"下面我们来做章小留的场景分析。 她现在辞职在家,完全是备考的状态。每天上午会在家学网课、或者去线下的培训班学习,下午会在家学词汇。晚上的话,可能要看韩剧。 主要场景在学词汇的下午。因为是在家里边,她使用的是台式机,鼠标和键盘都是外接的。每天早上起床的时候可能也需要复习一下。 所以她的两个主要使用场景是使用电脑学习,以及早上起床时用手机进行复习。 实际上,这个场景和王小康在晚上用手机复习的场景非常类似,可以都写上,最后进行功能合并时,重复的内容会被合并掉。 同时,因为这两个用户都是在备考,所以他们其实还有「考试复习」这个特殊场景。 在这个场景里,它的词库是有范围的,不一定是整个词库。而背单词的时候,需要有一个考试模式,限时答题,并给出得分。这些需求我们不一定都要通过福利单词这个产品来满足,但可以先写下来。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 章小留的使用场景分析","id":"138","title":"章小留的使用场景分析"},"139":{"body":"小白是上班族,所以学习时间是非常有限的,主要是在上下班通勤的时候学习,以及在周末的时候有一点空余时间。 通勤场景一般会在地铁上。运气好的时候就有座位,运气不好的时候还需要站立着。这时候她会使用手机和耳机来学习。 因为她的词汇学习主要是为了工作需要,所以在工作的时候可能还会有查词的需求,可以通过词典软件解决,但是她可能会想把生词加入到福利单词来记忆。 大部分时间地铁里是很挤的,有时候需要一个手扶住上面的吊环或者旁边的柱子,所以小白可能需要单手操作。 另外要意识到小白只是一个典型代表,她需要的是生物类的词汇,但是其他的上班族需要的词汇可能会覆盖各行各业,这部分的词库需要通过自定义词库来解决。 同时,小白很喜欢宠物,当她看见可爱的喵星人时,很可能希望将这个图片保存到相册。这里如果再结合到我们上面的考试模式的话,其实可以做得更游戏化一些。比如说我们可以加入一个图鉴,就是一个画册,里边有每一个单词对应的图。只有你对这个单词达到一定的熟练度以后,才能在里边看见。大体上这就是小白的使用场景。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 卢小白的使用场景分析","id":"139","title":"卢小白的使用场景分析"},"14":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 职业自由度","id":"14","title":"职业自由度"},"140":{"body":"现在我们三个用户画像的使用场景已经分析完了。接下来,我们就可以根据场景来确定功能了。也就是说,为了满足这些场景下的需求,我们在产品上需要提供哪些功能来支撑。 在确定功能的时候,有两类需要特别注意。一类是核心功能,没有它,所有画像都没法使用我们的产品。另一类是边界功能,没有它,某一个画像就没法使用我们的产品。核心功能是交集、边界功能是并集。 我们会根据画像的设定,将一些边界功能分配给他们。比如说,为什么卢小白她就会想保存图片到相册,章小留就不会呢?事实上章小留也会,但我们不需要把一个边界功能重复分配,因为最终都会覆盖到。 画像需要注意的是它特有的场景,比如考试模式是备考生的特有场景。对于不考试的同学来说有没有都无所谓,但是对考试的同学是非常有用的。 我们把边界功能标记出来以后,就可以框定一个大体的功能范围。 比如说,章小留使用的是苹果台式机,这就要PC版需要同时支持 Windows 和 Mac 两个操作系统。路小白上下班通勤的时候是单手操作,我们在手机上设计浮动键盘时,就要考虑到小屏幕手机上26键的全键盘单手时容易按错的问题。 对于卢小白来讲,她的空余时间不多,所以可能还会利用家务和健身的时间,这个时候如果她想复习单词,可能还有一个语音播报的需求。 章小留是追星族,那她在网上看韩剧的时候,会顺便把喜欢的偶像的图片给保存下来,制作成词库,甚至还会分享给同好。 这些都是边界功能。在早期设计的时候,可以先不考虑工期、开发量这些很现实的问题,我们可以先把它放进来思考,至于做不做、什么时候做,那是以后的事情。 我们要做的东西在早期应该尽可能的少,但是思考的范围却应该尽可能的广。我们是把很多东西都想明白了以后,选其中最核心的、最重要的来做。而不是说很多东西我压根就不想,只做眼前看到的那一丁点就开始做了。这样到项目中期,就会出现很多思考上的盲点,这些盲点甚至会导致我们的项目重做,所以需要尽可能避免。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 从场景到功能","id":"140","title":"从场景到功能"},"141":{"body":"我们可以通过思维导图软件来梳理功能。 想象一下新用户从什么地方开始使用我们的软件,跟着他的使用流程来同步构建功能。 比如说,首先会需要有一个用户系统,这样我们才能识别用户。接着我们肯定需要有词库,不然就没有单词可以背了。我们肯定也需要有单词的背诵、管理,如果我们要收费的话,肯定还需要有支付。 用户系统里边,我们考虑使用微信登入,这是目前最简单的办法,不用做用户系统、也不用做密码找回。有了登入肯定也得有退出。 有了用户系统以后我们就可以保存用户背单词的进度了。在词库这边呢,既然我们要做一个可切换和自定义的词库,那肯定会有一个列表。 这个列表,首先是会有一个官方的或者叫内置的,然后我们在建立一个本地的列表,给自定义词库用的。 自定义词库这边,我们可能还需要给提供一个工具来制作词库。我们需要有一个单词表、需要生成对应的音频、需要有对应的解释,以及我们背单词的时候看的图片。这是词库的大体功能。 如果我们要做图鉴的话,就需要有词库的完成度数据。就是用户背了词库里面百分之多少的单词、以及对每一个单词的熟练度。在这个基础上我们还需要有一个相册,用来欣赏高清图片。 自定义词库制作完成以后,它还需要有一个分享方式。我们可以允许用户通过二维码分享,其他的用户通过二维码扫码导入。 接下来,我们来看背单词的功能。 首先它需要有一个地方来输入字母,我们会根据输入的字母动态地进行遮罩的调整。然后我们需要把用户输入的时间或者错误的次数统计起来,这代表着对这个单词的熟练程度。我们也还需要有一些辅助按钮,用来显示单词的意思、以及跳过不会的单词。 在最后,当正确地输入了单词以后,我们需要显示一个高清图片,让用户可以很完整地看见这张图片,这是对其的奖励。 另外我们也需要把用户的背单词成绩记录下来,为了能更清楚地看见这个成绩,可能还需要提供一个进度统计,告诉用户背了词库里面的百分之多少,各自的熟练度是多少。 还有支付部分别忘了。首先我们要显示可以付费的商品,当点击购买按钮以后,要把微信支付给呼叫起来。在微信支付完成以后,要进行确认。同时我们也需要维护一个订单列表来进行售后和退款。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 通过思维导图梳理功能","id":"141","title":"通过思维导图梳理功能"},"142":{"body":"确定好功能表以后,接下来就可以进行分期了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 分期","id":"142","title":"分期"},"143":{"body":"因为我们现在的功能实际上已经非常多了,必须要把它分成不同的阶段来做。最小可行产品不太典型,这里我们以 PMF 验证完成后的第一个版本为例,来选择第一期的内容。第二期就是「以后再做」的功能,第三期就是「不知道啥时候做」的功能。 来看我们的功能列表: 推送提醒:可以放到第一期。但为了实现推送,需要有消息系统。如果要做定时提醒的话,还需要做设置界面。因为用户设置过提醒以后,可能有一天不需要了,要能及时取消,不然天天推送还挺烦人的。 考试模式:放到第二期。虽然对备考生很重要,但是因为整个开发量比较大,在挣钱之前可以先不做。 虚拟键盘:放到第一期。为了支持单手操作,我们需要给背单词的界面添加在移动设备上的键盘界面。不同输入法的键盘可能会导致兼容性问题,所以我们直接通过一个虚拟键盘来解决它。 自定义词库分享:放到第二期。 图鉴模式:放到第二期,也可能是第三期。 语音回放:放到第二期。 picture 17 确定分期的时候,也要同时检查功能点是否都对应上了。比如支付里面,我们需要把「微信支付的对接」加上。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 功能分期","id":"143","title":"功能分期"},"144":{"body":"确定好某一期的功能列表后,可以把各个功能归类到界面里。新建一个思维导图,写上显而易见的各个界面,然后把功能放到界面下去。 如果发现有功能没有界面放,恭喜你提前发现了做丢的界面,赶紧把这个界面也加进去吧。 picture 18 这一步完成以后,我们就可以开始进入设计阶段了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 功能归类到界面","id":"144","title":"功能归类到界面"},"145":{"body":"这一节开始我们会讲一些设计方面的东西。和专业的设计课不同,我们主要着眼于如何让非专业设计人员也能做出七十到八十分的设计。 首先我们来和大家聊一聊,什么是好的商业设计。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 什么是好的商业设计","id":"145","title":"什么是好的商业设计"},"146":{"body":"要做好一件事,首先要弄明白好的标准是什么,而这恰恰是讨论设计时的一个难点。 为什么呢? 我们写程序做软件,好不好是有一个相对可以量化的指标的。比如:用了多少行代码,执行了多久时间,占用了多少内存、在一秒以内可以承受的并发请求数是多少。这些都可以很精确地衡量出一个程序是否写得好。 但是,对于设计来讲,它是一个很个人化的东西。同样一个设计,有的人会觉得它好,有的人会觉得它不好,还没法说谁对谁错。甚至有一些艺术家,他的作品可能在当时就没有人能够理解,隔了很多年大家又把它拿出来,才发现惊为天人。 这就造成了一个问题,设计到底应该按什么样的标准去衡量?不光是设计师本身需要思考这个问题,设计需求的提供方其实也需要去思考。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 好设计的标准","id":"146","title":"好设计的标准"},"147":{"body":"但是后来我们发现,如果把设计的范围给缩小一些,就可能得出一个部分适用的答案。 艺术这个东西它确实是千人千面的,因个人的感受而异。但是我们为商业产品做的设计它并不等价于艺术,大部分情况下它是为商业服务的,我们就叫它「商业设计」吧。 一个好的商业设计,其实就是要让尽可能多的客户喜欢它。因为,喜欢上我们设计的人,很可能也会喜欢上我们的品牌和产品,最终转变成商业价值。 至于这个设计在艺术上深刻不深刻,完全是另外一个领域的事情。 这里有一个比较极端、但大家也很熟悉的例子,那就是椰树椰汁的产品设计。它基本上是把美感给扔了,但换取了很好的识别度,这就是一种商业上的权衡。 我们写程序的时候,要从代码思维上走出来,回到商业思维的角度上来;我们做设计的时候也要从设计本身走出来,从整个商业链条的角度去思考。 通常来讲,我们会面临的抉择,往往是在两类截然不同的设计之间。一类剑走偏锋、足够深刻,能理解它的一类人特别地喜欢,而不理解的又特别讨厌它;另一类设计,看似中庸,然而平中见奇,不同层次的人都可以看到自己喜欢的点。 如果这个设计要拿去参加艺术大赛,可能前者更合适。但如果用于商业产品,那我觉得应该选择后者。因为归根结底,它是用来承载功能、向客户传递品牌质感的,而不是要体现它自身有多深刻,那样反而喧宾夺主了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 商业设计","id":"147","title":"商业设计"},"148":{"body":"每个人的兴趣和爱好都是不同的,要做一个设计或者塑造一种风格,让绝大部分人都喜欢上是很难的。但我们幸运的发现,设计如果足够简洁的话,就不容易包含太多触发各种反感的点,更容易获得绝大部分人的喜爱。 而对于副业来讲,简洁风格的方案所需要的设计和开发资源都相对较少,配合起来又比较容易协调,所以简洁风格是我们的首选。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 简洁即美","id":"148","title":"简洁即美"},"149":{"body":"界面设计是很多尝试自己开发完整产品的程序员非常痛苦的事情。很多时候,如果我们去问设计师,很多人虽然会设计,却讲不出背后的道理。只会说,「这样做感觉上更好一些」,「这就是经验/灵感」。 我以前也是这么认为的,直到读了一本书才明白,原来界面设计背后一样是有规律的。 界面的表层结构展现的正是它内部的逻辑。 一个界面上应该摆放哪些控件,哪几个应该离得近,哪几个应该离得远,哪些应该用同样的风格,哪些又应该区别开来,这些都源于它背后严密的逻辑关系,而不是因为设计师的一时兴起。 那本书就是《写给大家看的设计书》。在书里,作者提出了界面排版的四个基本原则,通过活用这四个原则,我们就能够把界面设计得美观大方。 这四个原则分别是「重复」,「对比」,「对齐」和「亲密性」。 「重复」原则强调「一致性」,它说的是「在逻辑上一致的物件,在视觉上也应该一致」。 「对比」原则强调「层次感],它说的是「逻辑上不同的物件,在视觉上也应该不同」。所以我们要想办法拉出距离来。 「对齐」原则强调的是「安定感」。均匀的留白能够营造出一种稳定的感觉。这正是产品质感的一种潜意识渗透。对齐虽然是很小的细节,但是如果处理不好,很容易会破坏产品整体质感,而且会给有强迫症的朋友带来莫大的压力。 「亲密性」原则,强调区块的关系,它说的是「逻辑上存在很近的关系,那么这个关系也应该表现在视觉上」。相关的项应该彼此靠近,不相关的项应该彼此远离。 书里有非常详尽的介绍和让人顿悟的例子,建议大家都去阅读下原书。 picture 19 四大原则回答了常见的一些界面问题。比如说,上图中,白色方块之间的间距为什么不能比第一个方块和页面边界的距离大。 如果从纯感性的角度来讲,可能会说「这样放不好看」。但是如果通过亲密性原则来思考的话,我们会发现在逻辑上,相对于页面边框,白色方块是一个整体。一个白色方块和另一个方块的关系,显然比它和页面边框近。所以这种深层关系表现在视觉上,就是它们之间的边距差异。 如果视觉关系和逻辑关系不一致,我们就会觉得「别扭」、「不直观」。这些原则为我们通过逻辑理解设计推开了一扇门,让之前仅存于「感觉」和「经验」的设计技巧变得有章可循。熟悉它们以后,只要多加练习,再配合上一些简洁、清爽风格的设计细节,我们就可以在大部分场景下做出七十到八十分的界面来。 picture 20","breadcrumbs":"精益副业 » 精益独立开发实践 » 人人能用的四大原则 » 人人能用的四大原则","id":"149","title":"人人能用的四大原则"},"15":{"body":"前面说了副业给我们的职业带来了更多的可能性,接下来我们就来看,副业给我们的职业带来的更大的自由度。 首先是职业选择的自由。 这里我们先来讲一个比较有意思的概念,它叫做 F*** you money。这是国外的一个词,我们把它翻译成「中指备用金」。 它指的是一笔钱,数量大概是这个样子:突然有一天你跟老板闹翻了,你可以竖起中指,跟他讲说老子不干了,然后辞职回家。在这种情况下,你的生活质量也不会受到影响。 标准意义上的「中指备用金」,其实是和财务自由差不多额度的一笔钱,是以「不工作」为前提的。如果大家在北上深,要做到财务自由还是很难的。 我们这里要讲的是以「换工作」为前提的一个低配版本。也就是说,你可以随意裸辞,在找到下一份满意的工作之前,这段可能会长达半年甚至一年的时间里,没有任何收入,但你的生活品质不会受到太大影响。 很多年轻一点的同学可能觉得根本不需要这种备用金,因为现在的 90 后 00 后正是这么干的。但是当你的年龄稍微大一些,还着房贷车贷、养着老人小孩的时候,要是突然没有收入来源,压力实际上是非常大的。 而副业,恰恰可以为我们提供这么一笔钱。可能总额不大,但可以持续不断的提供。 比如我现在的课程放到网易云课堂上,即使自己不在微博去做主动的营销推广,通过网易平台上的自然流量进行的课程转化,也会有几千块钱。 我现在在重庆生活,这边房租非常的便宜,一个近七十平的小两居,房租每月不到两千。加上日常花销,也就几千块钱。所以现在即使不去上班挣钱,副业也可以在相当长的一段时间里保证我的基本生活不受影响。 这种情况下,我们就可以花更多的时间去思考自己的职业、未来和人生。去做一些短期内收入不明显,但长期收益巨大的决定。 这也就是副业带来的选择自由。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 从中指备用金说起 » 从中指备用金说起","id":"15","title":"从中指备用金说起"},"150":{"body":"接下来讲下,如何设计产品的 Logo 。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 独特Logo解决方案","id":"150","title":"独特Logo解决方案"},"151":{"body":"最简单的方式当然是请设计师来设计,我们只需要像产品经理那样在背后指指点点,改需求、当甲方就好了。但是,在做副业时,我们很可能没有足够的预算去雇佣专业的设计师。尤其是在软件还没有获得收益之前,如果花很多钱去请设计师设计,而产品本身又运营不起来的话,钱就白花了。 所以,学会自己做一些比较简单能用的 Logo 还是很重要的。等以后挣钱了,可以再花大钱请高手来重新设计。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 为什么要自己设计 Logo","id":"151","title":"为什么要自己设计 Logo"},"152":{"body":"Logo 的设计还是有些考验绘画能力的,即使是相对简单的简笔画,对于很多没画过图的程序员来讲,也挺难绘制一个像样的出来。 如果你有一定的绘画基础,或者想发掘自己隐藏的天赋,那么我特别建议大家用矢量软件来绘制,对于像我这样手残的同学来讲特别有用。 我最开始画 Logo ,是给自己的开源项目。刚开始使用的是像素绘图软件。由于缺乏练习,即使使用数位屏,也很难绘制出光滑的线条。即使偶尔画出来了,要调整它时,又会花费大量的时间。 后来我发现了矢量绘图软件,在它里边,我们绘制的其实不是线条,而是一个个形状。线条是我们指定的形状的边界,可以通过描边自动生成。最棒的一点是,当我们改变形状时,线条就自动随之变动,无需再重新绘制。 只要熟悉了形状的画法,我们就可以通过矢量绘图软件来绘制一些简单的、线条光滑饱满的图案了。 picture 21 作为对比,上图左边是我用像素绘图软件绘制的头像,右边是后来我用一个周末学习完矢量绘图软件后花一天时间重新绘制的。真的是好用太多了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 通过矢量软件绘制 Logo","id":"152","title":"通过矢量软件绘制 Logo"},"153":{"body":"当然,不是所有同学都有时间和精力去学习绘图的,所以我们还是回到适合更多人的方案上来。首先,我们可以使用网上的开源矢量资源。最近两年开始出现一些视觉效果非常不错的矢量插图网站。 picture 22 比如 unDraw ,它就提供大量的适合互联网和软件场景的开源矢量插图。更贴心的是,在网站右上角还提供了颜色按钮,通过调整颜色,我们可以得到和自己产品风格更为统一的矢量图。 一个需要注意的地方是,如果使用免费素材,一定要留意不要从国内那些没有注明作者和授权的网站上下载。因为这些来历不明的素材很可能给你带来版权风险,说不定哪天巨额索赔就找上你了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 免费和开放的矢量资源","id":"153","title":"免费和开放的矢量资源"},"154":{"body":"如果没有好的免费备选,或者没有太多时间去各个网站上挑,我们还可以通过购买的方式来获取素材。 picture 23 在购买素材的时候,要注意使用的限制。有的网站的素材是会限制使用的项目数、域名、甚至媒体类型的。我推荐大家优先购买采用「royalty-free」许可的网站。这种许可非常开放,往往只要付费就可以永久使用。 提供付费矢量图标的网站比较多,比如 flaticon.com ,thenounproject.com 都是比较有名的。我个人一直订阅的是后者,提供的图标够多,价格也比较便宜。它还提供了一个电脑客户端,可以很方便的搜索、复制粘贴图标文件。 这个网站目前提供的图标都是没有颜色的。当然这一点可能对我们来讲,并没有太大的影响。为什么呢,因为直接使用这些网站上的图标做 Logo ,会带来一个潜在的问题。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 购买付费素材","id":"154","title":"购买付费素材"},"155":{"body":"这种买断式授权的素材非常好用,但是既然我们可以花很少的钱来买这个设计,那同样的,其他人也可以来买这个设计拿去使用。正如许可中指出的,这种许可是非排他的。 如果这些图标只是用到界面上,多个应用之间相似甚至相同,可能还是好事,因为这降低了用户的学习成本。但如果用在 Logo 这种代表品牌的场景,就会出现多个应用 Logo 一样的尴尬场面。 只是从这种买断式素材网站上直接买一个素材就拿过来把它作为 Logo,那人家也可以从这个素材网站上买同样的素材作为它的 Logo。这种行为可能是无意的,也可能是有意的。这种情况下我们还不能说人家抄袭侵权,因为都是从同一个地方买的,你可以买,人家当然也可以买。除非你把这个图案拿去抢先注册了商标,否则就会存在潜在风险。 不过,我们可以通过混搭组合的方式,将 Logo 变得独一无二、且更贴近我们产品的本质。 你看,thenounproject.com 上有上百万的图标。我们单独使用,总有其他的用户和我们一样喜欢上某一个图标,并把它作为 Logo,这个时候我们两个产品就冲突了。 但是如果我们把这几百万的图标混搭组合起来,就会产生出上亿种组合,再要想重复,就变得非常困难了。而「从一个图案里边截取一部分,跟其他的地方拼合起来,构成一个新图案」的这种操作,即使对于一个没有绘画功底的同学来讲,只要能熟练地使用软件,也可以轻易完成。 另外,在增加识别度方面,除了混搭,还可以通过上色来实现。单色图标因为使用的颜色数少,往往比较单薄,看起来缺乏层次感。当我们把它作为产品 Logo 的时候,可能就不是那么耐看。这时候我们可以自己来给它上色。因为是矢量图标,所以调色和上色都非常简单。调色只要选中后改变线或者形状的颜色就可以。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 将付费素材变成独有的","id":"155","title":"将付费素材变成独有的"},"156":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 使用AdobeXD设计界面","id":"156","title":"使用AdobeXD设计界面"},"157":{"body":"picture 24 Adobe XD是由 Adobe 开发的矢量设计工具,它和 Sketch 类似,既可以用来绘制矢量界面,又包含原型设计功能,还可以在手机上预览设计好的界面。XD 支持 Windows 和 Mac,是 Adobe 为数不多的可以免费使用的软件(当然你可以付费升级 pro 版本)。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 什么是 Adobe XD","id":"157","title":"什么是 Adobe XD"},"158":{"body":"软件的使用主要还是靠大家勤学多练,这里我们和大家演示下如何用它来设计背单词界面。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 使用 Adobe XD 设计简单界面","id":"158","title":"使用 Adobe XD 设计简单界面"},"159":{"body":"首先,我们在 XD 里新建一个画板(art board)。 画板是什么?它相当于 Word 里边的页面。一般的纯设计工具没有画板这个概念,但 XD 也包含了原型功能,有时候我们需要在多个界面之间来回切换,而一个画板往往就是一个界面。 点击左侧的菜单里面倒数第2个画板的按钮 picture 25 ,这时候在屏幕最右边就会出来一系列预置的画板尺寸。 picture 26 它已经帮我们准备好了常用的规格,比如苹果的iPhone、iPad,谷歌的安卓机型,以及网页常见的尺寸。 我们只要从里边选择对应的尺寸就好了,当然也可以不选择它给你预置的,直接手工拖拽来画或者在属性里面调整画板的宽和高。那我们就新建一个iPhone Xs尺寸的画板好了。 然后按住 CTRL或者CMD + D,就可以直接复制画板。我们把第一个画板叫做背单词界面,然后开始设计。 picture 27","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 理解画板","id":"159","title":"理解画板"},"16":{"body":"除了可以给我们的职业带来自由度,副业更可以为我们的职业引入反脆弱结构。 「反脆弱」这个概念,它来自塔勒布的书《反脆弱——从不确定性中获益》。 picture 1 在书里边,塔勒布说,他之所以要专门造一个词,是因为大家往往对脆弱的反面有所误解,以为是「坚强」,也就是类似软件的「鲁棒性」。但事实上,反脆弱性比鲁棒性更棒。 什么意思呢?鲁棒性是说在风险来临的时候我们要做到不受影响。而反脆弱性更上一层楼,它说的是,当风险来临的时候,我们不但不受负面影响,还能从风险中受益,变得比原来更好。 具体到职业上,鲁棒性是说,万一现在公司发展不好,我们可以很容易地跳到平级的其他公司,继续我们之前的职业路线图。 而反脆弱性是说,当现在公司发展不好,我们可以很轻松的切换到另一个职业象限,实现跨越式的职业发展。 如果我们精心选择并发展合适的副业,它能带给我们的,正是后者。为什么这么说呢?这是由副业的天然特性决定的。因为它是我们用业余时间、在资源紧缺的情况下发展出来的。如果我们能把它转为主业,而它依然保留了对时间、资源需求不多的特性,那么这份工作就会极为舒适。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » PlanB和反脆弱 » PlanB和反脆弱","id":"16","title":"PlanB和反脆弱"},"160":{"body":"先来制作背单词时,字母没有输入完时显示的遮罩效果。选择左侧工具栏中的矩形 picture 29 工具,画出一个覆盖全部画板的长方形。然后调节填充颜色为黑色,透明度为 30%。 picture 30 然后我们到 unsplash.com 这个无版权网站上,找一只猫的图片,把它也放进来。 picture 28 这时候猫是在遮罩上方的,所以它挡住了遮罩。 picture 31 点击右键,选择「Send to back」将它放到遮罩后,我们就可以看到被半透明遮罩挡住的猫了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 遮罩的制作","id":"160","title":"遮罩的制作"},"161":{"body":"接下来,在遮罩上边,我们来放上单词释义和输入框。点击最左侧工具栏中的 picture 33 图标,切换到文字工具。 然后输入文字释义。 picture 32 在右侧的属性面板里,我们可以调节文字的字体、大小、颜色和对齐。 然后我们放上之前设计好的 Logo,加上单词输入框。 picture 34 注意这个输入框不一定非要是「框」,比如我们这里也可以把它做成下划线。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 单词释义和输入框","id":"161","title":"单词释义和输入框"},"162":{"body":"picture 35 虚拟键盘的制作在 XD 中也很简单,直接用矩形工具绘制就行。需要注意的是圆角的做法。 picture 36 其实很简单,在右侧的属性设置里边,把圆角从0 改为 5 就可以了。在做好一个按钮后,我们可以按住 Shift 同时选中按钮和上边的文字,在右键菜单中将其编组(Group);然后按 CTRL或者CMD + D 就可以复制按钮。 picture 37 当按钮多起来之后,要对齐它们还挺费事的。其实选中多个按钮后,可以在菜单 Object → Align 中来自动对齐;也可以在 Object → Distribute 中让它们自动均匀分布。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 虚拟键盘","id":"162","title":"虚拟键盘"},"163":{"body":"再下来,我们需要在界面中引入图标。既然是矢量界面,当然是矢量图标最好。前边我们已经介绍过 thenounproject.com 了,它还为 pro 用户提供了一个客户端。在这个客户端里边可以非常方便的复制图标。 picture 38 当我们通过关键字搜索到图标后,可以通过下载并将其拖拽到 XD 的方式引入;也可以直接在客户端中右键选择 Copy as SVG,然后直接粘贴。因为是 SVG 格式,调整完大小后可以很方便地更换颜色。 最后我们再微调一下输入框和单词释义的位置,背单词界面就做完了。其他界面的制作非常类似,就不在这里累述了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 矢量图标","id":"163","title":"矢量图标"},"164":{"body":"略过开发环节,我们来讲讲变现。绝大部分的支付方案都是面向企业的,面向个人的正规支付方案非常少。那么对于没注册公司的个人,怎么样才能比较安全地收款呢?","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 个人支付解决方案","id":"164","title":"个人支付解决方案"},"165":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 常见的几种个人收款方式","id":"165","title":"常见的几种个人收款方式"},"166":{"body":"市面上最简单粗暴的个人收款方案,就是利用微信或者支付宝的个人收款码来做。 具体的说,就是生成一张二维码,在这个二维码上面添加一个付款的备注,让用户备注中补充上特定的消息后(比如订单号)支付。当完成支付以后,我们就会通过APP或者网站,得到备注里面填的消息,通过识别,我们就能定位到订单,从而自动发货。也有不用备注,用支付金额来识别的。 这个方式淘宝店家已经用了很多年,它的问题就在于,从用户端的体验来讲,它需要填写额外的消息或者发送不确定的金额。从商家端的体验来讲,它需要有一个常驻的服务,随时去监测收款的相关消息,这就会有相当的不稳定因素在里边。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 个人收款码","id":"166","title":"个人收款码"},"167":{"body":"另一种解决方案,就是由那些有资质的企业申请到接口权限后,二次封装后提供给个人来用。这种方案的问题在于,钱是支付给提供接口的企业的,我们只能定期找他们结算提款。万一对方跑路了,我们的钱也就没了。这种方式风险非常高,不推荐。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 二次封装接口","id":"167","title":"二次封装接口"},"168":{"body":"「小微商户」是支付平台针对个人、也就是大量没有企业资质的用户推出的一个解决方案。最开始推出的时候,是为了帮助一些线下的店面,快捷地接入支付而存在的一个服务,然后又扩展到了网上的网店和商家。 一些银行和微信都有这个服务。但是微信并没有给它做专门的后台页面,所以我们在支付平台的后台里是看不见它的,它只有API。 微信把这一部分业务,交给了微信开放平台上的服务商。由服务商去调用这些接口来帮助个人接入到微信的支付服务里面来,同时服务商会提供后台的页面帮个人用户进行管理、也是服务商封装API供个人使用。 这种方案它的好处在于,它是完全合规的,而且这个钱是从微信直接打到小微商户的银行卡里边,不经过中间服务商,所以非常安全。 目前国内有名一点比如 xorpay.com 和 payjs.cn 。他们都是收费服务,前者的费用似乎更为便宜一些。这两个业务我们了解不多,大家使用之前请自行判断其靠谱系数。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 小微商户","id":"168","title":"小微商户"},"169":{"body":"如果我们就是写一个软件,想简单地进行销售获得收入的话,我们还可以使用一些现成的数字内容销售平台。面向国外市场的话,可以使用Gumroad.com;如果面向国内市场的话,可以使用mianbaoduo.com。 picture 39 逻辑上讲,所有的网店都能解决我们卖软件的需求,但相对而言,面包多这类专门面向数字商品的平台提供了更低的手续费和更为全面的 API 接口。 picture 40","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 数字内容销售平台","id":"169","title":"数字内容销售平台"},"17":{"body":"接着上一节,我们来看看副业带来的、全新的工作自由度。这里我们多展望一下未来,主要是给大家鼓气。副业是很累的,要把别人用来休息的时间用到额外的工作上,多想想它的好处可以鼓励我们坚持下去。 当然,就像前边提过的,工作自由度最高当然是财务自由,上不上班都行,完全没有压力。我们这一节要讨论的是,在暂时还必须上班的情况下,我们可以取得的一些自由——我们就叫它「工作自由」吧。 我一般从三点上来看工作自由度: 工作地点的自由 工作时间的自由 工作内容的自由。 不同的工作方式,有着不同的自由度。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 全新的工作自由度","id":"17","title":"全新的工作自由度"},"170":{"body":"市面上管理用户反馈的产品很多,不过大部分都是收费的;这里我们介绍下自己在用的、腾讯出品的免费工具「兔小巢」。 picture 41 这个产品最大的用户就是腾讯自己,原来叫「吐个槽」,最近才升级并更名为「兔小巢」。我们已经使用了几个月,用下来感受很不错。 从用户端来讲,它支持微信和QQ登入,能及时地推送回复通知;从运营端来讲,用起来明显可以感受到这是一款看似简单,功能却相当强大的产品。比如它可以设置移动端的展示方式;可以适配大型产品和通用产品;默认发帖可以隐藏,也就可以当做工单使用;甚至还配备了团队博客和知识库。 不足的地方是提供的 API 比较少,但也够在自己产品中展示用户反馈了。有了它,我觉得大部分情况下,就不用再去购买同类的付费产品了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 使用「兔小巢」处理用户反馈","id":"170","title":"使用「兔小巢」处理用户反馈"},"171":{"body":"下边分享一些整合细节,供大家参考。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 整合说明","id":"171","title":"整合说明"},"172":{"body":"兔小巢提供的是非常浅的整合,不管是在 Web 还是 APP 中,都是通过网页转向的方式来进行。通过设置,在反馈区上方可以显示一个链接,供用户返回到产品中。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 链接跳转","id":"172","title":"链接跳转"},"173":{"body":"但是通过链接跳转会遇到一个问题,就是在我们的产品和兔小巢之间,用户的登录状态会丢失,这样我们就不知道那个反馈是哪一个用户提交的了。 为此,兔小巢提供了一个 tucao.js ,让我们可以在跳转时传递用户的登录态,从而实现用户的统一。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 状态登入","id":"173","title":"状态登入"},"174":{"body":"在默认的模式下,我们只能点击链接后,在单独的页面上才能看到反馈信息。但通过兔小巢提供的 API ,我们可以直接在产品中显示反馈内容。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 反馈数据整合","id":"174","title":"反馈数据整合"},"175":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 2A3R漏斗和增长优化","id":"175","title":"2A3R漏斗和增长优化"},"176":{"body":"2A3R 漏斗,又叫 AARRR 漏斗,是一个用来描述用户转化的结构。 picture 42 它是一个五层结构,分别是: 获客层 激活层 留存层 推荐层 付费层 用户由上至下逐步转化,直至完成付费。其中,留存层、推荐层和付费层可以是并列的,因为用户激活以后,立刻就可以付费、推荐好友。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 什么是 2A3R 漏斗","id":"176","title":"什么是 2A3R 漏斗"},"177":{"body":"2A3R 漏斗的现实意义在于,它促使我们从结果出发,去反向优化前边各个环节的转化率。比如说,如果我们福利单词的销售额定为 1000 套,那么就是说最终到达付费层的用户有 1000 人。而在付费层上至少还有获客层、激活层。 这里我们把获客指标定义为「访问网站」;把激活指标定义为「用户登入」。假设每一层的转化率是 10%,那么访问我们产品的用户数需要达到 1000 乘以 100 等于 10 万人。 优化方向包括: 我们可以加大推广力度,让访问人数从十万变成一百万,这样就能卖掉一万套软件了。 我们可以优化「用户登入」环节,在微信里边做成自动登录,这样把原来 10% 的激活转化提高为 30%,这样即使依然是 10 万访客,销售额也会变为 3000 套。 我们可以强化「付费转化」环节,给第一次访问的用户一个限时折扣,比如 1 个小时内购买,买一送一。如果能拉升 10% 的支付转化,我们的销售也会上升。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 使用 2A3R 漏斗进行业务优化","id":"177","title":"使用 2A3R 漏斗进行业务优化"},"178":{"body":"留存层优化主要用于一些基于高粘度增长引擎的业务,或者免费+付费模式的产品。在这些模式下,用户需要经过很长时间的使用,才会付费。如果留存做不好,用户熬不到付费那天。 对于福利单词而言,留存层优化可以通过推送通知、定时提醒等功能来做。因为背单词本来就是一个周期性行为,所以我们有足够的理由去召回用户。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 留存层优化","id":"178","title":"留存层优化"},"179":{"body":"现在的流量已经是非常贵的了,所以我们必须珍惜每一滴流量。通过旧用户带来新用户,可以为我们提供免费流量;如果做得足够好,流量甚至能像滚雪球一样不断变大。这就是推荐层优化要做的事情。 在我们的应用中,我们可以选择几个用户情绪高涨的点来做分享触发: 完成当天的背单词目标,比如背了 100 个单词 完成有挑战的任务,比如连续 30 个单词不出错 看到赏心悦目的图片,比如看到超级呆萌的猫 在这些时刻,我们都可以引导用户通过海报来分享他们的激动心情,同时为我们带来新的用户。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 推荐层优化","id":"179","title":"推荐层优化"},"18":{"body":"比如最近新冠流行,很多公司都开始搞远程办公了,有些大公司甚至宣布员工可以永久远程办公。远程办公这种工作方式,就实现了工作地点自由。你可以去公司的办公室、也可以在自己的家里,甚至是在旅游的路上办公。 但是,远程办公并没有实现工作时间和工作内容的自由,你依然要和其他人同时办公,区别只是以前面对面,现在改成视频了而已。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 远程办公","id":"18","title":"远程办公"},"180":{"body":"关于增长优化,这里给大家推荐两本书。一本是肖恩·埃利斯的《增长黑客》,系统化地讲述了如果建立增长实验机制并从中受益;另一本是《病毒循环》,记录了众多流量传奇。它们中很多细节和技巧,都可以用到我们的副业当中。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 推荐阅读","id":"180","title":"推荐阅读"},"181":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 精益网课变现实践","id":"181","title":"精益网课变现实践"},"182":{"body":"这一节我们来讲大纲。大纲大家都会做,所以我们不全面的展开,只挑其中一些需要注意的点和大家交流。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 大纲的注意点","id":"182","title":"大纲的注意点"},"183":{"body":"最重要的一点,就是大纲一定要有条理性。如果在条例性上做得不够好,其他细节做得再好,这个课做出来在逻辑上也是乱的,最后学起来就会很别扭。 具体来说,我们要保证大纲的层次足够清楚,逻辑足够严密。有一个比较常用的结构推荐给大家,尤其适合知识性为课程。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 条理性","id":"183","title":"条理性"},"184":{"body":"这个结构分成三段,是一个总、分、总的结构。 总 在课程的最开始,我们会简明扼要地讲明白整个课程包含哪些内容;课程中的一些基础、原理也会放到这里。 分 之后呢,我们就可以按照章节进行展开,对每一个部分进行详细地讲解。 总 在最后我们会进行一个总结,同时放入一个大的实践章节。这样不但可以复习内容,还可以学以致用。当然在每一章结尾也可以安排小实践内容。 绝大部分以知识讲授为主的课程都可以采用这种总分总的结构,非常好用。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 三段式","id":"184","title":"三段式"},"185":{"body":"我们也可以用问问题的方式来引出我们的每一部分结构。比如「是什么」——「为什么」——「怎么做」。这种结构可以是全局的,也可以是针对每一部分的。它会让我们的逻辑和层次更清晰。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 提问式","id":"185","title":"提问式"},"186":{"body":"第二个需要注意的点是覆盖面。因为我们的课程往往是出于自己的实践经验,有时候会局限于我们所在的公司和所在的行业节点,它的覆盖不一定特别的全。所以我们的视角不一定能覆盖到所有的需求方。 有时候我们的课程是为了一类人做的,但另外一类人,实际上也可以学习我们的课程,就差一点点的周边知识。在这种情况下,如果我们可以注意到大纲的覆盖面,把缺少的那点知识补上,就可以扩大受众,让我们的销售变得更为容易。 那具体怎么保证大纲的覆盖面呢? 那首先大纲应该覆盖该领域的主要内容,这些内容通常来源于以下几个地方: 官方文档:官方会处理几乎所有来自社区和其他客户的需求,即使一些边缘的需求,因为囤积的时间比较长,也会慢慢地累积起来,所以一般来讲官方资料的覆盖度是最为全面的 行业的权威文档:虽然不是官方出品的,但因为日积月累它最后可能变成了事实标准,也是我们作为参考的一个主要来源 图书:这也是大参考源,对于经典知识来讲,一些销量比较好的图书,会经过多次的再版,并会加入一些之前没有覆盖的内容。使用微信读书的无限卡,无需购买就可以直接搜索大量计算机图书,对查资料来讲非常好用 同类课程:国外的同类课程往往也是非常好的参考,尤其是面向新技术的课程 然后呢,我们的大纲应该覆盖该领域最频繁出现的问题,那我们到什么地方找问题呢? 搜索关键词 专业问答网站,比如 stackoverflow.com GitHub 的 issue 区 课程平台的答疑区","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 覆盖面","id":"186","title":"覆盖面"},"187":{"body":"除了条例性和覆盖面,那我们最后,而且其实也是非常想强调的一个问题,就是大家一定要注意我们大纲的粒度。 大纲这名字听起来就像一个目录,很具备误导性。很多同学做大纲的时候,通常做两个层次就算是做得细的了。事实上,大纲的粒度越细,课程的品质就越可控,后期制作起来速度就越快。而且我们要拿大纲去做预售来验证需求,它越细,验证的效果就越好。 所以呢,建议大家把大纲至少细化到段落这个级别,同时把段落以下的一些知识点所涉及到的素材和资料,全部都整理到这个节点上去。 这里推荐大家使用 Dynalist 这种无限分级的树状笔记软件来做大纲,会特别方便。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 粒度","id":"187","title":"粒度"},"188":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 通过预售验证销量","id":"188","title":"通过预售验证销量"},"189":{"body":"随机抽样了某云课堂上近 500 门付费课程(通过搜索「课」字),其中销售不到 30 的有 24%,销售小于等于 1 的 10% 这是我之前分析某课程平台时的抽样数据,有十分之一的课程销量小于等于一,这个一还很可能是作者;而销售不到 30 套的课程约四分之一。 这些失败的课程背后,每一个都可能有几十几百个小时的制作时间,既然我们把宝贵的副业时间投入其中,就应该尽量避免重蹈覆辙。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 为什么要验证","id":"189","title":"为什么要验证"},"19":{"body":"freelancer,就是那种在网上接单并收取报酬的工作者。这种工作方式在工作地点上同样是自由的,而且经常全部内容都是自己做,需要和别人沟通协调的内容不多,客户主要卡交工时间,只要能赶上进度,时间是可以自己安排的。所以它还实现了工作时间自由。 但freelancer没有实现工作内容自由,因为工作内容都是由客户指定的,绝大部分情况下,都不是你自己想要开发的东西。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » freelancer","id":"19","title":"freelancer"},"190":{"body":"回到我们这一节课的标题上来,「通过预售验证销量」。两个关键词「预售」,「销量」。 预售,我们用什么来做预售?简单一点可以用「课程介绍」,复杂一些则可以提供「试学章节」,但我们测试下来最合适的是「课程大纲」。它能非常清楚的描述内容范围。 销量,如何来评估?我们需要给自己设定一个达标的销售额,一般设定为比成本略高,预售结束时如果销售不达标,我们就退款,不制作这个课程了。 抓住这两个关键,就可以做好验证。在此基础上,可以扩展出一个完整的流程: 准备课程介绍资料,主要是大纲和试学章节 设定验证的目标,设定预售达标值 开始预售 每天统计销售量,并根据反馈调整介绍 预售达标则进入课程制作 预售不达标则进行退款,并反思价值主张 要支撑这个流程,我们大致有三种方案: 通过众筹/预售平台来完成 自建众筹/预售平台 通过付费群简单解决下 下边我们分别来说:","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 如何验证","id":"190","title":"如何验证"},"191":{"body":"使用现成的众筹/预售平台是最省心的。其实最方便的是微博提供的众筹功能,集传播和销售于一体,很适合在微博有影响力的同学。 picture 49 之前我用的时候还挺好找,现在这个功能藏得有点深,在微博的钱包二级菜单里。当然,其他的平台也是可以的。大体来讲,这类平台的问题在于操作相对麻烦,对个人的话,除了收取服务费,往往还会代扣 20% 左右的税。 另一方面,课程还不是实物商品,众筹完了可以直接寄送;我们众筹完以后,可能还要提供在线观看课程的功能。如果放到其他平台,还有一个账号统一的问题要解决。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 众筹/预售平台","id":"191","title":"众筹/预售平台"},"192":{"body":"对于我们程序员来讲,自建众筹/预售平台是很容易的事情。找不到满意的平台,当然是自己动手丰衣足食。功能开发上很简单,但这里有一个非技术因素,那就是支付接口往往需要公司资质来申请,个人很难申请下来。所以还没有搞定支付的同学们在动手前要留意,不要花几周写完系统要上线时才想起来。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 自建众筹/预售平台","id":"192","title":"自建众筹/预售平台"},"193":{"body":"付费群就不需要任何的开发,交易完全走一对一支付,只要自己在年终走个税申报就行。它的缺点在于维护成本有点高,需要手工跟进整个众筹的流程;群功能也相对有限,甚至出现过仿冒老师的账号进行收款的事情。 这里也分享一个微信批量退款的小技巧:将要退款的同学拉到一个微信群中,然后发一个人数乘以金额的普通红包就可以了。注意是 普通 红包,不是 拼手气 红包。 综合以上,我们的建议是,早期通过付费群或者一对一付费就可以了。等到付费用户多了以后,再专门开发一个系统来做预售/众筹。 我们也做了一个众筹+课程托管的一体化平台自用,等成熟以后会考虑开放出来,感兴趣的同学可以关注下我的微博。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 付费群","id":"193","title":"付费群"},"194":{"body":"这一节开始我们来讲课程的制作。 我们将常见的课程分成四种片段: 文稿讲义类:这是我们最熟悉的PPT+语音的形式 屏幕录制类:在实战和演示时用得最多的形式 真人出镜类:技术类课程用得较少,一般在右下角放一个小窗显示真人 虚拟形象类:不想真人出镜时,可以用虚拟形象来代替 几乎所有的课程都是由以上四类课程片段组合而成,所以一旦学会了每种片段的制作,也就学会了几乎所有课程的制作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 常见的课程片段类型 » 常见的课程片段类型","id":"194","title":"常见的课程片段类型"},"195":{"body":"这里的文稿讲义,主要指使用幻灯片软件来进行播放的资料。如果是使用PDF这类材料,其实是属于「屏幕录制」类,我们会在下一节里详细讲解。 对于文稿讲义类课程片段,我们的画面、图文内容都已经做到了幻灯片里面,要录制的主要是声音。但我们有三种截然不同的方式来录制声音: 第一种是最通用的,通过全局录屏来完成。不管是使用什么软件,只要在电脑里,都会被录下来。 第二种是使用幻灯片软件自带的「演讲录制」功能来完成。 第三种是最不为人知的,通过幻灯片软件的「导出为视频」来完成,这种方式有一个非常大的优点,可以极大地降低修改成本,在后文中会详细说明 下边我们分别说明。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 文稿讲义类课程片段的制作","id":"195","title":"文稿讲义类课程片段的制作"},"196":{"body":"下一节会详细讲,这里就略过了。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 全局录屏","id":"196","title":"全局录屏"},"197":{"body":"picture 50 目前用得最多的幻灯片软件,分别是苹果公司的 Keynote 和微软的 PowerPoint。下边我们就以它们为例进行讲解。 首先,我们需要使用幻灯片软件将内容制作完成。课程完成度越高,修改起来成本就越高,所以要仔细检查有无错别字或其他疏漏,然后再进入音频录制阶段。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 使用幻灯片软件自带的「演讲录制」功能","id":"197","title":"使用幻灯片软件自带的「演讲录制」功能"},"198":{"body":"我们先来看在 Keynote 中如何录制。 在 Keynote 菜单「播放」里选择「录制幻灯片放映」 picture 52 然后我们就会进入一个深色背景的幻灯片录制的环境,在这个界面的最下方有一个红色的录制按钮。 picture 53 点击它就可以开始进行录音,可以随时暂停和停止。需要注意的是,这里录制的音频不是仅仅当前这页幻灯片的,而是整个幻灯片的。你可以来回切换幻灯片来录制音频,如果界面看到的有些不一样,可以通过调整预览界面的配置来修改。 当我们在录制环境中完成了整个课程的音频录制后,就可以回到主界面。从菜单中选择「文件」→「导出为」→「影片」。 picture 54 这样,Keynote 就会为刚才的录制生成视频。有一个需要特别注意的地方,就是导出窗口中,「播放」选项要选择为「幻灯片放映录制」。 picture 55 如果觉得导出的视频文件过大,可以使用 HandBrake 来进行压缩。这是一款开源的视频压缩软件,默认的预置(比如 fast1080p )就很好用。 picture 56","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程","id":"198","title":"如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程"},"199":{"body":"下边我们来看 PowerPoint 中如何操作,其实很类似,只是菜单名称和个别细节不同。选择菜单「幻灯片放映」→「录制幻灯片演示」。 picture 57 同样会进入一个暗色的录制界面。 picture 58 在左上角有一个时间正在走,在旁边有控制按钮,可以暂停。默认已经开始录制了,我们可以选择幻灯片进行讲解。全部讲解完成后,一样是导出视频。 picture 59 在顶部菜单中选择「文件」→「导出」。 picture 60 也有一个需要特别注意的地方,就是在导出窗口中要选中「使用录制时的计时和旁白」。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程","id":"199","title":"如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程"},"2":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业可能性","id":"2","title":"职业可能性"},"20":{"body":"再来看独立开发这种工作方式。它通过售卖独立的软件、游戏或者在线服务来赚取收益。所以在工作地点、工作时间上都是自由的。 由于是自主售卖产品,它在工作内容上,也是自由的。 这里是举个例子,实际上还有很多在地点、时间和内容上都很自由的工作。比如网课讲师。 picture 2 有意思的是,正是因为这些工作自由度高,所以适合作为副业来操作。反过来,一旦实际成熟,我们可以让副业反客为主,变成主业,从而随心所欲的掌控我们的日常工作。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 独立开发","id":"20","title":"独立开发"},"200":{"body":"单从录制来讲,前一种方法就非常方便了,可以说是一气呵成。但如果录制完成后我们发现有几句话讲错了需要修改,那么就相当麻烦了。究其原因,主要在于虽然幻灯片是一页一页的,但音频却是整体录制的,所以音频出问题就只能重录。 那么我们能不能让音频也变成一段一段的,对应到每一页呢?这样我们以后再修改的时候,只需要重新录制那一页的音频。 picture 62 这就是我们第三种方案的思路。Keynote 和 PowerPoint 虽然没有提供分页录制的功能,但它们都能往幻灯片上添加音频,并将其合并到视频中统一输出。 所以我们要做的,就是在每一页幻灯片上,添加上语音讲解的音频。比较方便的地方是,这两个软件都支持直接录制语音讲解,而且一页幻灯片上可以录制多段,还能手工调整顺序。 下边我们来看具体如何操作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 幻灯片导出为视频","id":"200","title":"幻灯片导出为视频"},"201":{"body":"还是先来看 Keynote。第一步依然是制作好图文部分的内容,最好把要讲的文稿放到演讲者注释区域,这样录制的时候可以参考。 然后先选中要添加语音讲解的幻灯片,从菜单中选择「插入」→「录制音频」。 picture 63 在弹出的小窗口中点击录音按钮就可以开始录音。 picture 64 录制完成可以试听,没问题后再插入到当前幻灯片。当一张幻灯片有多个音频时,可以选择右上角的「动画效果」菜单,再点击右下角的「构建顺序」就可以看到当前幻灯片中的音频列表了。被选中的时候,会有蓝色描边,通过拖拽可以很方便地调整顺序。 picture 65 导出和之前类似,还是通过「文件」→「导出为」→「影片」。 picture 66 但需要注意的是,这次在导出窗口中,播放选项要选为「自动播放」。 picture 67 同时,我们还要把下边两个等待时间设置为「0」秒钟。 picture 68","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 Keynote 以「导出为视频」的方式生成视频课程","id":"201","title":"如何使用 Keynote 以「导出为视频」的方式生成视频课程"},"202":{"body":"再来看看 PowerPoint 里边的做法。给幻灯片添加语音讲义也在菜单「插入」→「音频」中。 picture 69 选择「录制音频」可以直接录制。 picture 70 下边我们看看怎么调整多个音频的顺序。点击「动画」菜单,在右边会出现一个「动画窗格」,再点击它,在最右边就可以看到当前幻灯片上所有的音频的列表。 音频前边还有编号,可以一一对应到幻灯片上的音频。通过调节它们的上下顺序就可以手动的指定最终的音频播放顺序。 细心的同学可能会留意到这些音频都会被放到一个叫做动画的菜单里面,其实这个菜单的功能是指定动画播放的顺序,音频被当做动画的一种,所以也在里边了。通过同样的方式还可以控制插入的视频的播放顺序。 picture 71 最后依然是通过「文件」→「导出」来生成视频,但是记得去掉「使用录制的计时和旁白」前的小勾,同时把「没有设置时间的每张幻灯片所用的秒数」设置为「0」。 picture 72","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 PowerPoint 以「导出为视频」的方式生成视频课程","id":"202","title":"如何使用 PowerPoint 以「导出为视频」的方式生成视频课程"},"203":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制类课程片段的制作","id":"203","title":"屏幕录制类课程片段的制作"},"204":{"body":"屏幕录制软件的原理,是不停地截取屏幕画面,然后和音频合成为最终视频。屏幕录制的优点是可以把电脑屏幕上显示的所有东西都录下来,不管你在哪个应用里边,不受应用本身功能的限制。所以可以非常直观地向学员展示完整的操作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制的原理","id":"204","title":"屏幕录制的原理"},"205":{"body":"在试用了很多屏幕录制软件以后,我们选择了 OBS 。它的优点主要有: 功能强大 开源免费 跨平台","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制的软件","id":"205","title":"屏幕录制的软件"},"206":{"body":"OBS 不但可以录制屏幕,还有一个非常强大的功能就是直播。现在很多视频网站的直播都支持用 OBS 来进行推流。所以学会了它,不但可以录制屏幕,而且可以进行直播,一箭双雕、非常划算。 然后,OBS 可以非常容易地进行屏幕之间的叠加,比如画中画模式,这就非常适合我们马上要讲到的「真人出镜」和「虚拟形象」类型的课程片段。 同时呢,OBS 还支持通过快捷键在各个场景之间来回切换,在录制课程的时候可以非常方便的进行转场,这个功能不少收费软件都没有。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 功能强大","id":"206","title":"功能强大"},"207":{"body":"和那些昂贵的收费软件不同,OBS 是开源而且免费的,这意味着使用它没有任何版权风险。我们在制作付费课程的时候,需要特别留意版权方面的问题。因为平时以个人身份在免费文章和视频中用一些字体、图片是没问题的;但在收费的商业课程中,就可能面临被起诉索赔的风险。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 开源免费","id":"207","title":"开源免费"},"208":{"body":"再来说一下,为什么跨平台的特性非常重要。在课程中,尤其是编程类课程中,我们经常会遇到需要讲解某个工具软件在各个操作系统上的安装和使用的情况,这时候就需要在多个平台上录屏。 如果使用一个特有平台上的录屏软件,在录制其他平台上的课程内容时,就不能使用了。只能重新购买和学习一个新的录屏软件。这不但浪费钱,更浪费时间和精力。 而使用 OBS 就没有这种困扰,它不但支持 Windows 和 Mac 系统,连主流 Linux 系统都是支持的。 所以,在我们后续课程中,将以 OBS 为例进行讲解。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 跨平台","id":"208","title":"跨平台"},"209":{"body":"OBS 的功能非常强大,还有包含了直播相关的功能,所以需要理解它特有的一些概念后,用起来才会更加顺手。 像一般的屏幕录制软件,只需要启动后点击录制按钮,进行录制就完了。但 OBS 中,它有自己的层次逻辑。 picture 73","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » OBS 的层次逻辑","id":"209","title":"OBS 的层次逻辑"},"21":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 职业成长性","id":"21","title":"职业成长性"},"210":{"body":"OBS 的第一个层次叫做「场景」,你可以把它理解为一种预设。 为什么需要场景?比如我们一个讲师,他每天上午要进行直播,这个时候视频的来源是摄像头和电脑屏幕;然后他每天下午要录制课程,这时视频的来源就只需要电脑屏幕,但他有两块屏幕,他希望都录进去。 如果没有场景这个概念,那我们每天上午到下午的时候,就需要不停的修改配置,非常麻烦。而有了场景以后,我们只需要把上午和下午定义成两个场景,使用的时候切换下就OK了。 你可能会想为什么要叫「场景」而不是直接叫「预设」呢?因为 OBS 中场景比预设更为常用和强大,它是可以实时切换的。 也就是说,如果我们有三个显示器ABC,可以在场景一里显示A;在场景二中显示BC;然后根据需求通过键盘快捷键来切换,甚至还能给它添加转场特效。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 场景","id":"210","title":"场景"},"211":{"body":"picture 74 在定义好「场景」以后,就可以往里面添加「来源」。最常用的来源其实就两类,也就是视频和音频。视频最主要的是显示器,也就是电脑屏幕,偶尔还有摄像头。音频的话主要就是麦克风。 picture 75 来看一下 OBS 的来源菜单。 首先它提供了「图像」和「图像幻灯片放映」,如果我们想在视频上面显示一张固定的图片或者图片轮播可以用它。 比较有意思的是,我们还可以把一个场景指定为来源,这样就可以非常容易地实现场景嵌套。也可以把媒体作为一个来源,这样就会在画面上面播放另外一个视频。 文本来源这里可以输入一些文字,指定它的颜色、字号和字体,然后它就会显示到屏幕上方。可用来显示我们机构的品牌名称之类的。可以看到,一些本来是后期才进行处理的功能,在 OBS 里都可以通过来源来实现。 显示器采集也就是我们的屏幕;视频采集设备通常就是指摄像头;音频输入采集这里通常就是耳机、麦克风或者外接的USB声卡之类。 这里还有一个音频输出采集,可以用来做多层次的音频加工。比如说我们电脑上有一个软件,就像柯南的蝴蝶结一样,可以对输入的声音进行变声,那我们就可以把这个软件的输出作为来源接入到 OBS 里边,录制下来的声音就是变声后的效果。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 来源","id":"211","title":"来源"},"212":{"body":"在多个来源之间,其实是有上下层级的概念的。打开 OBS 的来源小窗口,我们可以看见当前已经添加的所有来源。 来源是从上至下进行覆盖的。也就是说来源窗口的最上边一层,在最终视频中也会显示到最上面,上一层的内容会压住下边各层的内容。 picture 77 这个对于我们制作真人出镜类型的课程片段很重要,因为它通常是通过摄像头和显示器两个来源叠加得到的。摄像头的画面小、通常显示在右下角;显示器的画面大,往往覆盖整个视频画面。在来源窗口里,摄像头需要在显示器上层才看得见,不然会被显示器画面完全挡住。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 来源的层次","id":"212","title":"来源的层次"},"213":{"body":"picture 78 如果通过来源采集的信息不是百分之百符合我们的需求,还可以通过滤镜来进行进一步加工。OBS带有两类滤镜,一类叫做「音视频滤镜」,可以对音视频进行处理,比如进行噪音的抑制或者把音量放大;另一类叫「效果滤镜」,包括各种各样的特效,比如「色度键」可以用来抠背景。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 滤镜","id":"213","title":"滤镜"},"214":{"body":"虽然前面其实已经陆续讲到了真人出镜类课程片段的基本原理,这里还是再明确下。","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 真人出镜类课程片段的制作","id":"214","title":"真人出镜类课程片段的制作"},"215":{"body":"「真人出镜」类的 视频 非常简单,只需要使用摄像头、手机或者摄影机直接录制就好了。而「真人出镜」类的 课程 反而要复杂一些。这是因为在课程中,讲师其实并不是主体,课程内容才是。所以我们往往会采用「画中画」的模式,将讲师的头像部分做成一个小方块放到画面中。 picture 79 但这有一个小问题,就是这个方块会带背景。如果它的背景和作为主体的课程不搭,看起来就会比较别扭。要是能把背景变成透明的,它就能更好地融入到课程中。","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 什么是真人出镜类课程片段","id":"215","title":"什么是真人出镜类课程片段"},"216":{"body":"那么,怎么才能让背景变成透明的呢?答案是「抠图」。对于计算机来讲,将数字内容的一部分变成透明是非常简单的,真正的麻烦在于它不知道哪一些像素是背景、哪一些像素是讲师,所以我们需要一个方式来告诉计算机。 现在最常用的,也是最简单有效的一个办法,叫做「绿幕抠图」。就是在讲师身后放上绿色的背景布,再告诉计算机,绿色的部分都是背景,把它抠掉。这样就实现了背景的透明。 有同学可能会问说,为什么非要绿色,其他的颜色行不行?答案是可以的,但如果把背景设置成黑色,很多人的眼睛和头发都是黑色的,这些部分也会被透明,看起来会很灵异。 而绿色在日常生活中出现的频次比较低,所以一般默认用绿色来作为背景。但如果有天你穿了个绿色的衣裳,那就可以考虑换用蓝色的背景了。 picture 80 这一部分的具体操作是这样: 在场景中添加一个「显示器采集」来源,选为我们想要录制的电脑屏幕,放到来源窗口最底层。 在场景中再添加一个「视频采集设备」来源,选为摄像头,将其放置到屏幕右下方,在来源窗口中位于显示器之上。 在摄像头来源的右键菜单中,选择「滤镜」,在「效果滤镜」中添加一个「色度键」滤镜,背景为默认的绿色。 调整「相似度」和「平滑」的值,让背景消失得更为柔和。 picture 82 picture 83 关掉滤镜窗口,这时候在 OBS 的预览界面上我们看到的摄像头画面背景就应该已经透明了。 picture 84","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 抠图","id":"216","title":"抠图"},"217":{"body":"如果你是使用笔记本电脑,通常自带一个摄像头;如果是台式机,就需要自己装一个。摄像头需要对着讲师的脸,因为摄像头看到的,就是学员最后在课程里面看到的角度。 然后我们在讲师背后竖一个比较大的绿幕,充满整个摄像头的背景区域。一般两米宽高就够了,不够的话可以调整摄像头。 绿幕可以在电商网站输入「绿幕布」关键词搜索购买。有一些专业的幕布会比较贵,但我们早期可以买便宜的幕布来试水,一般几十块钱就能搞定。 为了让讲师和背景之间分离得更清晰一些,可以再通过光源进行补光。这里我们用手办做了个示意图给大家。这个灯的色温不能调,所以看起来稍微有点偏黄。实际录制的时候,可以用白色的灯来补光。 picture 81","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 真人出镜的其他细节","id":"217","title":"真人出镜的其他细节"},"218":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 虚拟形象类课程片段的制作","id":"218","title":"虚拟形象类课程片段的制作"},"219":{"body":"最后,我们再来看一下虚拟形象类课程片段的制作。虚拟形象实际上跟真人出镜差不多,但因为可以用卡通的形象来代表真人,所以形式上看起来会更加有意思,更适合年轻的同学。 在上一节里面,摄像头里拍到的是真实的画面,现在我们要想将真实的变成虚拟的,就要使用虚拟摄像头。 所谓的虚拟摄像头,就是其实并不存在这么一个物理上的摄像头,这个摄像头是用软件来模拟的。但是其他软件并不知道,它们会以为这个摄像头是真实的,于是它们之间就可以无缝地进行整合。","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 虚拟形象的原理","id":"219","title":"虚拟形象的原理"},"22":{"body":"前边说的都是当职业需要跨象限的时候,副业能提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,它也能提供非常大的帮助。 首先,副业可以成为新技术的练兵场。 现在社区里边吐槽得很多的一个现象是「面试造火箭,上班拧螺丝」。去面试一个前端岗位,问一些前端框架的最新版细节、底层原理,这是合理的,属于前端的业务范围。但如果把深度学习、大数据、云原生、容器编排、区块链甚至量子计算都拿来面试,就有点装了。 picture 1 但是面试本质上就不是合格考试,而是竞争考试 —— 是要在一群人中选择最好的,所以这也还可以理解。但最不好理解的是,当我们过五关斩六将入职以后,发现这家公司还在用十年前的技术栈,代码管理用的还是 SVN。 不光是小公司、也不光是传统行业;甚至在一些互联网行业的大公司的某些部门里,也会出现这种情况。吐槽规吐槽,但为什么这种情况相当普遍呢?这其实是由于「技术债务驱动的架构更新」导致的。 什么是「技术债务驱动的架构更新」? 把时间拉回五年前,现在有一个业务需要上线,于是我们用当下(也就是五年前)最新的技术构建了这套系统。然后,随着时间慢慢过去,新技术不断涌出,但是线上系统依然能用,业务团队要求稳定;产品团队需要的是不断添加新功能;根本没有机会对技术栈本身进行大幅更新。虽然技术栈逐渐变得陈旧,但是「又不是不能用,理解万岁」嘛。在这种想法下,技术债务不断累积,直到有一天,技术债务快把整个架构压垮了,甚至业务被迫中止一两天后,公司终于决定了 —— 要重新整套系统。于是,又会选用当前时间点最先进的技术来重新开发一套全新的系统。所以你会发现很多公司的系统,它并不是持续不断地更新、不是随时保持最新;而是在新旧之间反复横跳。 由于五年中,业务变动的可能性和幅度都非常大,所以对公司来讲,重写系统是可能比维护系统更合理的。但对于那些在五年里一直用原来技术栈持续不断地维护旧系统的同学来讲,他们的技术栈被迫变旧了。 而当决定开发新系统的时候,公司又希望使用当下最新的技术栈。这就要求原系统的程序员在一瞬间学会新技术,并开发出一套稳定的系统来。大部分人是做不到的,但从公司的角度讲没有关系,淘汰掉,招聘新人组建新团队就好了,说不定成本还能更低点呢。 picture 2 所以在这种结构的架构更新里边,如果程序员自己不想办法去学新技术,不去找地方去应用新技术,那么就像温水里的青蛙,最后终会用后即弃。 我很喜欢一句话,它听起来有些残酷,但真实,也时时推动着我去学习最新的技术。 一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。 —— Stewart Brand 副业给了我们一个坐上压路机,避免被碾压的机会。程序员这个行业跟其他行业还不一样,它对新技术的要求并不只是认知,光知道新知识、了解新思路是不够的,还需要一个实打实的练手环境,花上相当长时间去踩坑,才能稳妥地做出一个稳定的方案。副业提供了一个真实业务,让我们可以把最新的技术用到上面,随时保持技术栈最新,增强主业的职业竞争力。","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 新技术练兵场 » 新技术练兵场","id":"22","title":"新技术练兵场"},"220":{"body":"我们使用的是 FaceRig 这个虚拟摄像头软件,它提供了很多的3D模型,还支持导入 Live2D 这个游戏和动画用得较多的模型格式。如果是通过 Steam 购买的 FaceRig,那么在创意工坊里边可以看到全球玩家上传的各种模型,喜欢的可以直接订阅,它就会出现在我们的 FaceRig 里边。 当然,我们也可以制作自己的卡通形象,生成模型并导入。顺便说一下,对于多人参与的课程来讲,虚拟IP是非常有用的。如果我们将大量的精力和推广资源放到真人讲师的IP上面,万一这个讲师离开团队,之前的投入就废掉了,甚至会变成竞争对手的资源。但是如果我们采用虚拟IP,就完全没有这个问题。","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » FaceRig","id":"220","title":"FaceRig"},"221":{"body":"为了模拟摄像头,FaceRig 构造了一个 3D 空间。这个空间由「模型」和「背景」两部分组成。选好模型、配好背景,打开跟踪器让模型和我们的表情同步,就实现了用虚拟形象代替真人形象。 下边我们更为详细地讲述下步骤: 购买和安装 选择模型 选择背景 打开追踪器 打开广播 购买和安装 最方便的方式是在 Steam 这个平台上进行购买,它会帮你自动安装各种依赖,确保能运行起来。如果想用 Live2D 的模型,还需要购买对应的插件。 picture 85 选择模型 启动完成以后,点击顶部菜单最右边的UI按钮就可以切换右侧的面板;这个面板的第一格就是我们的模型。 点开以后可以选择喜欢的模型。 picture 86 选择背景 还是在右侧的面板,第二个图标就是。点开它可以看见预置的各种背景。如果想要最终背景透明,可以选择绿色背景方便下一步抠图。 picture 87 打开追踪器 现在虽然模型都有了,但它跟我们真人说话的表情语气没有关联起来,所以要打开追踪器。点击顶部导航,「切换追踪」按钮(图上画红圈的),摄像头就会通过人脸识别来捕捉我们的表情。这个时候我们摇脑袋和做出各种表情的话,就会同步到模型上。 picture 88 打开广播 这些都做完了以后,一定要记得还有最后一步就是要 打开广播 。所谓广播就是 FaceRig 把画面虚拟成一个摄像头,并同步到整个系统里,其他的软件就会把它当做一个真实的摄像头。 picture 89 打开广播也非常简单,就是点击顶部的这个像电台一样的按钮。点击打开,再点一下关闭。 当广播打开后,在 OBS 里去添加一个新的视频捕捉设备的时候,就会发现有一个名字包含 FaceRig 的摄像头,把它作为来源,就可以引入和真人表情同步的虚拟形象了。 picture 90","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 步骤","id":"221","title":"步骤"},"222":{"body":"视频剪辑是我们做课时用得非常多的技巧。剪辑是一门细节很多的技术,幸运的是,做课所需的只是非常基础的一些功能,所以我们才有可能花很少的时间学会。这也是我们这一节的内容。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 最常用的视频剪辑操作","id":"222","title":"最常用的视频剪辑操作"},"223":{"body":"视频剪辑的软件非常多,但整体功能上大同小异。经过一系列的试用,我个人用得最多的是这两个软件: 苹果公司出品的 iMovie Adobe 公司出品的 Premiere(一般简称PR) iMovie 是 Mac 专有的免费软件,完全可以胜任大部分的常规剪辑工作。后来苹果公司还开发了 iOS 版本,这样我们在 iPhone 和 iPad 上也能使用它。 如果我们只是想简单地调整下视频片段的顺序、删除某个片段、或者对某部分进行速度调整的话,iMovie 是个不错的选择。 PR 则是系统复杂、功能强大的专业剪辑软件,很多专业人士都在使用它。PR 是一个付费软件,但同时支持 Mac 和 Windows。 我们后续以 PR 为例进行讲解,在其他的剪辑软件里相关的操作也是非常类似的,往往只是菜单位置不同,大家可以自行摸索。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 剪辑软件","id":"223","title":"剪辑软件"},"224":{"body":"视频片段的调整是最常遇到的需求。因为我们在录课的时候很可能其中有一段讲错了,会想把它去掉,再把后边的内容给接上去;或者讲课时有一部分内容讲丢了,在后边补讲的,想把它给挪到前面去。这些情况时常发生。 比如说我们现在有一段视频,希望删除其中红色的部分,应该怎么操作呢? picture 3 直观来讲,应该是选中一个片段然后按删除键。有一些编辑软件就是这样做的。但在 PR 中,这个操作通常被分两步:先分段、再删除。 picture 2 所以我们会先用剃刀工具将视频给切割成三段,切割的位置正好在红色部分的开始和结束,这样它就会变成一个独立的片段。 然后切换到选择工具,选择这个片段,再按删除键,片段就会被删除。 picture 4 但我们会发现,视频中间空出来了一段空白。 picture 1 这是因为在 PR 里边,连续视频并不是一种常态,所以它没有自动去掉两个视频片段之间的空白。可以在这段空白上点右键,选择「波纹删除」,这样后边的视频就会自动补上来了。 picture 5 当然,在删除视频的时候,如果不是直接按删除键,而是点击右键,选择「波纹删除」会更加方便一些。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段的调整","id":"224","title":"视频片段的调整"},"225":{"body":"这里有一个需要特别注意的概念。在我最初的想象中,视频片段应该是很「硬」的,当两个视频片段有重合时,后一个片段会自动后移并紧跟前一个视频对齐。但在 PR 中,视频片段是很「软」的,当两个片段重合的时候,重叠部分会被覆盖掉,再也分不开了。可以把它们想象成两个透明胶带,一旦粘上,就很难无损分开了。 picture 6 所以,对于不熟悉 PR 的新手来讲,想要两个片段紧密连接,最简单的方式还是分开放,然后「波纹删除」中间的空白来自动对齐。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 柔软的视频片段","id":"225","title":"柔软的视频片段"},"226":{"body":"正因为这些片段很「软」,当我们在进行顺序调整时,也要倍加小心。这里我们可以利用 PR 的多轨道。我们可以暂时把要移动的片段放到另一个轨道上,然后调整原来轨道上片段的顺序,挪出一个新的位置,再从外轨上把片段给挪回来。 picture 7","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段顺序的调整","id":"226","title":"视频片段顺序的调整"},"227":{"body":"速度调整在做课时也很常见,比如说我们通过网络安装软件的时候可能就很慢,得操作二三十分钟,但我们不可能让学员一直等二三十分钟。一个方式是直接减掉这个过程,但如果其中又包含了一些操作细节,我们可能就需要把这一段视频加速。 picture 8 在需要调整速度的视频片段上边点击右键,选择「速度/持续时间」选项,会弹出设定窗口。 窗口上默认的速度是100,如果想加速,就改为大于100;想减速,就小于100。 有一个需要注意的问题,就是如果减速,视频片段会变长。如果前后有其他片段,就可能造成覆盖,所以这种情况下,最好放到另一个轨道上再调整速度。 另外,在加速的时候,原来的声音会变调,如果想要保持正常,记得选中「保持音频音调」。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段速度的调整","id":"227","title":"视频片段速度的调整"},"228":{"body":"这个操作也是很常见的,比如讲课中有几句讲错了,但是不方便删除视频,可以只删除这一部分的音频。 但是,默认情况下,音频和视频是绑定的。所以我们需要将要处理音频的部分切割成独立的片段,然后在右键菜单→「音频增益」中把它的音量调到听不到(比如-100dB)。 picture 9 当然我们也可以通过选中片段后点右键菜单,选择「取消连接」来解除音频和视频的绑定。这样就可以随意编辑音频了。 除了像视频一样分段、调整顺序等,我们可能还需要对音频进行去噪、调音等更进一步的操作,这时候我们可以在对应的片段上点击右键,选择「在 Adobe Audition 中编辑剪辑」在另一个软件中来处理。具体的操作我们将放到下一节讲解。 picture 10","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频中的音频处理","id":"228","title":"视频中的音频处理"},"229":{"body":"音频的后期处理和视频类似,也是非常专业的领域,所以我们这里也只讲最简单的处理。在我们做课时,经常会用到的技巧主要包括: 去噪 标准化 混响 去齿音和嘶声 下边我们依次来看看。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 最常用的音频处理操作","id":"229","title":"最常用的音频处理操作"},"23":{"body":"除了技术,副业也可以帮助我们在业务上获得新认知,保持敏感性。 之前我们在做程序员职业成长服务的时候,发现了一个问题。很多初阶的程序员没法升到中高阶,有两个很大的非技术影响因素,一个是管理能力、另一个是业务理解能力。 管理能力比较好理解。每一个程序员即使把自己的潜力发挥到极致,成为十倍开发者( 10x developer),他可以处理的事情也是有限的。 但是如果管理能力好,他就可以培养出很多拥有和自己同等技能的人,这样就不只是十倍、而是可以成百上千倍地复制能力,为公司增加更多的生产力。 业务理解能力这一块,是因为在绝大部分的公司里,技术都是为业务服务的。所以需要针对业务的各种需求、各种流程来做解决方案。 如果对业务不了解,那么即使技术很不错,因为不知道某些业务细节,最后设计出来的方案可能也不是最优的。这就像我们小学时做应用题,有一个隐藏条件包含在业务逻辑中,如果忽视了它,即使数学再好,做出来的答案也是错的。 所以,程序员应该需要培养自己对业务的理解能力。但比较讽刺的是,很多公司的初阶程序员,恰恰没有机会去了解业务。尤其是一些比较大的公司,很多业务相关的问题都是在中高阶的技术决策层就已经解决掉了,分配到初阶程序员这里,就只剩下一些规划好的、待实现的技术方案了。 这就会形成职业上的一个断层,让初阶程序员无法变成行业专家。很多公司是无意的,也有极少数公司是有意为之。因为高阶的岗位是有限的,如果你成长起来后没有位置,就会跳槽了。所以,公司不培养我们的时候,我们就只能自己培养自己。 而副业正是磨练自己的好方法。我们可以做一个跟我们主业相关的副业,通过自己的项目来了解需求、理解业务,从而弄明白公司在做什么样的事情,怎样才能做得更好。将自己从一个纯粹的螺丝钉,变成独当一面的解决方案高手。","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 业务敏感度 » 业务敏感度","id":"23","title":"业务敏感度"},"230":{"body":"「去噪」就是「去除噪音」。一般分为两个步骤: 定义噪音 去除噪音 为什么会有「定义噪音」这个步骤呢?因为对于计算机来讲,它并不知道哪一部分声音叫做噪音。 比如我们在录一首歌的时候,邻居家的猫在旁边叫,这个声音就算是噪音。但如果是想录一个宠物视频,猫在里面就不是噪音,它可能是主角。所以是否是噪音,是需要根据场景来进行定义的,计算机理解不了这点。 当然,这个例子比较特殊。通常来讲,要去掉的噪音叫做「底噪」。就是声音很小的背景噪音,比如电流声,远处汽车和行人的声音。这种时候,只需要选取一段只有这些背景音的音频,将其定义为噪音,那么软件就可以把和它类似的声音去掉。 音频处理也有很多软件能做,但因为我们视频剪辑用 PR,所以音频用 Audition(简称 AU )来做会更为方便。它在我们修改音频后,会自动更新 PR 里边的片段。 下边我们来看 AU 中具体怎么操作。首先选中一段只有背景噪音的音频,在顶部菜单中选择「效果」→「降噪/恢复」→「捕捉噪音样本」,就可以把它定义为噪音。 picture 11 然后,在顶部菜单中选择「效果」→「降噪/恢复」→「降噪(处理)」,开始去噪。 picture 12 记得在弹出的窗口中点击「选择完整文件」,再点「应用」就会开始处理。 picture 13","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 去噪","id":"230","title":"去噪"},"231":{"body":"标准化也是一个很有用的功能。我们录音的时候,尤其是换了场地和设备录音的时候,可能声音的范围(最高音和最低音)就不一致。这种时候,就需要通过「标准化」来将这个范围统一,这样听起来音量差异才不至于太大。 picture 14 在 AU 中的具体操作如下: 在顶部菜单中选择「效果」→ 「振幅与压限」→「标准化(处理)」。 picture 15 然后在弹出的窗口中,可以将其标准化到 0 dB (如果觉得音量过大,也可以试试 -6 dB)。 picture 16","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 标准化","id":"231","title":"标准化"},"232":{"body":"我不知道大家有没有这种感受,就是有时候听一些电脑生成的音频时,会觉得声音非常纯粹,很好听,但听起来不像是真的。而一些现场录制的音频,音质可能没那么好,但听起来却会有种非常强的空间感。 这是因为我们日常在说话的时候,声音会分成两个层次到达我们的耳朵。 picture 17 一个层次是直接从发声处传到了耳朵里,另一个层次是声波打到周围的环境上,比如墙面、地面、桌椅上,被反射后,有一些很弱的声音以稍微延迟一点的时间进入我们的耳朵。我们日常听到的多是这种叠加后的声音。 在电脑中生成的音频如果不特意处理,是没有这种叠加的。这就让声音有点「平」或者「干」。为了增强声音的空间感,很多编辑软件提供了叫做「混响」的功能。其原理就是模拟现实中的声音叠加,将一部分声音强制延迟后混音,这样的声音更有立体感。 下边我们看看在 AU 中怎么具体操作。 在顶部菜单中选择「效果」→ 「混响」→「混响」。 picture 18 在弹出窗口中,可以调节各项参数。点击播放按钮可以试听。 picture 19 选择好以后,点「应用」进行处理。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 混响","id":"232","title":"混响"},"233":{"body":"齿音是指我们说话时,呼入呼出的气流和嘴唇、牙齿之间摩擦产生的声音;嘶声则有些类似于广播电台中常听见的嘶嘶嘶的声音。这些声音混在音频中,可能听起来不那么舒服,所以 AU 也提供了工具来清除它们。这部分的操作很简单,这里就不详细说明了,这两个功能的菜单分别在: 齿音:「效果」→「振幅与压限」→「消除齿音」 嘶声:「效果」→「降噪/恢复」→「降低嘶声」","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 齿音和嘶声","id":"233","title":"齿音和嘶声"},"234":{"body":"其实顺序并不是强制的,怎么都行。但考虑到标准化时有可能把底噪放大,所以我一般会按下图的顺序来进行各项音频处理操作。 picture 20 整个过程中,去噪和标准化才是最重要的,其他的三项时间紧张时可以偷懒不做。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 建议顺序","id":"234","title":"建议顺序"},"235":{"body":"对于技术类课程来讲,字幕是非常有用的。一些技术名词光是读出来,有时候很难明白它是什么意思。而如果有字幕,就可以一目了然了。","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕的制作和自动生成","id":"235","title":"字幕的制作和自动生成"},"236":{"body":"所谓字幕呢,是指我们在播放视频的时候,显示在屏幕下方的、和语音同步的文字。为了让计算机正确地显示出字幕,我们需要告诉它两个信息: 这个字幕的文本是什么 这个文本应该在什么时间开始显示,在什么时间结束 也就是说,最基本的字幕信息应该包含「文字本身」以及「文字显示的时间段」。 当我们把多条字幕的信息合并放到一起,就有了字幕文件。字幕文件可以是单独的文件,在播放视频时载入并显示,这种方式称为「外挂」;也可以在压制视频时直接压制到视频里,这样即使播放器不支持字幕功能,也可以正常显示。 字幕的格式有很多种,srt 格式是最简单的格式之一。 picture 21 它由多段文本组成,每段文本分为三行: 第一行是序号,一般从 0 开始递增 第二行是显示时间段,中间用箭头分隔 第三行是这个时间段应该显示的文字","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕及其格式","id":"236","title":"字幕及其格式"},"237":{"body":"我们使用的字幕编辑软件是 ArcTime ,它是一款跨平台的免费软件。启动以后的界面是这样的: picture 22 左上部分区域是视频的预览区,可以从顶部菜单的「文件」→「导入音视频文件」载入要编辑字幕的视频。然后它就会显示预览区。 预览区下方就是字幕区,有根据音频生成的波形在上边。在这个区域点击右键,选择「插入空白字幕」,就会插入一个空白的字幕条,双击可以输入字幕,拖拽可以调整显示的时长和起止时间。 添加好字幕以后,点击预览区的播放按钮,可以实时地看到新添加的字幕效果。需要注意的是,目前的版本中,删除某条字幕的操作是不能撤销的。这可能是这个软件为数不多的缺点了。 整个视频的全部字幕添加完以后,点击顶部菜单中的「导出」→「字幕文件」就会将刚才编辑的字幕生成一个字幕文件了。 picture 23 如果想要把字幕直接压制到视频里边,则可以选择「快速压制视频」选项。","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕编辑软件","id":"237","title":"字幕编辑软件"},"238":{"body":"ArcTime 还内置了一个为视频生成字幕的功能,放置在「语音识别」菜单中,但这些功能是收费的。 对于程序员来讲,有一个更为廉价的方式获得同样的效果,那就是直接写代码去调用云服务商提供的 API。比如 阿里云 、腾讯云和 百度翻译平台 就提供了相关接口。 更有开发者已经在 GitHub 上开源了基于这些接口的命令行和客户端软件。大家可以在 GitHub 搜索「VideoSrt」,自行安装试用。 picture 24","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕的自动生成","id":"238","title":"字幕的自动生成"},"239":{"body":"课程制作完成上线以后,并没有结束。长征才刚刚开始,我们需要不断得去运营它。这一节就来聊一聊流量池和二次购买。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 流量池和二次购买","id":"239","title":"流量池和二次购买"},"24":{"body":"","breadcrumbs":"如何优雅地做副业 » 如何优雅地做副业","id":"24","title":"如何优雅地做副业"},"240":{"body":"先来看一下在没有流量池的情况下,课程转化是什么样子的。 picture 26 首先,我们将自有的或者购买的流量引导到课程页面,以触发销售转化。但如果我们没有采取更多措施,之后这个流量就走掉了。当上架新课时,又需要重新寻找或购买流量。 这种方式优点是简单,但今天操作起来问题很大,因为我们已经错过了之前流量爆炸的时代,现在流量已经很贵了,这么浪费太可惜。那么,能不能把流量囤起来,供以后使用呢?","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 没有流量池的情况","id":"240","title":"没有流量池的情况"},"241":{"body":"picture 27 最简单的操作就是,把购买过课程的学员放到「学员池」里。当上架新课程以后,可以直接给他们发通知进行销售。这样就实现了流量的二次使用。很多同学觉得这是显而易见的,但事实上在操作的时候却很容易出问题。 比如说,很多讲师只是直接使用课程平台进行学员管理,而很多的平台不允许讲师给学员批量发送私信,甚至还会做关键字过滤。这种情况下,我们对学员的触达能力是非常弱的,需要建立更可控的流量池来替代。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 学员池","id":"241","title":"学员池"},"242":{"body":"picture 28 学员池重用了已经购买过课程的流量,但更多的没有购买课程的访客流量还是流失了。所以我们还可以更进一步,来做访客池。 把我们课程中有意思、有传播点的内容做成免费的素材,进行多渠道分发,把用户吸引过来并放到这个池子里,以备以后发送通知、触发销售。 常用的渠道包括: 搜索引擎 社交网络 媒体平台 课程平台 行业网站 学员池和访客池是我们最主要的两种流量池。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 访客池","id":"242","title":"访客池"},"243":{"body":"互联网发展到现在,各种产品已经极大的丰富,所以有大量的工具可以用来构造流量池。因为课程销售有非常明确的商业诉求,所以我们对流量池也有相对明确的评判标准。这里分享下我常用的三个标准: 进入门槛低:最好能免除用户注册,尽快获得用户的基本信息和触达权限 可触达率高:这样我们的销售信息才能被更多人看到 触达免费或廉价:太贵了用不起 如果想要获取种子用户用来验证大纲,还需要考虑互动性。 针对微博、公众号、企业信号、微信群、自建 APP 这几种最常用的方案,我们整理了一个对比表格以供大家参考: picture 30","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 构造流量池的工具","id":"243","title":"构造流量池的工具"},"244":{"body":"各种流量池都有自己的优缺点,我们应该选取当前阶段最适合的来进行流量的存储。我们也可以分阶段、渐进式地建立多级流量池,以在投入和收益上获得平衡。 比如早期我们可以直接使用微博的关注、哔哩哔哩的订阅来做流量池;然后将一部分核心用户引导到微信群和企业微信一对一服务中。这样把微博的获客门槛低和微信的触达率高这两个优点结合起来了。 在用户规模大一些以后,我们再去开发自己的App,实现对用户流量更高级别的控制。 picture 31","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 多级流量池","id":"244","title":"多级流量池"},"245":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 如何有效地反盗版","id":"245","title":"如何有效地反盗版"},"246":{"body":"虽然几乎所有讲师都认为反盗版是必须做的,但未必都明白反盗版的意义,觉得就是少挣了钱。实际上并不是这么简单,盗版最大的问题,是对正版用户带来的不公平。同样的课程,有人花了几千块钱买过来,有人却一分钱不付就可以得到,这让正版用户显得很傻。 其次,很多讲师以为把课程放到课程平台上,平台就会帮着进行反盗版,自己就不用管了。事实上,大部分平台的反盗版措施都非常有限,通常只能由讲师提交盗版链接,他们投诉下架。如果对方将课程放到境外网站,连下架都做不到。而且有些平台每周定时收集处理一次盗版信息,还不如自己直接投诉效率高。所以我们不能把反盗版推给平台去做,他们只能起到辅助作用,我们自己还是要足够重视。 还有一个普遍的错误想法,就是很多程序员觉得盗版是不可能完全杜绝的,所以干脆就不防范了。我们的确没有办法从技术上来完全杜绝视频课的盗版,但却可以采取各种措施来降低被盗版的概率。 要从做盗版的人的经济收益的角度来思考盗版这件事情,如果我们的课盗版门槛很低,就可能导致大量盗版,因为不需要付出太多的代价。相反,如果我们课的盗版门槛很高,那就要花很多功夫才能盗版。 很多盗版手段是针对平台的,当我们课程的盗版门槛变高以后,盗版狗有两个选择,一个是投入时间和金钱去升级盗版手段,另一个选择是用原来的盗版方法继续盗版其他门槛低的课程。绝大部分情况下,它们会选择后者。 有同学可能会说,这样其实并没有解决盗版的问题。是的,从宏观上来讲,确实没有解决盗版问题;但从个体的角度来看,我们又的确避免了自己的课程被盗版。 要从宏观层面上去解决知识产权问题,需要国家、法律、以及社会各方面一起持续不断地推动,我们作为个体,积极响应国家的政策,并保护好自己的知识产权,就是在为这事添砖加瓦。 picture 32","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 树立反盗版的正确思路","id":"246","title":"树立反盗版的正确思路"},"247":{"body":"所以反盗版其实就是要不断提升盗版的门槛,降低盗版狗的收益,让它们无利可图。我们自己实践过的方法中,最有效的可以归纳成四个字、两个词:卖空和卖多。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 如何有效地反盗版","id":"247","title":"如何有效地反盗版"},"248":{"body":"卖空其实就是预售,还没有课程,就开始销售。你很难盗版一个还不存在的课程。而且在我们精益网课流程中,本来就是通过预售来验证需求的,所以做起来很顺手。 这个思路再扩展一下,比起一次性提供课程,连载课程的反盗版门槛更高。因为它每周只更新一到两节课程,持续时间很长。这样盗版的成本一下被提升了 N 倍。 卖空的思路很简单,但效果却非常明显,强烈推荐大家尝试。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 卖空","id":"248","title":"卖空"},"249":{"body":"卖多是说,现在大家课程放到平台上,盗版门槛是一样高的。但是我们可以多提供一些平台没有的、盗版不了的服务来反盗版。这些服务可以包括: 答疑 督学 社群 线下服务 在进行这些服务的时候,我们可以先进行身份确认,无法提供购买证明的人就不能享受这些服务了。 更进一步,如果我们把课程中不可或缺的部分挪到这些服务中来,那么看盗版视频的人甚至不能完整的学完课程,这就让盗版课程失去了意义。 有一个不错的实践可以分享给大家。我们的主要课程是全栈课,既有前端又有后端。为了反盗版,我们开发了一个云端的编程环境,将后端课程放在其中,然后限制只有正版学员才能登录这个系统,采用这个系统的课程后来就再也没有被盗版过。 这个系统的开发很简单,只需要在云平台上启动一个基于容器的、带有桌面的系统,然后再运行一个基于 Web 的 VNC 去连接它,就可以实现在浏览器中远程操作桌面系统了。感兴趣的同学可以去了解下 NoVNC 这个开源项目。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 卖多","id":"249","title":"卖多"},"25":{"body":"在通过大量章节充分了解了副业的重要意义之后,相信大家已经明白了「为什么」。下边我们开始来讲「是什么」和「怎么做」。 在做一件事情之前,我的习惯是要想明白它的本质,弄清楚它的核心资源,了解它的核心优势。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 想明白核心资源和核心优势","id":"25","title":"想明白核心资源和核心优势"},"250":{"body":"","breadcrumbs":"精益副业 » 进一步提升副业的鲁棒性 » 进一步提升副业的鲁棒性","id":"250","title":"进一步提升副业的鲁棒性"},"251":{"body":"前面我们通过两个大章节的实践课程,为大家详细讲解了怎么通过独立开发和网络课程制作来发展副业。之所以会选择这两个方向,除了它们非常典型、有很高的投入产出比,还有一个原因 —— 它们之间可以形成非常好的互补。 目前看来,在国内要通过独立开发赚到一流企业程序员的年收入(大致三十到五十万),还是比较困难的。免费加收费模式虽然后期收益巨大,但前期需要长时间的投入。 相对而言,网络课程的售卖更容易带来现金收益。如果我们把独立开发的整个过程完整的录制下来,并加工成网络课程进行销售,那么即使独立开发项目最终难以通过销售软件和服务来赚取足够多的收益,我们还可以通过网络课程获得收入。 而且,不管对于课程学员还是独立软件/服务使用者来讲,都更有益。课程的学员可以学到更为真实、更贴近一线、且经过事实验证的开发技巧;软件/服务使用者则可以获得详尽的文档、架构说明,更有机会进一步深入了解整个规划、设计、开发过程,充分理解业务,甚至因此变成代码贡献者。 从流量上讲,软件/服务可以给课程带来学员;课程可以给软件/服务带来用户。两者互相促进,为我们的副业更添了一层保障。 picture 25 最终,我们就可以实现一个多次利用「副产品优势」的三级收入模式。在这个模式下,我们首先通过主业赚取最核心的收益,以供日常生活和基本发展。然后,我们在主业工作中积累的知识、经验、人脉基础上,开发我们的副业,比如独立软件或服务。在独立开发的过程中,我们再次把它的副产品——制作过程,录制成课程进行售卖。最终,我们可以分别从主业、独立开发以及课程三个渠道获取收益。 这样即使某些收入源不是特别好,我们的整体收入还是相对高的,这就让我们有足够的时间和资源去修正这些错误,让整体发展得越来越好。","breadcrumbs":"精益副业 » 进一步提升副业的鲁棒性 » 网课+独立开发的双引擎副业模式 » 网课+独立开发的双引擎副业模式","id":"251","title":"网课+独立开发的双引擎副业模式"},"26":{"body":"来看我们这本书的副标题 —— 「程序员如何优雅地做副业」。它有两个重点,一个是「优雅」、一个是「副业」。 既然是「副业」,就表明我们还有一份作为「主业」的正职工作。副业只是我们从本来已经很繁忙的工作、生活时间里面活活挤出来的一点时间精力去做的业务。 所以对于副业来讲,最核心、最宝贵的资源,就是我们的时间片。 为什么这么说呢? 因为对于一家企业来讲,它有足够多的资源可以调配。它可以通过雇人的方式,批量增加可用的时间片。但是对于我们处于「副业」状态的业务来讲,精力和资源都是非常有限的。 副业本来挣得就很少,如果还要去雇人的话,每一个人分下来就会更少,会有入不敷出的风险。另外,人多了以后,在沟通上、管理上的成本也会飙升。所以副业的人应该尽可能少。 于是,时间片就成为了整个副业中,最为有限、最难拓展的资源。我们应该围绕紧缺的核心资源来规划副业。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 副业的核心资源 » 副业的核心资源","id":"26","title":"副业的核心资源"},"27":{"body":"我们的目标读者是程序员。大部分的程序员要么是在写软件、要么是在写网站、要么是在写APP,通常属于软件或者互联网行业。 软件行业和互联网行业的竞争是非常激烈的。而我们在上一节里面说过,副业它有一个先天的特点,或者说是不足,也就是我们能在这个业务上可以投入的时间和精力是非常有限的。 市场是非常残酷的,它并不会管你这个产品的制作方是个人还是公司,开发它的程序员是全职还是兼职。最终用户会以同样的标准来看评判产品,优胜劣汰。 那在一个竞争如此激烈的市场里面,一个先天投入不足的业务,凭什么可以战胜其他的项目,获得成功呢?这是我们开始之前就要想明白的问题。只有想明白了这个问题,我们在做副业的时候才是有的放矢,而不是随波逐流。 这个问题困扰了我挺久,后来在读《 创业就是要细分垄断 》时,里边一段话让我觉得非常有启发。 它大概意思是说,所谓的「快鱼吃慢鱼」,并不是说人家加班到晚上12点,你就天天逼着员工加班看凌晨四点的中关村。快鱼的快不是这种意义上的快,而是策略上的快。 书里还举了 AirBnb 的例子。它通过共享的方式来创造供应,AirBnb 增加一个民宿只需要几天,而连锁酒店可能要花上半年。就算连锁酒店的员工每天工作85 个小时,也赶不上 AirBnb 的速度。这就是策略上的快。 所以,回到副业上面来,如果想要我们的副业具备很强的竞争力,我们就必须根据其独有的特点,为其制定一个有竞争力的策略。 比如说,我们的副业项目往往规模不用做到特别大。因为如果我们想做到财务自由,那么1000万左右的人民币基本上也就够了。1000万这个数字对个人来讲可能很多,但是对于企业来讲,其实是一个非常小的市场。尤其对于一些以融资方式发展的创业公司和上市公司来讲,这种规模的市场根本就没有办法生存。所以,如果我们选择的目标市场足够好的话,是可以避免很大一部分公司的竞争的。 当然,即使是在一两千万的市场里边,仍然会有不少的竞争对手。我们仍然需要结合副业的特点来构造自己的优势。这里给大家介绍其中一种,叫做「副产品优势」。我们本身是有正职工作的,通过日常工作,会积累很多的经验知识和其他资源。如果我们把这些东西利用起来,把它做成副业的产品的话,它的成本是非常低的,而在深度上,往往又会有很高的门槛。 举一个实际的例子。 比如,我一个朋友是云平台的架构师,他的工作是专门为传统企业往云平台上做业务迁移提供解决方案,方便这些企业购买他所在公司的云计算产品。 但是在这个过程中,他接触了大量的、各行各业的公司的迁移需求,并为他们做了架构方案。这让他的架构能力突飞猛进,架构经验也远超旁人。 这个时候,如果他以副业的形式,开设讲授架构技巧的课程,对他来讲成本是非常低的。因为无论他做不做这个副业,都要投同样多的精力在这件事情上。 作为对比,如果一位全职网课讲师想要来做同样主题的课程,那么就需要从头开始学习完整的架构知识,并花足够长的时间,比如说几个月甚至几年,去接触大量的实际案例,最终才可能做出同样品质的课程。 而对专职讲师来讲,他的收益仅仅是课程收益,并不包含主业的薪资,所以最终收益甚至可能还赶不上他为了制作课程进行的投入。在这种情况下,全职反而成为了一种劣势,这就是我们所谓的副产品优势。 当然,我们还可以根据副业的其他特点,发掘出各种独特的竞争力。但只有围绕核心的稀缺资源进行规划,并从策略上建立我们的核心优势,才能真正做到优雅地做副业。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 副业的核心优势 » 副业的核心优势","id":"27","title":"副业的核心优势"},"28":{"body":"这一节开始,我们就来讲讲副业的核心资源——时间片。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片","id":"28","title":"时间片"},"29":{"body":"前边说过,时间片是我们副业的核心资源,所以直接把它以一个比较低的价格销售出去,是不划算的。这种方式和「优雅」这两个字不太匹配,但我们这里还是会简单介绍一下。 它不会作为我们这本书的重点,但大家有一个简单的了解也是好的,至少可以作为其他副业方式的对比。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 时间片的销售","id":"29","title":"时间片的销售"},"3":{"body":"2014年的时候,我做过一个「程序员拍卖」的项目。听起来很神奇,其实就是将我们遴选过的优质程序员推送给各家在招聘的公司,让他们来竞价,从而帮程序员们找到一份满意的工作。 那两年,我们为上千名程序员找到了工作。后来我把从中学到的对于程序员职业的理解写成了一本小书,叫做 《程序员跳槽全攻略》 。 书里我创造了一个用来分析程序员职业的工具,叫做「方糖职业路线图」。它根据现金流将程序员的职业空间分布到了E、S、B、I 四个象限中,我们依次来说说。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » 职业的四大象限","id":"3","title":"职业的四大象限"},"30":{"body":"不经任何加工直接销售时间片,最主要是以「私单」的方式来进行的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 私单","id":"30","title":"私单"},"31":{"body":"传统的私单主要是外包模式。也就是说,一家公司有一个项目要做,它把这个独立项目完整的包给你。双方约定完成的时间、验收的标准和价格。大一点的项目,还会有阶段性的交付和付款。 除了这种完全线下的外包,还有基于网络的 freelancer 方式。大体上是基于网络接单,然后按发包方的要求进行开发。因为没有地域的制约,可以承接国外的业务。 目前的情况看,中国程序员在海外外包市场上并不占据优势,尤其是个人。因为现在海外接单平台上有大量的印度、巴基斯坦等国家的程序员,他们要价非常的低,而且平均而言,英文沟通能力比中国程序员要强一点。接这些单子会比较累。 做起来比较舒服、利润比较多、沟通上比较容易的私单,往往是通过行业人脉和开源项目来的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 外包","id":"31","title":"外包"},"32":{"body":"大部分的外包在我看来都是很痛苦的,因为它其实和程序员的技术栈不对应。 沟通问题 我们平时在公司开发时,都是产品经理把需求梳理好,然后和程序员进行沟通,好一点的还有高保真原型。即使在这样的情况下,进行需求调整的时候,我们还是会很难受。大量的代码需要改动,如果上线时间表比较紧,我们就会被逼着加班。 而外包模式下,需求方往往就变成了外部的人群。因为个人的工作量有限,所以通常不会是特别大的单子,这就有可能遇到大量不靠谱的发包方。他们很可能并不了解开发的流程,也表达不清自己的需求。 这就要求我们有相当的沟通技巧。如果是基于网络的沟通,效率会进一步降低,问一句得等半天才能有响应。 甚至,很多时候我们会被迫去做需求分析工作,因为整个环节中缺失了产品经理 —— 很多发包方觉得根本不需要这个中间角色。 尾款问题 即使熬过了开发阶段,还有一个尾款收取问题。新手容易因为太过信任对方先交工再收钱;老手也逃不掉那种开发完了对方的创业公司倒闭了的情况。 比较大的项目或者面向特定行业的项目,在签单之前可能会有招投标,然后可能会有层层的审批。在款项的时间预期上要有心理准备,经常会有项目都做完了审批还没有走完的情况。 项目全部由自己开发还好,如果需要其他人的配合,那我们就需要自己垫付资金。这些风险需要合理的控制。 开票问题 个人做私单还有一个烦心的事情,就是大部分的单子都是需要开具发票的。这时候就只能去找一些公司代开。这种代开是有费用的,所以在定价的时候要把这些也考虑进去。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 外包的坑","id":"32","title":"外包的坑"},"33":{"body":"正是因为这种整单外包的方式会带来各种麻烦,最近开始出现一个更加「简单粗暴」的私单方式,叫做「按需雇用」。这是面向发包方的说法,对于程序员来讲其实应该叫做「驻场开发」。 我们平时都有正职工作,但是如果不是去了黑心企业的话,周末的时间还是空出来的。这时候我们就可以到其他公司去上一两天班。通常是一些创业公司,去解决一些他们的开发没有能力或者精力解决的问题。 在这种模式下,费用是按时薪结算,沟通也更为顺畅。只要像平时一样多上一天班就可以获得好几倍的回报。而且当天晚上就可以获得收入,也没有尾款的烦恼。 所以如果非要销售时间片的话,我觉得这种方式更高效一些。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 按需雇用","id":"33","title":"按需雇用"},"34":{"body":"但是正如我们前面所说的,你的时间片是非常有限的。像按需雇用这种方式,虽然收益看起来高一点,但它的天花板也是非常明显的。 我们可以很容易地算出来。假设我们每周末拿出一天,一个月也就只有四天而已。就算一天能挣2000块钱,一个月也就是8000块钱。 这是最理想的情况下,因为只能周末工作,所以往往并不是每周都会有活;同时,如果遇到开发内容不是特别熟悉的情况,可能还要花一点时间去学习相关的资料。 整体来讲,我们认为私单,尤其是按需雇用,属于一个中高收益、中低风险、但是也有明显的收入天花板的一个副业。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 更优雅的方式","id":"34","title":"更优雅的方式"},"35":{"body":"时间片的优化有两个思路。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 时间片的优化","id":"35","title":"时间片的优化"},"36":{"body":"提升单位时间的收益其实就是提升时薪(但并不一定局限于按时薪支付的副业,其他形式可以折算成时薪),有几个简单的思路。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 提升单位时间的收益","id":"36","title":"提升单位时间的收益"},"37":{"body":"「切换地域」就是说,我们同样是干活,但如果服务对象所在的位置不同的话,单位时间的收益也是不同的。 比如你在重庆,给本地公司去做一些外包,那整个项目的基础价格就是参照当地程序员的人工成本来进行比价的。但如果是在重庆可以给北京的公司做外包,那发包方就会更多地参照北京的各种成本来进行相应的股价,这样我们就可以把自己单位时间的收益提升上去。当然,需要考虑沟通的效率和成本。 把这个思路扩大一点,就变成在国内做国外的业务了。 因为和国内相比,国外的人力成本通常会贵很多,如果你在二三线城市,那么成本又更低。这样就出现了一个价格差,如果能控制好这个价格差,我们就能挣到更多的钱。 当然前边也说过,这里边有竞争和外语沟通的问题,需要根据自己的实际情况来选择。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 切换地域","id":"37","title":"切换地域"},"38":{"body":"在没有建立起自己的知名度之前,非常单纯地去做外包,面对的往往是价格战的红海。地球那么大,总有人的时间比你不值钱。 而且外包它是一个开放性的需求,如果真要把很多雇主的需求细细做好的话,对技术栈的广度要求还挺高的。因为每一个项目它要求的技术栈可能不一样。项目做的越多,用到的偏门技术就可能越多。 所以我们要想办法解决竞争的问题。细分市场就是一个很好的思路,比如说我们可以给一些标准化的开源产品做二次开发来挣钱。 这其实不是什么特别新的思路,早在个人站长时代就有人专门给 Discuz!这个开源论坛软件写插件和定制功能挣钱,而且还真养活了不少小公司。 现在我们可以把这个思路更扩展开一些,比如说我们把从「支持国内项目」变成「支持国际知名的项目」。 这样的话,我们就能解决掉出海接活面临的大部分起步问题。 你看: 我们从什么地方来获得客户?直接从开源社区获取客户。 如何证明我们的开发能力? 可以写一些高质量的开源插件,给大家免费使用,并作为我们的demo。 如何来获取比较高的收益?专门给一个项目写插件的团队并不是太多,选择够好的话,就可以成为这个细分领域的No.1,获得一些品牌上的溢价。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 从外包到二次开发","id":"38","title":"从外包到二次开发"},"39":{"body":"提升单位时间的效率对于按工作量支付的副业来说特别重要。 比如说我们现在有一个项目,交付后的收益是10万块钱。以原来的方式完成它,可能需要花100个小时。现在我们想到了一种新办法,把效率提升了10倍,那么原来100个小时才能完成的活,现在10个小时就能做完了,这就是效率的提升。 多出来的90个小时我们可以用到其他项目上,哪怕是用来休息,也是很好的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 提升单位时间的效率","id":"39","title":"提升单位时间的效率"},"4":{"body":"E象限是雇员象限。别人给我们发工资,我们帮别人挣钱。这是风险最小的象限,我们的工作任务是别人分配的,只要认真完成,每个月都能得到预期中的收益。 在从开发走向高级开发后,往往就可以开始选择发展路线。E象限的典型的发展路线有两种,专家线和管理线。 E象限的优点是稳定,缺点是天花板非常明显。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » E象限(雇员象限)、帮别人挣钱","id":"4","title":"E象限(雇员象限)、帮别人挣钱"},"40":{"body":"当然,通过增强意志力来强迫自己去提升生产效率,其实是很难奏效的。 因为我们本来就是在利用工作之余的时间。在这个时间上,很难保证精力非常充沛。别说提升工作效率,能保证在做这些事情的时候尽可能的不被干扰,不让自己的生产效率降下去,已经是非常不错了。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 打鸡血难以奏效","id":"40","title":"打鸡血难以奏效"},"41":{"body":"但是非常幸运的是,我们是程序员。我们从事的工作,它本身就有一部分是由机器来完成的,所以我们可以引入自动化来提升效率。机器是使用电来工作,它的效率提升空间是非常大的,而且它也不需要休息,可以7×24小时地进行工作。 代码生成器 对于程序员的日常工作来说,最主要的自动化方式就是代码生成器。 但一说到代码生成器,就会听到很多反对声音。如果你用过一些比较早期的代码生成器产品,很可能你也会会有一些负面印象。 在大概十多年前吧,我当时所在的公司也就购买了一套代码生成工具。根据说明书,配置好业务逻辑,然后就可以同时生成ASP、PHP和JSP的代码。 公司买来以后就强制性行推广,但在硬推了两个月以后,发现推不动,只好放弃了。 最主要的原因是因为它没有办法处理我们特有的一些逻辑,加上每一个部门有自己独立的规范和周边库,在那个工具里边没法用上。之后很长的时间里,我们整个部门的人都对代码生成器非常反感。 但是后来还是经不住偷懒的诱惑,我自己一直在偷偷地不断尝试。渐渐地发现,其实要做一套全世界通用的代码生成系统可能会特别难;但是如果只是给自己做一个专用的代码生成工具却非常简单,只要遵循以下两个原则。 只为自己设计 第一个原则是「只为自己设计」。 因为每一个公司,每一个部门甚至每一个岗位它所面临的需求是千差万别的,很难通过一个通用工具来解决,所以我们也很难买到为自己量身定制的工具。 但如果自己来开发工具的话,就完全不同了。我们可以完全按照自己的工作流程、按照每天写代码的需求来进行设计。我们非常清楚写代码的时候,元数据是存放到什么地方的、通过什么样的方式进行加工、以及最终要生成怎样的代码。所以可以开发出非常好用的自用代码生成工具。 能自动化的自动化,不能自动化的半自动化 第二个原则是「能自动化的自动化,不能自动化的半自动化」,后半句特别重要。 很多程序员在设计代码生成工具的时候,往往太过完美主义,老想着要做一个系统把所有的工作都做完,最好点一下按钮后,什么事情都不用去做了。 这当然是最理想的方式,但是我们的开发环境和其他的办公软件之间不一定存在交互接口,很多软件只有图形界面,不支持通过 API 进行数据交换。所以,很多时候我们就没法做成全自动。完美主义或者叫强迫症的同学就会说,既然这个东西不能完全自动化,那就直接手动来处理吧。 但我们开发代码生成器的根本目标并不是要做一个完整的自动化产品,而是要提升我们的生产效率。所以,即使有一些地方不能做到完全的自动化,我们也可以把它做成半自动化。 半自动化有两个思路。第一个思路是,我们可以通过交互方式来解决一些不能自动化,或者需要花很多时间去处理的细节问题。 举一个例子,这个例子发生的年代比较久远,现在可能已经不适用了。 我们当初在做网站的时候,有很多的资料都是编辑给的。那个年代还没有产品经理,都是由网站编辑给我们资料。他们都使用 office 软件来存放数据。 当时是没有比较好的 office 格式解析包的,所以很多同学都放弃了数据的解析,改为手工输入。我给了一个解决方案,就是直接在 office 里复制数据表格,然后再粘贴到一个 textarea 里,最后用 PHP 分析 tab 和换行符号,把数据分离出来。为了防止分析错误,还做了一个界面来进行确认和手动修正。虽然没能实现全自动,但是比起手工输入数据,这个方案效率的提升是几十倍的。所以不要过分纠结于全自动化,有的解决方案不完美,但也可以很精彩。 另外一个思路是,只对小操作做自动化,用来生成代码片段。比如说,我们在写输入处理的时候,往往需要根据数据表字段来对输入进行验证,这往往是一个重复劳动。所以,我就写了一个命令行的小工具,它可以直接读取数据表里边的字段和对应的注释,根据注释里的标记来判断对应的字段的验证信息,最后会自动生成验证部分的代码。我把这些代码粘贴到编辑器后,再进行相应的修改,就可以很快的完成验证工作。这没有什么技术含量,但是它可以切实提高我们的生产效率。 这些只是我想到的思路,当然还有很多其他的。比如有的同学是通过工具链,通过命令行交互,来实现自动化。 人工智能 代码模板呢,只能解决相对比较死板的规则。但最近随着人工智能的进步,在某些特定的场景下,原来很多低效率的人工操作其实可以交给 AI 了。 现在,AI 的正确率确实达不到和人类同等水平。但是,还是前边那句话,「不能完全自动化的,可以考虑做成半自动化」。针对 AI 正确率不高的场景,我们可以通过人机结合的方式来处理。 比如说,我们要进行图片分类,之前可能需要花上十几个小时的人工。现在使用 AI 进行分类,只需要十几秒。但是它可能有20%的图片分类是错的。 我们就可以先让 AI 来进行分类,然后再人工确认一遍。确认花的时间可能是两个小时,但即使这样,比起之前的十个小时来讲,效率也提升到了五倍。 最近很多人工智能接口的品质已经不错了。比如说,熟悉我微博的同学都知道,我经常会用语音的合成和识别服务来提升内容生产效率。 比如我经常会发一些技术视频,但是又不想自己录音,于是就会使用人工智能来生成语音。而大家正在看的这本书里,至少有一半的内容我是通过语音识别APP,以每分钟100多字的速度记录下来,然后再二次进行修改、校正完成的。 所以不管你对 AI 有什么看法,它现在已经在实实在在地改变着我们的生活。我们要思考的是,如何更好地利用它。 如果服务足够可靠,我们就可以做成自动化服务,直接提供给最终用户;如果服务还不够可靠,我们可以把它放到中间流程里来提升效率。 比如,同样是代码生成技术,如果我们把它做成面向不懂技术的人群的产品,服务不是很可靠的话,最终效果就会很惨;但同样品质的接口,如果我们把它做成面向开发者的服务,而且是在编辑器里面实时地进行代码补全和建议的工具,它就会显得非常好用,可以极大地提升生产效率。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 自动化","id":"41","title":"自动化"},"42":{"body":"前面我们讲了时间片的优化,敏锐的同学可能已经感受到了,时间片的限制其实是有办法突破的。下边我们就专门来讲一下怎么突破时间片限制。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 突破时间片限制","id":"42","title":"突破时间片限制"},"43":{"body":"第一个思路叫「倍增」,就是让时间片的数量成倍的增加。但这里有一个前提,就是不能过多的增加我们的精力消耗和风险。 因为不考虑这个前提的时间片倍增非常容易,只需要增加雇员就可以了。但我们随时都要提醒自己,这是在做副业。 如果我们雇用全职人员,就需要有办公场地、还需要到现场进行人员管理。这对于有正职工作的同学来说,是很难分身的。除非你把办公场地放到正职工作的公司附近,用空闲时间去管理。但这依然有精力上的风险,搞不好既没做好副业,又影响了正职工作,这就本末倒置了。 既然雇用全职的路子走不通,我们就只能考虑雇用兼职。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 倍增","id":"43","title":"倍增"},"44":{"body":"主要的方式就是将部分业务外包。前边我们其实刚聊过外包,只不过在这里,我们从接单方变成了发包方。 外包的方式,可以将大块的业务交给别人去做,自己只需要花少量的时间片来做沟通和管理。等于接单方的时间片也为我们所用了,所以整体来看,时间片是倍增了。 外包还会带来一些潜在的风险。 我们的时间片是倍增了,但我们的成本也在成倍地增加,也就是说本身我们的项目需要有足够的利润空间才适合使用这种方式。如果控制不好,很可能最后整个项目做下来不挣钱甚至亏本。 另外,外包方式下,沟通和项目管理也是比较大的挑战。因为它不是那种每天在一起的沟通环境、也不是直接的上下级关系。只能以合同的形式来进行约束,很多时候甚至连合同都没有。这种情况下,其中某些环节出现问题,我们就需要为整个项目承担风险。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 外包","id":"44","title":"外包"},"45":{"body":"其实还存在其他的雇用兼职的方式,比如众包。众包和外包类似,但粒度更细,接单方更多,甚至我们都不知道接单方是谁。 一个典型的例子是 Facebook 的多语言翻译工作,他们提供了一个在线翻译工具,让懂该语言的用户每人来翻译几句,因为用户数量庞大,很快就能完成整个翻译工作。 众包的收益非常不错,一方面是成本上的,因为接单方多,所以会产生竞价。如果分摊的工作量非常小,甚至可以是免费的。另一方面是时间上的,同样因为接单方多,完成的速度会非常惊人。 不过,为了支持大量的接单方,我们的业务结构需要进行相应的调整。 比如说,通常我们可以把一个系统分成平台部分和扩展部分。平台部分,我们可以自己制作;扩展部分就可以把它设计成插件、扩展、中间件,将这些东西以众包的方式分出去。即使其中的组件出问题,对我们核心平台的影响也是小的。 这样对接单方来讲还有一个突出的好处,就是这种组件本身的逻辑和它的相关资源是闭合的,只需要知道输入输出,内部实现完全可以自己决定。组件开发者之间也不需要沟通,只需要跟平台以文档、API的形式来进行沟通,在使用细节上以工单的方式来进行反馈就可以了。这可以大幅度降低我们的管理成本。更进一步,我们可以开发工具来对众包进行支持,进一步提高效率。 所以,如果能培养起好的众包生态,我们是可以实现低投入的时间片倍增的。对于不想开公司、对时间片又需求大的业务来说,是非常值得尝试的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 众包","id":"45","title":"众包"},"46":{"body":"另外一个突破时间片限制的方式我叫它「超卖」,就是把一份时间片卖给多个人。 在很多非常个性化的业务里边,我们是为对方专门定制的服务和内容,所以一份时间片只能卖给一个人。但是,当我们业务做得足够久了之后,就会聚集起来很多有相同需求的人。 这时候我们就可以把他们的公共需求抽取出来,做一份面向这个公共需求的产品或者服务。这样的话,我们只需要花一份时间来做产品,就可以把它卖给多个人,也就间接地实现了时间片的超卖。 比较典型的例子是建站。这曾经是很多小公司赖以生存的业务。在最开始的时候呢,建站公司都是去跟客户谈,想建一个什么样的网站,然后找设计师进行界面设计,完了以后再进行开发。这种服务就是一对一的时间片售卖。 但后来很多公司发现其中重复的需求太多,于是就把建站的需求做成了一个系统。在这个系统上,客户可以自行选择模板,添加功能模块,输入内容,通过浏览器就可以很快地生成自己想要的网站。整个过程甚至不需要其他人参与。 从个性化服务到标准化服务,是实现时间片超卖的主要思路。 再举一个更明显一点的例子。熟悉我的同学都知道,网课是我一个很重要的业务。但和其他的机构不同,我从来不做直播课。所谓直播课是说,我提前准备好教学内容,等大家都上线了,然后我们在一个直播房间里边,一边讲课一边学习。相对的是录播课,是说我提前把这个内容录好,然后大家自己找时间去看视频就好了。 从讲师的角度来看呢,直播课就是一对一的时间片消耗模式,每讲一次,都要消耗一次我的时间片。而录播课则是一对多的时间片消耗模式,不管有多少学员,他们只需要去看录制好的视频就行,我付出的时间片不会增加。这也实现了时间片的超卖。 从上边的两个例子可以看出,时间片的超卖背后,实际上是商业模式的调整。 最理想的情况下,我们只需要付出一份时间片,然后即使我们什么都不做,它都可以持续不断地进行售卖。不管我们是在吃饭睡觉、看电影逛街、还是在旅行休假,这个产品都会持续不断地给我们带来收入。这种收入我们称为被动收入,能带来被动收入的东西,我们叫它资产。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 超卖","id":"46","title":"超卖"},"47":{"body":"","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产和被动收入","id":"47","title":"资产和被动收入"},"48":{"body":"资产的定义见仁见智了,我比较习惯用罗伯特·清崎在《穷爸爸富爸爸》里的定义,那就是「 能把钱放进你口袋的东西 」就是资产。换句话说,能产生 被动收入 的东西,其实就是资产。 《穷爸爸富爸爸》这本书很多人都读过,罗伯特·清崎后来还写了一个系列,核心是富人不为钱工作,而是 让钱为自己工作 。 在书里边,主要通过「购买」的方式来获得资产。这里是书中列出来的资产类型: 股票 债券 能够产生收入的房地产 票据(借据) 版税,如音乐、手稿、专利 其他任何有价值、可产生收入或者增值潜力且有很好销路的东西 这个系列后来就跑去教人投资和理财了。 其实投资也可以视为一种副业。优点很多,比如占用精力相对较少、没有收入天花板等;但也有两个明显的缺点。 最主要的缺点是风险高,且不易评估。还有一个缺点是, 投资你得先有资 、 理财你得先有财 。在风险可控的范围内,大部分投资理财的回报率差异不会特别大。如果你手上一百万都不到,可能折腾一年、背着挺大的风险也就是多挣了几万块钱。 投资理财是一门深奥的学问,我们不在本书中展开,大家可以阅读相关的专门书籍。 在罗伯特的资产清单中,还有一个可以无成本获得类别 —— 版税。但其实在中国因为书卖得特别便宜,而版权又普遍不受重视,一些大公司都堂而皇之地侵权,其实很难获得高收益。 如果没有初步的积累、或者不想背负过大的风险,怎样才能获得资产?","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 什么是资产 » 什么是资产","id":"48","title":"什么是资产"},"49":{"body":"资产最简单粗暴的获得方式当然是通过购买。但好的资产未必人家愿意卖,当然更可能的是,我们未必买得起。 但是除了购买,其实还有一个逐渐被遗忘的方式 —— 直接「创造资产」。对于很多传统行业的人来说,创造资产会大量的消耗精力,最后成本可能并不会比购买资产低多少。 但现在软件吞噬了世界,数字化业务已经茁壮成长,数字资产的生产资料日益廉价。而我们是程序员,正是那个可以通过自己的技能栈低成本、低风险的创造数字资产的群体。 并不是每个人都有我们这么幸运,其实大部分的程序员,离完整地做出一个商业产品,缺的可能只是一点美感和设计能力。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的获得方式 » 资产的获得方式","id":"49","title":"资产的获得方式"},"5":{"body":"S象限是自雇象限,自己挣钱自己花,一般不雇用别人。比如做独立开发、组建工作室做外包和建站,甚至也可能做一些和编程没有关系的事情。 S象限最大的优点是,自己的业务自己做主,挣的钱也都是自己的。一个三五十万的外包做下来,一年的基本生活保障就有了。 S象限的缺点是,收益未必能比E象限多多少,而风险却高很多。光靠单纯的编程技能往往搞不定,还需要把接活拉活的能力、协调沟通的能力都培养起来。这些能力往往在程序员的舒适区外,需要花精力和时间去培养。因为收入是业务驱动的,所以行业的风险也会直接转嫁到我们这里。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » S象限(自雇象限)、为自己挣钱","id":"5","title":"S象限(自雇象限)、为自己挣钱"},"50":{"body":"当然,并不是所有的数字资产都适合我们以副业的方式去创造。不过就像前面不断重复的,副业是一个资源和精力都非常缺乏的状态,我们也只能从庞大的可能性中,选择那些适合的产品和服务。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 资产的量化评估","id":"50","title":"资产的量化评估"},"51":{"body":"说到底有哪些产品和服务适合副业呢?下边是我觉得值得留意的几个特征。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 适合副业的几个特征","id":"51","title":"适合副业的几个特征"},"52":{"body":"首先是「 自传播 」,就是说这个东西做出来了以后,它本身有很强的感染力,它的用户会主动地去推荐给其他用户,这样的话我们就不用花很大的成本去做营销。 对于大部分程序员来讲,把程序写出来只是时间和精力问题。写不出来程序的程序员很少,但卖不出去程序的程序员非常多。所以,如果我们做的东西本身就能传播,那么我们就可以在零市场预算的情况下获得成长。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 自传播","id":"52","title":"自传播"},"53":{"body":"第二类叫做「 UGC 」,用户贡献内容,它其实可以理解为一种更广意义上的众包。核心也是突破时间片限制。比如说我现在经营一个原创博客,天天都是自己写,就会觉得自己累得都不行了。 但如果我们去做一个访谈类的博客,弄一个相对固定的问题列表,然后拿着这个列表去采访各行各业的人,把结果做成一期一期的内容。这样用户就贡献了至少一半的内容了。 如果我们再改成办一个杂志,每一期大家根据主题投稿,你就从主创变身成编辑了。虽然投稿里有好有坏,良莠不齐,但我们的主要任务已经变成去筛选了,只要贡献内容的用户足够的多,那整体质量还是有保证的。最主要是内容的量就上来了。一个人的话,不管你多么努力,总是有一个上限的,因为你毕竟是人类。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » UGC","id":"53","title":"UGC"},"54":{"body":"「 自动化 」前边有提过。 就是说应用做起来以后,它所有的环节全部都可以由机器完成,我们什么都不用管,只需要把它扔到云平台上,然后定期给云平台打钱。当然这是一个理想的情况,意外总是会出现的,而且各种意外会约好在同一天出来逛街,别问我为啥知道。但是在绝大部分情况下,我们都可以不去管它,它都可以自动化运行。这种被动资产是非常适合副业来做的。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 自动化","id":"54","title":"自动化"},"55":{"body":"我们也可以更为量化地给资产定一个评估标准,确定好要考察的几个方面,每个方面做一个满分为5分的评分,对每一项评分就可以得到一个多边形,从而一目了然的看到各类资产的状况。 这个标准每个人的想法可能不同,这里分享的是我自己用得比较多的标准。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 量化评估标准","id":"55","title":"量化评估标准"},"56":{"body":"项目的一般投入都是三项:「人」、「钱」、「时间」。 「人」和「时间」不多说,通常就是我们自己和挤出来的那点时间了。 「钱」方面,我们也需要一点启动资金,但 不用花大钱去购买各种固定资产。这也是我们这个行业能自己动手创造资产的一个重要原因 。尤其是现在,云计算已经普及了。即使是很大访问量的网站,我们直接租用云服务,按用量付费,省钱又省心。我大学刚毕业的时候,要是做大点的网站,还要自己去买服务器,自己扛去机房托管。现在只需要点点鼠标就能买到一堆 vps ,其实是蛮幸福的。 要提醒大家的是,一定不要忘记维护成本。我们卖时间片的时候,活干完就完了,钱就拿到手了。 但是在自己创造资产的时候,资产的每个细节基本都得自己来 cover 的,所以 维护成本一定要算进去 。 维护成本往往不是那么显而易见。比如说吧,网课也是有维护成本的,尤其是技术类的,它的更新成本其实相当高。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 投入","id":"56","title":"投入"},"57":{"body":"在评估产出的时候,可以分为「一次性的回报」和「周期性的回报」。 一次性回报,比如我们给人家做技术顾问。可能就是在周三拿到一个邮件介绍说是什么样的一个需求,有什么问题要解答。我们花上2~3个小时来准备,在周末约一个时间,面谈一个小时,把之前准备的内容聊清楚,聊完了以后,回报就拿到手了。这就是一次性回报。 周期性回报,比如说我们在 掘金 上写了一个小册,那只要有人在购买,我们就会不停的有收益,这种收入一般按月结,所以每次看起来没多少,但加起来还是挺多的。我之前算了一下,发现 在我创造的各种资产中,掘金小册的投入产出比是最高的 。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 产出","id":"57","title":"产出"},"58":{"body":"持续性是以前忽略掉的评分项,后来被我追加上来。这其实是一个非常浅显的道理, 一个资产放在那个地方,它不可能一直就持续地挣钱 。就像电池光用不充电的话,总会有用光的一天(别和我提太阳能电池)。 这是因为我们创造这个资产的时候,它是面对一个市场需求的,而需求本身它会随时间变动。绝大部分的情况下,需求和我们提供的解决方案之间的契合度,会随着时间越来越差。最后就会变成,要么我们就不去管它,让它慢慢地随着时间去消亡;要么我们又要花成本去维护它,把它从偏差的地方给拉回来,重新覆盖到需求上面。把用户的满意度、用户的体验、市场的趋势给重新考虑进去,让我们资产的生命期变得更长。 对于不同的资产,只是过程的快慢会不一样,但整体来讲,都是会有这么一个过程的。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 可持续性","id":"58","title":"可持续性"},"59":{"body":"程序员创造产品最大的风险是「 没人用 」,因为虽然大部分科班出身的程序员都学过需求分析,但仍然各种喜欢拿着锤子找钉子。 当然,这对于没有做过独立开发或者自己产品的同学来讲,是一个必经的阶段。所以早期项目的风险都会非常高,但并不是说风险高我们就不做了,我们可以相对的调低投入,原来要投入三个月上线的产品,可以花三天做个最小可行产品(MVP,后文会说明)上线,测试到需求以后,再继续加码。这样也能慢慢的获取到一个平衡点。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 风险","id":"59","title":"风险"},"6":{"body":"B象限是创业象限,和S象限最大的不同是我们不是自己干活,而是雇用其他人来帮我们干活挣钱。 它的优点在于,可以让我们从S象限的天花板中解脱出来,拥有规模化成长的可能性。 而缺点在于,它有一个比较大的固定成本。即使是对于轻资产的互联网公司来说,也是如此。比如人力成本。招聘、组建、培养一个团队是非常耗费时间和精力的,所以即使当业务不好的时候,我们还是需要支付大量的工资来维持团队,以便之后能快速恢复业务。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » B象限(创业象限)、让雇员挣钱","id":"6","title":"B象限(创业象限)、让雇员挣钱"},"60":{"body":"最后我加了一个评估标准叫做门槛。因为「副业」的关系,我们的各项资源都是受限的,这个评估标准体现了受限情况下创造资产的难度。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 门槛","id":"60","title":"门槛"},"61":{"body":"在这一部分,我们整理了大量的副业,并从中拿出适合程序员的来进行评估和讨论。","breadcrumbs":"优选资产 » 优选资产","id":"61","title":"优选资产"},"62":{"body":"","breadcrumbs":"优选资产 » 知识和人脉的变现 » 知识和人脉的变现","id":"62","title":"知识和人脉的变现"},"63":{"body":"picture 2 总体来讲,付费视频课是一个中等投入,然后产出极高的副业。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 付费视频课","id":"63","title":"付费视频课"},"64":{"body":"前期需要做一些课程内容的准备;后期你需要对视频进行剪辑;录音还需要购买硬件。大部分的程序员并没有视频剪辑技能,所以这里有学习成本。硬件的话倒不算贵,便宜点的不到一千就能搞定。但是这是在我们赚到钱之前就要投入进去的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低投入 ★","id":"64","title":"低投入 ★"},"65":{"body":"从产出上来讲,课程是一个非常好的品类。中国人有良好的为教育花钱的传统,大部分的用户都愿意为好的课程花钱。一些优质的、上百节的大课可以卖到几千甚至几万。相比其他的副业,它的产出是非常高的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 高产出 ★★★★★","id":"65","title":"高产出 ★★★★★"},"66":{"body":"我们是做技术类的课程。技术内容本身的变更是非常快的,除非我们做一些非常经典的基础课,比如说计算机原理、算法等等。 如果是跟语言、框架、实战相关的各种前沿课程,大概半年到一年就需要更新一次。如果我们使用屏幕录制方式来制作课程,在修改的时候,很可能需要重录相当部分,修改起来成本很高。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 可持续性 ★★","id":"66","title":"可持续性 ★★"},"67":{"body":"风险不低。如果做的课程比较长,比如几十上百集的大课,用业余时间来做可能会花上几个月甚至一两年,有时候做完技术都更新了。如果最终卖不出去的话,损失是很大的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低风险 ★★","id":"67","title":"低风险 ★★"},"68":{"body":"门槛不算高也不算低。如果经常在公司里面给团队做分享的话,那对你来讲这个门槛就很低。如果一直都是默默无闻地在做技术的话,可能就需要去练习一下怎么讲课。 因为我们最终是可以通过剪辑来进行调整的,所以也只是一个时间投入上的问题。讲得不好,你就多讲几遍;哪一句讲错了,就重新再讲。所以它本身的硬性门槛并不高。 关于风险和维护成本这两点,其实是有办法可以解决的,我们会在后续用专门的章节来讨论,这里就不展开了。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低门槛 ★★★","id":"68","title":"低门槛 ★★★"},"69":{"body":"picture 3 付费专栏就是付费的系列文章,绝大部分是技术教程,也有一些面向程序员的「心灵鸡汤」。我们可以简单地把它看成是传统出版的网络化。 对于技术内容来说,传统的纸书出版方式有一些明显的缺点。比如,不是彩页的话代码不能高亮,彩页的话书又特别贵。书里的代码也不能边看边调试。纸书的出品周期也较长,更新也慢,一些最新的技术会有一个较长的空白期。 而在线的付费专栏恰恰可以解决掉这些问题:它基于浏览器,自然可以通过 JS 来进行代码高亮;内容可以在线修改,几乎可以实时生效;做得细的技术专栏往往还内嵌了基于浏览器的调试环境,可以做到边学边练。 再加上原来技术博客的群众基础很好,于是技术平台和社区纷纷添加了付费专栏功能。这其中,做得比较好的应该算掘金的 小册 。 picture 6 下面我们来看一下付费专栏作为副业资产的各项评分。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 付费专栏","id":"69","title":"付费专栏"},"7":{"body":"I象限是投资象限,是在我们有了一定的资本之后的一种让钱挣钱的方式。在B象限里,我们需要创办企业来挣钱,这需要大量的精力。即使你的精力异常充沛,同时运营三五家公司也就到上限了。I象限让我们以投资的方式参与到大量的公司中去,共享这些公司的增长,从而实现资产的增值。 在了解了四大象限以后,我们可以发现,如果赶不上公司上市这种可遇不可求的事情、或者能一路升迁做到大公司高层,先不说财务自由,光是要想在北上深买房安家,只留在E象限都是非常困难的 —— 我们必须向其他象限发展。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » I象限(投资象限)、让钱挣钱","id":"7","title":"I象限(投资象限)、让钱挣钱"},"70":{"body":"从投入上来讲,文字专栏比视频课程投入要低很多。但是技术内容比起其他文章的写作来讲,需要有技术实践作为基础,经常还要嵌入代码,调整格式,投入相对要高些。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低投入 ★★★","id":"70","title":"低投入 ★★★"},"71":{"body":"文字专栏的售价普遍比视频课程要低,像掘金小册的话,一般就在20~30块钱之间,还经常打折促销。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 高产出 ★★★","id":"71","title":"高产出 ★★★"},"72":{"body":"前面已经说过,技术内容一般更新频次高。但是图文专栏的更新成本很低,只需要编辑文字、加入新的内容就好,不需要像视频那样重新录制和剪辑。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 可持续性 ★★★","id":"72","title":"可持续性 ★★★"},"73":{"body":"文章的创作成本很低,而且我们可以通过发布短文来测试主题是否受欢迎,在确认后再开始系列文章的书写。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低风险 ★★★★","id":"73","title":"低风险 ★★★★"},"74":{"body":"只要会写文章,就可以做付费专栏。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低门槛 ★★★★★","id":"74","title":"低门槛 ★★★★★"},"75":{"body":"picture 4 所谓付费社群就是指一些收费的微信群,QQ群或者付费可见的信息流、圈子类产品。 之所以把付费社群单独拿出来讲,是因为它更偏重于销售的不是内容本身,而是一种人脉关系、社区氛围或者互动型的服务。 像付费课程,通常是类似于出版。我提供内容,你来进行学习。通过文章评论和回复进行互动,时效性和效率比较低。 而在付费社群里边,大家互动起来会比较方便。比如在群里,你一句我一语很快就可以讨论起来。所以,付费课程和付费社群其实是有互补关系的两个产品。 我们可以把付费课程放到课程平台,然后把实时的学员答疑或者其他服务,再做成付费社群。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 付费社群","id":"75","title":"付费社群"},"76":{"body":"付费社群的投入是非常低的。如果我们要做课程的话,需要累积相当多的内容。但是付费社群它卖的不是内容本身,所以即使它没有内容,也可以立刻进行销售。 而且因为社群的互动环境在形式上比较随意,有个什么想法随时发一段文字或者几张照片都可以,内容创作的成本很低。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低投入 ★★★★","id":"76","title":"低投入 ★★★★"},"77":{"body":"产出方面就要看具体销售的是什么东西。氛围和讨论环境本身,通常不会特别值钱。但是如果能利用起来,价值就会非常高。比如用付费社群来做中高端猎头服务。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 高产出 ★★★","id":"77","title":"高产出 ★★★"},"78":{"body":"需要持续不断的有内容更新。当然也可以引导其他用户贡献内容。如果一段时间没有内容和话题,就很难维持社群的活跃,氛围会随着时间慢慢变冷,严重影响第二年的续费。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 可持续性 ★","id":"78","title":"可持续性 ★"},"79":{"body":"没什么特别的风险。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低风险 ★★★★★","id":"79","title":"低风险 ★★★★★"},"8":{"body":"然而在没有副业的情况下,我们的职业就是单进程、只能做单选题。 我们在象限之间的移动,往往只能是突发式的。前一天还在E象限做雇员,第二天突然就辞职创业或者做外包去了。然而贸然进入一个新象限,将面临非常大的风险。因为每一个象限,它背后的商业模式是不同的,对人的能力、思维、精力的要求也都完全不一样。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » 没有副业的职业","id":"8","title":"没有副业的职业"},"80":{"body":"会建群会聊天就可以开始。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低门槛 ★★★★★","id":"80","title":"低门槛 ★★★★★"},"81":{"body":"picture 5 如果把电子书也算进来,目前可以分发图书的方式大概有三类。 第一类是自己独立撰写图书,并生成 PDF 等电子书格式通过自己的渠道进行销售。这种更类似于数字商品售卖,所以并不包含在本节图书出版中。 第二类是通过出版商单独发行电子版。因为电子书不需要印刷,所以比起纸版图书门槛更低一些。我之前用 BookDNA 出版过电子书,只需要将书提交给他们,就可以上架到亚马逊、苹果、京东、多看等多个平台。收入他们会代收,按分成结算回来。 第三类就是通过出版社出纸书,有时候也会同时把电子书版权签下来。一般纸版的门槛会高一些,需要有一定的影响力或者完成度已经较高的书稿作为参考。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 图书出版","id":"81","title":"图书出版"},"82":{"body":"图书出版的投入非常大。一般至少需要花费3到6个月来编写初稿,加上审校印刷等环节,最后出版可能还需要花上半年,整个周期很长。 基于现有的内容,比如课程、文章整理创作书稿投入会相对较低,但仍有大量的工作要做。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低投入 ★","id":"82","title":"低投入 ★"},"83":{"body":"产出要把物质回报和非物质回报分开来看。 通过 BookDNA 等出版社专门出版电子书,可以按图书销售收入获得分成,大概在 70% ,还算不错。如果是纸版书,一般版税就只有 8%~15%,整体收入相当有限。 但纸版书对个人品牌提升的效果明显,而且可以通过线下书店等渠道获得读者,所以在非物质回报上比较高。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 高产出 ★★★","id":"83","title":"高产出 ★★★"},"84":{"body":"图书的更新频次都很低,一般只有销售得不错,才会在再版时进行修订。所以我们可以认为它的可持续性还算不错。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 可持续性 ★★★★","id":"84","title":"可持续性 ★★★★"},"85":{"body":"主要还是时间投入,没有太多额外的风险。因为我们主要是出版技术书籍,内容方面的风险也非常小。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低风险 ★★★★","id":"85","title":"低风险 ★★★★"},"86":{"body":"不管是电子版还是纸版,都要经过图书编辑审核,通过以后才能出版。尤其是纸书,要考虑至少收回印刷成本,所以门槛还是很高的。 如果在 GitHub 或者其他地方有发布电子书,且有较好的反馈,那么纸版的出版谈起来门槛就会低很多。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低门槛 ★","id":"86","title":"低门槛 ★"},"87":{"body":"那接下来我们就来聊聊程序员的专业领域 —— 通过开发自有的产品和服务、作为 side project 运营来变现。","breadcrumbs":"优选资产 » 自有产品和服务 » 自有产品和服务","id":"87","title":"自有产品和服务"},"88":{"body":"首先要说的是很多同学都很困扰的问题。 我以前以为最困扰的问题应该是如何抽出时间和精力来做一个项目,但后来发现还有一个同样甚至更为困扰大家的问题,那就是有了时间以后,不知道做什么。 通常来讲,解决方案有两种。 一种是通过日常的工作和生活发现原生需求;另一种是通过观察分析和阅读报告来发现。","breadcrumbs":"优选资产 » 自有产品和服务 » 需求的发现","id":"88","title":"需求的发现"},"89":{"body":"最靠谱的方式就是,留意那些我们自己在日常的生活和工作中遇到的困扰,然后为它去做解决方案,最后把这个解决方案做成产品,出售给有同样需求的人。 这种需求叫做原生需求,不是我们因为有了某个技术而幻想出来的应用场景。原生需求不是等我我们去寻找,而是它会主动找到我们。这种需求非常真实可靠。 但有一个问题,我们程序员相对于整个大众来讲,其实是一个非常小众的人群。这个人群有一些独特的文化、行为和思考方式。所以程序员遇到的原生需求,很可能只适合程序员人群,而不适合其他更为大众的市场。这就让它的目标市场比较小。 而程序员又是一个动手能力非常强、开源文化深入骨髓的群体,绝大部分的解决方案都能找到开源项目,或者改几行代码就能实现了。一些大公司还时不时的开源一堆非常强悍的工具,所以面向这个群体的免费或开源工具很受欢迎,但收费工具却是非常难做的。 反而是如果你在非专业领域有一些更为大众的兴趣爱好,从那些方面来发现需求的话,难度就会下降很多。 需求的验证 另外要重复强调的就是,需求的验证不能以口头承诺甚至免费用户来验。做需求分析的时候你去问,很多都会说我觉得这个东西挺好的。但你让他们付钱的时候情况就完全不同了。 大家可以回想下自己在过去一年里边,为哪些软件或服务支付超过 100 元人民币。我之前发过一篇微博问我的粉丝(大部分是程序员),后来发现绝大部分都是一些资源型的服务,比如视频会员、云主机、网课、网盘;软件就非常少了。所以我们还是要尽可能的从更广泛的人群里去发掘更值钱的需求来做。 降低起始难度 上边并不是说程序员人群的需求不能做,而是说难度比较高。 作为副业,我们投入的精力是有限的,如果一上来就是玩 Hard 模式,失败的概率会非常高。如果经常失败的话,最后就变成一种习惯了,渐渐的,也就会不再想去做副业,甚至连创业的冲动也跟着没有了,这就非常可惜。","breadcrumbs":"优选资产 » 自有产品和服务 » 原生需求","id":"89","title":"原生需求"},"9":{"body":"先来说说「辞职创业」。 媒体很喜欢把创业宣传得一蹴而就,仿佛只要有一个独特的想法,就可以一夜暴富、咸鱼翻身。 程序员群体的理想主义趋向又比较明显,加上有无数包装出来的成功案例,所以这是程序员从E象限移动到B象限最常见的途径。 有激进派的,拿着自己的一点积蓄就英勇地加入的创业的队伍;有稳健点的,在搞定了天使投资以后再离职的。 但创业的光环在市场的面前毫无用处,要找到一个真正有商业价值的需求非常困难,往往要花很长的时间试错。而后,还要针对这个需求做出比现有方案至少好十倍的新方案。同时,还有大量公司管理、人力招聘、融资沟通方面的事务,这些都会让创业新手难以招架。 不少程序员朋友找我聊他们的创业想法,我发现他们真的只有想法 —— 完全没有进行过验证,他们并不了解B象限的生存法则。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » E→B,辞职创业","id":"9","title":"E→B,辞职创业"},"90":{"body":"另一个路径是观察分析那些已经在挣钱的应用,阅读它的用户评论,发现可以改良的点,制作更好的产品。这个工作量还是很大的,所以也可以考虑直接购买一些分析报告。 这里的分析报告不是那种行业的通用报告,那是针对创业公司和大公司的,需要投入很多资源,以爆发式增长的方式去推动,并不适合副业。 最近在国外开始有一些专门针对副业和 Side project 的分析报告。他们收集整个市场的信息,然后针对大致一亿美金以下的细分市场做趋势分析。这种市场一般冲着上市去的创业公司看不上,所以留下了比较大的市场空间。 我最近读过报告的有两家,一家是 Trends.vc,另一家是 SoftwareIdeas.io。不过这两家本身也是初创或副业业务,不知道各位读到这本书的时候是否还在运营。这里最主要的还是给大家提供一种思路。 我们在做副业的时候,也需要慢慢来改变我们的一些习惯。比如说对于程序员来讲,绝大部分的东西都是可以自力更生的。所有能自己做的就自己做,不能自己做的,我们会找开源项目。这样我们会更有安全感,做的事情也会更加靠谱。但是我们在做商业的时候,尤其是在做副业的时候,遇到的问题就在于我们的精力是非常有限的,在价格适中、又有购买能力的情况下,更好的方式是通过购买而不是自己开发。","breadcrumbs":"优选资产 » 自有产品和服务 » 观察分析和阅读报告","id":"90","title":"观察分析和阅读报告"},"91":{"body":"picture 5 对于我们绝大部分程序员来讲,开发是自己的本职工作,所以都比较擅长。但是在做副业的时候,我们还不可避免地需要把自己的软件卖出去。而销售往往是我们的弱项,有没有一个办法让我们可以避免它呢? 答案就是应用商店。早期的应用商店是一个非常好的入口,它会分门别类的将软件陈列在上面,有需求的用户会通过分类浏览或者搜索查询的方式来安装或者购买。 但经过一段时间的发展,应用商店里边的软件已经越来越多,各种需求被满足得也越来越充分。 现在大部分的应用商店已经是红海市场,也就意味着说,即使你在应用商店上架了软件,也不等于其他的用户有机会看见它,因为软件实在是太太太多了。 所以,我们需要想办法在应用市场的应用海洋中获取流量。一般来讲免费获得流量的途径有两个。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 应用市场卖 APP","id":"91","title":"应用市场卖 APP"},"92":{"body":"一个是通过关键字搜索。一般应用商店都会有搜索入口,用户输入关键字,商店则会列出匹配的应用列表。如果我们指定的关键字被搜得更多,那就更容易覆盖到更多的人群。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 关键字搜索","id":"92","title":"关键字搜索"},"93":{"body":"另外一个途径是编辑推荐。一些看起来有创意、格调比较高的APP更容易被推荐。而同样功能但是界面不好看的应用,则很难被推荐。所以界面设计不光是用户体验的问题,甚至还直接影响我们的获客。 虽然现在应用市场很多,但是有强用户付费习惯的国内市场,其实也就是苹果商店,所以我们如果以挣钱为主要目标的话,就应该优先考虑苹果商店这个市场。Google 在国内没有商店业务,如果是面向全球市场的业务,可以上 Google Play。 下边来看看评分项。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 编辑推荐","id":"93","title":"编辑推荐"},"94":{"body":"从投入上来说,如果你本身不是 iOS 开发者,又没有苹果电脑,那么可能需要为 iOS APP 开发购买一些硬件,同时苹果开发者还有一个至少 699 的开发者年费。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低投入 ★★★","id":"94","title":"低投入 ★★★"},"95":{"body":"一旦进入市场某个分类排行前列,可以获得的流量还是很多的。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 高产出 ★★★★","id":"95","title":"高产出 ★★★★"},"96":{"body":"需要跟上操作系统的更新升级。应用市场会定期下架一些 SDK 版本过低的APP。大部分时候只重新编译就好了,但如果使用的一些库出现了兼容性问题,那么就需要有大量的维护工作了。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 可持续性 ★★★","id":"96","title":"可持续性 ★★★"},"97":{"body":"软件应用商店托管,数据同步可以用 iCloud 等,没什么特别风险。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低风险 ★★★★","id":"97","title":"低风险 ★★★★"},"98":{"body":"对移动客户端的开发者来讲,基本上没有门槛。其他开发者要进入这个市场,需要学习移动开发技能。当然也有桌面应用市场,但数据比移动市场差很多。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低门槛 ★★★","id":"98","title":"低门槛 ★★★"},"99":{"body":"","breadcrumbs":"精益副业 » 精益副业","id":"99","title":"精益副业"}},"length":252,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{"0":{"df":1,"docs":{"15":{"tf":1.0}}},"df":5,"docs":{"162":{"tf":1.0},"201":{"tf":1.0},"202":{"tf":1.0},"231":{"tf":1.0},"236":{"tf":1.0}}},"1":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.7320508075688772}},"万":{"df":0,"docs":{},"左":{"df":0,"docs":{},"右":{"df":0,"docs":{},"的":{"df":0,"docs":{},"人":{"df":0,"docs":{},"民":{"df":0,"docs":{},"币":{"df":0,"docs":{},"基":{"df":0,"docs":{},"本":{"df":0,"docs":{},"上":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"够":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"1":{"0":{"0":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}},"d":{"b":{"df":1,"docs":{"228":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"121":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"89":{"tf":1.0}},",":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"想":{"df":0,"docs":{},"加":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"改":{"df":0,"docs":{},"为":{"df":0,"docs":{},"大":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":0,"docs":{},";":{"df":0,"docs":{},"想":{"df":0,"docs":{},"减":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"小":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":1,"docs":{"227":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":5,"docs":{"107":{"tf":1.0},"126":{"tf":1.0},"177":{"tf":2.23606797749979},"189":{"tf":1.0},"228":{"tf":1.0}},"x":{"df":1,"docs":{"23":{"tf":1.0}}},"万":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"。":{"df":0,"docs":{},"以":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"它":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"能":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"花":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"。":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"想":{"df":0,"docs":{},"到":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"新":{"df":0,"docs":{},"办":{"df":0,"docs":{},"法":{"df":0,"docs":{},",":{"df":0,"docs":{},"把":{"df":0,"docs":{},"效":{"df":0,"docs":{},"率":{"df":0,"docs":{},"提":{"df":0,"docs":{},"升":{"df":0,"docs":{},"了":{"1":{"0":{"df":0,"docs":{},"倍":{"df":0,"docs":{},",":{"df":0,"docs":{},"那":{"df":0,"docs":{},"么":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"才":{"df":0,"docs":{},"能":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"的":{"df":0,"docs":{},"活":{"df":0,"docs":{},",":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"1":{"0":{"df":1,"docs":{"39":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}},"1":{"df":2,"docs":{"126":{"tf":1.0},"230":{"tf":1.0}}},"2":{"df":3,"docs":{"133":{"tf":1.0},"230":{"tf":1.0},"27":{"tf":1.0}}},"3":{"df":2,"docs":{"133":{"tf":1.0},"230":{"tf":1.0}}},"4":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"5":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"6":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"7":{"df":2,"docs":{"143":{"tf":1.0},"232":{"tf":1.0}}},"8":{"df":2,"docs":{"144":{"tf":1.0},"232":{"tf":1.0}}},"9":{"df":2,"docs":{"149":{"tf":1.0},"232":{"tf":1.0}}},"df":6,"docs":{"113":{"tf":1.0},"16":{"tf":1.0},"177":{"tf":1.0},"189":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0}}},"2":{"0":{"0":{"0":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"一":{"df":0,"docs":{},"个":{"df":0,"docs":{},"月":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"是":{"8":{"0":{"0":{"0":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"1":{"4":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}},"2":{"0":{"df":0,"docs":{},"年":{"4":{"df":1,"docs":{"13":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":4,"docs":{"149":{"tf":1.0},"191":{"tf":1.0},"234":{"tf":1.0},"41":{"tf":1.0}},"~":{"3":{"0":{"df":1,"docs":{"71":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"1":{"df":2,"docs":{"152":{"tf":1.0},"236":{"tf":1.0}}},"2":{"df":2,"docs":{"153":{"tf":1.0},"237":{"tf":1.0}}},"3":{"df":2,"docs":{"154":{"tf":1.0},"237":{"tf":1.0}}},"4":{"df":3,"docs":{"157":{"tf":1.0},"189":{"tf":1.0},"238":{"tf":1.0}}},"5":{"df":2,"docs":{"159":{"tf":1.0},"251":{"tf":1.0}}},"6":{"df":3,"docs":{"140":{"tf":1.0},"159":{"tf":1.0},"240":{"tf":1.0}}},"7":{"df":2,"docs":{"159":{"tf":1.0},"241":{"tf":1.0}}},"8":{"df":2,"docs":{"160":{"tf":1.0},"242":{"tf":1.0}}},"9":{"df":1,"docs":{"160":{"tf":1.0}}},"a":{"3":{"df":0,"docs":{},"r":{"df":4,"docs":{"121":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":6,"docs":{"114":{"tf":1.0},"159":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0},"63":{"tf":1.0}},"~":{"3":{"df":1,"docs":{"57":{"tf":1.0}}},"df":0,"docs":{}}},"3":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"160":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"189":{"tf":1.4142135623730951},"243":{"tf":1.0}}},"1":{"df":2,"docs":{"160":{"tf":1.0},"244":{"tf":1.0}}},"2":{"df":2,"docs":{"161":{"tf":1.0},"246":{"tf":1.0}}},"3":{"df":1,"docs":{"161":{"tf":1.0}}},"4":{"df":1,"docs":{"161":{"tf":1.0}}},"5":{"df":2,"docs":{"10":{"tf":1.0},"162":{"tf":1.0}}},"6":{"df":1,"docs":{"162":{"tf":1.0}}},"7":{"df":1,"docs":{"162":{"tf":1.0}}},"8":{"df":1,"docs":{"163":{"tf":1.0}}},"9":{"df":1,"docs":{"169":{"tf":1.0}}},"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":3,"docs":{"116":{"tf":1.0},"224":{"tf":1.0},"69":{"tf":1.0}},"到":{"6":{"df":1,"docs":{"82":{"tf":1.0}}},"df":0,"docs":{}}},"4":{"0":{"df":2,"docs":{"118":{"tf":1.0},"169":{"tf":1.0}}},"1":{"df":1,"docs":{"170":{"tf":1.0}}},"2":{"df":1,"docs":{"176":{"tf":1.0}}},"9":{"df":1,"docs":{"191":{"tf":1.0}}},"df":3,"docs":{"117":{"tf":1.0},"224":{"tf":1.0},"75":{"tf":1.0}}},"5":{"0":{"0":{"df":1,"docs":{"189":{"tf":1.0}}},"df":2,"docs":{"123":{"tf":1.4142135623730951},"197":{"tf":1.0}}},"2":{"df":1,"docs":{"198":{"tf":1.0}}},"3":{"df":1,"docs":{"198":{"tf":1.0}}},"4":{"df":1,"docs":{"198":{"tf":1.0}}},"5":{"df":1,"docs":{"198":{"tf":1.0}}},"6":{"df":1,"docs":{"198":{"tf":1.0}}},"7":{"df":1,"docs":{"199":{"tf":1.0}}},"8":{"df":1,"docs":{"199":{"tf":1.0}}},"9":{"df":1,"docs":{"199":{"tf":1.0}}},"df":6,"docs":{"118":{"tf":1.0},"162":{"tf":1.0},"224":{"tf":1.0},"55":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}},"6":{"0":{"df":1,"docs":{"199":{"tf":1.0}}},"2":{"df":1,"docs":{"200":{"tf":1.0}}},"3":{"df":1,"docs":{"201":{"tf":1.0}}},"4":{"df":1,"docs":{"201":{"tf":1.0}}},"5":{"df":1,"docs":{"201":{"tf":1.0}}},"6":{"df":1,"docs":{"201":{"tf":1.0}}},"7":{"df":1,"docs":{"201":{"tf":1.0}}},"8":{"df":1,"docs":{"201":{"tf":1.0}}},"9":{"9":{"df":1,"docs":{"94":{"tf":1.0}}},"df":1,"docs":{"202":{"tf":1.0}}},"df":5,"docs":{"102":{"tf":1.0},"119":{"tf":1.0},"225":{"tf":1.0},"231":{"tf":1.0},"69":{"tf":1.0}}},"7":{"0":{"df":2,"docs":{"202":{"tf":1.0},"83":{"tf":1.0}}},"1":{"df":1,"docs":{"202":{"tf":1.0}}},"2":{"df":1,"docs":{"202":{"tf":1.0}}},"3":{"df":1,"docs":{"209":{"tf":1.0}}},"4":{"df":1,"docs":{"211":{"tf":1.0}}},"5":{"df":1,"docs":{"211":{"tf":1.0}}},"7":{"df":1,"docs":{"212":{"tf":1.0}}},"8":{"df":1,"docs":{"213":{"tf":1.0}}},"9":{"df":1,"docs":{"215":{"tf":1.0}}},"df":3,"docs":{"103":{"tf":1.0},"120":{"tf":1.0},"226":{"tf":1.0}},"×":{"2":{"4":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"8":{"%":{"df":0,"docs":{},"~":{"1":{"5":{"df":1,"docs":{"83":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"0":{"df":1,"docs":{"216":{"tf":1.0}}},"1":{"df":1,"docs":{"217":{"tf":1.0}}},"2":{"df":1,"docs":{"216":{"tf":1.0}}},"3":{"df":1,"docs":{"216":{"tf":1.0}}},"4":{"df":1,"docs":{"216":{"tf":1.0}}},"5":{"df":2,"docs":{"221":{"tf":1.0},"27":{"tf":1.0}}},"6":{"df":1,"docs":{"221":{"tf":1.0}}},"7":{"df":1,"docs":{"221":{"tf":1.0}}},"8":{"df":1,"docs":{"221":{"tf":1.0}}},"9":{"df":1,"docs":{"221":{"tf":1.0}}},"df":3,"docs":{"104":{"tf":1.0},"121":{"tf":1.0},"227":{"tf":1.0}}},"9":{"0":{"df":3,"docs":{"15":{"tf":1.0},"221":{"tf":1.0},"39":{"tf":1.0}}},"df":3,"docs":{"106":{"tf":1.0},"122":{"tf":1.0},"228":{"tf":1.0}}},"a":{"4":{"df":1,"docs":{"132":{"tf":1.0}}},"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":1,"docs":{"176":{"tf":1.0}}}}}},"b":{"c":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"一":{"df":0,"docs":{},"里":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"a":{"df":0,"docs":{},";":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"二":{"df":0,"docs":{},"中":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"b":{"c":{"df":1,"docs":{"210":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"103":{"tf":1.0}}}}}},"d":{"df":0,"docs":{},"o":{"b":{"df":4,"docs":{"157":{"tf":2.0},"158":{"tf":1.0},"223":{"tf":1.0},"228":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":1,"docs":{"156":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":2,"docs":{"133":{"tf":1.0},"41":{"tf":2.449489742783178}},"r":{"b":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"27":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"n":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"df":1,"docs":{"114":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"i":{"df":7,"docs":{"168":{"tf":1.4142135623730951},"169":{"tf":1.0},"170":{"tf":1.0},"174":{"tf":1.0},"238":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}},"p":{"df":9,"docs":{"166":{"tf":1.0},"172":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"27":{"tf":1.0},"91":{"tf":1.0},"93":{"tf":1.0},"94":{"tf":1.0},"96":{"tf":1.0}},",":{"df":0,"docs":{},"以":{"df":0,"docs":{},"每":{"df":0,"docs":{},"分":{"df":0,"docs":{},"钟":{"1":{"0":{"0":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"r":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":2,"docs":{"237":{"tf":1.0},"238":{"tf":1.0}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"159":{"tf":1.0}}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"、":{"df":0,"docs":{},"p":{"df":0,"docs":{},"h":{"df":0,"docs":{},"p":{"df":0,"docs":{},"和":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}}}}}},"u":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"228":{"tf":1.0},"230":{"tf":1.0}}}}},"df":4,"docs":{"230":{"tf":1.4142135623730951},"231":{"tf":1.0},"232":{"tf":1.0},"233":{"tf":1.0}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"160":{"tf":1.0}}}},"df":0,"docs":{}},"df":4,"docs":{"10":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.0}},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"d":{"df":0,"docs":{},"n":{"a":{"df":2,"docs":{"81":{"tf":1.0},"83":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"创":{"df":0,"docs":{},"业":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"和":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}}}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"163":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"56":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"或":{"df":0,"docs":{},"者":{"c":{"df":0,"docs":{},"m":{"d":{"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"d":{"b":{"df":1,"docs":{"231":{"tf":1.4142135623730951}}},"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":1,"docs":{"38":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"z":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"y":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"187":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":4,"docs":{"10":{"tf":1.0},"4":{"tf":2.0},"7":{"tf":1.0},"8":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.0},"9":{"tf":1.0}}},"df":2,"docs":{"10":{"tf":1.0},"12":{"tf":1.0}}},"、":{"df":0,"docs":{},"s":{"df":0,"docs":{},"、":{"b":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":1,"docs":{"3":{"tf":1.0}}}}},"df":0,"docs":{}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"移":{"df":0,"docs":{},"动":{"df":0,"docs":{},"到":{"b":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"220":{"tf":2.0},"221":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"1":{"0":{"8":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":1,"docs":{"15":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"154":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"154":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":2,"docs":{"19":{"tf":1.7320508075688772},"31":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{"df":3,"docs":{"186":{"tf":1.0},"238":{"tf":1.4142135623730951},"86":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"93":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"a":{"d":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},";":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"面":{"df":0,"docs":{},"向":{"df":0,"docs":{},"国":{"df":0,"docs":{},"内":{"df":0,"docs":{},"市":{"df":0,"docs":{},"场":{"df":0,"docs":{},"的":{"df":0,"docs":{},"话":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"使":{"df":0,"docs":{},"用":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"n":{"b":{"a":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"169":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"k":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"d":{"df":1,"docs":{"89":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"97":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":1,"docs":{"223":{"tf":1.7320508075688772}}}}}},"o":{"df":2,"docs":{"223":{"tf":1.0},"94":{"tf":1.4142135623730951}}},"p":{"a":{"d":{"df":2,"docs":{"137":{"tf":1.4142135623730951},"223":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"159":{"tf":1.0},"223":{"tf":1.0}},"e":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"a":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"是":{"df":0,"docs":{},"非":{"df":0,"docs":{},"常":{"df":0,"docs":{},"有":{"df":0,"docs":{},"用":{"df":0,"docs":{},"的":{"df":0,"docs":{},"。":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"将":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"和":{"df":0,"docs":{},"推":{"df":0,"docs":{},"广":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"放":{"df":0,"docs":{},"到":{"df":0,"docs":{},"真":{"df":0,"docs":{},"人":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"的":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"上":{"df":0,"docs":{},"面":{"df":0,"docs":{},",":{"df":0,"docs":{},"万":{"df":0,"docs":{},"一":{"df":0,"docs":{},"这":{"df":0,"docs":{},"个":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"离":{"df":0,"docs":{},"开":{"df":0,"docs":{},"团":{"df":0,"docs":{},"队":{"df":0,"docs":{},",":{"df":0,"docs":{},"之":{"df":0,"docs":{},"前":{"df":0,"docs":{},"的":{"df":0,"docs":{},"投":{"df":0,"docs":{},"入":{"df":0,"docs":{},"就":{"df":0,"docs":{},"废":{"df":0,"docs":{},"掉":{"df":0,"docs":{},"了":{"df":0,"docs":{},",":{"df":0,"docs":{},"甚":{"df":0,"docs":{},"至":{"df":0,"docs":{},"会":{"df":0,"docs":{},"变":{"df":0,"docs":{},"成":{"df":0,"docs":{},"竞":{"df":0,"docs":{},"争":{"df":0,"docs":{},"对":{"df":0,"docs":{},"手":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"。":{"df":0,"docs":{},"但":{"df":0,"docs":{},"是":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"采":{"df":0,"docs":{},"用":{"df":0,"docs":{},"虚":{"df":0,"docs":{},"拟":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"220":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"186":{"tf":1.0}}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"投":{"df":0,"docs":{},"资":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"是":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"有":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"定":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"本":{"df":0,"docs":{},"之":{"df":0,"docs":{},"后":{"df":0,"docs":{},"的":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"让":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"。":{"df":0,"docs":{},"在":{"b":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"里":{"df":0,"docs":{},",":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"创":{"df":0,"docs":{},"办":{"df":0,"docs":{},"企":{"df":0,"docs":{},"业":{"df":0,"docs":{},"来":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"这":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"。":{"df":0,"docs":{},"即":{"df":0,"docs":{},"使":{"df":0,"docs":{},"你":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"异":{"df":0,"docs":{},"常":{"df":0,"docs":{},"充":{"df":0,"docs":{},"沛":{"df":0,"docs":{},",":{"df":0,"docs":{},"同":{"df":0,"docs":{},"时":{"df":0,"docs":{},"运":{"df":0,"docs":{},"营":{"df":0,"docs":{},"三":{"df":0,"docs":{},"五":{"df":0,"docs":{},"家":{"df":0,"docs":{},"公":{"df":0,"docs":{},"司":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"到":{"df":0,"docs":{},"上":{"df":0,"docs":{},"限":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"df":0,"docs":{},"i":{"df":1,"docs":{"7":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":1,"docs":{"69":{"tf":1.0}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"198":{"tf":2.0},"200":{"tf":1.0},"201":{"tf":1.4142135623730951}}}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"208":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"2":{"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":6,"docs":{"150":{"tf":1.4142135623730951},"151":{"tf":1.4142135623730951},"152":{"tf":1.7320508075688772},"154":{"tf":1.0},"155":{"tf":2.6457513110645907},"161":{"tf":1.0}}}}}},"m":{"a":{"c":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.4142135623730951}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"111":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"p":{"df":3,"docs":{"111":{"tf":1.4142135623730951},"121":{"tf":1.0},"59":{"tf":1.0}}}}},"n":{"df":1,"docs":{"248":{"tf":1.0}},"o":{".":{"1":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"v":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"b":{"df":11,"docs":{"205":{"tf":1.0},"206":{"tf":2.0},"207":{"tf":1.0},"208":{"tf":1.4142135623730951},"209":{"tf":1.7320508075688772},"210":{"tf":1.4142135623730951},"211":{"tf":1.7320508075688772},"212":{"tf":1.0},"213":{"tf":1.0},"216":{"tf":1.0},"221":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"k":{"df":1,"docs":{"210":{"tf":1.0}}}},"p":{"a":{"df":0,"docs":{},"y":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{".":{"c":{"df":0,"docs":{},"n":{"df":1,"docs":{"168":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"c":{"df":1,"docs":{"140":{"tf":1.0}}},"d":{"df":0,"docs":{},"f":{"df":2,"docs":{"195":{"tf":1.0},"81":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"a":{"df":1,"docs":{"128":{"tf":1.0}}},"df":0,"docs":{}}}}}},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"105":{"tf":1.0}}}}}}}}},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"i":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":74,"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"104":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"134":{"tf":1.7320508075688772},"143":{"tf":1.0},"144":{"tf":1.0},"149":{"tf":1.4142135623730951},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.7320508075688772},"16":{"tf":1.0},"160":{"tf":2.0},"161":{"tf":1.7320508075688772},"162":{"tf":1.7320508075688772},"163":{"tf":1.0},"169":{"tf":1.4142135623730951},"170":{"tf":1.0},"176":{"tf":1.0},"191":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":2.23606797749979},"199":{"tf":2.0},"20":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":2.449489742783178},"202":{"tf":2.0},"209":{"tf":1.0},"211":{"tf":1.4142135623730951},"212":{"tf":1.0},"213":{"tf":1.0},"215":{"tf":1.0},"216":{"tf":2.0},"217":{"tf":1.0},"22":{"tf":1.4142135623730951},"221":{"tf":2.449489742783178},"224":{"tf":2.23606797749979},"225":{"tf":1.0},"226":{"tf":1.0},"227":{"tf":1.0},"228":{"tf":1.4142135623730951},"230":{"tf":1.7320508075688772},"231":{"tf":1.7320508075688772},"232":{"tf":1.7320508075688772},"234":{"tf":1.0},"236":{"tf":1.0},"237":{"tf":1.4142135623730951},"238":{"tf":1.0},"240":{"tf":1.0},"241":{"tf":1.0},"242":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"246":{"tf":1.0},"251":{"tf":1.0},"63":{"tf":1.0},"69":{"tf":1.4142135623730951},"75":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}}}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"114":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.0}}},"df":0,"docs":{}},"y":{"df":1,"docs":{"93":{"tf":1.0}}}},"df":0,"docs":{}},"m":{"df":0,"docs":{},"f":{"df":2,"docs":{"111":{"tf":2.0},"143":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"199":{"tf":1.4142135623730951},"200":{"tf":1.0},"202":{"tf":1.4142135623730951}}}}}}}}}}},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"194":{"tf":1.0}}}},"r":{"df":5,"docs":{"223":{"tf":1.7320508075688772},"224":{"tf":1.4142135623730951},"225":{"tf":1.4142135623730951},"226":{"tf":1.0},"230":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"(":{"df":0,"docs":{},"一":{"df":0,"docs":{},"般":{"df":0,"docs":{},"简":{"df":0,"docs":{},"称":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":1,"docs":{"223":{"tf":1.0}}}}}}}}}}}}}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":2,"docs":{"157":{"tf":1.0},"163":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}}}}},"s":{"d":{"df":1,"docs":{"105":{"tf":1.0}}},"df":0,"docs":{}}},"q":{"df":0,"docs":{},"q":{"df":3,"docs":{"120":{"tf":1.0},"170":{"tf":1.0},"75":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"154":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"s":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"96":{"tf":1.0}}}},"df":3,"docs":{"10":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"160":{"tf":1.0}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"157":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":1,"docs":{"90":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"236":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"186":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}}},"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"g":{"df":1,"docs":{"163":{"tf":1.4142135623730951}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"的":{"df":0,"docs":{},"缺":{"df":0,"docs":{},"点":{"df":0,"docs":{},"是":{"df":0,"docs":{},",":{"df":0,"docs":{},"收":{"df":0,"docs":{},"益":{"df":0,"docs":{},"未":{"df":0,"docs":{},"必":{"df":0,"docs":{},"能":{"df":0,"docs":{},"比":{"df":0,"docs":{},"e":{"df":1,"docs":{"5":{"tf":1.0}}}}}}}}}}}}}}}}},"t":{"a":{"b":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":3,"docs":{"154":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"v":{"c":{"df":1,"docs":{"90":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"125":{"tf":1.0}}},"u":{"c":{"a":{"df":0,"docs":{},"o":{".":{"df":0,"docs":{},"j":{"df":1,"docs":{"173":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"i":{"df":1,"docs":{"221":{"tf":1.0}}},"n":{"d":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"w":{"df":1,"docs":{"153":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"160":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"124":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"s":{"b":{"df":1,"docs":{"211":{"tf":1.0}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"111":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"238":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":1,"docs":{"56":{"tf":1.0}}}},"w":{"df":0,"docs":{},"e":{"b":{"df":2,"docs":{"172":{"tf":1.0},"249":{"tf":1.0}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}}},"x":{"d":{"df":5,"docs":{"157":{"tf":1.7320508075688772},"158":{"tf":1.0},"159":{"tf":1.4142135623730951},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"y":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"168":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"s":{"df":1,"docs":{"159":{"tf":1.0}}}}}},"breadcrumbs":{"root":{"0":{"0":{"df":1,"docs":{"15":{"tf":1.0}}},"df":5,"docs":{"162":{"tf":1.0},"201":{"tf":1.0},"202":{"tf":1.0},"231":{"tf":1.0},"236":{"tf":1.0}}},"1":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.7320508075688772}},"万":{"df":0,"docs":{},"左":{"df":0,"docs":{},"右":{"df":0,"docs":{},"的":{"df":0,"docs":{},"人":{"df":0,"docs":{},"民":{"df":0,"docs":{},"币":{"df":0,"docs":{},"基":{"df":0,"docs":{},"本":{"df":0,"docs":{},"上":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"够":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"1":{"0":{"0":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}},"d":{"b":{"df":1,"docs":{"228":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"121":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"89":{"tf":1.0}},",":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"想":{"df":0,"docs":{},"加":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"改":{"df":0,"docs":{},"为":{"df":0,"docs":{},"大":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":0,"docs":{},";":{"df":0,"docs":{},"想":{"df":0,"docs":{},"减":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"小":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":1,"docs":{"227":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":5,"docs":{"107":{"tf":1.0},"126":{"tf":1.0},"177":{"tf":2.23606797749979},"189":{"tf":1.0},"228":{"tf":1.0}},"x":{"df":1,"docs":{"23":{"tf":1.0}}},"万":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"。":{"df":0,"docs":{},"以":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"它":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"能":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"花":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"。":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"想":{"df":0,"docs":{},"到":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"新":{"df":0,"docs":{},"办":{"df":0,"docs":{},"法":{"df":0,"docs":{},",":{"df":0,"docs":{},"把":{"df":0,"docs":{},"效":{"df":0,"docs":{},"率":{"df":0,"docs":{},"提":{"df":0,"docs":{},"升":{"df":0,"docs":{},"了":{"1":{"0":{"df":0,"docs":{},"倍":{"df":0,"docs":{},",":{"df":0,"docs":{},"那":{"df":0,"docs":{},"么":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"才":{"df":0,"docs":{},"能":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"的":{"df":0,"docs":{},"活":{"df":0,"docs":{},",":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"1":{"0":{"df":1,"docs":{"39":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}},"1":{"df":2,"docs":{"126":{"tf":1.0},"230":{"tf":1.0}}},"2":{"df":3,"docs":{"133":{"tf":1.0},"230":{"tf":1.0},"27":{"tf":1.0}}},"3":{"df":2,"docs":{"133":{"tf":1.0},"230":{"tf":1.0}}},"4":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"5":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"6":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"7":{"df":2,"docs":{"143":{"tf":1.0},"232":{"tf":1.0}}},"8":{"df":2,"docs":{"144":{"tf":1.0},"232":{"tf":1.0}}},"9":{"df":2,"docs":{"149":{"tf":1.0},"232":{"tf":1.0}}},"df":6,"docs":{"113":{"tf":1.0},"16":{"tf":1.0},"177":{"tf":1.0},"189":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0}}},"2":{"0":{"0":{"0":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"一":{"df":0,"docs":{},"个":{"df":0,"docs":{},"月":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"是":{"8":{"0":{"0":{"0":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"1":{"4":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}},"2":{"0":{"df":0,"docs":{},"年":{"4":{"df":1,"docs":{"13":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":4,"docs":{"149":{"tf":1.0},"191":{"tf":1.0},"234":{"tf":1.0},"41":{"tf":1.0}},"~":{"3":{"0":{"df":1,"docs":{"71":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"1":{"df":2,"docs":{"152":{"tf":1.0},"236":{"tf":1.0}}},"2":{"df":2,"docs":{"153":{"tf":1.0},"237":{"tf":1.0}}},"3":{"df":2,"docs":{"154":{"tf":1.0},"237":{"tf":1.0}}},"4":{"df":3,"docs":{"157":{"tf":1.0},"189":{"tf":1.0},"238":{"tf":1.0}}},"5":{"df":2,"docs":{"159":{"tf":1.0},"251":{"tf":1.0}}},"6":{"df":3,"docs":{"140":{"tf":1.0},"159":{"tf":1.0},"240":{"tf":1.0}}},"7":{"df":2,"docs":{"159":{"tf":1.0},"241":{"tf":1.0}}},"8":{"df":2,"docs":{"160":{"tf":1.0},"242":{"tf":1.0}}},"9":{"df":1,"docs":{"160":{"tf":1.0}}},"a":{"3":{"df":0,"docs":{},"r":{"df":7,"docs":{"121":{"tf":1.0},"175":{"tf":1.7320508075688772},"176":{"tf":2.0},"177":{"tf":2.0},"178":{"tf":1.0},"179":{"tf":1.0},"180":{"tf":1.0}}}},"df":0,"docs":{}},"df":6,"docs":{"114":{"tf":1.0},"159":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0},"63":{"tf":1.0}},"~":{"3":{"df":1,"docs":{"57":{"tf":1.0}}},"df":0,"docs":{}}},"3":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"160":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"189":{"tf":1.4142135623730951},"243":{"tf":1.0}}},"1":{"df":2,"docs":{"160":{"tf":1.0},"244":{"tf":1.0}}},"2":{"df":2,"docs":{"161":{"tf":1.0},"246":{"tf":1.0}}},"3":{"df":1,"docs":{"161":{"tf":1.0}}},"4":{"df":1,"docs":{"161":{"tf":1.0}}},"5":{"df":2,"docs":{"10":{"tf":1.0},"162":{"tf":1.0}}},"6":{"df":1,"docs":{"162":{"tf":1.0}}},"7":{"df":1,"docs":{"162":{"tf":1.0}}},"8":{"df":1,"docs":{"163":{"tf":1.0}}},"9":{"df":1,"docs":{"169":{"tf":1.0}}},"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":3,"docs":{"116":{"tf":1.0},"224":{"tf":1.0},"69":{"tf":1.0}},"到":{"6":{"df":1,"docs":{"82":{"tf":1.0}}},"df":0,"docs":{}}},"4":{"0":{"df":2,"docs":{"118":{"tf":1.0},"169":{"tf":1.0}}},"1":{"df":1,"docs":{"170":{"tf":1.0}}},"2":{"df":1,"docs":{"176":{"tf":1.0}}},"9":{"df":1,"docs":{"191":{"tf":1.0}}},"df":3,"docs":{"117":{"tf":1.0},"224":{"tf":1.0},"75":{"tf":1.0}}},"5":{"0":{"0":{"df":1,"docs":{"189":{"tf":1.0}}},"df":2,"docs":{"123":{"tf":1.4142135623730951},"197":{"tf":1.0}}},"2":{"df":1,"docs":{"198":{"tf":1.0}}},"3":{"df":1,"docs":{"198":{"tf":1.0}}},"4":{"df":1,"docs":{"198":{"tf":1.0}}},"5":{"df":1,"docs":{"198":{"tf":1.0}}},"6":{"df":1,"docs":{"198":{"tf":1.0}}},"7":{"df":1,"docs":{"199":{"tf":1.0}}},"8":{"df":1,"docs":{"199":{"tf":1.0}}},"9":{"df":1,"docs":{"199":{"tf":1.0}}},"df":6,"docs":{"118":{"tf":1.0},"162":{"tf":1.0},"224":{"tf":1.0},"55":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}},"6":{"0":{"df":1,"docs":{"199":{"tf":1.0}}},"2":{"df":1,"docs":{"200":{"tf":1.0}}},"3":{"df":1,"docs":{"201":{"tf":1.0}}},"4":{"df":1,"docs":{"201":{"tf":1.0}}},"5":{"df":1,"docs":{"201":{"tf":1.0}}},"6":{"df":1,"docs":{"201":{"tf":1.0}}},"7":{"df":1,"docs":{"201":{"tf":1.0}}},"8":{"df":1,"docs":{"201":{"tf":1.0}}},"9":{"9":{"df":1,"docs":{"94":{"tf":1.0}}},"df":1,"docs":{"202":{"tf":1.0}}},"df":5,"docs":{"102":{"tf":1.0},"119":{"tf":1.0},"225":{"tf":1.0},"231":{"tf":1.0},"69":{"tf":1.0}}},"7":{"0":{"df":2,"docs":{"202":{"tf":1.0},"83":{"tf":1.0}}},"1":{"df":1,"docs":{"202":{"tf":1.0}}},"2":{"df":1,"docs":{"202":{"tf":1.0}}},"3":{"df":1,"docs":{"209":{"tf":1.0}}},"4":{"df":1,"docs":{"211":{"tf":1.0}}},"5":{"df":1,"docs":{"211":{"tf":1.0}}},"7":{"df":1,"docs":{"212":{"tf":1.0}}},"8":{"df":1,"docs":{"213":{"tf":1.0}}},"9":{"df":1,"docs":{"215":{"tf":1.0}}},"df":3,"docs":{"103":{"tf":1.0},"120":{"tf":1.0},"226":{"tf":1.0}},"×":{"2":{"4":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"8":{"%":{"df":0,"docs":{},"~":{"1":{"5":{"df":1,"docs":{"83":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"0":{"df":1,"docs":{"216":{"tf":1.0}}},"1":{"df":1,"docs":{"217":{"tf":1.0}}},"2":{"df":1,"docs":{"216":{"tf":1.0}}},"3":{"df":1,"docs":{"216":{"tf":1.0}}},"4":{"df":1,"docs":{"216":{"tf":1.0}}},"5":{"df":2,"docs":{"221":{"tf":1.0},"27":{"tf":1.0}}},"6":{"df":1,"docs":{"221":{"tf":1.0}}},"7":{"df":1,"docs":{"221":{"tf":1.0}}},"8":{"df":1,"docs":{"221":{"tf":1.0}}},"9":{"df":1,"docs":{"221":{"tf":1.0}}},"df":3,"docs":{"104":{"tf":1.0},"121":{"tf":1.0},"227":{"tf":1.0}}},"9":{"0":{"df":3,"docs":{"15":{"tf":1.0},"221":{"tf":1.0},"39":{"tf":1.0}}},"df":3,"docs":{"106":{"tf":1.0},"122":{"tf":1.0},"228":{"tf":1.0}}},"a":{"4":{"df":1,"docs":{"132":{"tf":1.0}}},"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":1,"docs":{"176":{"tf":1.0}}}}}},"b":{"c":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"一":{"df":0,"docs":{},"里":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"a":{"df":0,"docs":{},";":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"二":{"df":0,"docs":{},"中":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"b":{"c":{"df":1,"docs":{"210":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"103":{"tf":1.0}}}}}},"d":{"df":0,"docs":{},"o":{"b":{"df":4,"docs":{"157":{"tf":2.23606797749979},"158":{"tf":1.4142135623730951},"223":{"tf":1.0},"228":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":8,"docs":{"156":{"tf":1.7320508075688772},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":2,"docs":{"133":{"tf":1.0},"41":{"tf":2.449489742783178}},"r":{"b":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"27":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"n":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"df":1,"docs":{"114":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"i":{"df":7,"docs":{"168":{"tf":1.4142135623730951},"169":{"tf":1.0},"170":{"tf":1.0},"174":{"tf":1.0},"238":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}},"p":{"df":13,"docs":{"166":{"tf":1.0},"172":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"27":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":1.0},"93":{"tf":1.4142135623730951},"94":{"tf":1.4142135623730951},"95":{"tf":1.0},"96":{"tf":1.4142135623730951},"97":{"tf":1.0},"98":{"tf":1.0}},",":{"df":0,"docs":{},"以":{"df":0,"docs":{},"每":{"df":0,"docs":{},"分":{"df":0,"docs":{},"钟":{"1":{"0":{"0":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"r":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":2,"docs":{"237":{"tf":1.0},"238":{"tf":1.0}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"159":{"tf":1.0}}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"、":{"df":0,"docs":{},"p":{"df":0,"docs":{},"h":{"df":0,"docs":{},"p":{"df":0,"docs":{},"和":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}}}}}},"u":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"228":{"tf":1.0},"230":{"tf":1.0}}}}},"df":4,"docs":{"230":{"tf":1.4142135623730951},"231":{"tf":1.0},"232":{"tf":1.0},"233":{"tf":1.0}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"160":{"tf":1.0}}}},"df":0,"docs":{}},"df":4,"docs":{"10":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"d":{"df":0,"docs":{},"n":{"a":{"df":2,"docs":{"81":{"tf":1.0},"83":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"创":{"df":0,"docs":{},"业":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"和":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}}}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"163":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"56":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"或":{"df":0,"docs":{},"者":{"c":{"df":0,"docs":{},"m":{"d":{"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"d":{"b":{"df":1,"docs":{"231":{"tf":1.4142135623730951}}},"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":1,"docs":{"38":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"z":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"y":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"187":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":4,"docs":{"10":{"tf":1.0},"4":{"tf":2.23606797749979},"7":{"tf":1.0},"8":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}},"df":2,"docs":{"10":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951}}},"、":{"df":0,"docs":{},"s":{"df":0,"docs":{},"、":{"b":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":1,"docs":{"3":{"tf":1.0}}}}},"df":0,"docs":{}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"移":{"df":0,"docs":{},"动":{"df":0,"docs":{},"到":{"b":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"220":{"tf":2.23606797749979},"221":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"1":{"0":{"8":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":1,"docs":{"15":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"154":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"154":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":2,"docs":{"19":{"tf":2.0},"31":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{"df":3,"docs":{"186":{"tf":1.0},"238":{"tf":1.4142135623730951},"86":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"93":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"a":{"d":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},";":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"面":{"df":0,"docs":{},"向":{"df":0,"docs":{},"国":{"df":0,"docs":{},"内":{"df":0,"docs":{},"市":{"df":0,"docs":{},"场":{"df":0,"docs":{},"的":{"df":0,"docs":{},"话":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"使":{"df":0,"docs":{},"用":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"n":{"b":{"a":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"169":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"k":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"d":{"df":1,"docs":{"89":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"97":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":1,"docs":{"223":{"tf":1.7320508075688772}}}}}},"o":{"df":2,"docs":{"223":{"tf":1.0},"94":{"tf":1.4142135623730951}}},"p":{"a":{"d":{"df":2,"docs":{"137":{"tf":1.4142135623730951},"223":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"159":{"tf":1.0},"223":{"tf":1.0}},"e":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"a":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"是":{"df":0,"docs":{},"非":{"df":0,"docs":{},"常":{"df":0,"docs":{},"有":{"df":0,"docs":{},"用":{"df":0,"docs":{},"的":{"df":0,"docs":{},"。":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"将":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"和":{"df":0,"docs":{},"推":{"df":0,"docs":{},"广":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"放":{"df":0,"docs":{},"到":{"df":0,"docs":{},"真":{"df":0,"docs":{},"人":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"的":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"上":{"df":0,"docs":{},"面":{"df":0,"docs":{},",":{"df":0,"docs":{},"万":{"df":0,"docs":{},"一":{"df":0,"docs":{},"这":{"df":0,"docs":{},"个":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"离":{"df":0,"docs":{},"开":{"df":0,"docs":{},"团":{"df":0,"docs":{},"队":{"df":0,"docs":{},",":{"df":0,"docs":{},"之":{"df":0,"docs":{},"前":{"df":0,"docs":{},"的":{"df":0,"docs":{},"投":{"df":0,"docs":{},"入":{"df":0,"docs":{},"就":{"df":0,"docs":{},"废":{"df":0,"docs":{},"掉":{"df":0,"docs":{},"了":{"df":0,"docs":{},",":{"df":0,"docs":{},"甚":{"df":0,"docs":{},"至":{"df":0,"docs":{},"会":{"df":0,"docs":{},"变":{"df":0,"docs":{},"成":{"df":0,"docs":{},"竞":{"df":0,"docs":{},"争":{"df":0,"docs":{},"对":{"df":0,"docs":{},"手":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"。":{"df":0,"docs":{},"但":{"df":0,"docs":{},"是":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"采":{"df":0,"docs":{},"用":{"df":0,"docs":{},"虚":{"df":0,"docs":{},"拟":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"220":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"186":{"tf":1.0}}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"投":{"df":0,"docs":{},"资":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"是":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"有":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"定":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"本":{"df":0,"docs":{},"之":{"df":0,"docs":{},"后":{"df":0,"docs":{},"的":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"让":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"。":{"df":0,"docs":{},"在":{"b":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"里":{"df":0,"docs":{},",":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"创":{"df":0,"docs":{},"办":{"df":0,"docs":{},"企":{"df":0,"docs":{},"业":{"df":0,"docs":{},"来":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"这":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"。":{"df":0,"docs":{},"即":{"df":0,"docs":{},"使":{"df":0,"docs":{},"你":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"异":{"df":0,"docs":{},"常":{"df":0,"docs":{},"充":{"df":0,"docs":{},"沛":{"df":0,"docs":{},",":{"df":0,"docs":{},"同":{"df":0,"docs":{},"时":{"df":0,"docs":{},"运":{"df":0,"docs":{},"营":{"df":0,"docs":{},"三":{"df":0,"docs":{},"五":{"df":0,"docs":{},"家":{"df":0,"docs":{},"公":{"df":0,"docs":{},"司":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"到":{"df":0,"docs":{},"上":{"df":0,"docs":{},"限":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"df":0,"docs":{},"i":{"df":1,"docs":{"7":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":1,"docs":{"69":{"tf":1.0}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"198":{"tf":2.23606797749979},"200":{"tf":1.0},"201":{"tf":1.7320508075688772}}}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"208":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"2":{"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":7,"docs":{"150":{"tf":2.0},"151":{"tf":2.0},"152":{"tf":2.23606797749979},"153":{"tf":1.0},"154":{"tf":1.4142135623730951},"155":{"tf":2.8284271247461903},"161":{"tf":1.0}}}}}},"m":{"a":{"c":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.4142135623730951}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"111":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"p":{"df":3,"docs":{"111":{"tf":1.4142135623730951},"121":{"tf":1.0},"59":{"tf":1.0}}}}},"n":{"df":1,"docs":{"248":{"tf":1.0}},"o":{".":{"1":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"v":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"b":{"df":11,"docs":{"205":{"tf":1.0},"206":{"tf":2.0},"207":{"tf":1.0},"208":{"tf":1.4142135623730951},"209":{"tf":2.0},"210":{"tf":1.4142135623730951},"211":{"tf":1.7320508075688772},"212":{"tf":1.0},"213":{"tf":1.0},"216":{"tf":1.0},"221":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"k":{"df":1,"docs":{"210":{"tf":1.0}}}},"p":{"a":{"df":0,"docs":{},"y":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{".":{"c":{"df":0,"docs":{},"n":{"df":1,"docs":{"168":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"c":{"df":1,"docs":{"140":{"tf":1.0}}},"d":{"df":0,"docs":{},"f":{"df":2,"docs":{"195":{"tf":1.0},"81":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"a":{"df":1,"docs":{"128":{"tf":1.0}}},"df":0,"docs":{}}}}}},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"105":{"tf":1.0}}}}}}}}},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"i":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":74,"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"104":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"134":{"tf":1.7320508075688772},"143":{"tf":1.0},"144":{"tf":1.0},"149":{"tf":1.4142135623730951},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.7320508075688772},"16":{"tf":1.0},"160":{"tf":2.0},"161":{"tf":1.7320508075688772},"162":{"tf":1.7320508075688772},"163":{"tf":1.0},"169":{"tf":1.4142135623730951},"170":{"tf":1.0},"176":{"tf":1.0},"191":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":2.23606797749979},"199":{"tf":2.0},"20":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":2.449489742783178},"202":{"tf":2.0},"209":{"tf":1.0},"211":{"tf":1.4142135623730951},"212":{"tf":1.0},"213":{"tf":1.0},"215":{"tf":1.0},"216":{"tf":2.0},"217":{"tf":1.0},"22":{"tf":1.4142135623730951},"221":{"tf":2.449489742783178},"224":{"tf":2.23606797749979},"225":{"tf":1.0},"226":{"tf":1.0},"227":{"tf":1.0},"228":{"tf":1.4142135623730951},"230":{"tf":1.7320508075688772},"231":{"tf":1.7320508075688772},"232":{"tf":1.7320508075688772},"234":{"tf":1.0},"236":{"tf":1.0},"237":{"tf":1.4142135623730951},"238":{"tf":1.0},"240":{"tf":1.0},"241":{"tf":1.0},"242":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"246":{"tf":1.0},"251":{"tf":1.0},"63":{"tf":1.0},"69":{"tf":1.4142135623730951},"75":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}}}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"114":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"y":{"df":1,"docs":{"93":{"tf":1.0}}}},"df":0,"docs":{}},"m":{"df":0,"docs":{},"f":{"df":2,"docs":{"111":{"tf":2.0},"143":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"199":{"tf":1.7320508075688772},"200":{"tf":1.0},"202":{"tf":1.7320508075688772}}}}}}}}}}},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"194":{"tf":1.0}}}},"r":{"df":5,"docs":{"223":{"tf":1.7320508075688772},"224":{"tf":1.4142135623730951},"225":{"tf":1.4142135623730951},"226":{"tf":1.0},"230":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"(":{"df":0,"docs":{},"一":{"df":0,"docs":{},"般":{"df":0,"docs":{},"简":{"df":0,"docs":{},"称":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":1,"docs":{"223":{"tf":1.0}}}}}}}}}}}}}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":2,"docs":{"157":{"tf":1.0},"163":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}}}}},"s":{"d":{"df":1,"docs":{"105":{"tf":1.0}}},"df":0,"docs":{}}},"q":{"df":0,"docs":{},"q":{"df":3,"docs":{"120":{"tf":1.0},"170":{"tf":1.0},"75":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"154":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"s":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"96":{"tf":1.0}}}},"df":3,"docs":{"10":{"tf":1.0},"5":{"tf":2.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"160":{"tf":1.0}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"157":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":1,"docs":{"90":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"236":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"186":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}}},"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"g":{"df":1,"docs":{"163":{"tf":1.4142135623730951}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"的":{"df":0,"docs":{},"缺":{"df":0,"docs":{},"点":{"df":0,"docs":{},"是":{"df":0,"docs":{},",":{"df":0,"docs":{},"收":{"df":0,"docs":{},"益":{"df":0,"docs":{},"未":{"df":0,"docs":{},"必":{"df":0,"docs":{},"能":{"df":0,"docs":{},"比":{"df":0,"docs":{},"e":{"df":1,"docs":{"5":{"tf":1.0}}}}}}}}}}}}}}}}},"t":{"a":{"b":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":3,"docs":{"154":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"v":{"c":{"df":1,"docs":{"90":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"125":{"tf":1.0}}},"u":{"c":{"a":{"df":0,"docs":{},"o":{".":{"df":0,"docs":{},"j":{"df":1,"docs":{"173":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"i":{"df":1,"docs":{"221":{"tf":1.0}}},"n":{"d":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"w":{"df":1,"docs":{"153":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"160":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"124":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"s":{"b":{"df":1,"docs":{"211":{"tf":1.0}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"111":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"238":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":1,"docs":{"56":{"tf":1.0}}}},"w":{"df":0,"docs":{},"e":{"b":{"df":2,"docs":{"172":{"tf":1.0},"249":{"tf":1.0}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}}},"x":{"d":{"df":5,"docs":{"157":{"tf":2.0},"158":{"tf":1.4142135623730951},"159":{"tf":1.4142135623730951},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"y":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"168":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"s":{"df":1,"docs":{"159":{"tf":1.0}}}}}},"title":{"root":{"2":{"a":{"3":{"df":0,"docs":{},"r":{"df":3,"docs":{"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"d":{"df":0,"docs":{},"o":{"b":{"df":2,"docs":{"157":{"tf":1.0},"158":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":1,"docs":{"156":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":1,"docs":{"91":{"tf":1.0}}}}},"b":{"df":1,"docs":{"6":{"tf":1.0}}},"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.0},"9":{"tf":1.0}}},"df":2,"docs":{"10":{"tf":1.0},"12":{"tf":1.0}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":1,"docs":{"220":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":2,"docs":{"198":{"tf":1.0},"201":{"tf":1.0}}}}}}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":3,"docs":{"150":{"tf":1.0},"151":{"tf":1.0},"152":{"tf":1.0}}}}}},"o":{"b":{"df":1,"docs":{"209":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"199":{"tf":1.0},"202":{"tf":1.0}}}}}}}}}}}},"s":{"df":1,"docs":{"5":{"tf":1.0}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.0}}},"df":0,"docs":{}}},"x":{"d":{"df":2,"docs":{"157":{"tf":1.0},"158":{"tf":1.0}}},"df":0,"docs":{}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}); ================================================ FILE: docs/searchindex.json ================================================ {"doc_urls":["index.html#精益副业","01.html#为什么副业特别重要","0101.html#职业可能性","010101.html#职业的四大象限","010101.html#e象限雇员象限帮别人挣钱","010101.html#s象限自雇象限为自己挣钱","010101.html#b象限创业象限让雇员挣钱","010101.html#i象限投资象限让钱挣钱","010102.html#没有副业的职业","010102.html#eb辞职创业","010102.html#es回老家开工作室","010103.html#副业带来的可能性","010103.html#es回老家开工作室","010103.html#eb创业","0102.html#职业自由度","010201.html#从中指备用金说起","010202.html#planb和反脆弱","010203.html#全新的工作自由度","010203.html#远程办公","010203.html#freelancer","010203.html#独立开发","0103.html#职业成长性","010301A.html#新技术练兵场","010302.html#业务敏感度","02.html#如何优雅地做副业","0201.html#想明白核心资源和核心优势","020101.html#副业的核心资源","020102.html#副业的核心优势","0202.html#时间片","020201.html#时间片的销售","020201.html#私单","020201.html#外包","020201.html#外包的坑","020201.html#按需雇用","020201.html#更优雅的方式","020202.html#时间片的优化","020202.html#提升单位时间的收益","020202.html#切换地域","020202.html#从外包到二次开发","020202.html#提升单位时间的效率","020202.html#打鸡血难以奏效","020202.html#自动化","020203.html#突破时间片限制","020203.html#倍增","020203.html#外包","020203.html#众包","020203.html#超卖","0203.html#资产和被动收入","020301.html#什么是资产","020302.html#资产的获得方式","020303.html#资产的量化评估","020303.html#适合副业的几个特征","020303.html#自传播","020303.html#ugc","020303.html#自动化","020303.html#量化评估标准","020303.html#投入","020303.html#产出","020303.html#可持续性","020303.html#风险","020303.html#门槛","03.html#优选资产","0301.html#知识和人脉的变现","030101.html#付费视频课","030101.html#低投入-","030101.html#高产出-","030101.html#可持续性-","030101.html#低风险-","030101.html#低门槛-","030102.html#付费专栏","030102.html#低投入-","030102.html#高产出-","030102.html#可持续性-","030102.html#低风险-","030102.html#低门槛-","030103.html#付费社群","030103.html#低投入-","030103.html#高产出-","030103.html#可持续性-","030103.html#低风险-","030103.html#低门槛-","030104.html#图书出版","030104.html#低投入-","030104.html#高产出-","030104.html#可持续性-","030104.html#低风险-","030104.html#低门槛-","0302.html#自有产品和服务","0302.html#需求的发现","0302.html#原生需求","0302.html#观察分析和阅读报告","030201.html#应用市场卖-app","030201.html#关键字搜索","030201.html#编辑推荐","030201.html#低投入-","030201.html#高产出-","030201.html#可持续性-","030201.html#低风险-","030201.html#低门槛-","04.html#精益副业","0401.html#精益副业流程","040104.html#商业模式画布","040104.html#价值的定义","040104.html#创造价值","040104.html#销售价值","040104.html#分层结构","040104.html#画布结构","040104.html#价值主张画布","040104.html#客户细分","040104.html#价值主张","040104.html#契合","040105.html#最小可行产品和产品市场契合","0403.html#精益独立开发实践","040301.html#独立开发的精益流程","040302.html#福利单词项目简介","040303.html#福利单词的商业模式画布","040303.html#价值主张","040303.html#客户细分","040303.html#价值主张的细化","040303.html#渠道通路","040303.html#客户关系","040303.html#关键活动","040303.html#关键资源","040303.html#作者授权","040303.html#换用无版权图片","040303.html#用户自行提供图片","040303.html#成本收益","040304.html#通过用户画像细化客户","040304.html#什么是用户画像","040304.html#福利单词的用户画像","040304.html#四六级备考生","040304.html#留学移民预备军","040304.html#专业提升小白领","040304.html#画像的头像制作","040304.html#最终的用户画像","040305.html#画像场景功能和分期","040305.html#使用场景分析","040305.html#王小康的使用场景分析","040305.html#章小留的使用场景分析","040305.html#卢小白的使用场景分析","040305.html#从场景到功能","040305.html#通过思维导图梳理功能","040305.html#分期","040305.html#功能分期","040305.html#功能归类到界面","040306.html#什么是好的商业设计","040306.html#好设计的标准","040306.html#商业设计","040306.html#简洁即美","040307.html#人人能用的四大原则","040308.html#独特logo解决方案","040308.html#为什么要自己设计-logo","040308.html#通过矢量软件绘制-logo","040308.html#免费和开放的矢量资源","040308.html#购买付费素材","040308.html#将付费素材变成独有的","040309.html#使用adobexd设计界面","040309.html#什么是-adobe-xd","040309.html#使用-adobe-xd-设计简单界面","040309.html#理解画板","040309.html#遮罩的制作","040309.html#单词释义和输入框","040309.html#虚拟键盘","040309.html#矢量图标","040310.html#个人支付解决方案","040310.html#常见的几种个人收款方式","040310.html#个人收款码","040310.html#二次封装接口","040310.html#小微商户","040310.html#数字内容销售平台","040311.html#使用兔小巢处理用户反馈","040311.html#整合说明","040311.html#链接跳转","040311.html#状态登入","040311.html#反馈数据整合","040312.html#2a3r漏斗和增长优化","040312.html#什么是-2a3r-漏斗","040312.html#使用-2a3r-漏斗进行业务优化","040312.html#留存层优化","040312.html#推荐层优化","040312.html#推荐阅读","0402.html#精益网课变现实践","040207.html#大纲的注意点","040207.html#条理性","040207.html#三段式","040207.html#提问式","040207.html#覆盖面","040207.html#粒度","040209.html#通过预售验证销量","040209.html#为什么要验证","040209.html#如何验证","040209.html#众筹预售平台","040209.html#自建众筹预售平台","040209.html#付费群","040210.html#常见的课程片段类型","040211.html#文稿讲义类课程片段的制作","040211.html#全局录屏","040211.html#使用幻灯片软件自带的演讲录制功能","040211.html#如何使用-keynote-的录制幻灯片放映功能生成视频课程","040211.html#如何使用-powerpoint的录制幻灯片演示功能生成视频课程","040211.html#幻灯片导出为视频","040211.html#如何使用-keynote-以导出为视频的方式生成视频课程","040211.html#如何使用-powerpoint-以导出为视频的方式生成视频课程","040212.html#屏幕录制类课程片段的制作","040212.html#屏幕录制的原理","040212.html#屏幕录制的软件","040212.html#功能强大","040212.html#开源免费","040212.html#跨平台","040212.html#obs-的层次逻辑","040212.html#场景","040212.html#来源","040212.html#来源的层次","040212.html#滤镜","040213.html#真人出镜类课程片段的制作","040213.html#什么是真人出镜类课程片段","040213.html#抠图","040213.html#真人出镜的其他细节","040214.html#虚拟形象类课程片段的制作","040214.html#虚拟形象的原理","040214.html#facerig","040214.html#步骤","040215.html#最常用的视频剪辑操作","040215.html#剪辑软件","040215.html#视频片段的调整","040215.html#柔软的视频片段","040215.html#视频片段顺序的调整","040215.html#视频片段速度的调整","040215.html#视频中的音频处理","040216.html#最常用的音频处理操作","040216.html#去噪","040216.html#标准化","040216.html#混响","040216.html#齿音和嘶声","040216.html#建议顺序","040217.html#字幕的制作和自动生成","040217.html#字幕及其格式","040217.html#字幕编辑软件","040217.html#字幕的自动生成","040218.html#流量池和二次购买","040218.html#没有流量池的情况","040218.html#学员池","040218.html#访客池","040218.html#构造流量池的工具","040218.html#多级流量池","040219.html#如何有效地反盗版","040219.html#树立反盗版的正确思路","040219.html#如何有效地反盗版","040219.html#卖空","040219.html#卖多","0404.html#进一步提升副业的鲁棒性","040401.html#网课独立开发的双引擎副业模式"],"index":{"documentStore":{"docInfo":{"0":{"body":0,"breadcrumbs":0,"title":0},"1":{"body":0,"breadcrumbs":0,"title":0},"10":{"body":5,"breadcrumbs":1,"title":1},"100":{"body":0,"breadcrumbs":0,"title":0},"101":{"body":0,"breadcrumbs":0,"title":0},"102":{"body":2,"breadcrumbs":0,"title":0},"103":{"body":3,"breadcrumbs":0,"title":0},"104":{"body":2,"breadcrumbs":0,"title":0},"105":{"body":2,"breadcrumbs":0,"title":0},"106":{"body":2,"breadcrumbs":0,"title":0},"107":{"body":2,"breadcrumbs":0,"title":0},"108":{"body":0,"breadcrumbs":0,"title":0},"109":{"body":0,"breadcrumbs":0,"title":0},"11":{"body":0,"breadcrumbs":0,"title":0},"110":{"body":0,"breadcrumbs":0,"title":0},"111":{"body":12,"breadcrumbs":0,"title":0},"112":{"body":0,"breadcrumbs":0,"title":0},"113":{"body":2,"breadcrumbs":0,"title":0},"114":{"body":4,"breadcrumbs":0,"title":0},"115":{"body":0,"breadcrumbs":0,"title":0},"116":{"body":2,"breadcrumbs":0,"title":0},"117":{"body":2,"breadcrumbs":0,"title":0},"118":{"body":3,"breadcrumbs":0,"title":0},"119":{"body":2,"breadcrumbs":0,"title":0},"12":{"body":0,"breadcrumbs":1,"title":1},"120":{"body":3,"breadcrumbs":0,"title":0},"121":{"body":6,"breadcrumbs":0,"title":0},"122":{"body":2,"breadcrumbs":0,"title":0},"123":{"body":2,"breadcrumbs":0,"title":0},"124":{"body":1,"breadcrumbs":0,"title":0},"125":{"body":1,"breadcrumbs":0,"title":0},"126":{"body":4,"breadcrumbs":0,"title":0},"127":{"body":0,"breadcrumbs":0,"title":0},"128":{"body":1,"breadcrumbs":0,"title":0},"129":{"body":0,"breadcrumbs":0,"title":0},"13":{"body":6,"breadcrumbs":1,"title":1},"130":{"body":0,"breadcrumbs":0,"title":0},"131":{"body":0,"breadcrumbs":0,"title":0},"132":{"body":1,"breadcrumbs":0,"title":0},"133":{"body":7,"breadcrumbs":0,"title":0},"134":{"body":6,"breadcrumbs":0,"title":0},"135":{"body":0,"breadcrumbs":0,"title":0},"136":{"body":0,"breadcrumbs":0,"title":0},"137":{"body":2,"breadcrumbs":0,"title":0},"138":{"body":0,"breadcrumbs":0,"title":0},"139":{"body":0,"breadcrumbs":0,"title":0},"14":{"body":0,"breadcrumbs":0,"title":0},"140":{"body":4,"breadcrumbs":0,"title":0},"141":{"body":0,"breadcrumbs":0,"title":0},"142":{"body":0,"breadcrumbs":0,"title":0},"143":{"body":3,"breadcrumbs":0,"title":0},"144":{"body":2,"breadcrumbs":0,"title":0},"145":{"body":0,"breadcrumbs":0,"title":0},"146":{"body":0,"breadcrumbs":0,"title":0},"147":{"body":0,"breadcrumbs":0,"title":0},"148":{"body":0,"breadcrumbs":0,"title":0},"149":{"body":4,"breadcrumbs":0,"title":0},"15":{"body":4,"breadcrumbs":0,"title":0},"150":{"body":1,"breadcrumbs":2,"title":1},"151":{"body":1,"breadcrumbs":2,"title":1},"152":{"body":4,"breadcrumbs":2,"title":1},"153":{"body":3,"breadcrumbs":1,"title":0},"154":{"body":7,"breadcrumbs":1,"title":0},"155":{"body":8,"breadcrumbs":1,"title":0},"156":{"body":0,"breadcrumbs":2,"title":1},"157":{"body":11,"breadcrumbs":3,"title":2},"158":{"body":0,"breadcrumbs":3,"title":2},"159":{"body":17,"breadcrumbs":1,"title":0},"16":{"body":2,"breadcrumbs":2,"title":1},"160":{"body":12,"breadcrumbs":1,"title":0},"161":{"body":7,"breadcrumbs":1,"title":0},"162":{"body":17,"breadcrumbs":1,"title":0},"163":{"body":8,"breadcrumbs":1,"title":0},"164":{"body":0,"breadcrumbs":0,"title":0},"165":{"body":0,"breadcrumbs":0,"title":0},"166":{"body":1,"breadcrumbs":0,"title":0},"167":{"body":0,"breadcrumbs":0,"title":0},"168":{"body":4,"breadcrumbs":0,"title":0},"169":{"body":6,"breadcrumbs":0,"title":0},"17":{"body":0,"breadcrumbs":0,"title":0},"170":{"body":4,"breadcrumbs":0,"title":0},"171":{"body":0,"breadcrumbs":0,"title":0},"172":{"body":2,"breadcrumbs":0,"title":0},"173":{"body":1,"breadcrumbs":0,"title":0},"174":{"body":1,"breadcrumbs":0,"title":0},"175":{"body":0,"breadcrumbs":2,"title":1},"176":{"body":4,"breadcrumbs":2,"title":1},"177":{"body":13,"breadcrumbs":2,"title":1},"178":{"body":0,"breadcrumbs":1,"title":0},"179":{"body":2,"breadcrumbs":1,"title":0},"18":{"body":0,"breadcrumbs":0,"title":0},"180":{"body":0,"breadcrumbs":1,"title":0},"181":{"body":0,"breadcrumbs":0,"title":0},"182":{"body":0,"breadcrumbs":0,"title":0},"183":{"body":0,"breadcrumbs":0,"title":0},"184":{"body":0,"breadcrumbs":0,"title":0},"185":{"body":0,"breadcrumbs":0,"title":0},"186":{"body":3,"breadcrumbs":0,"title":0},"187":{"body":1,"breadcrumbs":0,"title":0},"188":{"body":0,"breadcrumbs":0,"title":0},"189":{"body":6,"breadcrumbs":0,"title":0},"19":{"body":2,"breadcrumbs":1,"title":1},"190":{"body":0,"breadcrumbs":0,"title":0},"191":{"body":3,"breadcrumbs":0,"title":0},"192":{"body":0,"breadcrumbs":0,"title":0},"193":{"body":0,"breadcrumbs":0,"title":0},"194":{"body":1,"breadcrumbs":0,"title":0},"195":{"body":1,"breadcrumbs":0,"title":0},"196":{"body":0,"breadcrumbs":0,"title":0},"197":{"body":4,"breadcrumbs":0,"title":0},"198":{"body":15,"breadcrumbs":1,"title":1},"199":{"body":9,"breadcrumbs":1,"title":1},"2":{"body":0,"breadcrumbs":0,"title":0},"20":{"body":2,"breadcrumbs":0,"title":0},"200":{"body":4,"breadcrumbs":0,"title":0},"201":{"body":14,"breadcrumbs":1,"title":1},"202":{"body":10,"breadcrumbs":1,"title":1},"203":{"body":0,"breadcrumbs":0,"title":0},"204":{"body":0,"breadcrumbs":0,"title":0},"205":{"body":1,"breadcrumbs":0,"title":0},"206":{"body":4,"breadcrumbs":0,"title":0},"207":{"body":1,"breadcrumbs":0,"title":0},"208":{"body":5,"breadcrumbs":0,"title":0},"209":{"body":4,"breadcrumbs":1,"title":1},"21":{"body":0,"breadcrumbs":0,"title":0},"210":{"body":4,"breadcrumbs":0,"title":0},"211":{"body":8,"breadcrumbs":0,"title":0},"212":{"body":3,"breadcrumbs":0,"title":0},"213":{"body":3,"breadcrumbs":0,"title":0},"214":{"body":0,"breadcrumbs":0,"title":0},"215":{"body":2,"breadcrumbs":0,"title":0},"216":{"body":9,"breadcrumbs":0,"title":0},"217":{"body":2,"breadcrumbs":0,"title":0},"218":{"body":0,"breadcrumbs":0,"title":0},"219":{"body":0,"breadcrumbs":0,"title":0},"22":{"body":7,"breadcrumbs":0,"title":0},"220":{"body":7,"breadcrumbs":1,"title":1},"221":{"body":20,"breadcrumbs":0,"title":0},"222":{"body":0,"breadcrumbs":0,"title":0},"223":{"body":14,"breadcrumbs":0,"title":0},"224":{"body":12,"breadcrumbs":0,"title":0},"225":{"body":4,"breadcrumbs":0,"title":0},"226":{"body":3,"breadcrumbs":0,"title":0},"227":{"body":3,"breadcrumbs":0,"title":0},"228":{"body":7,"breadcrumbs":0,"title":0},"229":{"body":0,"breadcrumbs":0,"title":0},"23":{"body":2,"breadcrumbs":0,"title":0},"230":{"body":11,"breadcrumbs":0,"title":0},"231":{"body":11,"breadcrumbs":0,"title":0},"232":{"body":7,"breadcrumbs":0,"title":0},"233":{"body":1,"breadcrumbs":0,"title":0},"234":{"body":2,"breadcrumbs":0,"title":0},"235":{"body":0,"breadcrumbs":0,"title":0},"236":{"body":4,"breadcrumbs":0,"title":0},"237":{"body":5,"breadcrumbs":0,"title":0},"238":{"body":7,"breadcrumbs":0,"title":0},"239":{"body":0,"breadcrumbs":0,"title":0},"24":{"body":0,"breadcrumbs":0,"title":0},"240":{"body":2,"breadcrumbs":0,"title":0},"241":{"body":2,"breadcrumbs":0,"title":0},"242":{"body":2,"breadcrumbs":0,"title":0},"243":{"body":3,"breadcrumbs":0,"title":0},"244":{"body":3,"breadcrumbs":0,"title":0},"245":{"body":0,"breadcrumbs":0,"title":0},"246":{"body":2,"breadcrumbs":0,"title":0},"247":{"body":0,"breadcrumbs":0,"title":0},"248":{"body":1,"breadcrumbs":0,"title":0},"249":{"body":3,"breadcrumbs":0,"title":0},"25":{"body":0,"breadcrumbs":0,"title":0},"250":{"body":0,"breadcrumbs":0,"title":0},"251":{"body":2,"breadcrumbs":0,"title":0},"26":{"body":0,"breadcrumbs":0,"title":0},"27":{"body":7,"breadcrumbs":0,"title":0},"28":{"body":0,"breadcrumbs":0,"title":0},"29":{"body":0,"breadcrumbs":0,"title":0},"3":{"body":2,"breadcrumbs":0,"title":0},"30":{"body":0,"breadcrumbs":0,"title":0},"31":{"body":1,"breadcrumbs":0,"title":0},"32":{"body":0,"breadcrumbs":0,"title":0},"33":{"body":0,"breadcrumbs":0,"title":0},"34":{"body":1,"breadcrumbs":0,"title":0},"35":{"body":0,"breadcrumbs":0,"title":0},"36":{"body":0,"breadcrumbs":0,"title":0},"37":{"body":0,"breadcrumbs":0,"title":0},"38":{"body":3,"breadcrumbs":0,"title":0},"39":{"body":2,"breadcrumbs":0,"title":0},"4":{"body":3,"breadcrumbs":1,"title":1},"40":{"body":0,"breadcrumbs":0,"title":0},"41":{"body":17,"breadcrumbs":0,"title":0},"42":{"body":0,"breadcrumbs":0,"title":0},"43":{"body":0,"breadcrumbs":0,"title":0},"44":{"body":0,"breadcrumbs":0,"title":0},"45":{"body":2,"breadcrumbs":0,"title":0},"46":{"body":0,"breadcrumbs":0,"title":0},"47":{"body":0,"breadcrumbs":0,"title":0},"48":{"body":0,"breadcrumbs":0,"title":0},"49":{"body":0,"breadcrumbs":0,"title":0},"5":{"body":3,"breadcrumbs":1,"title":1},"50":{"body":0,"breadcrumbs":0,"title":0},"51":{"body":0,"breadcrumbs":0,"title":0},"52":{"body":0,"breadcrumbs":0,"title":0},"53":{"body":1,"breadcrumbs":1,"title":1},"54":{"body":0,"breadcrumbs":0,"title":0},"55":{"body":1,"breadcrumbs":0,"title":0},"56":{"body":2,"breadcrumbs":0,"title":0},"57":{"body":1,"breadcrumbs":0,"title":0},"58":{"body":0,"breadcrumbs":0,"title":0},"59":{"body":1,"breadcrumbs":0,"title":0},"6":{"body":2,"breadcrumbs":1,"title":1},"60":{"body":0,"breadcrumbs":0,"title":0},"61":{"body":0,"breadcrumbs":0,"title":0},"62":{"body":0,"breadcrumbs":0,"title":0},"63":{"body":2,"breadcrumbs":0,"title":0},"64":{"body":0,"breadcrumbs":0,"title":0},"65":{"body":0,"breadcrumbs":0,"title":0},"66":{"body":0,"breadcrumbs":0,"title":0},"67":{"body":0,"breadcrumbs":0,"title":0},"68":{"body":0,"breadcrumbs":0,"title":0},"69":{"body":5,"breadcrumbs":0,"title":0},"7":{"body":2,"breadcrumbs":0,"title":0},"70":{"body":0,"breadcrumbs":0,"title":0},"71":{"body":1,"breadcrumbs":0,"title":0},"72":{"body":0,"breadcrumbs":0,"title":0},"73":{"body":0,"breadcrumbs":0,"title":0},"74":{"body":0,"breadcrumbs":0,"title":0},"75":{"body":3,"breadcrumbs":0,"title":0},"76":{"body":0,"breadcrumbs":0,"title":0},"77":{"body":0,"breadcrumbs":0,"title":0},"78":{"body":0,"breadcrumbs":0,"title":0},"79":{"body":0,"breadcrumbs":0,"title":0},"8":{"body":1,"breadcrumbs":0,"title":0},"80":{"body":0,"breadcrumbs":0,"title":0},"81":{"body":4,"breadcrumbs":0,"title":0},"82":{"body":1,"breadcrumbs":0,"title":0},"83":{"body":3,"breadcrumbs":0,"title":0},"84":{"body":0,"breadcrumbs":0,"title":0},"85":{"body":0,"breadcrumbs":0,"title":0},"86":{"body":1,"breadcrumbs":0,"title":0},"87":{"body":2,"breadcrumbs":0,"title":0},"88":{"body":0,"breadcrumbs":0,"title":0},"89":{"body":2,"breadcrumbs":0,"title":0},"9":{"body":2,"breadcrumbs":1,"title":1},"90":{"body":4,"breadcrumbs":0,"title":0},"91":{"body":2,"breadcrumbs":2,"title":1},"92":{"body":0,"breadcrumbs":1,"title":0},"93":{"body":4,"breadcrumbs":1,"title":0},"94":{"body":4,"breadcrumbs":1,"title":0},"95":{"body":0,"breadcrumbs":1,"title":0},"96":{"body":2,"breadcrumbs":1,"title":0},"97":{"body":1,"breadcrumbs":1,"title":0},"98":{"body":0,"breadcrumbs":1,"title":0},"99":{"body":0,"breadcrumbs":0,"title":0}},"docs":{"0":{"body":"","breadcrumbs":"精益副业 » 精益副业","id":"0","title":"精益副业"},"1":{"body":"在很多人的印象中,副业也许只是挣点零花钱补贴家用的小打小闹。但实际上,它对于我们的整个职业有非常大的影响,甚至会改变我们的人生。 本章我们将从「职业可能性」、「职业自由度」以及「职业成长性」三个方面来进行说明。","breadcrumbs":"为什么副业特别重要 » 为什么副业特别重要","id":"1","title":"为什么副业特别重要"},"10":{"body":"S象限,在这里可以看成是 Easy 难度的B象限,因为自雇没有员工,可以不处理公司管理相关事务。 最熟悉的讨论就是回老家结婚,不,开工作室。我有不少北漂朋友都选择了这条路。本质上来说,这其实是一个好选择,但问题在于,如果没有做好前期准备,失败率也是非常高的。 在大公司工作的人容易产生一种幻觉,那就是把平台的能力当做自己的能力。以大公司的身份去和别人谈合作的时候,感觉都很容易。等到自己离完职才发现,同样的客户,你根本都见不到人。 我知道不少朋友都是因为高估了自己拉业务的能力,最后不得不又重返北上深。 加上全球经济放缓、美元投资减少,这种单线切换的方式又包含巨大的风险,所以很多程序员都选择了被锁死在E象限,成为永久的打工人。 我并不是说打工不好,但如果你不能较快地晋升到高级职位的话,就要仔细考虑如何应对正在形成的35岁新门槛。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » E→S,回老家开工作室","id":"10","title":"E→S,回老家开工作室"},"100":{"body":"","breadcrumbs":"精益副业 » 精益副业流程 » 精益副业流程","id":"100","title":"精益副业流程"},"101":{"body":"前边我们说到,在精益创业方法论里,有两个非常重要的假设,第一个就是「价值创建假设」。 因为不管是向用户销售软件还是在线服务,它本质上来讲其实是一种价值交换。也就是我们「给什么样的客户」「提供什么样的服务」,然后「收多少钱」的一个简单逻辑。 而围绕着价值的定义、创造和传播,我们可以使用一个非常棒的工具来描述它,这个工具叫做商业模式画布。商业模式听起来是一个很高大上的名词,但它具体化以后就很容易理解。 商业模式画布是以价值为中心的一张图,让我们把所有和价值相关的内容都放到上面,从而可以一目了然地纵观全局。 那下面,我们就来看一下商业模式画布是怎么围绕核心价值,一层一层建立起来的。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 商业模式画布","id":"101","title":"商业模式画布"},"102":{"body":"商业模式的核心,就是「价值主张」。也就是刚刚提过的,对谁,提供什么样的服务,收多少钱。 picture 6","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值的定义","id":"102","title":"价值的定义"},"103":{"body":"定义好价值以后,我们会从两方面来考虑它。首先是如何把这个价值给创造出来;然后是如何把这个价值给销售出去。 在价值创造这边,我们可以把它细化为三个方面。 picture 7 包括: 我们需要进行什么样的活动?这里的「活动」是「activity」,其实也可以叫做动作。 我们需要什么样的资源? 我们需要进行哪些合作?","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 创造价值","id":"103","title":"创造价值"},"104":{"body":"在价值销售这边呢,我们就要思考: picture 8 我们的价值主张定义得够不够好? 我们的渠道通路是不是足够的通畅,到达是不是有效? 我们的客户关系要怎么来建立和维系? 其实价值主张应该放到价值定义里边,但因为价值主张它直接涉及到了客户细分,又直接影响到了销售,所以我暂时把它放到销售这一边。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 销售价值","id":"104","title":"销售价值"},"105":{"body":"按前面的描述,我们比较容易把商业模式画布当成一张图。但事实上,它其实更类似于Photoshop 软件中 的 PSD 文件,是分层的。其中每一层针对一个细分人群。 这主要是因为我们提出的价值主张,很难同时覆盖多个人群。同样的价值主张对一类人来讲可能是非常棒的东西;而对于另一类人来讲可能就毫无用处。 所以,我们提出价值主张之前,就需要进行客户细分,把我们的客户分成几类典型的角色,再针对每一类角色来提出更为具体、更有针对性的价值主张。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 分层结构","id":"105","title":"分层结构"},"106":{"body":"下面我们就实际来看一下商业模式画布的布局。 picture 9 在表格的最中间,就是我们的价值主张。在最右边,是客户细分。我们可以用不同颜色的文字,来代表不同的细分客户和针对他们的价值主张。 在价值主张表格的左边,是关于价值创造的区域,有「关键活动」、「关键资源」、「关键合作伙伴」;在价值主张表格的右边,是关于价值销售的区域,除了我们刚才已经说过的「客户细分」,还包含了「客户关系」和「渠道通路」。 表格的最下边一行,分成了两部分,左边是「成本构成」,右边是「收入来源」,它们都是根据我们上面的表格来进行计算的。一旦计算完,我们就可以预先知道这个项目做下来能不能挣钱,或者说挣钱的可能性有多大。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 画布结构","id":"106","title":"画布结构"},"107":{"body":"在整个商业模式画布里边,「价值主张」和「客户细分」是最为基础、也最为关键的地方。如果价值主张没定义好,其他的做得再好也没有用。 所以,为了更好地进行价值主张设计,我们还有一张专门针对这两个部分的、更为详尽的「价值主张画布」。 picture 10 上边这张图就是「价值主张画布」。它左边是「价值主张」,右边是「客户细分」。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值主张画布","id":"107","title":"价值主张画布"},"108":{"body":"在「客户细分」这里,它更为详尽地描述了客户的情况。 这个圆分为三部分,最右侧描述了客户想要进行的工作、要完成的业务;下方是他在完成这些工作的时候所感受到的痛苦;上方是在完成工作后可以得到的收益。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 客户细分","id":"108","title":"客户细分"},"109":{"body":"图左边的正方形就是我们的价值主张。可以看到,价值主张是针对需求提供的解决方案。比如:针对痛点,我们会提供「痛点缓释方案」,让客户在完成工作的过程中,没有那么痛苦;针对收益,提出「收益创造方案」,让收益变得更多。 在这两个方案的基础上,我们通过产品和服务的形式来将其落地,也就是正方形的左侧部分。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 价值主张","id":"109","title":"价值主张"},"11":{"body":"当我们有了副业,情况就完全不一样了。 因为我们从单进程变成了多进程,可以并行地进行尝试。最重要的是,这种尝试并不会影响我们的主业,不会降低我们的生活质量。 我们还是以上一节的两个例子来看。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » 副业带来的可能性","id":"11","title":"副业带来的可能性"},"110":{"body":"大家可以注意到,在「客户细分」的圆形和「价值主张」的方形中间,有两个正对着的箭头,它表示「价值主张」和「客户细分」之间要达成契合。 因为我们会把整个客户群体分成多个细分群体,所以价值主张画布,它其实也是多份的。针对每一个细分的客户群体,都会有一张自己的价值主张画布。","breadcrumbs":"精益副业 » 精益副业流程 » 商业模式画布 » 契合","id":"110","title":"契合"},"111":{"body":"上一节讲了如何通过商业模式画布来规划商业逻辑,但是「所有的战略和规划都是假设」,只有被验证以后的认知才是可靠、可信的。所以接下来,我们就需要用实验的方式来对它们进行验证。 通常,我们会采用「最小可行产品」(Minimum Viable Product,缩写为 MVP)来进行验证。 「最小可行产品」有两个关键词。一个是「可行」,它其实并不是指用户拿过去能用,而是指它可以很好地验证我们的假设。 另一个关键词是「最小」。它是说,除了验证所必需的功能以外,其他的功能都应该先不做。那些功能应该在验证完成之后再去添加,不然如果我们验证失败的话,功能就白做了。在我们的精力非常有限的情况下,这种浪费是非常可惜的。 严格意义上来讲,我们可以针对整个商业规划里边的每一个假设来做一个最小可行产品对其进行验证。但是我们的精力是有限的,所以通常只对核心假设通过MVP来验证。这个核心假设就是我们之前提到过的「价值创建假设」。 一旦这个假设被证实了,我们就认为我们找到了「产品和市场之间的契合」(Product-Market Fit,缩写为 PMF)。 具体而言,我们会在验证假设之前,定下一些量化的指标。在我们验证的时候,进行相应的衡量。最后根据指标的数据,来判断是否达到了 PMF。如果是,就可以进一步的增加功能,往前推进;如果不是,则需要调整,甚至需要通过战略转型来重新找到 PMF。 这种转型可以是针对原有市场的细分市场重新提出价值主张;也可能是扩大需求,让它支持更广泛的人群。但无论如何,在找到 PMF 之前,我们都应该专注于价值假设的验证,而不是功能的丰富和市场的推广。","breadcrumbs":"精益副业 » 精益副业流程 » 最小可行产品和产品市场契合 » 最小可行产品和产品市场契合","id":"111","title":"最小可行产品和产品市场契合"},"112":{"body":"前面我们给大家介绍了精益副业的基本概念,因为只有理论,所以看起来可能比较抽象。 从这一章开始,我们就以实际的副业实践为例,看看如何使用精益副业流程贯穿始终,多快好省地发展副业。我们安排了两个深度实践,一个是独立开发、一个是网课。下边我们开始第一部分。","breadcrumbs":"精益副业 » 精益独立开发实践 » 精益独立开发实践","id":"112","title":"精益独立开发实践"},"113":{"body":"picture 1 前面我们了解了精益创业的一些核心理念,接下来我们就在「独立开发」这个更为具体的副业活动中来看看如何应用精益流程。 这个流程和很多硅谷公司的产品流程很像,但是针对副业做了一些调整和优化。经过三年多时间的使用,我们自己用起来已经很顺手。 首先定义价值主张,然后围绕着价值来设计商业模式画布。 完成画布以后,我们把画布里的「客户细分」部分拿出来,做成「用户画像」。这是一个将细分客户具体化、变得有血有肉的工具 有了画像,再据此还原用户使用产品的各个场景,他们是用电脑还是用手机、是在家里还是在车上使用等等。 想象为了在上述场景下向用户传递价值,我们需要什么样的功能,这样就会得到一个功能列表 功能列表会很长,不同功能的优先级也不同。所以我们会对功能进行分期,其中最重要也是最靠前的一个功能分期,就是用来开发「最小可行产品」的分期。 当「最小可行产品」开发完成后,进行「产品市场契合」的验证,如果达不到设定的验证目标,就需要调整功能,甚至重新设计价值主张。 当通过「产品市场契合」后,我们就可以按照分期迭代开发产品的其他功能了。 在迭代过程中,我们会持续对新上线的部分功能进行增长优化,保证每一部分功能达到预定的目标。 以上就是我们为独立开发优化的精益流程,虽然讲起来比较多,但实际操作起来还是比较简单的。而且我们其实省略了不少大公司流程中的环节,比如用户访谈、焦点小组等。 下一节开始,我们将用一个具体的例子来讲解。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独立开发的精益流程 » 独立开发的精益流程","id":"113","title":"独立开发的精益流程"},"114":{"body":"先来介绍一下我们的实战项目 —— 福利单词。 它来自于我在学习过程中的一个原生需求。最开始我是使用 Anki 这个软件来背单词,软件很好用,但是每次都有一种逼着自己去背的感觉,背完以后如释重负。为了提醒自己不要逃避,我还定了一个闹钟每天催自己。 有一天,我又因为上 Pixiv (一个二次元内容创作社区)看图忘记了时间。突然间我想到,能不能把背单词和看图片这两个行为绑定到一起呢? 你看,背单词虽然有用,但让我痛苦,度日如年;看图片很欢乐,流连忘返,但似乎不是很「有用」。如果我们把两者结合到一起,一边看图一边背单词,是不是就可以让背单词不那么难受,可以持续不断地背下去了? 这就是福利单词的出发点。 接下来,我们就来看看,怎么从这个还有些模糊的想法中提出一个明确的价值主张,然后围绕它进行商业模式规划、功能和界面设计、验证和迭代开发,最终使其成为一个商业产品。 picture 2 需要说明的是,开发过程很难在有限的篇幅中讲解清楚,也偏离了本书的主题,所以我们只会简略地提及一些需要注意的地方,并不会进行开发的教学。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词项目简介 » 福利单词项目简介","id":"114","title":"福利单词项目简介"},"115":{"body":"前边我们已经讲解过商业模式画布,这一节我们就以「福利单词」为例,来看看怎么使用。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 福利单词的商业模式画布","id":"115","title":"福利单词的商业模式画布"},"116":{"body":"picture 3 首先来看一下价值主张。它的核心价值就是,让那些觉得学习起来很痛苦的人不那么痛苦,给一点糖,让其可以持续地、无痛地学习下去。它试图给学习过程添加一些乐趣来综合不是那么爱学习的人的痛苦,从而把一个短暂的、难以忍受的学习行为变成一个可以持续忍受、甚至通过习惯驱动可以持久化的行为。 所以我们在「价值主张」这一栏上写上两个关键字,一个叫「无痛学习」,一个叫「持久化的学习」,这是这个产品最核心的两个「价值主张」。 有了这个价值,我们就能帮助客户完成很多以前想学、但是因为各种原因没有办法学下去的东西,从而实现其个人成长和提升。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 价值主张","id":"116","title":"价值主张"},"117":{"body":"picture 4 如果要具体化价值主张,就要来看客户细分。 因为是单词学习软件,所以客户群体往往还是跟学习英文需求相关的。具体划分下来,我觉得可以分成三大类。 第一类是在学校要考英语四级或者六级的大学生。 第二类是有留学或者移民需求,需要考雅思、托福的群体。 第三类是需要专业英语来提升自己在职场的业务能力的上班族。 前两类群体是要备考应试的,后一类则更注重实用能力的提升。从学习的内容上来讲,只是题库的不同。所以如果我们的软件支持了「词库切换」或者「自定义词库」功能,就可以比较容易地覆盖他们的学习需求了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 客户细分","id":"117","title":"客户细分"},"118":{"body":"picture 5 光是「有词库,你来背」这个主张和其他背单词软件并没有什么不同,所以我们需要在「价值主张」里再加上「糖」。 但是,对于不同的群体来讲,「糖」是不一样的。如果只是放一些二次元的萌妹子,只有喜欢动漫的人会觉得这是他们的「糖」,可以吸引着他们,每天都来看一看。对于其他一些二次元无感的人群来讲,这些图就毫无吸引力,于是我们需要增加「糖」的种类。 比方说有的妹子就喜欢看帅哥、有的粉丝就喜欢看偶像、有的铲屎官就喜欢看猫猫狗狗、有的吃货就喜欢看肉和甜点。这一部分,我们可以用多图库的方式来满足。 于是,针对不同的客户细分,我们提出三个更为细化的价值主张: 「每天看40分钟妹子,一个月记住四六级词汇」 「看着帅哥,把雅思托福词汇搞定」 「一边云吸猫一边升职加薪」 现在听起来是不是就有吸引力多了?","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 价值主张的细化","id":"118","title":"价值主张的细化"},"119":{"body":"picture 6 在「渠道通路」的这个方格里面呢,我们的种子用户主要由微博带过来的流量构成。 通过种子用户进行测试,一旦转化率达标,我们就可以开始对外去做一些合作,以及以微博为起点投放广告,观察广告投放的成本和其带来的流量的关系,以此判断下一步操作。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 渠道通路","id":"119","title":"渠道通路"},"12":{"body":"采用副业的方式操作,我们在离开北上深之前就可以创立自己的工作室,并开始接活。一方面拓展客户,累积口碑,另一方面,我们还可以从客户的案例中提取重复需求,将其产品化、服务化。等到有了自己的客户和产品,我们在哪个城市已经不那么重要了,甚至可以在全国一个城市住上那么一两个月,一边旅行一边工作。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » E→S,回老家开工作室","id":"12","title":"E→S,回老家开工作室"},"120":{"body":"picture 7 在「客户关系」这里,我们会通过腾讯提供的「兔小巢」这个产品来提供售后支持。它是类似于反馈板的免费工具。用户在上面提交问题,我们会收到微信或者QQ的通知,可以通过网页在电脑上或者手机上进行答复。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 客户关系","id":"120","title":"客户关系"},"121":{"body":"picture 8 接下来我们来看一下「关键活动」。 用来验证需求的最小可行产品(MVP),是一个简单网页,只包含 100 个单词、100 张图片和简单的输入文字切换图片功能即可。我们还需要一个统计数据,看看每一个访客到底背了多少个单词。这关系到我们价值主张里的「无痛」和「持久」。 当这个价值被验证后,就可以进入第一期开发。 虽然是一个全平台应用,我们第一期却只做网页版。具体业务包括:背单词的界面,以及选择词库的界面。这是最核心的业务功能。如果我们第一期想要有收入,那么就需要支付和订单系统。 为了对转化过程进行分析、更好地挣钱,我们还需要开发一个2A3R漏斗的统计,让用户从获客层顺利滑入付费层。如果需要通过分享裂变获取更多流量,我们也需要统计发起分享的用户数据。如果要允许用户自定义词库,我们就要提供对应的制作工具。 以上这些,构成了我们的关键活动。关键活动可以采用不同颜色的文字来标记不同的分期,也可以一期一期追加。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 关键活动","id":"121","title":"关键活动"},"122":{"body":"picture 9 在关键资源上,除了需要具备人、钱和时间以外,我们这个项目还有特有的资源需要考虑,那就是背单词所用的图片,这是一个非常值得注意的问题。 在最小可用产品中,因为不涉及到收费,我们可以使用的图片很多。一旦开始收费,如果还是不加识别地从网上下载各种版权不明的图片,放到自己软件里并以收费的方式进行售卖,很可能会出现侵权。 所以,我们就需要思考图片资源的解决方案。粗略分析后,有以下几种思路: 作者授权 换用无版权图片 用户自行提供图片","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 关键资源","id":"122","title":"关键资源"},"123":{"body":"直接找作者把图片买下来,然后作为付费词库卖给用户,这是最直接的方式。但有问题,那就是价格,光是大一点的词库就有超过一万个单词,也就是说我们要买一万多张图。如果按一张图 50 元计算,需要 50 万的投入。 在一分钱都还没挣之前就做出这么大的投入,风险还是很高的。这种方式更适合我们挣到钱以后,在扩大规模时使用。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 作者授权","id":"123","title":"作者授权"},"124":{"body":"当然,我们也可以寻找无版权的图片来做图库。这样即使我们打包在软件里进行商业销售也不会有任何问题。互联网上已经有比较庞大的无版权高清图库了,比如 Unsplash 等。不过这些图库主要是风景和动物,人物类非常少。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 换用无版权图片","id":"124","title":"换用无版权图片"},"125":{"body":"本质而言,我们卖的是「看图背词」的工具,而不是图片本身。现在之所以在版权上有风险,是因为打包导致的。所以我们可以尝试着将付费的服务和免费的图片分离开。 比如我们可以给用户提供自定义图库的制作工具,让他们把自己收藏的图片导入进去。这样既能达到目的,又没有版权上的风险。 类似需要考虑的,还有背单词时用到的音频。最简单粗暴的方式是使用云平台的TTS(文字转语音)接口直接生成。","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 用户自行提供图片","id":"125","title":"用户自行提供图片"},"126":{"body":"picture 10 在填好这几个格子以后,我们就可以开始对成本和收益进行相应的预估,算出预期利润区间。 由于我们开发的项目相对比较小,用到的资源也不是特别的多,所以商业模式画布做得还不算细致。不过通常来讲,第一版的商业模式,画布本身也不会特别细。它是随着项目的进展不断被细化的。 最后我们来看看完整的商业模式画布: picture 11","breadcrumbs":"精益副业 » 精益独立开发实践 » 福利单词的商业模式画布 » 成本收益","id":"126","title":"成本收益"},"127":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 通过用户画像细化客户","id":"127","title":"通过用户画像细化客户"},"128":{"body":"在商业模式画布里面,我们对客户进行了细分,把客户分成了不同的组,每一组代表一个独立的需求。 用户画像(persona)呢,就是给这些已经分好的组,每一组搞一个人设、建一个虚拟形象,让其变得有血有肉、有姓名有年龄有性别、有自己的身份有自己的爱好、有使用产品的场景。 这样当我们聊到这个用户画像的时候,就像在讲自己的朋友、同事一般熟悉的人一样。 把抽象的需求变成活灵活现的人,这样我们在进行产品设计的时候,就更容易还原到场景,带着画面去想象这个人的需求和行动,这就是用户画像的意义。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 什么是用户画像","id":"128","title":"什么是用户画像"},"129":{"body":"接下来,我们就在福利单词的客户细分基础上,为每一类客户建立用户画像。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 福利单词的用户画像","id":"129","title":"福利单词的用户画像"},"13":{"body":"有了副业,B象限等于完全开放了。不要纠结于是否成立了公司,那只是一个形式。真正驱动公司的是业务能力和运营公司的能力,而这些我们都可以通过副业练出来。 把创业想法以 Side Project 的方式来运作,以最简单的产品直扑最核心的需求。没有经验和所谓的产品感都不要紧,因为副业我们是输得起的。这个项目找不到需求,那么复盘以后开始下一个。那些创业公司花大价钱验证的认知,我们通过 Side Project 同样能获得,只是时间可能更长一些而已。 这种低风险的创业模式,也是非常契合当下的创业环境的。创新工场的汪华 在2020年4月的一场分享 中提到,移动互联网信息、交易等纯界面层的战争已经基本结束,那种靠想法和快速扩张的打法,已经很难奏效了。 所以通过副业的方式,扎扎实实地经营一家企业,靠对市场的理解、优质的产品、良好的管理和持续发展取胜,才是新时代更好的选择。 可以看到,引入副业后,我们可以以低风险、并行的方式在职业象限中移动,为职业的发展带来了无穷的可能性。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 副业带来的可能性 » E→B,创业","id":"13","title":"E→B,创业"},"130":{"body":"首先是备考四六级的大学生这个细分客户群。我们叫他王小康,设定为一个大三的男生。他现在有一个迫切的任务,就是一定要通过四级考试。这位同学是一个动漫宅,他喜欢看的图就是二次元的萌妹子。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 四六级备考生","id":"130","title":"四六级备考生"},"131":{"body":"然后我们来给有留学移民需求、需要考雅思和托福的人群做一个用户画像。我们叫她章小留,她是一个大学刚毕业一年的女生,现在有出国留学的想法,正在准备雅思考试。这位同学是追星族,喜欢看的图片是韩国帅哥。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 留学移民预备军","id":"131","title":"留学移民预备军"},"132":{"body":"第三个细分人群的用户画像,我们叫她卢小白,是一个毕业两年左右的女生。在生物公司从事技术相关的工作,她需要尽快熟悉大量的生物专业方向的英文单词,方便她更好地了解公司业务。她家里有猫,喜欢看的图片是萌宠和美食。 确定了这三个用户画像的基本资料以后,我们会给他们配上头像,写上他们的需求关键字,把它整理到一页A4纸上。 这样我们就可以把它打印出来,贴到墙上,在做产品设计的时候可以随时去看他们,就像看着我们身边的熟人一样。","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 专业提升小白领","id":"132","title":"专业提升小白领"},"133":{"body":"很多书里面都强调说,用户画像的头像要尽可能真实,最好用真人头像。但需要注意在网上乱找真人头像容易导致肖像权问题,这里给大家推荐一个通过AI生成真人头像的网站,叫做 thispersondoesnotexist.com。 picture 12 不过这个网站生成的多是欧美人,对国内的产品来讲,反而各种违和。我更喜欢使用日系的动漫捏脸网站来做,比如 charat.me 这个网站。 picture 13","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 画像的头像制作","id":"133","title":"画像的头像制作"},"134":{"body":"有了头像,再配上角色的说明和需求关键字,我们就有了一个简单好用的用户画像。下边是我们制作好的三个画像: picture 14 picture 15 picture 16","breadcrumbs":"精益副业 » 精益独立开发实践 » 通过用户画像细化客户 » 最终的用户画像","id":"134","title":"最终的用户画像"},"135":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 画像→场景→功能和分期","id":"135","title":"画像→场景→功能和分期"},"136":{"body":"有了栩栩如生的用户画像,我们就可以从画像想象出场景,再由场景梳理出功能列表并进行分期。下边我们就具体来看下怎么分析使用场景。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 使用场景分析","id":"136","title":"使用场景分析"},"137":{"body":"首先是王小康的使用场景,包括在学生宿舍、在图书馆以及在课堂上。 在宿舍,他每天晚上八点到九点使用台式机。因为宿舍比较吵,他会戴着耳机学习。这时候他使用的是外接键盘。 晚上睡觉之前,他还会窝在被窝里玩一会儿手机,时间大概是晚上十一点半到十二点,也就是睡觉前的半个小时,这时候的使用场景就是用手机背单词。 图书馆也是一个典型场景,因为在这个环境里边,需要保持安静。所以你要么戴耳机,要么将设备调成静音。王小康一般是下午三点到五点去图书馆自习,这个时候他使用的是笔记本电脑和 iPad 。 需要注意的是使用 iPad 的时候是没有键盘的,所以在输入上面没有使用外接键盘方便,整体输入速度会下降很多。 图书馆和学生宿舍是两个相当不同的场景。宿舍里很可能有室友在玩游戏或者聊天,很容易分心,甚至连背单词这件事都很容易忘掉,所以我们需要有提醒。 相对而言,图书馆就是安静的沉浸式环境,没有人来打扰你,大家都在忙着学自己的东西。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 王小康的使用场景分析","id":"137","title":"王小康的使用场景分析"},"138":{"body":"下面我们来做章小留的场景分析。 她现在辞职在家,完全是备考的状态。每天上午会在家学网课、或者去线下的培训班学习,下午会在家学词汇。晚上的话,可能要看韩剧。 主要场景在学词汇的下午。因为是在家里边,她使用的是台式机,鼠标和键盘都是外接的。每天早上起床的时候可能也需要复习一下。 所以她的两个主要使用场景是使用电脑学习,以及早上起床时用手机进行复习。 实际上,这个场景和王小康在晚上用手机复习的场景非常类似,可以都写上,最后进行功能合并时,重复的内容会被合并掉。 同时,因为这两个用户都是在备考,所以他们其实还有「考试复习」这个特殊场景。 在这个场景里,它的词库是有范围的,不一定是整个词库。而背单词的时候,需要有一个考试模式,限时答题,并给出得分。这些需求我们不一定都要通过福利单词这个产品来满足,但可以先写下来。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 章小留的使用场景分析","id":"138","title":"章小留的使用场景分析"},"139":{"body":"小白是上班族,所以学习时间是非常有限的,主要是在上下班通勤的时候学习,以及在周末的时候有一点空余时间。 通勤场景一般会在地铁上。运气好的时候就有座位,运气不好的时候还需要站立着。这时候她会使用手机和耳机来学习。 因为她的词汇学习主要是为了工作需要,所以在工作的时候可能还会有查词的需求,可以通过词典软件解决,但是她可能会想把生词加入到福利单词来记忆。 大部分时间地铁里是很挤的,有时候需要一个手扶住上面的吊环或者旁边的柱子,所以小白可能需要单手操作。 另外要意识到小白只是一个典型代表,她需要的是生物类的词汇,但是其他的上班族需要的词汇可能会覆盖各行各业,这部分的词库需要通过自定义词库来解决。 同时,小白很喜欢宠物,当她看见可爱的喵星人时,很可能希望将这个图片保存到相册。这里如果再结合到我们上面的考试模式的话,其实可以做得更游戏化一些。比如说我们可以加入一个图鉴,就是一个画册,里边有每一个单词对应的图。只有你对这个单词达到一定的熟练度以后,才能在里边看见。大体上这就是小白的使用场景。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 卢小白的使用场景分析","id":"139","title":"卢小白的使用场景分析"},"14":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 职业自由度","id":"14","title":"职业自由度"},"140":{"body":"现在我们三个用户画像的使用场景已经分析完了。接下来,我们就可以根据场景来确定功能了。也就是说,为了满足这些场景下的需求,我们在产品上需要提供哪些功能来支撑。 在确定功能的时候,有两类需要特别注意。一类是核心功能,没有它,所有画像都没法使用我们的产品。另一类是边界功能,没有它,某一个画像就没法使用我们的产品。核心功能是交集、边界功能是并集。 我们会根据画像的设定,将一些边界功能分配给他们。比如说,为什么卢小白她就会想保存图片到相册,章小留就不会呢?事实上章小留也会,但我们不需要把一个边界功能重复分配,因为最终都会覆盖到。 画像需要注意的是它特有的场景,比如考试模式是备考生的特有场景。对于不考试的同学来说有没有都无所谓,但是对考试的同学是非常有用的。 我们把边界功能标记出来以后,就可以框定一个大体的功能范围。 比如说,章小留使用的是苹果台式机,这就要PC版需要同时支持 Windows 和 Mac 两个操作系统。路小白上下班通勤的时候是单手操作,我们在手机上设计浮动键盘时,就要考虑到小屏幕手机上26键的全键盘单手时容易按错的问题。 对于卢小白来讲,她的空余时间不多,所以可能还会利用家务和健身的时间,这个时候如果她想复习单词,可能还有一个语音播报的需求。 章小留是追星族,那她在网上看韩剧的时候,会顺便把喜欢的偶像的图片给保存下来,制作成词库,甚至还会分享给同好。 这些都是边界功能。在早期设计的时候,可以先不考虑工期、开发量这些很现实的问题,我们可以先把它放进来思考,至于做不做、什么时候做,那是以后的事情。 我们要做的东西在早期应该尽可能的少,但是思考的范围却应该尽可能的广。我们是把很多东西都想明白了以后,选其中最核心的、最重要的来做。而不是说很多东西我压根就不想,只做眼前看到的那一丁点就开始做了。这样到项目中期,就会出现很多思考上的盲点,这些盲点甚至会导致我们的项目重做,所以需要尽可能避免。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 从场景到功能","id":"140","title":"从场景到功能"},"141":{"body":"我们可以通过思维导图软件来梳理功能。 想象一下新用户从什么地方开始使用我们的软件,跟着他的使用流程来同步构建功能。 比如说,首先会需要有一个用户系统,这样我们才能识别用户。接着我们肯定需要有词库,不然就没有单词可以背了。我们肯定也需要有单词的背诵、管理,如果我们要收费的话,肯定还需要有支付。 用户系统里边,我们考虑使用微信登入,这是目前最简单的办法,不用做用户系统、也不用做密码找回。有了登入肯定也得有退出。 有了用户系统以后我们就可以保存用户背单词的进度了。在词库这边呢,既然我们要做一个可切换和自定义的词库,那肯定会有一个列表。 这个列表,首先是会有一个官方的或者叫内置的,然后我们在建立一个本地的列表,给自定义词库用的。 自定义词库这边,我们可能还需要给提供一个工具来制作词库。我们需要有一个单词表、需要生成对应的音频、需要有对应的解释,以及我们背单词的时候看的图片。这是词库的大体功能。 如果我们要做图鉴的话,就需要有词库的完成度数据。就是用户背了词库里面百分之多少的单词、以及对每一个单词的熟练度。在这个基础上我们还需要有一个相册,用来欣赏高清图片。 自定义词库制作完成以后,它还需要有一个分享方式。我们可以允许用户通过二维码分享,其他的用户通过二维码扫码导入。 接下来,我们来看背单词的功能。 首先它需要有一个地方来输入字母,我们会根据输入的字母动态地进行遮罩的调整。然后我们需要把用户输入的时间或者错误的次数统计起来,这代表着对这个单词的熟练程度。我们也还需要有一些辅助按钮,用来显示单词的意思、以及跳过不会的单词。 在最后,当正确地输入了单词以后,我们需要显示一个高清图片,让用户可以很完整地看见这张图片,这是对其的奖励。 另外我们也需要把用户的背单词成绩记录下来,为了能更清楚地看见这个成绩,可能还需要提供一个进度统计,告诉用户背了词库里面的百分之多少,各自的熟练度是多少。 还有支付部分别忘了。首先我们要显示可以付费的商品,当点击购买按钮以后,要把微信支付给呼叫起来。在微信支付完成以后,要进行确认。同时我们也需要维护一个订单列表来进行售后和退款。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 通过思维导图梳理功能","id":"141","title":"通过思维导图梳理功能"},"142":{"body":"确定好功能表以后,接下来就可以进行分期了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 分期","id":"142","title":"分期"},"143":{"body":"因为我们现在的功能实际上已经非常多了,必须要把它分成不同的阶段来做。最小可行产品不太典型,这里我们以 PMF 验证完成后的第一个版本为例,来选择第一期的内容。第二期就是「以后再做」的功能,第三期就是「不知道啥时候做」的功能。 来看我们的功能列表: 推送提醒:可以放到第一期。但为了实现推送,需要有消息系统。如果要做定时提醒的话,还需要做设置界面。因为用户设置过提醒以后,可能有一天不需要了,要能及时取消,不然天天推送还挺烦人的。 考试模式:放到第二期。虽然对备考生很重要,但是因为整个开发量比较大,在挣钱之前可以先不做。 虚拟键盘:放到第一期。为了支持单手操作,我们需要给背单词的界面添加在移动设备上的键盘界面。不同输入法的键盘可能会导致兼容性问题,所以我们直接通过一个虚拟键盘来解决它。 自定义词库分享:放到第二期。 图鉴模式:放到第二期,也可能是第三期。 语音回放:放到第二期。 picture 17 确定分期的时候,也要同时检查功能点是否都对应上了。比如支付里面,我们需要把「微信支付的对接」加上。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 功能分期","id":"143","title":"功能分期"},"144":{"body":"确定好某一期的功能列表后,可以把各个功能归类到界面里。新建一个思维导图,写上显而易见的各个界面,然后把功能放到界面下去。 如果发现有功能没有界面放,恭喜你提前发现了做丢的界面,赶紧把这个界面也加进去吧。 picture 18 这一步完成以后,我们就可以开始进入设计阶段了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 画像→场景→功能和分期 » 功能归类到界面","id":"144","title":"功能归类到界面"},"145":{"body":"这一节开始我们会讲一些设计方面的东西。和专业的设计课不同,我们主要着眼于如何让非专业设计人员也能做出七十到八十分的设计。 首先我们来和大家聊一聊,什么是好的商业设计。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 什么是好的商业设计","id":"145","title":"什么是好的商业设计"},"146":{"body":"要做好一件事,首先要弄明白好的标准是什么,而这恰恰是讨论设计时的一个难点。 为什么呢? 我们写程序做软件,好不好是有一个相对可以量化的指标的。比如:用了多少行代码,执行了多久时间,占用了多少内存、在一秒以内可以承受的并发请求数是多少。这些都可以很精确地衡量出一个程序是否写得好。 但是,对于设计来讲,它是一个很个人化的东西。同样一个设计,有的人会觉得它好,有的人会觉得它不好,还没法说谁对谁错。甚至有一些艺术家,他的作品可能在当时就没有人能够理解,隔了很多年大家又把它拿出来,才发现惊为天人。 这就造成了一个问题,设计到底应该按什么样的标准去衡量?不光是设计师本身需要思考这个问题,设计需求的提供方其实也需要去思考。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 好设计的标准","id":"146","title":"好设计的标准"},"147":{"body":"但是后来我们发现,如果把设计的范围给缩小一些,就可能得出一个部分适用的答案。 艺术这个东西它确实是千人千面的,因个人的感受而异。但是我们为商业产品做的设计它并不等价于艺术,大部分情况下它是为商业服务的,我们就叫它「商业设计」吧。 一个好的商业设计,其实就是要让尽可能多的客户喜欢它。因为,喜欢上我们设计的人,很可能也会喜欢上我们的品牌和产品,最终转变成商业价值。 至于这个设计在艺术上深刻不深刻,完全是另外一个领域的事情。 这里有一个比较极端、但大家也很熟悉的例子,那就是椰树椰汁的产品设计。它基本上是把美感给扔了,但换取了很好的识别度,这就是一种商业上的权衡。 我们写程序的时候,要从代码思维上走出来,回到商业思维的角度上来;我们做设计的时候也要从设计本身走出来,从整个商业链条的角度去思考。 通常来讲,我们会面临的抉择,往往是在两类截然不同的设计之间。一类剑走偏锋、足够深刻,能理解它的一类人特别地喜欢,而不理解的又特别讨厌它;另一类设计,看似中庸,然而平中见奇,不同层次的人都可以看到自己喜欢的点。 如果这个设计要拿去参加艺术大赛,可能前者更合适。但如果用于商业产品,那我觉得应该选择后者。因为归根结底,它是用来承载功能、向客户传递品牌质感的,而不是要体现它自身有多深刻,那样反而喧宾夺主了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 商业设计","id":"147","title":"商业设计"},"148":{"body":"每个人的兴趣和爱好都是不同的,要做一个设计或者塑造一种风格,让绝大部分人都喜欢上是很难的。但我们幸运的发现,设计如果足够简洁的话,就不容易包含太多触发各种反感的点,更容易获得绝大部分人的喜爱。 而对于副业来讲,简洁风格的方案所需要的设计和开发资源都相对较少,配合起来又比较容易协调,所以简洁风格是我们的首选。","breadcrumbs":"精益副业 » 精益独立开发实践 » 什么是好的商业设计 » 简洁即美","id":"148","title":"简洁即美"},"149":{"body":"界面设计是很多尝试自己开发完整产品的程序员非常痛苦的事情。很多时候,如果我们去问设计师,很多人虽然会设计,却讲不出背后的道理。只会说,「这样做感觉上更好一些」,「这就是经验/灵感」。 我以前也是这么认为的,直到读了一本书才明白,原来界面设计背后一样是有规律的。 界面的表层结构展现的正是它内部的逻辑。 一个界面上应该摆放哪些控件,哪几个应该离得近,哪几个应该离得远,哪些应该用同样的风格,哪些又应该区别开来,这些都源于它背后严密的逻辑关系,而不是因为设计师的一时兴起。 那本书就是《写给大家看的设计书》。在书里,作者提出了界面排版的四个基本原则,通过活用这四个原则,我们就能够把界面设计得美观大方。 这四个原则分别是「重复」,「对比」,「对齐」和「亲密性」。 「重复」原则强调「一致性」,它说的是「在逻辑上一致的物件,在视觉上也应该一致」。 「对比」原则强调「层次感],它说的是「逻辑上不同的物件,在视觉上也应该不同」。所以我们要想办法拉出距离来。 「对齐」原则强调的是「安定感」。均匀的留白能够营造出一种稳定的感觉。这正是产品质感的一种潜意识渗透。对齐虽然是很小的细节,但是如果处理不好,很容易会破坏产品整体质感,而且会给有强迫症的朋友带来莫大的压力。 「亲密性」原则,强调区块的关系,它说的是「逻辑上存在很近的关系,那么这个关系也应该表现在视觉上」。相关的项应该彼此靠近,不相关的项应该彼此远离。 书里有非常详尽的介绍和让人顿悟的例子,建议大家都去阅读下原书。 picture 19 四大原则回答了常见的一些界面问题。比如说,上图中,白色方块之间的间距为什么不能比第一个方块和页面边界的距离大。 如果从纯感性的角度来讲,可能会说「这样放不好看」。但是如果通过亲密性原则来思考的话,我们会发现在逻辑上,相对于页面边框,白色方块是一个整体。一个白色方块和另一个方块的关系,显然比它和页面边框近。所以这种深层关系表现在视觉上,就是它们之间的边距差异。 如果视觉关系和逻辑关系不一致,我们就会觉得「别扭」、「不直观」。这些原则为我们通过逻辑理解设计推开了一扇门,让之前仅存于「感觉」和「经验」的设计技巧变得有章可循。熟悉它们以后,只要多加练习,再配合上一些简洁、清爽风格的设计细节,我们就可以在大部分场景下做出七十到八十分的界面来。 picture 20","breadcrumbs":"精益副业 » 精益独立开发实践 » 人人能用的四大原则 » 人人能用的四大原则","id":"149","title":"人人能用的四大原则"},"15":{"body":"前面说了副业给我们的职业带来了更多的可能性,接下来我们就来看,副业给我们的职业带来的更大的自由度。 首先是职业选择的自由。 这里我们先来讲一个比较有意思的概念,它叫做 F*** you money。这是国外的一个词,我们把它翻译成「中指备用金」。 它指的是一笔钱,数量大概是这个样子:突然有一天你跟老板闹翻了,你可以竖起中指,跟他讲说老子不干了,然后辞职回家。在这种情况下,你的生活质量也不会受到影响。 标准意义上的「中指备用金」,其实是和财务自由差不多额度的一笔钱,是以「不工作」为前提的。如果大家在北上深,要做到财务自由还是很难的。 我们这里要讲的是以「换工作」为前提的一个低配版本。也就是说,你可以随意裸辞,在找到下一份满意的工作之前,这段可能会长达半年甚至一年的时间里,没有任何收入,但你的生活品质不会受到太大影响。 很多年轻一点的同学可能觉得根本不需要这种备用金,因为现在的 90 后 00 后正是这么干的。但是当你的年龄稍微大一些,还着房贷车贷、养着老人小孩的时候,要是突然没有收入来源,压力实际上是非常大的。 而副业,恰恰可以为我们提供这么一笔钱。可能总额不大,但可以持续不断的提供。 比如我现在的课程放到网易云课堂上,即使自己不在微博去做主动的营销推广,通过网易平台上的自然流量进行的课程转化,也会有几千块钱。 我现在在重庆生活,这边房租非常的便宜,一个近七十平的小两居,房租每月不到两千。加上日常花销,也就几千块钱。所以现在即使不去上班挣钱,副业也可以在相当长的一段时间里保证我的基本生活不受影响。 这种情况下,我们就可以花更多的时间去思考自己的职业、未来和人生。去做一些短期内收入不明显,但长期收益巨大的决定。 这也就是副业带来的选择自由。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 从中指备用金说起 » 从中指备用金说起","id":"15","title":"从中指备用金说起"},"150":{"body":"接下来讲下,如何设计产品的 Logo 。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 独特Logo解决方案","id":"150","title":"独特Logo解决方案"},"151":{"body":"最简单的方式当然是请设计师来设计,我们只需要像产品经理那样在背后指指点点,改需求、当甲方就好了。但是,在做副业时,我们很可能没有足够的预算去雇佣专业的设计师。尤其是在软件还没有获得收益之前,如果花很多钱去请设计师设计,而产品本身又运营不起来的话,钱就白花了。 所以,学会自己做一些比较简单能用的 Logo 还是很重要的。等以后挣钱了,可以再花大钱请高手来重新设计。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 为什么要自己设计 Logo","id":"151","title":"为什么要自己设计 Logo"},"152":{"body":"Logo 的设计还是有些考验绘画能力的,即使是相对简单的简笔画,对于很多没画过图的程序员来讲,也挺难绘制一个像样的出来。 如果你有一定的绘画基础,或者想发掘自己隐藏的天赋,那么我特别建议大家用矢量软件来绘制,对于像我这样手残的同学来讲特别有用。 我最开始画 Logo ,是给自己的开源项目。刚开始使用的是像素绘图软件。由于缺乏练习,即使使用数位屏,也很难绘制出光滑的线条。即使偶尔画出来了,要调整它时,又会花费大量的时间。 后来我发现了矢量绘图软件,在它里边,我们绘制的其实不是线条,而是一个个形状。线条是我们指定的形状的边界,可以通过描边自动生成。最棒的一点是,当我们改变形状时,线条就自动随之变动,无需再重新绘制。 只要熟悉了形状的画法,我们就可以通过矢量绘图软件来绘制一些简单的、线条光滑饱满的图案了。 picture 21 作为对比,上图左边是我用像素绘图软件绘制的头像,右边是后来我用一个周末学习完矢量绘图软件后花一天时间重新绘制的。真的是好用太多了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 通过矢量软件绘制 Logo","id":"152","title":"通过矢量软件绘制 Logo"},"153":{"body":"当然,不是所有同学都有时间和精力去学习绘图的,所以我们还是回到适合更多人的方案上来。首先,我们可以使用网上的开源矢量资源。最近两年开始出现一些视觉效果非常不错的矢量插图网站。 picture 22 比如 unDraw ,它就提供大量的适合互联网和软件场景的开源矢量插图。更贴心的是,在网站右上角还提供了颜色按钮,通过调整颜色,我们可以得到和自己产品风格更为统一的矢量图。 一个需要注意的地方是,如果使用免费素材,一定要留意不要从国内那些没有注明作者和授权的网站上下载。因为这些来历不明的素材很可能给你带来版权风险,说不定哪天巨额索赔就找上你了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 免费和开放的矢量资源","id":"153","title":"免费和开放的矢量资源"},"154":{"body":"如果没有好的免费备选,或者没有太多时间去各个网站上挑,我们还可以通过购买的方式来获取素材。 picture 23 在购买素材的时候,要注意使用的限制。有的网站的素材是会限制使用的项目数、域名、甚至媒体类型的。我推荐大家优先购买采用「royalty-free」许可的网站。这种许可非常开放,往往只要付费就可以永久使用。 提供付费矢量图标的网站比较多,比如 flaticon.com ,thenounproject.com 都是比较有名的。我个人一直订阅的是后者,提供的图标够多,价格也比较便宜。它还提供了一个电脑客户端,可以很方便的搜索、复制粘贴图标文件。 这个网站目前提供的图标都是没有颜色的。当然这一点可能对我们来讲,并没有太大的影响。为什么呢,因为直接使用这些网站上的图标做 Logo ,会带来一个潜在的问题。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 购买付费素材","id":"154","title":"购买付费素材"},"155":{"body":"这种买断式授权的素材非常好用,但是既然我们可以花很少的钱来买这个设计,那同样的,其他人也可以来买这个设计拿去使用。正如许可中指出的,这种许可是非排他的。 如果这些图标只是用到界面上,多个应用之间相似甚至相同,可能还是好事,因为这降低了用户的学习成本。但如果用在 Logo 这种代表品牌的场景,就会出现多个应用 Logo 一样的尴尬场面。 只是从这种买断式素材网站上直接买一个素材就拿过来把它作为 Logo,那人家也可以从这个素材网站上买同样的素材作为它的 Logo。这种行为可能是无意的,也可能是有意的。这种情况下我们还不能说人家抄袭侵权,因为都是从同一个地方买的,你可以买,人家当然也可以买。除非你把这个图案拿去抢先注册了商标,否则就会存在潜在风险。 不过,我们可以通过混搭组合的方式,将 Logo 变得独一无二、且更贴近我们产品的本质。 你看,thenounproject.com 上有上百万的图标。我们单独使用,总有其他的用户和我们一样喜欢上某一个图标,并把它作为 Logo,这个时候我们两个产品就冲突了。 但是如果我们把这几百万的图标混搭组合起来,就会产生出上亿种组合,再要想重复,就变得非常困难了。而「从一个图案里边截取一部分,跟其他的地方拼合起来,构成一个新图案」的这种操作,即使对于一个没有绘画功底的同学来讲,只要能熟练地使用软件,也可以轻易完成。 另外,在增加识别度方面,除了混搭,还可以通过上色来实现。单色图标因为使用的颜色数少,往往比较单薄,看起来缺乏层次感。当我们把它作为产品 Logo 的时候,可能就不是那么耐看。这时候我们可以自己来给它上色。因为是矢量图标,所以调色和上色都非常简单。调色只要选中后改变线或者形状的颜色就可以。","breadcrumbs":"精益副业 » 精益独立开发实践 » 独特Logo解决方案 » 将付费素材变成独有的","id":"155","title":"将付费素材变成独有的"},"156":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 使用AdobeXD设计界面","id":"156","title":"使用AdobeXD设计界面"},"157":{"body":"picture 24 Adobe XD是由 Adobe 开发的矢量设计工具,它和 Sketch 类似,既可以用来绘制矢量界面,又包含原型设计功能,还可以在手机上预览设计好的界面。XD 支持 Windows 和 Mac,是 Adobe 为数不多的可以免费使用的软件(当然你可以付费升级 pro 版本)。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 什么是 Adobe XD","id":"157","title":"什么是 Adobe XD"},"158":{"body":"软件的使用主要还是靠大家勤学多练,这里我们和大家演示下如何用它来设计背单词界面。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 使用 Adobe XD 设计简单界面","id":"158","title":"使用 Adobe XD 设计简单界面"},"159":{"body":"首先,我们在 XD 里新建一个画板(art board)。 画板是什么?它相当于 Word 里边的页面。一般的纯设计工具没有画板这个概念,但 XD 也包含了原型功能,有时候我们需要在多个界面之间来回切换,而一个画板往往就是一个界面。 点击左侧的菜单里面倒数第2个画板的按钮 picture 25 ,这时候在屏幕最右边就会出来一系列预置的画板尺寸。 picture 26 它已经帮我们准备好了常用的规格,比如苹果的iPhone、iPad,谷歌的安卓机型,以及网页常见的尺寸。 我们只要从里边选择对应的尺寸就好了,当然也可以不选择它给你预置的,直接手工拖拽来画或者在属性里面调整画板的宽和高。那我们就新建一个iPhone Xs尺寸的画板好了。 然后按住 CTRL或者CMD + D,就可以直接复制画板。我们把第一个画板叫做背单词界面,然后开始设计。 picture 27","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 理解画板","id":"159","title":"理解画板"},"16":{"body":"除了可以给我们的职业带来自由度,副业更可以为我们的职业引入反脆弱结构。 「反脆弱」这个概念,它来自塔勒布的书《反脆弱——从不确定性中获益》。 picture 1 在书里边,塔勒布说,他之所以要专门造一个词,是因为大家往往对脆弱的反面有所误解,以为是「坚强」,也就是类似软件的「鲁棒性」。但事实上,反脆弱性比鲁棒性更棒。 什么意思呢?鲁棒性是说在风险来临的时候我们要做到不受影响。而反脆弱性更上一层楼,它说的是,当风险来临的时候,我们不但不受负面影响,还能从风险中受益,变得比原来更好。 具体到职业上,鲁棒性是说,万一现在公司发展不好,我们可以很容易地跳到平级的其他公司,继续我们之前的职业路线图。 而反脆弱性是说,当现在公司发展不好,我们可以很轻松的切换到另一个职业象限,实现跨越式的职业发展。 如果我们精心选择并发展合适的副业,它能带给我们的,正是后者。为什么这么说呢?这是由副业的天然特性决定的。因为它是我们用业余时间、在资源紧缺的情况下发展出来的。如果我们能把它转为主业,而它依然保留了对时间、资源需求不多的特性,那么这份工作就会极为舒适。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » PlanB和反脆弱 » PlanB和反脆弱","id":"16","title":"PlanB和反脆弱"},"160":{"body":"先来制作背单词时,字母没有输入完时显示的遮罩效果。选择左侧工具栏中的矩形 picture 29 工具,画出一个覆盖全部画板的长方形。然后调节填充颜色为黑色,透明度为 30%。 picture 30 然后我们到 unsplash.com 这个无版权网站上,找一只猫的图片,把它也放进来。 picture 28 这时候猫是在遮罩上方的,所以它挡住了遮罩。 picture 31 点击右键,选择「Send to back」将它放到遮罩后,我们就可以看到被半透明遮罩挡住的猫了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 遮罩的制作","id":"160","title":"遮罩的制作"},"161":{"body":"接下来,在遮罩上边,我们来放上单词释义和输入框。点击最左侧工具栏中的 picture 33 图标,切换到文字工具。 然后输入文字释义。 picture 32 在右侧的属性面板里,我们可以调节文字的字体、大小、颜色和对齐。 然后我们放上之前设计好的 Logo,加上单词输入框。 picture 34 注意这个输入框不一定非要是「框」,比如我们这里也可以把它做成下划线。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 单词释义和输入框","id":"161","title":"单词释义和输入框"},"162":{"body":"picture 35 虚拟键盘的制作在 XD 中也很简单,直接用矩形工具绘制就行。需要注意的是圆角的做法。 picture 36 其实很简单,在右侧的属性设置里边,把圆角从0 改为 5 就可以了。在做好一个按钮后,我们可以按住 Shift 同时选中按钮和上边的文字,在右键菜单中将其编组(Group);然后按 CTRL或者CMD + D 就可以复制按钮。 picture 37 当按钮多起来之后,要对齐它们还挺费事的。其实选中多个按钮后,可以在菜单 Object → Align 中来自动对齐;也可以在 Object → Distribute 中让它们自动均匀分布。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 虚拟键盘","id":"162","title":"虚拟键盘"},"163":{"body":"再下来,我们需要在界面中引入图标。既然是矢量界面,当然是矢量图标最好。前边我们已经介绍过 thenounproject.com 了,它还为 pro 用户提供了一个客户端。在这个客户端里边可以非常方便的复制图标。 picture 38 当我们通过关键字搜索到图标后,可以通过下载并将其拖拽到 XD 的方式引入;也可以直接在客户端中右键选择 Copy as SVG,然后直接粘贴。因为是 SVG 格式,调整完大小后可以很方便地更换颜色。 最后我们再微调一下输入框和单词释义的位置,背单词界面就做完了。其他界面的制作非常类似,就不在这里累述了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用AdobeXD设计界面 » 矢量图标","id":"163","title":"矢量图标"},"164":{"body":"略过开发环节,我们来讲讲变现。绝大部分的支付方案都是面向企业的,面向个人的正规支付方案非常少。那么对于没注册公司的个人,怎么样才能比较安全地收款呢?","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 个人支付解决方案","id":"164","title":"个人支付解决方案"},"165":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 常见的几种个人收款方式","id":"165","title":"常见的几种个人收款方式"},"166":{"body":"市面上最简单粗暴的个人收款方案,就是利用微信或者支付宝的个人收款码来做。 具体的说,就是生成一张二维码,在这个二维码上面添加一个付款的备注,让用户备注中补充上特定的消息后(比如订单号)支付。当完成支付以后,我们就会通过APP或者网站,得到备注里面填的消息,通过识别,我们就能定位到订单,从而自动发货。也有不用备注,用支付金额来识别的。 这个方式淘宝店家已经用了很多年,它的问题就在于,从用户端的体验来讲,它需要填写额外的消息或者发送不确定的金额。从商家端的体验来讲,它需要有一个常驻的服务,随时去监测收款的相关消息,这就会有相当的不稳定因素在里边。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 个人收款码","id":"166","title":"个人收款码"},"167":{"body":"另一种解决方案,就是由那些有资质的企业申请到接口权限后,二次封装后提供给个人来用。这种方案的问题在于,钱是支付给提供接口的企业的,我们只能定期找他们结算提款。万一对方跑路了,我们的钱也就没了。这种方式风险非常高,不推荐。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 二次封装接口","id":"167","title":"二次封装接口"},"168":{"body":"「小微商户」是支付平台针对个人、也就是大量没有企业资质的用户推出的一个解决方案。最开始推出的时候,是为了帮助一些线下的店面,快捷地接入支付而存在的一个服务,然后又扩展到了网上的网店和商家。 一些银行和微信都有这个服务。但是微信并没有给它做专门的后台页面,所以我们在支付平台的后台里是看不见它的,它只有API。 微信把这一部分业务,交给了微信开放平台上的服务商。由服务商去调用这些接口来帮助个人接入到微信的支付服务里面来,同时服务商会提供后台的页面帮个人用户进行管理、也是服务商封装API供个人使用。 这种方案它的好处在于,它是完全合规的,而且这个钱是从微信直接打到小微商户的银行卡里边,不经过中间服务商,所以非常安全。 目前国内有名一点比如 xorpay.com 和 payjs.cn 。他们都是收费服务,前者的费用似乎更为便宜一些。这两个业务我们了解不多,大家使用之前请自行判断其靠谱系数。","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 小微商户","id":"168","title":"小微商户"},"169":{"body":"如果我们就是写一个软件,想简单地进行销售获得收入的话,我们还可以使用一些现成的数字内容销售平台。面向国外市场的话,可以使用Gumroad.com;如果面向国内市场的话,可以使用mianbaoduo.com。 picture 39 逻辑上讲,所有的网店都能解决我们卖软件的需求,但相对而言,面包多这类专门面向数字商品的平台提供了更低的手续费和更为全面的 API 接口。 picture 40","breadcrumbs":"精益副业 » 精益独立开发实践 » 个人支付解决方案 » 数字内容销售平台","id":"169","title":"数字内容销售平台"},"17":{"body":"接着上一节,我们来看看副业带来的、全新的工作自由度。这里我们多展望一下未来,主要是给大家鼓气。副业是很累的,要把别人用来休息的时间用到额外的工作上,多想想它的好处可以鼓励我们坚持下去。 当然,就像前边提过的,工作自由度最高当然是财务自由,上不上班都行,完全没有压力。我们这一节要讨论的是,在暂时还必须上班的情况下,我们可以取得的一些自由——我们就叫它「工作自由」吧。 我一般从三点上来看工作自由度: 工作地点的自由 工作时间的自由 工作内容的自由。 不同的工作方式,有着不同的自由度。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 全新的工作自由度","id":"17","title":"全新的工作自由度"},"170":{"body":"市面上管理用户反馈的产品很多,不过大部分都是收费的;这里我们介绍下自己在用的、腾讯出品的免费工具「兔小巢」。 picture 41 这个产品最大的用户就是腾讯自己,原来叫「吐个槽」,最近才升级并更名为「兔小巢」。我们已经使用了几个月,用下来感受很不错。 从用户端来讲,它支持微信和QQ登入,能及时地推送回复通知;从运营端来讲,用起来明显可以感受到这是一款看似简单,功能却相当强大的产品。比如它可以设置移动端的展示方式;可以适配大型产品和通用产品;默认发帖可以隐藏,也就可以当做工单使用;甚至还配备了团队博客和知识库。 不足的地方是提供的 API 比较少,但也够在自己产品中展示用户反馈了。有了它,我觉得大部分情况下,就不用再去购买同类的付费产品了。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 使用「兔小巢」处理用户反馈","id":"170","title":"使用「兔小巢」处理用户反馈"},"171":{"body":"下边分享一些整合细节,供大家参考。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 整合说明","id":"171","title":"整合说明"},"172":{"body":"兔小巢提供的是非常浅的整合,不管是在 Web 还是 APP 中,都是通过网页转向的方式来进行。通过设置,在反馈区上方可以显示一个链接,供用户返回到产品中。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 链接跳转","id":"172","title":"链接跳转"},"173":{"body":"但是通过链接跳转会遇到一个问题,就是在我们的产品和兔小巢之间,用户的登录状态会丢失,这样我们就不知道那个反馈是哪一个用户提交的了。 为此,兔小巢提供了一个 tucao.js ,让我们可以在跳转时传递用户的登录态,从而实现用户的统一。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 状态登入","id":"173","title":"状态登入"},"174":{"body":"在默认的模式下,我们只能点击链接后,在单独的页面上才能看到反馈信息。但通过兔小巢提供的 API ,我们可以直接在产品中显示反馈内容。","breadcrumbs":"精益副业 » 精益独立开发实践 » 使用「兔小巢」处理用户反馈 » 反馈数据整合","id":"174","title":"反馈数据整合"},"175":{"body":"","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 2A3R漏斗和增长优化","id":"175","title":"2A3R漏斗和增长优化"},"176":{"body":"2A3R 漏斗,又叫 AARRR 漏斗,是一个用来描述用户转化的结构。 picture 42 它是一个五层结构,分别是: 获客层 激活层 留存层 推荐层 付费层 用户由上至下逐步转化,直至完成付费。其中,留存层、推荐层和付费层可以是并列的,因为用户激活以后,立刻就可以付费、推荐好友。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 什么是 2A3R 漏斗","id":"176","title":"什么是 2A3R 漏斗"},"177":{"body":"2A3R 漏斗的现实意义在于,它促使我们从结果出发,去反向优化前边各个环节的转化率。比如说,如果我们福利单词的销售额定为 1000 套,那么就是说最终到达付费层的用户有 1000 人。而在付费层上至少还有获客层、激活层。 这里我们把获客指标定义为「访问网站」;把激活指标定义为「用户登入」。假设每一层的转化率是 10%,那么访问我们产品的用户数需要达到 1000 乘以 100 等于 10 万人。 优化方向包括: 我们可以加大推广力度,让访问人数从十万变成一百万,这样就能卖掉一万套软件了。 我们可以优化「用户登入」环节,在微信里边做成自动登录,这样把原来 10% 的激活转化提高为 30%,这样即使依然是 10 万访客,销售额也会变为 3000 套。 我们可以强化「付费转化」环节,给第一次访问的用户一个限时折扣,比如 1 个小时内购买,买一送一。如果能拉升 10% 的支付转化,我们的销售也会上升。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 使用 2A3R 漏斗进行业务优化","id":"177","title":"使用 2A3R 漏斗进行业务优化"},"178":{"body":"留存层优化主要用于一些基于高粘度增长引擎的业务,或者免费+付费模式的产品。在这些模式下,用户需要经过很长时间的使用,才会付费。如果留存做不好,用户熬不到付费那天。 对于福利单词而言,留存层优化可以通过推送通知、定时提醒等功能来做。因为背单词本来就是一个周期性行为,所以我们有足够的理由去召回用户。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 留存层优化","id":"178","title":"留存层优化"},"179":{"body":"现在的流量已经是非常贵的了,所以我们必须珍惜每一滴流量。通过旧用户带来新用户,可以为我们提供免费流量;如果做得足够好,流量甚至能像滚雪球一样不断变大。这就是推荐层优化要做的事情。 在我们的应用中,我们可以选择几个用户情绪高涨的点来做分享触发: 完成当天的背单词目标,比如背了 100 个单词 完成有挑战的任务,比如连续 30 个单词不出错 看到赏心悦目的图片,比如看到超级呆萌的猫 在这些时刻,我们都可以引导用户通过海报来分享他们的激动心情,同时为我们带来新的用户。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 推荐层优化","id":"179","title":"推荐层优化"},"18":{"body":"比如最近新冠流行,很多公司都开始搞远程办公了,有些大公司甚至宣布员工可以永久远程办公。远程办公这种工作方式,就实现了工作地点自由。你可以去公司的办公室、也可以在自己的家里,甚至是在旅游的路上办公。 但是,远程办公并没有实现工作时间和工作内容的自由,你依然要和其他人同时办公,区别只是以前面对面,现在改成视频了而已。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 远程办公","id":"18","title":"远程办公"},"180":{"body":"关于增长优化,这里给大家推荐两本书。一本是肖恩·埃利斯的《增长黑客》,系统化地讲述了如果建立增长实验机制并从中受益;另一本是《病毒循环》,记录了众多流量传奇。它们中很多细节和技巧,都可以用到我们的副业当中。","breadcrumbs":"精益副业 » 精益独立开发实践 » 2A3R漏斗和增长优化 » 推荐阅读","id":"180","title":"推荐阅读"},"181":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 精益网课变现实践","id":"181","title":"精益网课变现实践"},"182":{"body":"这一节我们来讲大纲。大纲大家都会做,所以我们不全面的展开,只挑其中一些需要注意的点和大家交流。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 大纲的注意点","id":"182","title":"大纲的注意点"},"183":{"body":"最重要的一点,就是大纲一定要有条理性。如果在条例性上做得不够好,其他细节做得再好,这个课做出来在逻辑上也是乱的,最后学起来就会很别扭。 具体来说,我们要保证大纲的层次足够清楚,逻辑足够严密。有一个比较常用的结构推荐给大家,尤其适合知识性为课程。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 条理性","id":"183","title":"条理性"},"184":{"body":"这个结构分成三段,是一个总、分、总的结构。 总 在课程的最开始,我们会简明扼要地讲明白整个课程包含哪些内容;课程中的一些基础、原理也会放到这里。 分 之后呢,我们就可以按照章节进行展开,对每一个部分进行详细地讲解。 总 在最后我们会进行一个总结,同时放入一个大的实践章节。这样不但可以复习内容,还可以学以致用。当然在每一章结尾也可以安排小实践内容。 绝大部分以知识讲授为主的课程都可以采用这种总分总的结构,非常好用。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 三段式","id":"184","title":"三段式"},"185":{"body":"我们也可以用问问题的方式来引出我们的每一部分结构。比如「是什么」——「为什么」——「怎么做」。这种结构可以是全局的,也可以是针对每一部分的。它会让我们的逻辑和层次更清晰。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 提问式","id":"185","title":"提问式"},"186":{"body":"第二个需要注意的点是覆盖面。因为我们的课程往往是出于自己的实践经验,有时候会局限于我们所在的公司和所在的行业节点,它的覆盖不一定特别的全。所以我们的视角不一定能覆盖到所有的需求方。 有时候我们的课程是为了一类人做的,但另外一类人,实际上也可以学习我们的课程,就差一点点的周边知识。在这种情况下,如果我们可以注意到大纲的覆盖面,把缺少的那点知识补上,就可以扩大受众,让我们的销售变得更为容易。 那具体怎么保证大纲的覆盖面呢? 那首先大纲应该覆盖该领域的主要内容,这些内容通常来源于以下几个地方: 官方文档:官方会处理几乎所有来自社区和其他客户的需求,即使一些边缘的需求,因为囤积的时间比较长,也会慢慢地累积起来,所以一般来讲官方资料的覆盖度是最为全面的 行业的权威文档:虽然不是官方出品的,但因为日积月累它最后可能变成了事实标准,也是我们作为参考的一个主要来源 图书:这也是大参考源,对于经典知识来讲,一些销量比较好的图书,会经过多次的再版,并会加入一些之前没有覆盖的内容。使用微信读书的无限卡,无需购买就可以直接搜索大量计算机图书,对查资料来讲非常好用 同类课程:国外的同类课程往往也是非常好的参考,尤其是面向新技术的课程 然后呢,我们的大纲应该覆盖该领域最频繁出现的问题,那我们到什么地方找问题呢? 搜索关键词 专业问答网站,比如 stackoverflow.com GitHub 的 issue 区 课程平台的答疑区","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 覆盖面","id":"186","title":"覆盖面"},"187":{"body":"除了条例性和覆盖面,那我们最后,而且其实也是非常想强调的一个问题,就是大家一定要注意我们大纲的粒度。 大纲这名字听起来就像一个目录,很具备误导性。很多同学做大纲的时候,通常做两个层次就算是做得细的了。事实上,大纲的粒度越细,课程的品质就越可控,后期制作起来速度就越快。而且我们要拿大纲去做预售来验证需求,它越细,验证的效果就越好。 所以呢,建议大家把大纲至少细化到段落这个级别,同时把段落以下的一些知识点所涉及到的素材和资料,全部都整理到这个节点上去。 这里推荐大家使用 Dynalist 这种无限分级的树状笔记软件来做大纲,会特别方便。","breadcrumbs":"精益副业 » 精益网课变现实践 » 大纲的注意点 » 粒度","id":"187","title":"粒度"},"188":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 通过预售验证销量","id":"188","title":"通过预售验证销量"},"189":{"body":"随机抽样了某云课堂上近 500 门付费课程(通过搜索「课」字),其中销售不到 30 的有 24%,销售小于等于 1 的 10% 这是我之前分析某课程平台时的抽样数据,有十分之一的课程销量小于等于一,这个一还很可能是作者;而销售不到 30 套的课程约四分之一。 这些失败的课程背后,每一个都可能有几十几百个小时的制作时间,既然我们把宝贵的副业时间投入其中,就应该尽量避免重蹈覆辙。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 为什么要验证","id":"189","title":"为什么要验证"},"19":{"body":"freelancer,就是那种在网上接单并收取报酬的工作者。这种工作方式在工作地点上同样是自由的,而且经常全部内容都是自己做,需要和别人沟通协调的内容不多,客户主要卡交工时间,只要能赶上进度,时间是可以自己安排的。所以它还实现了工作时间自由。 但freelancer没有实现工作内容自由,因为工作内容都是由客户指定的,绝大部分情况下,都不是你自己想要开发的东西。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » freelancer","id":"19","title":"freelancer"},"190":{"body":"回到我们这一节课的标题上来,「通过预售验证销量」。两个关键词「预售」,「销量」。 预售,我们用什么来做预售?简单一点可以用「课程介绍」,复杂一些则可以提供「试学章节」,但我们测试下来最合适的是「课程大纲」。它能非常清楚的描述内容范围。 销量,如何来评估?我们需要给自己设定一个达标的销售额,一般设定为比成本略高,预售结束时如果销售不达标,我们就退款,不制作这个课程了。 抓住这两个关键,就可以做好验证。在此基础上,可以扩展出一个完整的流程: 准备课程介绍资料,主要是大纲和试学章节 设定验证的目标,设定预售达标值 开始预售 每天统计销售量,并根据反馈调整介绍 预售达标则进入课程制作 预售不达标则进行退款,并反思价值主张 要支撑这个流程,我们大致有三种方案: 通过众筹/预售平台来完成 自建众筹/预售平台 通过付费群简单解决下 下边我们分别来说:","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 如何验证","id":"190","title":"如何验证"},"191":{"body":"使用现成的众筹/预售平台是最省心的。其实最方便的是微博提供的众筹功能,集传播和销售于一体,很适合在微博有影响力的同学。 picture 49 之前我用的时候还挺好找,现在这个功能藏得有点深,在微博的钱包二级菜单里。当然,其他的平台也是可以的。大体来讲,这类平台的问题在于操作相对麻烦,对个人的话,除了收取服务费,往往还会代扣 20% 左右的税。 另一方面,课程还不是实物商品,众筹完了可以直接寄送;我们众筹完以后,可能还要提供在线观看课程的功能。如果放到其他平台,还有一个账号统一的问题要解决。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 众筹/预售平台","id":"191","title":"众筹/预售平台"},"192":{"body":"对于我们程序员来讲,自建众筹/预售平台是很容易的事情。找不到满意的平台,当然是自己动手丰衣足食。功能开发上很简单,但这里有一个非技术因素,那就是支付接口往往需要公司资质来申请,个人很难申请下来。所以还没有搞定支付的同学们在动手前要留意,不要花几周写完系统要上线时才想起来。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 自建众筹/预售平台","id":"192","title":"自建众筹/预售平台"},"193":{"body":"付费群就不需要任何的开发,交易完全走一对一支付,只要自己在年终走个税申报就行。它的缺点在于维护成本有点高,需要手工跟进整个众筹的流程;群功能也相对有限,甚至出现过仿冒老师的账号进行收款的事情。 这里也分享一个微信批量退款的小技巧:将要退款的同学拉到一个微信群中,然后发一个人数乘以金额的普通红包就可以了。注意是 普通 红包,不是 拼手气 红包。 综合以上,我们的建议是,早期通过付费群或者一对一付费就可以了。等到付费用户多了以后,再专门开发一个系统来做预售/众筹。 我们也做了一个众筹+课程托管的一体化平台自用,等成熟以后会考虑开放出来,感兴趣的同学可以关注下我的微博。","breadcrumbs":"精益副业 » 精益网课变现实践 » 通过预售验证销量 » 付费群","id":"193","title":"付费群"},"194":{"body":"这一节开始我们来讲课程的制作。 我们将常见的课程分成四种片段: 文稿讲义类:这是我们最熟悉的PPT+语音的形式 屏幕录制类:在实战和演示时用得最多的形式 真人出镜类:技术类课程用得较少,一般在右下角放一个小窗显示真人 虚拟形象类:不想真人出镜时,可以用虚拟形象来代替 几乎所有的课程都是由以上四类课程片段组合而成,所以一旦学会了每种片段的制作,也就学会了几乎所有课程的制作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 常见的课程片段类型 » 常见的课程片段类型","id":"194","title":"常见的课程片段类型"},"195":{"body":"这里的文稿讲义,主要指使用幻灯片软件来进行播放的资料。如果是使用PDF这类材料,其实是属于「屏幕录制」类,我们会在下一节里详细讲解。 对于文稿讲义类课程片段,我们的画面、图文内容都已经做到了幻灯片里面,要录制的主要是声音。但我们有三种截然不同的方式来录制声音: 第一种是最通用的,通过全局录屏来完成。不管是使用什么软件,只要在电脑里,都会被录下来。 第二种是使用幻灯片软件自带的「演讲录制」功能来完成。 第三种是最不为人知的,通过幻灯片软件的「导出为视频」来完成,这种方式有一个非常大的优点,可以极大地降低修改成本,在后文中会详细说明 下边我们分别说明。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 文稿讲义类课程片段的制作","id":"195","title":"文稿讲义类课程片段的制作"},"196":{"body":"下一节会详细讲,这里就略过了。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 全局录屏","id":"196","title":"全局录屏"},"197":{"body":"picture 50 目前用得最多的幻灯片软件,分别是苹果公司的 Keynote 和微软的 PowerPoint。下边我们就以它们为例进行讲解。 首先,我们需要使用幻灯片软件将内容制作完成。课程完成度越高,修改起来成本就越高,所以要仔细检查有无错别字或其他疏漏,然后再进入音频录制阶段。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 使用幻灯片软件自带的「演讲录制」功能","id":"197","title":"使用幻灯片软件自带的「演讲录制」功能"},"198":{"body":"我们先来看在 Keynote 中如何录制。 在 Keynote 菜单「播放」里选择「录制幻灯片放映」 picture 52 然后我们就会进入一个深色背景的幻灯片录制的环境,在这个界面的最下方有一个红色的录制按钮。 picture 53 点击它就可以开始进行录音,可以随时暂停和停止。需要注意的是,这里录制的音频不是仅仅当前这页幻灯片的,而是整个幻灯片的。你可以来回切换幻灯片来录制音频,如果界面看到的有些不一样,可以通过调整预览界面的配置来修改。 当我们在录制环境中完成了整个课程的音频录制后,就可以回到主界面。从菜单中选择「文件」→「导出为」→「影片」。 picture 54 这样,Keynote 就会为刚才的录制生成视频。有一个需要特别注意的地方,就是导出窗口中,「播放」选项要选择为「幻灯片放映录制」。 picture 55 如果觉得导出的视频文件过大,可以使用 HandBrake 来进行压缩。这是一款开源的视频压缩软件,默认的预置(比如 fast1080p )就很好用。 picture 56","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程","id":"198","title":"如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程"},"199":{"body":"下边我们来看 PowerPoint 中如何操作,其实很类似,只是菜单名称和个别细节不同。选择菜单「幻灯片放映」→「录制幻灯片演示」。 picture 57 同样会进入一个暗色的录制界面。 picture 58 在左上角有一个时间正在走,在旁边有控制按钮,可以暂停。默认已经开始录制了,我们可以选择幻灯片进行讲解。全部讲解完成后,一样是导出视频。 picture 59 在顶部菜单中选择「文件」→「导出」。 picture 60 也有一个需要特别注意的地方,就是在导出窗口中要选中「使用录制时的计时和旁白」。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程","id":"199","title":"如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程"},"2":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业可能性","id":"2","title":"职业可能性"},"20":{"body":"再来看独立开发这种工作方式。它通过售卖独立的软件、游戏或者在线服务来赚取收益。所以在工作地点、工作时间上都是自由的。 由于是自主售卖产品,它在工作内容上,也是自由的。 这里是举个例子,实际上还有很多在地点、时间和内容上都很自由的工作。比如网课讲师。 picture 2 有意思的是,正是因为这些工作自由度高,所以适合作为副业来操作。反过来,一旦实际成熟,我们可以让副业反客为主,变成主业,从而随心所欲的掌控我们的日常工作。","breadcrumbs":"为什么副业特别重要 » 职业自由度 » 全新的工作自由度 » 独立开发","id":"20","title":"独立开发"},"200":{"body":"单从录制来讲,前一种方法就非常方便了,可以说是一气呵成。但如果录制完成后我们发现有几句话讲错了需要修改,那么就相当麻烦了。究其原因,主要在于虽然幻灯片是一页一页的,但音频却是整体录制的,所以音频出问题就只能重录。 那么我们能不能让音频也变成一段一段的,对应到每一页呢?这样我们以后再修改的时候,只需要重新录制那一页的音频。 picture 62 这就是我们第三种方案的思路。Keynote 和 PowerPoint 虽然没有提供分页录制的功能,但它们都能往幻灯片上添加音频,并将其合并到视频中统一输出。 所以我们要做的,就是在每一页幻灯片上,添加上语音讲解的音频。比较方便的地方是,这两个软件都支持直接录制语音讲解,而且一页幻灯片上可以录制多段,还能手工调整顺序。 下边我们来看具体如何操作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 幻灯片导出为视频","id":"200","title":"幻灯片导出为视频"},"201":{"body":"还是先来看 Keynote。第一步依然是制作好图文部分的内容,最好把要讲的文稿放到演讲者注释区域,这样录制的时候可以参考。 然后先选中要添加语音讲解的幻灯片,从菜单中选择「插入」→「录制音频」。 picture 63 在弹出的小窗口中点击录音按钮就可以开始录音。 picture 64 录制完成可以试听,没问题后再插入到当前幻灯片。当一张幻灯片有多个音频时,可以选择右上角的「动画效果」菜单,再点击右下角的「构建顺序」就可以看到当前幻灯片中的音频列表了。被选中的时候,会有蓝色描边,通过拖拽可以很方便地调整顺序。 picture 65 导出和之前类似,还是通过「文件」→「导出为」→「影片」。 picture 66 但需要注意的是,这次在导出窗口中,播放选项要选为「自动播放」。 picture 67 同时,我们还要把下边两个等待时间设置为「0」秒钟。 picture 68","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 Keynote 以「导出为视频」的方式生成视频课程","id":"201","title":"如何使用 Keynote 以「导出为视频」的方式生成视频课程"},"202":{"body":"再来看看 PowerPoint 里边的做法。给幻灯片添加语音讲义也在菜单「插入」→「音频」中。 picture 69 选择「录制音频」可以直接录制。 picture 70 下边我们看看怎么调整多个音频的顺序。点击「动画」菜单,在右边会出现一个「动画窗格」,再点击它,在最右边就可以看到当前幻灯片上所有的音频的列表。 音频前边还有编号,可以一一对应到幻灯片上的音频。通过调节它们的上下顺序就可以手动的指定最终的音频播放顺序。 细心的同学可能会留意到这些音频都会被放到一个叫做动画的菜单里面,其实这个菜单的功能是指定动画播放的顺序,音频被当做动画的一种,所以也在里边了。通过同样的方式还可以控制插入的视频的播放顺序。 picture 71 最后依然是通过「文件」→「导出」来生成视频,但是记得去掉「使用录制的计时和旁白」前的小勾,同时把「没有设置时间的每张幻灯片所用的秒数」设置为「0」。 picture 72","breadcrumbs":"精益副业 » 精益网课变现实践 » 文稿讲义类课程片段的制作 » 如何使用 PowerPoint 以「导出为视频」的方式生成视频课程","id":"202","title":"如何使用 PowerPoint 以「导出为视频」的方式生成视频课程"},"203":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制类课程片段的制作","id":"203","title":"屏幕录制类课程片段的制作"},"204":{"body":"屏幕录制软件的原理,是不停地截取屏幕画面,然后和音频合成为最终视频。屏幕录制的优点是可以把电脑屏幕上显示的所有东西都录下来,不管你在哪个应用里边,不受应用本身功能的限制。所以可以非常直观地向学员展示完整的操作。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制的原理","id":"204","title":"屏幕录制的原理"},"205":{"body":"在试用了很多屏幕录制软件以后,我们选择了 OBS 。它的优点主要有: 功能强大 开源免费 跨平台","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 屏幕录制的软件","id":"205","title":"屏幕录制的软件"},"206":{"body":"OBS 不但可以录制屏幕,还有一个非常强大的功能就是直播。现在很多视频网站的直播都支持用 OBS 来进行推流。所以学会了它,不但可以录制屏幕,而且可以进行直播,一箭双雕、非常划算。 然后,OBS 可以非常容易地进行屏幕之间的叠加,比如画中画模式,这就非常适合我们马上要讲到的「真人出镜」和「虚拟形象」类型的课程片段。 同时呢,OBS 还支持通过快捷键在各个场景之间来回切换,在录制课程的时候可以非常方便的进行转场,这个功能不少收费软件都没有。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 功能强大","id":"206","title":"功能强大"},"207":{"body":"和那些昂贵的收费软件不同,OBS 是开源而且免费的,这意味着使用它没有任何版权风险。我们在制作付费课程的时候,需要特别留意版权方面的问题。因为平时以个人身份在免费文章和视频中用一些字体、图片是没问题的;但在收费的商业课程中,就可能面临被起诉索赔的风险。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 开源免费","id":"207","title":"开源免费"},"208":{"body":"再来说一下,为什么跨平台的特性非常重要。在课程中,尤其是编程类课程中,我们经常会遇到需要讲解某个工具软件在各个操作系统上的安装和使用的情况,这时候就需要在多个平台上录屏。 如果使用一个特有平台上的录屏软件,在录制其他平台上的课程内容时,就不能使用了。只能重新购买和学习一个新的录屏软件。这不但浪费钱,更浪费时间和精力。 而使用 OBS 就没有这种困扰,它不但支持 Windows 和 Mac 系统,连主流 Linux 系统都是支持的。 所以,在我们后续课程中,将以 OBS 为例进行讲解。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 跨平台","id":"208","title":"跨平台"},"209":{"body":"OBS 的功能非常强大,还有包含了直播相关的功能,所以需要理解它特有的一些概念后,用起来才会更加顺手。 像一般的屏幕录制软件,只需要启动后点击录制按钮,进行录制就完了。但 OBS 中,它有自己的层次逻辑。 picture 73","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » OBS 的层次逻辑","id":"209","title":"OBS 的层次逻辑"},"21":{"body":"","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 职业成长性","id":"21","title":"职业成长性"},"210":{"body":"OBS 的第一个层次叫做「场景」,你可以把它理解为一种预设。 为什么需要场景?比如我们一个讲师,他每天上午要进行直播,这个时候视频的来源是摄像头和电脑屏幕;然后他每天下午要录制课程,这时视频的来源就只需要电脑屏幕,但他有两块屏幕,他希望都录进去。 如果没有场景这个概念,那我们每天上午到下午的时候,就需要不停的修改配置,非常麻烦。而有了场景以后,我们只需要把上午和下午定义成两个场景,使用的时候切换下就OK了。 你可能会想为什么要叫「场景」而不是直接叫「预设」呢?因为 OBS 中场景比预设更为常用和强大,它是可以实时切换的。 也就是说,如果我们有三个显示器ABC,可以在场景一里显示A;在场景二中显示BC;然后根据需求通过键盘快捷键来切换,甚至还能给它添加转场特效。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 场景","id":"210","title":"场景"},"211":{"body":"picture 74 在定义好「场景」以后,就可以往里面添加「来源」。最常用的来源其实就两类,也就是视频和音频。视频最主要的是显示器,也就是电脑屏幕,偶尔还有摄像头。音频的话主要就是麦克风。 picture 75 来看一下 OBS 的来源菜单。 首先它提供了「图像」和「图像幻灯片放映」,如果我们想在视频上面显示一张固定的图片或者图片轮播可以用它。 比较有意思的是,我们还可以把一个场景指定为来源,这样就可以非常容易地实现场景嵌套。也可以把媒体作为一个来源,这样就会在画面上面播放另外一个视频。 文本来源这里可以输入一些文字,指定它的颜色、字号和字体,然后它就会显示到屏幕上方。可用来显示我们机构的品牌名称之类的。可以看到,一些本来是后期才进行处理的功能,在 OBS 里都可以通过来源来实现。 显示器采集也就是我们的屏幕;视频采集设备通常就是指摄像头;音频输入采集这里通常就是耳机、麦克风或者外接的USB声卡之类。 这里还有一个音频输出采集,可以用来做多层次的音频加工。比如说我们电脑上有一个软件,就像柯南的蝴蝶结一样,可以对输入的声音进行变声,那我们就可以把这个软件的输出作为来源接入到 OBS 里边,录制下来的声音就是变声后的效果。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 来源","id":"211","title":"来源"},"212":{"body":"在多个来源之间,其实是有上下层级的概念的。打开 OBS 的来源小窗口,我们可以看见当前已经添加的所有来源。 来源是从上至下进行覆盖的。也就是说来源窗口的最上边一层,在最终视频中也会显示到最上面,上一层的内容会压住下边各层的内容。 picture 77 这个对于我们制作真人出镜类型的课程片段很重要,因为它通常是通过摄像头和显示器两个来源叠加得到的。摄像头的画面小、通常显示在右下角;显示器的画面大,往往覆盖整个视频画面。在来源窗口里,摄像头需要在显示器上层才看得见,不然会被显示器画面完全挡住。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 来源的层次","id":"212","title":"来源的层次"},"213":{"body":"picture 78 如果通过来源采集的信息不是百分之百符合我们的需求,还可以通过滤镜来进行进一步加工。OBS带有两类滤镜,一类叫做「音视频滤镜」,可以对音视频进行处理,比如进行噪音的抑制或者把音量放大;另一类叫「效果滤镜」,包括各种各样的特效,比如「色度键」可以用来抠背景。","breadcrumbs":"精益副业 » 精益网课变现实践 » 屏幕录制类课程片段的制作 » 滤镜","id":"213","title":"滤镜"},"214":{"body":"虽然前面其实已经陆续讲到了真人出镜类课程片段的基本原理,这里还是再明确下。","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 真人出镜类课程片段的制作","id":"214","title":"真人出镜类课程片段的制作"},"215":{"body":"「真人出镜」类的 视频 非常简单,只需要使用摄像头、手机或者摄影机直接录制就好了。而「真人出镜」类的 课程 反而要复杂一些。这是因为在课程中,讲师其实并不是主体,课程内容才是。所以我们往往会采用「画中画」的模式,将讲师的头像部分做成一个小方块放到画面中。 picture 79 但这有一个小问题,就是这个方块会带背景。如果它的背景和作为主体的课程不搭,看起来就会比较别扭。要是能把背景变成透明的,它就能更好地融入到课程中。","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 什么是真人出镜类课程片段","id":"215","title":"什么是真人出镜类课程片段"},"216":{"body":"那么,怎么才能让背景变成透明的呢?答案是「抠图」。对于计算机来讲,将数字内容的一部分变成透明是非常简单的,真正的麻烦在于它不知道哪一些像素是背景、哪一些像素是讲师,所以我们需要一个方式来告诉计算机。 现在最常用的,也是最简单有效的一个办法,叫做「绿幕抠图」。就是在讲师身后放上绿色的背景布,再告诉计算机,绿色的部分都是背景,把它抠掉。这样就实现了背景的透明。 有同学可能会问说,为什么非要绿色,其他的颜色行不行?答案是可以的,但如果把背景设置成黑色,很多人的眼睛和头发都是黑色的,这些部分也会被透明,看起来会很灵异。 而绿色在日常生活中出现的频次比较低,所以一般默认用绿色来作为背景。但如果有天你穿了个绿色的衣裳,那就可以考虑换用蓝色的背景了。 picture 80 这一部分的具体操作是这样: 在场景中添加一个「显示器采集」来源,选为我们想要录制的电脑屏幕,放到来源窗口最底层。 在场景中再添加一个「视频采集设备」来源,选为摄像头,将其放置到屏幕右下方,在来源窗口中位于显示器之上。 在摄像头来源的右键菜单中,选择「滤镜」,在「效果滤镜」中添加一个「色度键」滤镜,背景为默认的绿色。 调整「相似度」和「平滑」的值,让背景消失得更为柔和。 picture 82 picture 83 关掉滤镜窗口,这时候在 OBS 的预览界面上我们看到的摄像头画面背景就应该已经透明了。 picture 84","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 抠图","id":"216","title":"抠图"},"217":{"body":"如果你是使用笔记本电脑,通常自带一个摄像头;如果是台式机,就需要自己装一个。摄像头需要对着讲师的脸,因为摄像头看到的,就是学员最后在课程里面看到的角度。 然后我们在讲师背后竖一个比较大的绿幕,充满整个摄像头的背景区域。一般两米宽高就够了,不够的话可以调整摄像头。 绿幕可以在电商网站输入「绿幕布」关键词搜索购买。有一些专业的幕布会比较贵,但我们早期可以买便宜的幕布来试水,一般几十块钱就能搞定。 为了让讲师和背景之间分离得更清晰一些,可以再通过光源进行补光。这里我们用手办做了个示意图给大家。这个灯的色温不能调,所以看起来稍微有点偏黄。实际录制的时候,可以用白色的灯来补光。 picture 81","breadcrumbs":"精益副业 » 精益网课变现实践 » 真人出镜类课程片段的制作 » 真人出镜的其他细节","id":"217","title":"真人出镜的其他细节"},"218":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 虚拟形象类课程片段的制作","id":"218","title":"虚拟形象类课程片段的制作"},"219":{"body":"最后,我们再来看一下虚拟形象类课程片段的制作。虚拟形象实际上跟真人出镜差不多,但因为可以用卡通的形象来代表真人,所以形式上看起来会更加有意思,更适合年轻的同学。 在上一节里面,摄像头里拍到的是真实的画面,现在我们要想将真实的变成虚拟的,就要使用虚拟摄像头。 所谓的虚拟摄像头,就是其实并不存在这么一个物理上的摄像头,这个摄像头是用软件来模拟的。但是其他软件并不知道,它们会以为这个摄像头是真实的,于是它们之间就可以无缝地进行整合。","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 虚拟形象的原理","id":"219","title":"虚拟形象的原理"},"22":{"body":"前边说的都是当职业需要跨象限的时候,副业能提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,它也能提供非常大的帮助。 首先,副业可以成为新技术的练兵场。 现在社区里边吐槽得很多的一个现象是「面试造火箭,上班拧螺丝」。去面试一个前端岗位,问一些前端框架的最新版细节、底层原理,这是合理的,属于前端的业务范围。但如果把深度学习、大数据、云原生、容器编排、区块链甚至量子计算都拿来面试,就有点装了。 picture 1 但是面试本质上就不是合格考试,而是竞争考试 —— 是要在一群人中选择最好的,所以这也还可以理解。但最不好理解的是,当我们过五关斩六将入职以后,发现这家公司还在用十年前的技术栈,代码管理用的还是 SVN。 不光是小公司、也不光是传统行业;甚至在一些互联网行业的大公司的某些部门里,也会出现这种情况。吐槽规吐槽,但为什么这种情况相当普遍呢?这其实是由于「技术债务驱动的架构更新」导致的。 什么是「技术债务驱动的架构更新」? 把时间拉回五年前,现在有一个业务需要上线,于是我们用当下(也就是五年前)最新的技术构建了这套系统。然后,随着时间慢慢过去,新技术不断涌出,但是线上系统依然能用,业务团队要求稳定;产品团队需要的是不断添加新功能;根本没有机会对技术栈本身进行大幅更新。虽然技术栈逐渐变得陈旧,但是「又不是不能用,理解万岁」嘛。在这种想法下,技术债务不断累积,直到有一天,技术债务快把整个架构压垮了,甚至业务被迫中止一两天后,公司终于决定了 —— 要重新整套系统。于是,又会选用当前时间点最先进的技术来重新开发一套全新的系统。所以你会发现很多公司的系统,它并不是持续不断地更新、不是随时保持最新;而是在新旧之间反复横跳。 由于五年中,业务变动的可能性和幅度都非常大,所以对公司来讲,重写系统是可能比维护系统更合理的。但对于那些在五年里一直用原来技术栈持续不断地维护旧系统的同学来讲,他们的技术栈被迫变旧了。 而当决定开发新系统的时候,公司又希望使用当下最新的技术栈。这就要求原系统的程序员在一瞬间学会新技术,并开发出一套稳定的系统来。大部分人是做不到的,但从公司的角度讲没有关系,淘汰掉,招聘新人组建新团队就好了,说不定成本还能更低点呢。 picture 2 所以在这种结构的架构更新里边,如果程序员自己不想办法去学新技术,不去找地方去应用新技术,那么就像温水里的青蛙,最后终会用后即弃。 我很喜欢一句话,它听起来有些残酷,但真实,也时时推动着我去学习最新的技术。 一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。 —— Stewart Brand 副业给了我们一个坐上压路机,避免被碾压的机会。程序员这个行业跟其他行业还不一样,它对新技术的要求并不只是认知,光知道新知识、了解新思路是不够的,还需要一个实打实的练手环境,花上相当长时间去踩坑,才能稳妥地做出一个稳定的方案。副业提供了一个真实业务,让我们可以把最新的技术用到上面,随时保持技术栈最新,增强主业的职业竞争力。","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 新技术练兵场 » 新技术练兵场","id":"22","title":"新技术练兵场"},"220":{"body":"我们使用的是 FaceRig 这个虚拟摄像头软件,它提供了很多的3D模型,还支持导入 Live2D 这个游戏和动画用得较多的模型格式。如果是通过 Steam 购买的 FaceRig,那么在创意工坊里边可以看到全球玩家上传的各种模型,喜欢的可以直接订阅,它就会出现在我们的 FaceRig 里边。 当然,我们也可以制作自己的卡通形象,生成模型并导入。顺便说一下,对于多人参与的课程来讲,虚拟IP是非常有用的。如果我们将大量的精力和推广资源放到真人讲师的IP上面,万一这个讲师离开团队,之前的投入就废掉了,甚至会变成竞争对手的资源。但是如果我们采用虚拟IP,就完全没有这个问题。","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » FaceRig","id":"220","title":"FaceRig"},"221":{"body":"为了模拟摄像头,FaceRig 构造了一个 3D 空间。这个空间由「模型」和「背景」两部分组成。选好模型、配好背景,打开跟踪器让模型和我们的表情同步,就实现了用虚拟形象代替真人形象。 下边我们更为详细地讲述下步骤: 购买和安装 选择模型 选择背景 打开追踪器 打开广播 购买和安装 最方便的方式是在 Steam 这个平台上进行购买,它会帮你自动安装各种依赖,确保能运行起来。如果想用 Live2D 的模型,还需要购买对应的插件。 picture 85 选择模型 启动完成以后,点击顶部菜单最右边的UI按钮就可以切换右侧的面板;这个面板的第一格就是我们的模型。 点开以后可以选择喜欢的模型。 picture 86 选择背景 还是在右侧的面板,第二个图标就是。点开它可以看见预置的各种背景。如果想要最终背景透明,可以选择绿色背景方便下一步抠图。 picture 87 打开追踪器 现在虽然模型都有了,但它跟我们真人说话的表情语气没有关联起来,所以要打开追踪器。点击顶部导航,「切换追踪」按钮(图上画红圈的),摄像头就会通过人脸识别来捕捉我们的表情。这个时候我们摇脑袋和做出各种表情的话,就会同步到模型上。 picture 88 打开广播 这些都做完了以后,一定要记得还有最后一步就是要 打开广播 。所谓广播就是 FaceRig 把画面虚拟成一个摄像头,并同步到整个系统里,其他的软件就会把它当做一个真实的摄像头。 picture 89 打开广播也非常简单,就是点击顶部的这个像电台一样的按钮。点击打开,再点一下关闭。 当广播打开后,在 OBS 里去添加一个新的视频捕捉设备的时候,就会发现有一个名字包含 FaceRig 的摄像头,把它作为来源,就可以引入和真人表情同步的虚拟形象了。 picture 90","breadcrumbs":"精益副业 » 精益网课变现实践 » 虚拟形象类课程片段的制作 » 步骤","id":"221","title":"步骤"},"222":{"body":"视频剪辑是我们做课时用得非常多的技巧。剪辑是一门细节很多的技术,幸运的是,做课所需的只是非常基础的一些功能,所以我们才有可能花很少的时间学会。这也是我们这一节的内容。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 最常用的视频剪辑操作","id":"222","title":"最常用的视频剪辑操作"},"223":{"body":"视频剪辑的软件非常多,但整体功能上大同小异。经过一系列的试用,我个人用得最多的是这两个软件: 苹果公司出品的 iMovie Adobe 公司出品的 Premiere(一般简称PR) iMovie 是 Mac 专有的免费软件,完全可以胜任大部分的常规剪辑工作。后来苹果公司还开发了 iOS 版本,这样我们在 iPhone 和 iPad 上也能使用它。 如果我们只是想简单地调整下视频片段的顺序、删除某个片段、或者对某部分进行速度调整的话,iMovie 是个不错的选择。 PR 则是系统复杂、功能强大的专业剪辑软件,很多专业人士都在使用它。PR 是一个付费软件,但同时支持 Mac 和 Windows。 我们后续以 PR 为例进行讲解,在其他的剪辑软件里相关的操作也是非常类似的,往往只是菜单位置不同,大家可以自行摸索。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 剪辑软件","id":"223","title":"剪辑软件"},"224":{"body":"视频片段的调整是最常遇到的需求。因为我们在录课的时候很可能其中有一段讲错了,会想把它去掉,再把后边的内容给接上去;或者讲课时有一部分内容讲丢了,在后边补讲的,想把它给挪到前面去。这些情况时常发生。 比如说我们现在有一段视频,希望删除其中红色的部分,应该怎么操作呢? picture 3 直观来讲,应该是选中一个片段然后按删除键。有一些编辑软件就是这样做的。但在 PR 中,这个操作通常被分两步:先分段、再删除。 picture 2 所以我们会先用剃刀工具将视频给切割成三段,切割的位置正好在红色部分的开始和结束,这样它就会变成一个独立的片段。 然后切换到选择工具,选择这个片段,再按删除键,片段就会被删除。 picture 4 但我们会发现,视频中间空出来了一段空白。 picture 1 这是因为在 PR 里边,连续视频并不是一种常态,所以它没有自动去掉两个视频片段之间的空白。可以在这段空白上点右键,选择「波纹删除」,这样后边的视频就会自动补上来了。 picture 5 当然,在删除视频的时候,如果不是直接按删除键,而是点击右键,选择「波纹删除」会更加方便一些。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段的调整","id":"224","title":"视频片段的调整"},"225":{"body":"这里有一个需要特别注意的概念。在我最初的想象中,视频片段应该是很「硬」的,当两个视频片段有重合时,后一个片段会自动后移并紧跟前一个视频对齐。但在 PR 中,视频片段是很「软」的,当两个片段重合的时候,重叠部分会被覆盖掉,再也分不开了。可以把它们想象成两个透明胶带,一旦粘上,就很难无损分开了。 picture 6 所以,对于不熟悉 PR 的新手来讲,想要两个片段紧密连接,最简单的方式还是分开放,然后「波纹删除」中间的空白来自动对齐。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 柔软的视频片段","id":"225","title":"柔软的视频片段"},"226":{"body":"正因为这些片段很「软」,当我们在进行顺序调整时,也要倍加小心。这里我们可以利用 PR 的多轨道。我们可以暂时把要移动的片段放到另一个轨道上,然后调整原来轨道上片段的顺序,挪出一个新的位置,再从外轨上把片段给挪回来。 picture 7","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段顺序的调整","id":"226","title":"视频片段顺序的调整"},"227":{"body":"速度调整在做课时也很常见,比如说我们通过网络安装软件的时候可能就很慢,得操作二三十分钟,但我们不可能让学员一直等二三十分钟。一个方式是直接减掉这个过程,但如果其中又包含了一些操作细节,我们可能就需要把这一段视频加速。 picture 8 在需要调整速度的视频片段上边点击右键,选择「速度/持续时间」选项,会弹出设定窗口。 窗口上默认的速度是100,如果想加速,就改为大于100;想减速,就小于100。 有一个需要注意的问题,就是如果减速,视频片段会变长。如果前后有其他片段,就可能造成覆盖,所以这种情况下,最好放到另一个轨道上再调整速度。 另外,在加速的时候,原来的声音会变调,如果想要保持正常,记得选中「保持音频音调」。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频片段速度的调整","id":"227","title":"视频片段速度的调整"},"228":{"body":"这个操作也是很常见的,比如讲课中有几句讲错了,但是不方便删除视频,可以只删除这一部分的音频。 但是,默认情况下,音频和视频是绑定的。所以我们需要将要处理音频的部分切割成独立的片段,然后在右键菜单→「音频增益」中把它的音量调到听不到(比如-100dB)。 picture 9 当然我们也可以通过选中片段后点右键菜单,选择「取消连接」来解除音频和视频的绑定。这样就可以随意编辑音频了。 除了像视频一样分段、调整顺序等,我们可能还需要对音频进行去噪、调音等更进一步的操作,这时候我们可以在对应的片段上点击右键,选择「在 Adobe Audition 中编辑剪辑」在另一个软件中来处理。具体的操作我们将放到下一节讲解。 picture 10","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的视频剪辑操作 » 视频中的音频处理","id":"228","title":"视频中的音频处理"},"229":{"body":"音频的后期处理和视频类似,也是非常专业的领域,所以我们这里也只讲最简单的处理。在我们做课时,经常会用到的技巧主要包括: 去噪 标准化 混响 去齿音和嘶声 下边我们依次来看看。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 最常用的音频处理操作","id":"229","title":"最常用的音频处理操作"},"23":{"body":"除了技术,副业也可以帮助我们在业务上获得新认知,保持敏感性。 之前我们在做程序员职业成长服务的时候,发现了一个问题。很多初阶的程序员没法升到中高阶,有两个很大的非技术影响因素,一个是管理能力、另一个是业务理解能力。 管理能力比较好理解。每一个程序员即使把自己的潜力发挥到极致,成为十倍开发者( 10x developer),他可以处理的事情也是有限的。 但是如果管理能力好,他就可以培养出很多拥有和自己同等技能的人,这样就不只是十倍、而是可以成百上千倍地复制能力,为公司增加更多的生产力。 业务理解能力这一块,是因为在绝大部分的公司里,技术都是为业务服务的。所以需要针对业务的各种需求、各种流程来做解决方案。 如果对业务不了解,那么即使技术很不错,因为不知道某些业务细节,最后设计出来的方案可能也不是最优的。这就像我们小学时做应用题,有一个隐藏条件包含在业务逻辑中,如果忽视了它,即使数学再好,做出来的答案也是错的。 所以,程序员应该需要培养自己对业务的理解能力。但比较讽刺的是,很多公司的初阶程序员,恰恰没有机会去了解业务。尤其是一些比较大的公司,很多业务相关的问题都是在中高阶的技术决策层就已经解决掉了,分配到初阶程序员这里,就只剩下一些规划好的、待实现的技术方案了。 这就会形成职业上的一个断层,让初阶程序员无法变成行业专家。很多公司是无意的,也有极少数公司是有意为之。因为高阶的岗位是有限的,如果你成长起来后没有位置,就会跳槽了。所以,公司不培养我们的时候,我们就只能自己培养自己。 而副业正是磨练自己的好方法。我们可以做一个跟我们主业相关的副业,通过自己的项目来了解需求、理解业务,从而弄明白公司在做什么样的事情,怎样才能做得更好。将自己从一个纯粹的螺丝钉,变成独当一面的解决方案高手。","breadcrumbs":"为什么副业特别重要 » 职业成长性 » 业务敏感度 » 业务敏感度","id":"23","title":"业务敏感度"},"230":{"body":"「去噪」就是「去除噪音」。一般分为两个步骤: 定义噪音 去除噪音 为什么会有「定义噪音」这个步骤呢?因为对于计算机来讲,它并不知道哪一部分声音叫做噪音。 比如我们在录一首歌的时候,邻居家的猫在旁边叫,这个声音就算是噪音。但如果是想录一个宠物视频,猫在里面就不是噪音,它可能是主角。所以是否是噪音,是需要根据场景来进行定义的,计算机理解不了这点。 当然,这个例子比较特殊。通常来讲,要去掉的噪音叫做「底噪」。就是声音很小的背景噪音,比如电流声,远处汽车和行人的声音。这种时候,只需要选取一段只有这些背景音的音频,将其定义为噪音,那么软件就可以把和它类似的声音去掉。 音频处理也有很多软件能做,但因为我们视频剪辑用 PR,所以音频用 Audition(简称 AU )来做会更为方便。它在我们修改音频后,会自动更新 PR 里边的片段。 下边我们来看 AU 中具体怎么操作。首先选中一段只有背景噪音的音频,在顶部菜单中选择「效果」→「降噪/恢复」→「捕捉噪音样本」,就可以把它定义为噪音。 picture 11 然后,在顶部菜单中选择「效果」→「降噪/恢复」→「降噪(处理)」,开始去噪。 picture 12 记得在弹出的窗口中点击「选择完整文件」,再点「应用」就会开始处理。 picture 13","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 去噪","id":"230","title":"去噪"},"231":{"body":"标准化也是一个很有用的功能。我们录音的时候,尤其是换了场地和设备录音的时候,可能声音的范围(最高音和最低音)就不一致。这种时候,就需要通过「标准化」来将这个范围统一,这样听起来音量差异才不至于太大。 picture 14 在 AU 中的具体操作如下: 在顶部菜单中选择「效果」→ 「振幅与压限」→「标准化(处理)」。 picture 15 然后在弹出的窗口中,可以将其标准化到 0 dB (如果觉得音量过大,也可以试试 -6 dB)。 picture 16","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 标准化","id":"231","title":"标准化"},"232":{"body":"我不知道大家有没有这种感受,就是有时候听一些电脑生成的音频时,会觉得声音非常纯粹,很好听,但听起来不像是真的。而一些现场录制的音频,音质可能没那么好,但听起来却会有种非常强的空间感。 这是因为我们日常在说话的时候,声音会分成两个层次到达我们的耳朵。 picture 17 一个层次是直接从发声处传到了耳朵里,另一个层次是声波打到周围的环境上,比如墙面、地面、桌椅上,被反射后,有一些很弱的声音以稍微延迟一点的时间进入我们的耳朵。我们日常听到的多是这种叠加后的声音。 在电脑中生成的音频如果不特意处理,是没有这种叠加的。这就让声音有点「平」或者「干」。为了增强声音的空间感,很多编辑软件提供了叫做「混响」的功能。其原理就是模拟现实中的声音叠加,将一部分声音强制延迟后混音,这样的声音更有立体感。 下边我们看看在 AU 中怎么具体操作。 在顶部菜单中选择「效果」→ 「混响」→「混响」。 picture 18 在弹出窗口中,可以调节各项参数。点击播放按钮可以试听。 picture 19 选择好以后,点「应用」进行处理。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 混响","id":"232","title":"混响"},"233":{"body":"齿音是指我们说话时,呼入呼出的气流和嘴唇、牙齿之间摩擦产生的声音;嘶声则有些类似于广播电台中常听见的嘶嘶嘶的声音。这些声音混在音频中,可能听起来不那么舒服,所以 AU 也提供了工具来清除它们。这部分的操作很简单,这里就不详细说明了,这两个功能的菜单分别在: 齿音:「效果」→「振幅与压限」→「消除齿音」 嘶声:「效果」→「降噪/恢复」→「降低嘶声」","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 齿音和嘶声","id":"233","title":"齿音和嘶声"},"234":{"body":"其实顺序并不是强制的,怎么都行。但考虑到标准化时有可能把底噪放大,所以我一般会按下图的顺序来进行各项音频处理操作。 picture 20 整个过程中,去噪和标准化才是最重要的,其他的三项时间紧张时可以偷懒不做。","breadcrumbs":"精益副业 » 精益网课变现实践 » 最常用的音频处理操作 » 建议顺序","id":"234","title":"建议顺序"},"235":{"body":"对于技术类课程来讲,字幕是非常有用的。一些技术名词光是读出来,有时候很难明白它是什么意思。而如果有字幕,就可以一目了然了。","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕的制作和自动生成","id":"235","title":"字幕的制作和自动生成"},"236":{"body":"所谓字幕呢,是指我们在播放视频的时候,显示在屏幕下方的、和语音同步的文字。为了让计算机正确地显示出字幕,我们需要告诉它两个信息: 这个字幕的文本是什么 这个文本应该在什么时间开始显示,在什么时间结束 也就是说,最基本的字幕信息应该包含「文字本身」以及「文字显示的时间段」。 当我们把多条字幕的信息合并放到一起,就有了字幕文件。字幕文件可以是单独的文件,在播放视频时载入并显示,这种方式称为「外挂」;也可以在压制视频时直接压制到视频里,这样即使播放器不支持字幕功能,也可以正常显示。 字幕的格式有很多种,srt 格式是最简单的格式之一。 picture 21 它由多段文本组成,每段文本分为三行: 第一行是序号,一般从 0 开始递增 第二行是显示时间段,中间用箭头分隔 第三行是这个时间段应该显示的文字","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕及其格式","id":"236","title":"字幕及其格式"},"237":{"body":"我们使用的字幕编辑软件是 ArcTime ,它是一款跨平台的免费软件。启动以后的界面是这样的: picture 22 左上部分区域是视频的预览区,可以从顶部菜单的「文件」→「导入音视频文件」载入要编辑字幕的视频。然后它就会显示预览区。 预览区下方就是字幕区,有根据音频生成的波形在上边。在这个区域点击右键,选择「插入空白字幕」,就会插入一个空白的字幕条,双击可以输入字幕,拖拽可以调整显示的时长和起止时间。 添加好字幕以后,点击预览区的播放按钮,可以实时地看到新添加的字幕效果。需要注意的是,目前的版本中,删除某条字幕的操作是不能撤销的。这可能是这个软件为数不多的缺点了。 整个视频的全部字幕添加完以后,点击顶部菜单中的「导出」→「字幕文件」就会将刚才编辑的字幕生成一个字幕文件了。 picture 23 如果想要把字幕直接压制到视频里边,则可以选择「快速压制视频」选项。","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕编辑软件","id":"237","title":"字幕编辑软件"},"238":{"body":"ArcTime 还内置了一个为视频生成字幕的功能,放置在「语音识别」菜单中,但这些功能是收费的。 对于程序员来讲,有一个更为廉价的方式获得同样的效果,那就是直接写代码去调用云服务商提供的 API。比如 阿里云 、腾讯云和 百度翻译平台 就提供了相关接口。 更有开发者已经在 GitHub 上开源了基于这些接口的命令行和客户端软件。大家可以在 GitHub 搜索「VideoSrt」,自行安装试用。 picture 24","breadcrumbs":"精益副业 » 精益网课变现实践 » 字幕的制作和自动生成 » 字幕的自动生成","id":"238","title":"字幕的自动生成"},"239":{"body":"课程制作完成上线以后,并没有结束。长征才刚刚开始,我们需要不断得去运营它。这一节就来聊一聊流量池和二次购买。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 流量池和二次购买","id":"239","title":"流量池和二次购买"},"24":{"body":"","breadcrumbs":"如何优雅地做副业 » 如何优雅地做副业","id":"24","title":"如何优雅地做副业"},"240":{"body":"先来看一下在没有流量池的情况下,课程转化是什么样子的。 picture 26 首先,我们将自有的或者购买的流量引导到课程页面,以触发销售转化。但如果我们没有采取更多措施,之后这个流量就走掉了。当上架新课时,又需要重新寻找或购买流量。 这种方式优点是简单,但今天操作起来问题很大,因为我们已经错过了之前流量爆炸的时代,现在流量已经很贵了,这么浪费太可惜。那么,能不能把流量囤起来,供以后使用呢?","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 没有流量池的情况","id":"240","title":"没有流量池的情况"},"241":{"body":"picture 27 最简单的操作就是,把购买过课程的学员放到「学员池」里。当上架新课程以后,可以直接给他们发通知进行销售。这样就实现了流量的二次使用。很多同学觉得这是显而易见的,但事实上在操作的时候却很容易出问题。 比如说,很多讲师只是直接使用课程平台进行学员管理,而很多的平台不允许讲师给学员批量发送私信,甚至还会做关键字过滤。这种情况下,我们对学员的触达能力是非常弱的,需要建立更可控的流量池来替代。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 学员池","id":"241","title":"学员池"},"242":{"body":"picture 28 学员池重用了已经购买过课程的流量,但更多的没有购买课程的访客流量还是流失了。所以我们还可以更进一步,来做访客池。 把我们课程中有意思、有传播点的内容做成免费的素材,进行多渠道分发,把用户吸引过来并放到这个池子里,以备以后发送通知、触发销售。 常用的渠道包括: 搜索引擎 社交网络 媒体平台 课程平台 行业网站 学员池和访客池是我们最主要的两种流量池。","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 访客池","id":"242","title":"访客池"},"243":{"body":"互联网发展到现在,各种产品已经极大的丰富,所以有大量的工具可以用来构造流量池。因为课程销售有非常明确的商业诉求,所以我们对流量池也有相对明确的评判标准。这里分享下我常用的三个标准: 进入门槛低:最好能免除用户注册,尽快获得用户的基本信息和触达权限 可触达率高:这样我们的销售信息才能被更多人看到 触达免费或廉价:太贵了用不起 如果想要获取种子用户用来验证大纲,还需要考虑互动性。 针对微博、公众号、企业信号、微信群、自建 APP 这几种最常用的方案,我们整理了一个对比表格以供大家参考: picture 30","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 构造流量池的工具","id":"243","title":"构造流量池的工具"},"244":{"body":"各种流量池都有自己的优缺点,我们应该选取当前阶段最适合的来进行流量的存储。我们也可以分阶段、渐进式地建立多级流量池,以在投入和收益上获得平衡。 比如早期我们可以直接使用微博的关注、哔哩哔哩的订阅来做流量池;然后将一部分核心用户引导到微信群和企业微信一对一服务中。这样把微博的获客门槛低和微信的触达率高这两个优点结合起来了。 在用户规模大一些以后,我们再去开发自己的App,实现对用户流量更高级别的控制。 picture 31","breadcrumbs":"精益副业 » 精益网课变现实践 » 流量池和二次购买 » 多级流量池","id":"244","title":"多级流量池"},"245":{"body":"","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 如何有效地反盗版","id":"245","title":"如何有效地反盗版"},"246":{"body":"虽然几乎所有讲师都认为反盗版是必须做的,但未必都明白反盗版的意义,觉得就是少挣了钱。实际上并不是这么简单,盗版最大的问题,是对正版用户带来的不公平。同样的课程,有人花了几千块钱买过来,有人却一分钱不付就可以得到,这让正版用户显得很傻。 其次,很多讲师以为把课程放到课程平台上,平台就会帮着进行反盗版,自己就不用管了。事实上,大部分平台的反盗版措施都非常有限,通常只能由讲师提交盗版链接,他们投诉下架。如果对方将课程放到境外网站,连下架都做不到。而且有些平台每周定时收集处理一次盗版信息,还不如自己直接投诉效率高。所以我们不能把反盗版推给平台去做,他们只能起到辅助作用,我们自己还是要足够重视。 还有一个普遍的错误想法,就是很多程序员觉得盗版是不可能完全杜绝的,所以干脆就不防范了。我们的确没有办法从技术上来完全杜绝视频课的盗版,但却可以采取各种措施来降低被盗版的概率。 要从做盗版的人的经济收益的角度来思考盗版这件事情,如果我们的课盗版门槛很低,就可能导致大量盗版,因为不需要付出太多的代价。相反,如果我们课的盗版门槛很高,那就要花很多功夫才能盗版。 很多盗版手段是针对平台的,当我们课程的盗版门槛变高以后,盗版狗有两个选择,一个是投入时间和金钱去升级盗版手段,另一个选择是用原来的盗版方法继续盗版其他门槛低的课程。绝大部分情况下,它们会选择后者。 有同学可能会说,这样其实并没有解决盗版的问题。是的,从宏观上来讲,确实没有解决盗版问题;但从个体的角度来看,我们又的确避免了自己的课程被盗版。 要从宏观层面上去解决知识产权问题,需要国家、法律、以及社会各方面一起持续不断地推动,我们作为个体,积极响应国家的政策,并保护好自己的知识产权,就是在为这事添砖加瓦。 picture 32","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 树立反盗版的正确思路","id":"246","title":"树立反盗版的正确思路"},"247":{"body":"所以反盗版其实就是要不断提升盗版的门槛,降低盗版狗的收益,让它们无利可图。我们自己实践过的方法中,最有效的可以归纳成四个字、两个词:卖空和卖多。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 如何有效地反盗版","id":"247","title":"如何有效地反盗版"},"248":{"body":"卖空其实就是预售,还没有课程,就开始销售。你很难盗版一个还不存在的课程。而且在我们精益网课流程中,本来就是通过预售来验证需求的,所以做起来很顺手。 这个思路再扩展一下,比起一次性提供课程,连载课程的反盗版门槛更高。因为它每周只更新一到两节课程,持续时间很长。这样盗版的成本一下被提升了 N 倍。 卖空的思路很简单,但效果却非常明显,强烈推荐大家尝试。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 卖空","id":"248","title":"卖空"},"249":{"body":"卖多是说,现在大家课程放到平台上,盗版门槛是一样高的。但是我们可以多提供一些平台没有的、盗版不了的服务来反盗版。这些服务可以包括: 答疑 督学 社群 线下服务 在进行这些服务的时候,我们可以先进行身份确认,无法提供购买证明的人就不能享受这些服务了。 更进一步,如果我们把课程中不可或缺的部分挪到这些服务中来,那么看盗版视频的人甚至不能完整的学完课程,这就让盗版课程失去了意义。 有一个不错的实践可以分享给大家。我们的主要课程是全栈课,既有前端又有后端。为了反盗版,我们开发了一个云端的编程环境,将后端课程放在其中,然后限制只有正版学员才能登录这个系统,采用这个系统的课程后来就再也没有被盗版过。 这个系统的开发很简单,只需要在云平台上启动一个基于容器的、带有桌面的系统,然后再运行一个基于 Web 的 VNC 去连接它,就可以实现在浏览器中远程操作桌面系统了。感兴趣的同学可以去了解下 NoVNC 这个开源项目。","breadcrumbs":"精益副业 » 精益网课变现实践 » 如何有效地反盗版 » 卖多","id":"249","title":"卖多"},"25":{"body":"在通过大量章节充分了解了副业的重要意义之后,相信大家已经明白了「为什么」。下边我们开始来讲「是什么」和「怎么做」。 在做一件事情之前,我的习惯是要想明白它的本质,弄清楚它的核心资源,了解它的核心优势。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 想明白核心资源和核心优势","id":"25","title":"想明白核心资源和核心优势"},"250":{"body":"","breadcrumbs":"精益副业 » 进一步提升副业的鲁棒性 » 进一步提升副业的鲁棒性","id":"250","title":"进一步提升副业的鲁棒性"},"251":{"body":"前面我们通过两个大章节的实践课程,为大家详细讲解了怎么通过独立开发和网络课程制作来发展副业。之所以会选择这两个方向,除了它们非常典型、有很高的投入产出比,还有一个原因 —— 它们之间可以形成非常好的互补。 目前看来,在国内要通过独立开发赚到一流企业程序员的年收入(大致三十到五十万),还是比较困难的。免费加收费模式虽然后期收益巨大,但前期需要长时间的投入。 相对而言,网络课程的售卖更容易带来现金收益。如果我们把独立开发的整个过程完整的录制下来,并加工成网络课程进行销售,那么即使独立开发项目最终难以通过销售软件和服务来赚取足够多的收益,我们还可以通过网络课程获得收入。 而且,不管对于课程学员还是独立软件/服务使用者来讲,都更有益。课程的学员可以学到更为真实、更贴近一线、且经过事实验证的开发技巧;软件/服务使用者则可以获得详尽的文档、架构说明,更有机会进一步深入了解整个规划、设计、开发过程,充分理解业务,甚至因此变成代码贡献者。 从流量上讲,软件/服务可以给课程带来学员;课程可以给软件/服务带来用户。两者互相促进,为我们的副业更添了一层保障。 picture 25 最终,我们就可以实现一个多次利用「副产品优势」的三级收入模式。在这个模式下,我们首先通过主业赚取最核心的收益,以供日常生活和基本发展。然后,我们在主业工作中积累的知识、经验、人脉基础上,开发我们的副业,比如独立软件或服务。在独立开发的过程中,我们再次把它的副产品——制作过程,录制成课程进行售卖。最终,我们可以分别从主业、独立开发以及课程三个渠道获取收益。 这样即使某些收入源不是特别好,我们的整体收入还是相对高的,这就让我们有足够的时间和资源去修正这些错误,让整体发展得越来越好。","breadcrumbs":"精益副业 » 进一步提升副业的鲁棒性 » 网课+独立开发的双引擎副业模式 » 网课+独立开发的双引擎副业模式","id":"251","title":"网课+独立开发的双引擎副业模式"},"26":{"body":"来看我们这本书的副标题 —— 「程序员如何优雅地做副业」。它有两个重点,一个是「优雅」、一个是「副业」。 既然是「副业」,就表明我们还有一份作为「主业」的正职工作。副业只是我们从本来已经很繁忙的工作、生活时间里面活活挤出来的一点时间精力去做的业务。 所以对于副业来讲,最核心、最宝贵的资源,就是我们的时间片。 为什么这么说呢? 因为对于一家企业来讲,它有足够多的资源可以调配。它可以通过雇人的方式,批量增加可用的时间片。但是对于我们处于「副业」状态的业务来讲,精力和资源都是非常有限的。 副业本来挣得就很少,如果还要去雇人的话,每一个人分下来就会更少,会有入不敷出的风险。另外,人多了以后,在沟通上、管理上的成本也会飙升。所以副业的人应该尽可能少。 于是,时间片就成为了整个副业中,最为有限、最难拓展的资源。我们应该围绕紧缺的核心资源来规划副业。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 副业的核心资源 » 副业的核心资源","id":"26","title":"副业的核心资源"},"27":{"body":"我们的目标读者是程序员。大部分的程序员要么是在写软件、要么是在写网站、要么是在写APP,通常属于软件或者互联网行业。 软件行业和互联网行业的竞争是非常激烈的。而我们在上一节里面说过,副业它有一个先天的特点,或者说是不足,也就是我们能在这个业务上可以投入的时间和精力是非常有限的。 市场是非常残酷的,它并不会管你这个产品的制作方是个人还是公司,开发它的程序员是全职还是兼职。最终用户会以同样的标准来看评判产品,优胜劣汰。 那在一个竞争如此激烈的市场里面,一个先天投入不足的业务,凭什么可以战胜其他的项目,获得成功呢?这是我们开始之前就要想明白的问题。只有想明白了这个问题,我们在做副业的时候才是有的放矢,而不是随波逐流。 这个问题困扰了我挺久,后来在读《 创业就是要细分垄断 》时,里边一段话让我觉得非常有启发。 它大概意思是说,所谓的「快鱼吃慢鱼」,并不是说人家加班到晚上12点,你就天天逼着员工加班看凌晨四点的中关村。快鱼的快不是这种意义上的快,而是策略上的快。 书里还举了 AirBnb 的例子。它通过共享的方式来创造供应,AirBnb 增加一个民宿只需要几天,而连锁酒店可能要花上半年。就算连锁酒店的员工每天工作85 个小时,也赶不上 AirBnb 的速度。这就是策略上的快。 所以,回到副业上面来,如果想要我们的副业具备很强的竞争力,我们就必须根据其独有的特点,为其制定一个有竞争力的策略。 比如说,我们的副业项目往往规模不用做到特别大。因为如果我们想做到财务自由,那么1000万左右的人民币基本上也就够了。1000万这个数字对个人来讲可能很多,但是对于企业来讲,其实是一个非常小的市场。尤其对于一些以融资方式发展的创业公司和上市公司来讲,这种规模的市场根本就没有办法生存。所以,如果我们选择的目标市场足够好的话,是可以避免很大一部分公司的竞争的。 当然,即使是在一两千万的市场里边,仍然会有不少的竞争对手。我们仍然需要结合副业的特点来构造自己的优势。这里给大家介绍其中一种,叫做「副产品优势」。我们本身是有正职工作的,通过日常工作,会积累很多的经验知识和其他资源。如果我们把这些东西利用起来,把它做成副业的产品的话,它的成本是非常低的,而在深度上,往往又会有很高的门槛。 举一个实际的例子。 比如,我一个朋友是云平台的架构师,他的工作是专门为传统企业往云平台上做业务迁移提供解决方案,方便这些企业购买他所在公司的云计算产品。 但是在这个过程中,他接触了大量的、各行各业的公司的迁移需求,并为他们做了架构方案。这让他的架构能力突飞猛进,架构经验也远超旁人。 这个时候,如果他以副业的形式,开设讲授架构技巧的课程,对他来讲成本是非常低的。因为无论他做不做这个副业,都要投同样多的精力在这件事情上。 作为对比,如果一位全职网课讲师想要来做同样主题的课程,那么就需要从头开始学习完整的架构知识,并花足够长的时间,比如说几个月甚至几年,去接触大量的实际案例,最终才可能做出同样品质的课程。 而对专职讲师来讲,他的收益仅仅是课程收益,并不包含主业的薪资,所以最终收益甚至可能还赶不上他为了制作课程进行的投入。在这种情况下,全职反而成为了一种劣势,这就是我们所谓的副产品优势。 当然,我们还可以根据副业的其他特点,发掘出各种独特的竞争力。但只有围绕核心的稀缺资源进行规划,并从策略上建立我们的核心优势,才能真正做到优雅地做副业。","breadcrumbs":"如何优雅地做副业 » 想明白核心资源和核心优势 » 副业的核心优势 » 副业的核心优势","id":"27","title":"副业的核心优势"},"28":{"body":"这一节开始,我们就来讲讲副业的核心资源——时间片。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片","id":"28","title":"时间片"},"29":{"body":"前边说过,时间片是我们副业的核心资源,所以直接把它以一个比较低的价格销售出去,是不划算的。这种方式和「优雅」这两个字不太匹配,但我们这里还是会简单介绍一下。 它不会作为我们这本书的重点,但大家有一个简单的了解也是好的,至少可以作为其他副业方式的对比。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 时间片的销售","id":"29","title":"时间片的销售"},"3":{"body":"2014年的时候,我做过一个「程序员拍卖」的项目。听起来很神奇,其实就是将我们遴选过的优质程序员推送给各家在招聘的公司,让他们来竞价,从而帮程序员们找到一份满意的工作。 那两年,我们为上千名程序员找到了工作。后来我把从中学到的对于程序员职业的理解写成了一本小书,叫做 《程序员跳槽全攻略》 。 书里我创造了一个用来分析程序员职业的工具,叫做「方糖职业路线图」。它根据现金流将程序员的职业空间分布到了E、S、B、I 四个象限中,我们依次来说说。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » 职业的四大象限","id":"3","title":"职业的四大象限"},"30":{"body":"不经任何加工直接销售时间片,最主要是以「私单」的方式来进行的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 私单","id":"30","title":"私单"},"31":{"body":"传统的私单主要是外包模式。也就是说,一家公司有一个项目要做,它把这个独立项目完整的包给你。双方约定完成的时间、验收的标准和价格。大一点的项目,还会有阶段性的交付和付款。 除了这种完全线下的外包,还有基于网络的 freelancer 方式。大体上是基于网络接单,然后按发包方的要求进行开发。因为没有地域的制约,可以承接国外的业务。 目前的情况看,中国程序员在海外外包市场上并不占据优势,尤其是个人。因为现在海外接单平台上有大量的印度、巴基斯坦等国家的程序员,他们要价非常的低,而且平均而言,英文沟通能力比中国程序员要强一点。接这些单子会比较累。 做起来比较舒服、利润比较多、沟通上比较容易的私单,往往是通过行业人脉和开源项目来的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 外包","id":"31","title":"外包"},"32":{"body":"大部分的外包在我看来都是很痛苦的,因为它其实和程序员的技术栈不对应。 沟通问题 我们平时在公司开发时,都是产品经理把需求梳理好,然后和程序员进行沟通,好一点的还有高保真原型。即使在这样的情况下,进行需求调整的时候,我们还是会很难受。大量的代码需要改动,如果上线时间表比较紧,我们就会被逼着加班。 而外包模式下,需求方往往就变成了外部的人群。因为个人的工作量有限,所以通常不会是特别大的单子,这就有可能遇到大量不靠谱的发包方。他们很可能并不了解开发的流程,也表达不清自己的需求。 这就要求我们有相当的沟通技巧。如果是基于网络的沟通,效率会进一步降低,问一句得等半天才能有响应。 甚至,很多时候我们会被迫去做需求分析工作,因为整个环节中缺失了产品经理 —— 很多发包方觉得根本不需要这个中间角色。 尾款问题 即使熬过了开发阶段,还有一个尾款收取问题。新手容易因为太过信任对方先交工再收钱;老手也逃不掉那种开发完了对方的创业公司倒闭了的情况。 比较大的项目或者面向特定行业的项目,在签单之前可能会有招投标,然后可能会有层层的审批。在款项的时间预期上要有心理准备,经常会有项目都做完了审批还没有走完的情况。 项目全部由自己开发还好,如果需要其他人的配合,那我们就需要自己垫付资金。这些风险需要合理的控制。 开票问题 个人做私单还有一个烦心的事情,就是大部分的单子都是需要开具发票的。这时候就只能去找一些公司代开。这种代开是有费用的,所以在定价的时候要把这些也考虑进去。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 外包的坑","id":"32","title":"外包的坑"},"33":{"body":"正是因为这种整单外包的方式会带来各种麻烦,最近开始出现一个更加「简单粗暴」的私单方式,叫做「按需雇用」。这是面向发包方的说法,对于程序员来讲其实应该叫做「驻场开发」。 我们平时都有正职工作,但是如果不是去了黑心企业的话,周末的时间还是空出来的。这时候我们就可以到其他公司去上一两天班。通常是一些创业公司,去解决一些他们的开发没有能力或者精力解决的问题。 在这种模式下,费用是按时薪结算,沟通也更为顺畅。只要像平时一样多上一天班就可以获得好几倍的回报。而且当天晚上就可以获得收入,也没有尾款的烦恼。 所以如果非要销售时间片的话,我觉得这种方式更高效一些。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 按需雇用","id":"33","title":"按需雇用"},"34":{"body":"但是正如我们前面所说的,你的时间片是非常有限的。像按需雇用这种方式,虽然收益看起来高一点,但它的天花板也是非常明显的。 我们可以很容易地算出来。假设我们每周末拿出一天,一个月也就只有四天而已。就算一天能挣2000块钱,一个月也就是8000块钱。 这是最理想的情况下,因为只能周末工作,所以往往并不是每周都会有活;同时,如果遇到开发内容不是特别熟悉的情况,可能还要花一点时间去学习相关的资料。 整体来讲,我们认为私单,尤其是按需雇用,属于一个中高收益、中低风险、但是也有明显的收入天花板的一个副业。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的销售 » 更优雅的方式","id":"34","title":"更优雅的方式"},"35":{"body":"时间片的优化有两个思路。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 时间片的优化","id":"35","title":"时间片的优化"},"36":{"body":"提升单位时间的收益其实就是提升时薪(但并不一定局限于按时薪支付的副业,其他形式可以折算成时薪),有几个简单的思路。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 提升单位时间的收益","id":"36","title":"提升单位时间的收益"},"37":{"body":"「切换地域」就是说,我们同样是干活,但如果服务对象所在的位置不同的话,单位时间的收益也是不同的。 比如你在重庆,给本地公司去做一些外包,那整个项目的基础价格就是参照当地程序员的人工成本来进行比价的。但如果是在重庆可以给北京的公司做外包,那发包方就会更多地参照北京的各种成本来进行相应的股价,这样我们就可以把自己单位时间的收益提升上去。当然,需要考虑沟通的效率和成本。 把这个思路扩大一点,就变成在国内做国外的业务了。 因为和国内相比,国外的人力成本通常会贵很多,如果你在二三线城市,那么成本又更低。这样就出现了一个价格差,如果能控制好这个价格差,我们就能挣到更多的钱。 当然前边也说过,这里边有竞争和外语沟通的问题,需要根据自己的实际情况来选择。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 切换地域","id":"37","title":"切换地域"},"38":{"body":"在没有建立起自己的知名度之前,非常单纯地去做外包,面对的往往是价格战的红海。地球那么大,总有人的时间比你不值钱。 而且外包它是一个开放性的需求,如果真要把很多雇主的需求细细做好的话,对技术栈的广度要求还挺高的。因为每一个项目它要求的技术栈可能不一样。项目做的越多,用到的偏门技术就可能越多。 所以我们要想办法解决竞争的问题。细分市场就是一个很好的思路,比如说我们可以给一些标准化的开源产品做二次开发来挣钱。 这其实不是什么特别新的思路,早在个人站长时代就有人专门给 Discuz!这个开源论坛软件写插件和定制功能挣钱,而且还真养活了不少小公司。 现在我们可以把这个思路更扩展开一些,比如说我们把从「支持国内项目」变成「支持国际知名的项目」。 这样的话,我们就能解决掉出海接活面临的大部分起步问题。 你看: 我们从什么地方来获得客户?直接从开源社区获取客户。 如何证明我们的开发能力? 可以写一些高质量的开源插件,给大家免费使用,并作为我们的demo。 如何来获取比较高的收益?专门给一个项目写插件的团队并不是太多,选择够好的话,就可以成为这个细分领域的No.1,获得一些品牌上的溢价。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 从外包到二次开发","id":"38","title":"从外包到二次开发"},"39":{"body":"提升单位时间的效率对于按工作量支付的副业来说特别重要。 比如说我们现在有一个项目,交付后的收益是10万块钱。以原来的方式完成它,可能需要花100个小时。现在我们想到了一种新办法,把效率提升了10倍,那么原来100个小时才能完成的活,现在10个小时就能做完了,这就是效率的提升。 多出来的90个小时我们可以用到其他项目上,哪怕是用来休息,也是很好的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 提升单位时间的效率","id":"39","title":"提升单位时间的效率"},"4":{"body":"E象限是雇员象限。别人给我们发工资,我们帮别人挣钱。这是风险最小的象限,我们的工作任务是别人分配的,只要认真完成,每个月都能得到预期中的收益。 在从开发走向高级开发后,往往就可以开始选择发展路线。E象限的典型的发展路线有两种,专家线和管理线。 E象限的优点是稳定,缺点是天花板非常明显。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » E象限(雇员象限)、帮别人挣钱","id":"4","title":"E象限(雇员象限)、帮别人挣钱"},"40":{"body":"当然,通过增强意志力来强迫自己去提升生产效率,其实是很难奏效的。 因为我们本来就是在利用工作之余的时间。在这个时间上,很难保证精力非常充沛。别说提升工作效率,能保证在做这些事情的时候尽可能的不被干扰,不让自己的生产效率降下去,已经是非常不错了。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 打鸡血难以奏效","id":"40","title":"打鸡血难以奏效"},"41":{"body":"但是非常幸运的是,我们是程序员。我们从事的工作,它本身就有一部分是由机器来完成的,所以我们可以引入自动化来提升效率。机器是使用电来工作,它的效率提升空间是非常大的,而且它也不需要休息,可以7×24小时地进行工作。 代码生成器 对于程序员的日常工作来说,最主要的自动化方式就是代码生成器。 但一说到代码生成器,就会听到很多反对声音。如果你用过一些比较早期的代码生成器产品,很可能你也会会有一些负面印象。 在大概十多年前吧,我当时所在的公司也就购买了一套代码生成工具。根据说明书,配置好业务逻辑,然后就可以同时生成ASP、PHP和JSP的代码。 公司买来以后就强制性行推广,但在硬推了两个月以后,发现推不动,只好放弃了。 最主要的原因是因为它没有办法处理我们特有的一些逻辑,加上每一个部门有自己独立的规范和周边库,在那个工具里边没法用上。之后很长的时间里,我们整个部门的人都对代码生成器非常反感。 但是后来还是经不住偷懒的诱惑,我自己一直在偷偷地不断尝试。渐渐地发现,其实要做一套全世界通用的代码生成系统可能会特别难;但是如果只是给自己做一个专用的代码生成工具却非常简单,只要遵循以下两个原则。 只为自己设计 第一个原则是「只为自己设计」。 因为每一个公司,每一个部门甚至每一个岗位它所面临的需求是千差万别的,很难通过一个通用工具来解决,所以我们也很难买到为自己量身定制的工具。 但如果自己来开发工具的话,就完全不同了。我们可以完全按照自己的工作流程、按照每天写代码的需求来进行设计。我们非常清楚写代码的时候,元数据是存放到什么地方的、通过什么样的方式进行加工、以及最终要生成怎样的代码。所以可以开发出非常好用的自用代码生成工具。 能自动化的自动化,不能自动化的半自动化 第二个原则是「能自动化的自动化,不能自动化的半自动化」,后半句特别重要。 很多程序员在设计代码生成工具的时候,往往太过完美主义,老想着要做一个系统把所有的工作都做完,最好点一下按钮后,什么事情都不用去做了。 这当然是最理想的方式,但是我们的开发环境和其他的办公软件之间不一定存在交互接口,很多软件只有图形界面,不支持通过 API 进行数据交换。所以,很多时候我们就没法做成全自动。完美主义或者叫强迫症的同学就会说,既然这个东西不能完全自动化,那就直接手动来处理吧。 但我们开发代码生成器的根本目标并不是要做一个完整的自动化产品,而是要提升我们的生产效率。所以,即使有一些地方不能做到完全的自动化,我们也可以把它做成半自动化。 半自动化有两个思路。第一个思路是,我们可以通过交互方式来解决一些不能自动化,或者需要花很多时间去处理的细节问题。 举一个例子,这个例子发生的年代比较久远,现在可能已经不适用了。 我们当初在做网站的时候,有很多的资料都是编辑给的。那个年代还没有产品经理,都是由网站编辑给我们资料。他们都使用 office 软件来存放数据。 当时是没有比较好的 office 格式解析包的,所以很多同学都放弃了数据的解析,改为手工输入。我给了一个解决方案,就是直接在 office 里复制数据表格,然后再粘贴到一个 textarea 里,最后用 PHP 分析 tab 和换行符号,把数据分离出来。为了防止分析错误,还做了一个界面来进行确认和手动修正。虽然没能实现全自动,但是比起手工输入数据,这个方案效率的提升是几十倍的。所以不要过分纠结于全自动化,有的解决方案不完美,但也可以很精彩。 另外一个思路是,只对小操作做自动化,用来生成代码片段。比如说,我们在写输入处理的时候,往往需要根据数据表字段来对输入进行验证,这往往是一个重复劳动。所以,我就写了一个命令行的小工具,它可以直接读取数据表里边的字段和对应的注释,根据注释里的标记来判断对应的字段的验证信息,最后会自动生成验证部分的代码。我把这些代码粘贴到编辑器后,再进行相应的修改,就可以很快的完成验证工作。这没有什么技术含量,但是它可以切实提高我们的生产效率。 这些只是我想到的思路,当然还有很多其他的。比如有的同学是通过工具链,通过命令行交互,来实现自动化。 人工智能 代码模板呢,只能解决相对比较死板的规则。但最近随着人工智能的进步,在某些特定的场景下,原来很多低效率的人工操作其实可以交给 AI 了。 现在,AI 的正确率确实达不到和人类同等水平。但是,还是前边那句话,「不能完全自动化的,可以考虑做成半自动化」。针对 AI 正确率不高的场景,我们可以通过人机结合的方式来处理。 比如说,我们要进行图片分类,之前可能需要花上十几个小时的人工。现在使用 AI 进行分类,只需要十几秒。但是它可能有20%的图片分类是错的。 我们就可以先让 AI 来进行分类,然后再人工确认一遍。确认花的时间可能是两个小时,但即使这样,比起之前的十个小时来讲,效率也提升到了五倍。 最近很多人工智能接口的品质已经不错了。比如说,熟悉我微博的同学都知道,我经常会用语音的合成和识别服务来提升内容生产效率。 比如我经常会发一些技术视频,但是又不想自己录音,于是就会使用人工智能来生成语音。而大家正在看的这本书里,至少有一半的内容我是通过语音识别APP,以每分钟100多字的速度记录下来,然后再二次进行修改、校正完成的。 所以不管你对 AI 有什么看法,它现在已经在实实在在地改变着我们的生活。我们要思考的是,如何更好地利用它。 如果服务足够可靠,我们就可以做成自动化服务,直接提供给最终用户;如果服务还不够可靠,我们可以把它放到中间流程里来提升效率。 比如,同样是代码生成技术,如果我们把它做成面向不懂技术的人群的产品,服务不是很可靠的话,最终效果就会很惨;但同样品质的接口,如果我们把它做成面向开发者的服务,而且是在编辑器里面实时地进行代码补全和建议的工具,它就会显得非常好用,可以极大地提升生产效率。","breadcrumbs":"如何优雅地做副业 » 时间片 » 时间片的优化 » 自动化","id":"41","title":"自动化"},"42":{"body":"前面我们讲了时间片的优化,敏锐的同学可能已经感受到了,时间片的限制其实是有办法突破的。下边我们就专门来讲一下怎么突破时间片限制。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 突破时间片限制","id":"42","title":"突破时间片限制"},"43":{"body":"第一个思路叫「倍增」,就是让时间片的数量成倍的增加。但这里有一个前提,就是不能过多的增加我们的精力消耗和风险。 因为不考虑这个前提的时间片倍增非常容易,只需要增加雇员就可以了。但我们随时都要提醒自己,这是在做副业。 如果我们雇用全职人员,就需要有办公场地、还需要到现场进行人员管理。这对于有正职工作的同学来说,是很难分身的。除非你把办公场地放到正职工作的公司附近,用空闲时间去管理。但这依然有精力上的风险,搞不好既没做好副业,又影响了正职工作,这就本末倒置了。 既然雇用全职的路子走不通,我们就只能考虑雇用兼职。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 倍增","id":"43","title":"倍增"},"44":{"body":"主要的方式就是将部分业务外包。前边我们其实刚聊过外包,只不过在这里,我们从接单方变成了发包方。 外包的方式,可以将大块的业务交给别人去做,自己只需要花少量的时间片来做沟通和管理。等于接单方的时间片也为我们所用了,所以整体来看,时间片是倍增了。 外包还会带来一些潜在的风险。 我们的时间片是倍增了,但我们的成本也在成倍地增加,也就是说本身我们的项目需要有足够的利润空间才适合使用这种方式。如果控制不好,很可能最后整个项目做下来不挣钱甚至亏本。 另外,外包方式下,沟通和项目管理也是比较大的挑战。因为它不是那种每天在一起的沟通环境、也不是直接的上下级关系。只能以合同的形式来进行约束,很多时候甚至连合同都没有。这种情况下,其中某些环节出现问题,我们就需要为整个项目承担风险。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 外包","id":"44","title":"外包"},"45":{"body":"其实还存在其他的雇用兼职的方式,比如众包。众包和外包类似,但粒度更细,接单方更多,甚至我们都不知道接单方是谁。 一个典型的例子是 Facebook 的多语言翻译工作,他们提供了一个在线翻译工具,让懂该语言的用户每人来翻译几句,因为用户数量庞大,很快就能完成整个翻译工作。 众包的收益非常不错,一方面是成本上的,因为接单方多,所以会产生竞价。如果分摊的工作量非常小,甚至可以是免费的。另一方面是时间上的,同样因为接单方多,完成的速度会非常惊人。 不过,为了支持大量的接单方,我们的业务结构需要进行相应的调整。 比如说,通常我们可以把一个系统分成平台部分和扩展部分。平台部分,我们可以自己制作;扩展部分就可以把它设计成插件、扩展、中间件,将这些东西以众包的方式分出去。即使其中的组件出问题,对我们核心平台的影响也是小的。 这样对接单方来讲还有一个突出的好处,就是这种组件本身的逻辑和它的相关资源是闭合的,只需要知道输入输出,内部实现完全可以自己决定。组件开发者之间也不需要沟通,只需要跟平台以文档、API的形式来进行沟通,在使用细节上以工单的方式来进行反馈就可以了。这可以大幅度降低我们的管理成本。更进一步,我们可以开发工具来对众包进行支持,进一步提高效率。 所以,如果能培养起好的众包生态,我们是可以实现低投入的时间片倍增的。对于不想开公司、对时间片又需求大的业务来说,是非常值得尝试的。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 众包","id":"45","title":"众包"},"46":{"body":"另外一个突破时间片限制的方式我叫它「超卖」,就是把一份时间片卖给多个人。 在很多非常个性化的业务里边,我们是为对方专门定制的服务和内容,所以一份时间片只能卖给一个人。但是,当我们业务做得足够久了之后,就会聚集起来很多有相同需求的人。 这时候我们就可以把他们的公共需求抽取出来,做一份面向这个公共需求的产品或者服务。这样的话,我们只需要花一份时间来做产品,就可以把它卖给多个人,也就间接地实现了时间片的超卖。 比较典型的例子是建站。这曾经是很多小公司赖以生存的业务。在最开始的时候呢,建站公司都是去跟客户谈,想建一个什么样的网站,然后找设计师进行界面设计,完了以后再进行开发。这种服务就是一对一的时间片售卖。 但后来很多公司发现其中重复的需求太多,于是就把建站的需求做成了一个系统。在这个系统上,客户可以自行选择模板,添加功能模块,输入内容,通过浏览器就可以很快地生成自己想要的网站。整个过程甚至不需要其他人参与。 从个性化服务到标准化服务,是实现时间片超卖的主要思路。 再举一个更明显一点的例子。熟悉我的同学都知道,网课是我一个很重要的业务。但和其他的机构不同,我从来不做直播课。所谓直播课是说,我提前准备好教学内容,等大家都上线了,然后我们在一个直播房间里边,一边讲课一边学习。相对的是录播课,是说我提前把这个内容录好,然后大家自己找时间去看视频就好了。 从讲师的角度来看呢,直播课就是一对一的时间片消耗模式,每讲一次,都要消耗一次我的时间片。而录播课则是一对多的时间片消耗模式,不管有多少学员,他们只需要去看录制好的视频就行,我付出的时间片不会增加。这也实现了时间片的超卖。 从上边的两个例子可以看出,时间片的超卖背后,实际上是商业模式的调整。 最理想的情况下,我们只需要付出一份时间片,然后即使我们什么都不做,它都可以持续不断地进行售卖。不管我们是在吃饭睡觉、看电影逛街、还是在旅行休假,这个产品都会持续不断地给我们带来收入。这种收入我们称为被动收入,能带来被动收入的东西,我们叫它资产。","breadcrumbs":"如何优雅地做副业 » 时间片 » 突破时间片限制 » 超卖","id":"46","title":"超卖"},"47":{"body":"","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产和被动收入","id":"47","title":"资产和被动收入"},"48":{"body":"资产的定义见仁见智了,我比较习惯用罗伯特·清崎在《穷爸爸富爸爸》里的定义,那就是「 能把钱放进你口袋的东西 」就是资产。换句话说,能产生 被动收入 的东西,其实就是资产。 《穷爸爸富爸爸》这本书很多人都读过,罗伯特·清崎后来还写了一个系列,核心是富人不为钱工作,而是 让钱为自己工作 。 在书里边,主要通过「购买」的方式来获得资产。这里是书中列出来的资产类型: 股票 债券 能够产生收入的房地产 票据(借据) 版税,如音乐、手稿、专利 其他任何有价值、可产生收入或者增值潜力且有很好销路的东西 这个系列后来就跑去教人投资和理财了。 其实投资也可以视为一种副业。优点很多,比如占用精力相对较少、没有收入天花板等;但也有两个明显的缺点。 最主要的缺点是风险高,且不易评估。还有一个缺点是, 投资你得先有资 、 理财你得先有财 。在风险可控的范围内,大部分投资理财的回报率差异不会特别大。如果你手上一百万都不到,可能折腾一年、背着挺大的风险也就是多挣了几万块钱。 投资理财是一门深奥的学问,我们不在本书中展开,大家可以阅读相关的专门书籍。 在罗伯特的资产清单中,还有一个可以无成本获得类别 —— 版税。但其实在中国因为书卖得特别便宜,而版权又普遍不受重视,一些大公司都堂而皇之地侵权,其实很难获得高收益。 如果没有初步的积累、或者不想背负过大的风险,怎样才能获得资产?","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 什么是资产 » 什么是资产","id":"48","title":"什么是资产"},"49":{"body":"资产最简单粗暴的获得方式当然是通过购买。但好的资产未必人家愿意卖,当然更可能的是,我们未必买得起。 但是除了购买,其实还有一个逐渐被遗忘的方式 —— 直接「创造资产」。对于很多传统行业的人来说,创造资产会大量的消耗精力,最后成本可能并不会比购买资产低多少。 但现在软件吞噬了世界,数字化业务已经茁壮成长,数字资产的生产资料日益廉价。而我们是程序员,正是那个可以通过自己的技能栈低成本、低风险的创造数字资产的群体。 并不是每个人都有我们这么幸运,其实大部分的程序员,离完整地做出一个商业产品,缺的可能只是一点美感和设计能力。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的获得方式 » 资产的获得方式","id":"49","title":"资产的获得方式"},"5":{"body":"S象限是自雇象限,自己挣钱自己花,一般不雇用别人。比如做独立开发、组建工作室做外包和建站,甚至也可能做一些和编程没有关系的事情。 S象限最大的优点是,自己的业务自己做主,挣的钱也都是自己的。一个三五十万的外包做下来,一年的基本生活保障就有了。 S象限的缺点是,收益未必能比E象限多多少,而风险却高很多。光靠单纯的编程技能往往搞不定,还需要把接活拉活的能力、协调沟通的能力都培养起来。这些能力往往在程序员的舒适区外,需要花精力和时间去培养。因为收入是业务驱动的,所以行业的风险也会直接转嫁到我们这里。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » S象限(自雇象限)、为自己挣钱","id":"5","title":"S象限(自雇象限)、为自己挣钱"},"50":{"body":"当然,并不是所有的数字资产都适合我们以副业的方式去创造。不过就像前面不断重复的,副业是一个资源和精力都非常缺乏的状态,我们也只能从庞大的可能性中,选择那些适合的产品和服务。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 资产的量化评估","id":"50","title":"资产的量化评估"},"51":{"body":"说到底有哪些产品和服务适合副业呢?下边是我觉得值得留意的几个特征。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 适合副业的几个特征","id":"51","title":"适合副业的几个特征"},"52":{"body":"首先是「 自传播 」,就是说这个东西做出来了以后,它本身有很强的感染力,它的用户会主动地去推荐给其他用户,这样的话我们就不用花很大的成本去做营销。 对于大部分程序员来讲,把程序写出来只是时间和精力问题。写不出来程序的程序员很少,但卖不出去程序的程序员非常多。所以,如果我们做的东西本身就能传播,那么我们就可以在零市场预算的情况下获得成长。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 自传播","id":"52","title":"自传播"},"53":{"body":"第二类叫做「 UGC 」,用户贡献内容,它其实可以理解为一种更广意义上的众包。核心也是突破时间片限制。比如说我现在经营一个原创博客,天天都是自己写,就会觉得自己累得都不行了。 但如果我们去做一个访谈类的博客,弄一个相对固定的问题列表,然后拿着这个列表去采访各行各业的人,把结果做成一期一期的内容。这样用户就贡献了至少一半的内容了。 如果我们再改成办一个杂志,每一期大家根据主题投稿,你就从主创变身成编辑了。虽然投稿里有好有坏,良莠不齐,但我们的主要任务已经变成去筛选了,只要贡献内容的用户足够的多,那整体质量还是有保证的。最主要是内容的量就上来了。一个人的话,不管你多么努力,总是有一个上限的,因为你毕竟是人类。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » UGC","id":"53","title":"UGC"},"54":{"body":"「 自动化 」前边有提过。 就是说应用做起来以后,它所有的环节全部都可以由机器完成,我们什么都不用管,只需要把它扔到云平台上,然后定期给云平台打钱。当然这是一个理想的情况,意外总是会出现的,而且各种意外会约好在同一天出来逛街,别问我为啥知道。但是在绝大部分情况下,我们都可以不去管它,它都可以自动化运行。这种被动资产是非常适合副业来做的。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 自动化","id":"54","title":"自动化"},"55":{"body":"我们也可以更为量化地给资产定一个评估标准,确定好要考察的几个方面,每个方面做一个满分为5分的评分,对每一项评分就可以得到一个多边形,从而一目了然的看到各类资产的状况。 这个标准每个人的想法可能不同,这里分享的是我自己用得比较多的标准。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 量化评估标准","id":"55","title":"量化评估标准"},"56":{"body":"项目的一般投入都是三项:「人」、「钱」、「时间」。 「人」和「时间」不多说,通常就是我们自己和挤出来的那点时间了。 「钱」方面,我们也需要一点启动资金,但 不用花大钱去购买各种固定资产。这也是我们这个行业能自己动手创造资产的一个重要原因 。尤其是现在,云计算已经普及了。即使是很大访问量的网站,我们直接租用云服务,按用量付费,省钱又省心。我大学刚毕业的时候,要是做大点的网站,还要自己去买服务器,自己扛去机房托管。现在只需要点点鼠标就能买到一堆 vps ,其实是蛮幸福的。 要提醒大家的是,一定不要忘记维护成本。我们卖时间片的时候,活干完就完了,钱就拿到手了。 但是在自己创造资产的时候,资产的每个细节基本都得自己来 cover 的,所以 维护成本一定要算进去 。 维护成本往往不是那么显而易见。比如说吧,网课也是有维护成本的,尤其是技术类的,它的更新成本其实相当高。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 投入","id":"56","title":"投入"},"57":{"body":"在评估产出的时候,可以分为「一次性的回报」和「周期性的回报」。 一次性回报,比如我们给人家做技术顾问。可能就是在周三拿到一个邮件介绍说是什么样的一个需求,有什么问题要解答。我们花上2~3个小时来准备,在周末约一个时间,面谈一个小时,把之前准备的内容聊清楚,聊完了以后,回报就拿到手了。这就是一次性回报。 周期性回报,比如说我们在 掘金 上写了一个小册,那只要有人在购买,我们就会不停的有收益,这种收入一般按月结,所以每次看起来没多少,但加起来还是挺多的。我之前算了一下,发现 在我创造的各种资产中,掘金小册的投入产出比是最高的 。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 产出","id":"57","title":"产出"},"58":{"body":"持续性是以前忽略掉的评分项,后来被我追加上来。这其实是一个非常浅显的道理, 一个资产放在那个地方,它不可能一直就持续地挣钱 。就像电池光用不充电的话,总会有用光的一天(别和我提太阳能电池)。 这是因为我们创造这个资产的时候,它是面对一个市场需求的,而需求本身它会随时间变动。绝大部分的情况下,需求和我们提供的解决方案之间的契合度,会随着时间越来越差。最后就会变成,要么我们就不去管它,让它慢慢地随着时间去消亡;要么我们又要花成本去维护它,把它从偏差的地方给拉回来,重新覆盖到需求上面。把用户的满意度、用户的体验、市场的趋势给重新考虑进去,让我们资产的生命期变得更长。 对于不同的资产,只是过程的快慢会不一样,但整体来讲,都是会有这么一个过程的。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 可持续性","id":"58","title":"可持续性"},"59":{"body":"程序员创造产品最大的风险是「 没人用 」,因为虽然大部分科班出身的程序员都学过需求分析,但仍然各种喜欢拿着锤子找钉子。 当然,这对于没有做过独立开发或者自己产品的同学来讲,是一个必经的阶段。所以早期项目的风险都会非常高,但并不是说风险高我们就不做了,我们可以相对的调低投入,原来要投入三个月上线的产品,可以花三天做个最小可行产品(MVP,后文会说明)上线,测试到需求以后,再继续加码。这样也能慢慢的获取到一个平衡点。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 风险","id":"59","title":"风险"},"6":{"body":"B象限是创业象限,和S象限最大的不同是我们不是自己干活,而是雇用其他人来帮我们干活挣钱。 它的优点在于,可以让我们从S象限的天花板中解脱出来,拥有规模化成长的可能性。 而缺点在于,它有一个比较大的固定成本。即使是对于轻资产的互联网公司来说,也是如此。比如人力成本。招聘、组建、培养一个团队是非常耗费时间和精力的,所以即使当业务不好的时候,我们还是需要支付大量的工资来维持团队,以便之后能快速恢复业务。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » B象限(创业象限)、让雇员挣钱","id":"6","title":"B象限(创业象限)、让雇员挣钱"},"60":{"body":"最后我加了一个评估标准叫做门槛。因为「副业」的关系,我们的各项资源都是受限的,这个评估标准体现了受限情况下创造资产的难度。","breadcrumbs":"如何优雅地做副业 » 资产和被动收入 » 资产的量化评估 » 门槛","id":"60","title":"门槛"},"61":{"body":"在这一部分,我们整理了大量的副业,并从中拿出适合程序员的来进行评估和讨论。","breadcrumbs":"优选资产 » 优选资产","id":"61","title":"优选资产"},"62":{"body":"","breadcrumbs":"优选资产 » 知识和人脉的变现 » 知识和人脉的变现","id":"62","title":"知识和人脉的变现"},"63":{"body":"picture 2 总体来讲,付费视频课是一个中等投入,然后产出极高的副业。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 付费视频课","id":"63","title":"付费视频课"},"64":{"body":"前期需要做一些课程内容的准备;后期你需要对视频进行剪辑;录音还需要购买硬件。大部分的程序员并没有视频剪辑技能,所以这里有学习成本。硬件的话倒不算贵,便宜点的不到一千就能搞定。但是这是在我们赚到钱之前就要投入进去的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低投入 ★","id":"64","title":"低投入 ★"},"65":{"body":"从产出上来讲,课程是一个非常好的品类。中国人有良好的为教育花钱的传统,大部分的用户都愿意为好的课程花钱。一些优质的、上百节的大课可以卖到几千甚至几万。相比其他的副业,它的产出是非常高的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 高产出 ★★★★★","id":"65","title":"高产出 ★★★★★"},"66":{"body":"我们是做技术类的课程。技术内容本身的变更是非常快的,除非我们做一些非常经典的基础课,比如说计算机原理、算法等等。 如果是跟语言、框架、实战相关的各种前沿课程,大概半年到一年就需要更新一次。如果我们使用屏幕录制方式来制作课程,在修改的时候,很可能需要重录相当部分,修改起来成本很高。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 可持续性 ★★","id":"66","title":"可持续性 ★★"},"67":{"body":"风险不低。如果做的课程比较长,比如几十上百集的大课,用业余时间来做可能会花上几个月甚至一两年,有时候做完技术都更新了。如果最终卖不出去的话,损失是很大的。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低风险 ★★","id":"67","title":"低风险 ★★"},"68":{"body":"门槛不算高也不算低。如果经常在公司里面给团队做分享的话,那对你来讲这个门槛就很低。如果一直都是默默无闻地在做技术的话,可能就需要去练习一下怎么讲课。 因为我们最终是可以通过剪辑来进行调整的,所以也只是一个时间投入上的问题。讲得不好,你就多讲几遍;哪一句讲错了,就重新再讲。所以它本身的硬性门槛并不高。 关于风险和维护成本这两点,其实是有办法可以解决的,我们会在后续用专门的章节来讨论,这里就不展开了。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费视频课 » 低门槛 ★★★","id":"68","title":"低门槛 ★★★"},"69":{"body":"picture 3 付费专栏就是付费的系列文章,绝大部分是技术教程,也有一些面向程序员的「心灵鸡汤」。我们可以简单地把它看成是传统出版的网络化。 对于技术内容来说,传统的纸书出版方式有一些明显的缺点。比如,不是彩页的话代码不能高亮,彩页的话书又特别贵。书里的代码也不能边看边调试。纸书的出品周期也较长,更新也慢,一些最新的技术会有一个较长的空白期。 而在线的付费专栏恰恰可以解决掉这些问题:它基于浏览器,自然可以通过 JS 来进行代码高亮;内容可以在线修改,几乎可以实时生效;做得细的技术专栏往往还内嵌了基于浏览器的调试环境,可以做到边学边练。 再加上原来技术博客的群众基础很好,于是技术平台和社区纷纷添加了付费专栏功能。这其中,做得比较好的应该算掘金的 小册 。 picture 6 下面我们来看一下付费专栏作为副业资产的各项评分。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 付费专栏","id":"69","title":"付费专栏"},"7":{"body":"I象限是投资象限,是在我们有了一定的资本之后的一种让钱挣钱的方式。在B象限里,我们需要创办企业来挣钱,这需要大量的精力。即使你的精力异常充沛,同时运营三五家公司也就到上限了。I象限让我们以投资的方式参与到大量的公司中去,共享这些公司的增长,从而实现资产的增值。 在了解了四大象限以后,我们可以发现,如果赶不上公司上市这种可遇不可求的事情、或者能一路升迁做到大公司高层,先不说财务自由,光是要想在北上深买房安家,只留在E象限都是非常困难的 —— 我们必须向其他象限发展。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 职业的四大象限 » I象限(投资象限)、让钱挣钱","id":"7","title":"I象限(投资象限)、让钱挣钱"},"70":{"body":"从投入上来讲,文字专栏比视频课程投入要低很多。但是技术内容比起其他文章的写作来讲,需要有技术实践作为基础,经常还要嵌入代码,调整格式,投入相对要高些。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低投入 ★★★","id":"70","title":"低投入 ★★★"},"71":{"body":"文字专栏的售价普遍比视频课程要低,像掘金小册的话,一般就在20~30块钱之间,还经常打折促销。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 高产出 ★★★","id":"71","title":"高产出 ★★★"},"72":{"body":"前面已经说过,技术内容一般更新频次高。但是图文专栏的更新成本很低,只需要编辑文字、加入新的内容就好,不需要像视频那样重新录制和剪辑。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 可持续性 ★★★","id":"72","title":"可持续性 ★★★"},"73":{"body":"文章的创作成本很低,而且我们可以通过发布短文来测试主题是否受欢迎,在确认后再开始系列文章的书写。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低风险 ★★★★","id":"73","title":"低风险 ★★★★"},"74":{"body":"只要会写文章,就可以做付费专栏。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费专栏 » 低门槛 ★★★★★","id":"74","title":"低门槛 ★★★★★"},"75":{"body":"picture 4 所谓付费社群就是指一些收费的微信群,QQ群或者付费可见的信息流、圈子类产品。 之所以把付费社群单独拿出来讲,是因为它更偏重于销售的不是内容本身,而是一种人脉关系、社区氛围或者互动型的服务。 像付费课程,通常是类似于出版。我提供内容,你来进行学习。通过文章评论和回复进行互动,时效性和效率比较低。 而在付费社群里边,大家互动起来会比较方便。比如在群里,你一句我一语很快就可以讨论起来。所以,付费课程和付费社群其实是有互补关系的两个产品。 我们可以把付费课程放到课程平台,然后把实时的学员答疑或者其他服务,再做成付费社群。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 付费社群","id":"75","title":"付费社群"},"76":{"body":"付费社群的投入是非常低的。如果我们要做课程的话,需要累积相当多的内容。但是付费社群它卖的不是内容本身,所以即使它没有内容,也可以立刻进行销售。 而且因为社群的互动环境在形式上比较随意,有个什么想法随时发一段文字或者几张照片都可以,内容创作的成本很低。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低投入 ★★★★","id":"76","title":"低投入 ★★★★"},"77":{"body":"产出方面就要看具体销售的是什么东西。氛围和讨论环境本身,通常不会特别值钱。但是如果能利用起来,价值就会非常高。比如用付费社群来做中高端猎头服务。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 高产出 ★★★","id":"77","title":"高产出 ★★★"},"78":{"body":"需要持续不断的有内容更新。当然也可以引导其他用户贡献内容。如果一段时间没有内容和话题,就很难维持社群的活跃,氛围会随着时间慢慢变冷,严重影响第二年的续费。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 可持续性 ★","id":"78","title":"可持续性 ★"},"79":{"body":"没什么特别的风险。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低风险 ★★★★★","id":"79","title":"低风险 ★★★★★"},"8":{"body":"然而在没有副业的情况下,我们的职业就是单进程、只能做单选题。 我们在象限之间的移动,往往只能是突发式的。前一天还在E象限做雇员,第二天突然就辞职创业或者做外包去了。然而贸然进入一个新象限,将面临非常大的风险。因为每一个象限,它背后的商业模式是不同的,对人的能力、思维、精力的要求也都完全不一样。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » 没有副业的职业","id":"8","title":"没有副业的职业"},"80":{"body":"会建群会聊天就可以开始。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 付费社群 » 低门槛 ★★★★★","id":"80","title":"低门槛 ★★★★★"},"81":{"body":"picture 5 如果把电子书也算进来,目前可以分发图书的方式大概有三类。 第一类是自己独立撰写图书,并生成 PDF 等电子书格式通过自己的渠道进行销售。这种更类似于数字商品售卖,所以并不包含在本节图书出版中。 第二类是通过出版商单独发行电子版。因为电子书不需要印刷,所以比起纸版图书门槛更低一些。我之前用 BookDNA 出版过电子书,只需要将书提交给他们,就可以上架到亚马逊、苹果、京东、多看等多个平台。收入他们会代收,按分成结算回来。 第三类就是通过出版社出纸书,有时候也会同时把电子书版权签下来。一般纸版的门槛会高一些,需要有一定的影响力或者完成度已经较高的书稿作为参考。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 图书出版","id":"81","title":"图书出版"},"82":{"body":"图书出版的投入非常大。一般至少需要花费3到6个月来编写初稿,加上审校印刷等环节,最后出版可能还需要花上半年,整个周期很长。 基于现有的内容,比如课程、文章整理创作书稿投入会相对较低,但仍有大量的工作要做。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低投入 ★","id":"82","title":"低投入 ★"},"83":{"body":"产出要把物质回报和非物质回报分开来看。 通过 BookDNA 等出版社专门出版电子书,可以按图书销售收入获得分成,大概在 70% ,还算不错。如果是纸版书,一般版税就只有 8%~15%,整体收入相当有限。 但纸版书对个人品牌提升的效果明显,而且可以通过线下书店等渠道获得读者,所以在非物质回报上比较高。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 高产出 ★★★","id":"83","title":"高产出 ★★★"},"84":{"body":"图书的更新频次都很低,一般只有销售得不错,才会在再版时进行修订。所以我们可以认为它的可持续性还算不错。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 可持续性 ★★★★","id":"84","title":"可持续性 ★★★★"},"85":{"body":"主要还是时间投入,没有太多额外的风险。因为我们主要是出版技术书籍,内容方面的风险也非常小。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低风险 ★★★★","id":"85","title":"低风险 ★★★★"},"86":{"body":"不管是电子版还是纸版,都要经过图书编辑审核,通过以后才能出版。尤其是纸书,要考虑至少收回印刷成本,所以门槛还是很高的。 如果在 GitHub 或者其他地方有发布电子书,且有较好的反馈,那么纸版的出版谈起来门槛就会低很多。","breadcrumbs":"优选资产 » 知识和人脉的变现 » 图书出版 » 低门槛 ★","id":"86","title":"低门槛 ★"},"87":{"body":"那接下来我们就来聊聊程序员的专业领域 —— 通过开发自有的产品和服务、作为 side project 运营来变现。","breadcrumbs":"优选资产 » 自有产品和服务 » 自有产品和服务","id":"87","title":"自有产品和服务"},"88":{"body":"首先要说的是很多同学都很困扰的问题。 我以前以为最困扰的问题应该是如何抽出时间和精力来做一个项目,但后来发现还有一个同样甚至更为困扰大家的问题,那就是有了时间以后,不知道做什么。 通常来讲,解决方案有两种。 一种是通过日常的工作和生活发现原生需求;另一种是通过观察分析和阅读报告来发现。","breadcrumbs":"优选资产 » 自有产品和服务 » 需求的发现","id":"88","title":"需求的发现"},"89":{"body":"最靠谱的方式就是,留意那些我们自己在日常的生活和工作中遇到的困扰,然后为它去做解决方案,最后把这个解决方案做成产品,出售给有同样需求的人。 这种需求叫做原生需求,不是我们因为有了某个技术而幻想出来的应用场景。原生需求不是等我我们去寻找,而是它会主动找到我们。这种需求非常真实可靠。 但有一个问题,我们程序员相对于整个大众来讲,其实是一个非常小众的人群。这个人群有一些独特的文化、行为和思考方式。所以程序员遇到的原生需求,很可能只适合程序员人群,而不适合其他更为大众的市场。这就让它的目标市场比较小。 而程序员又是一个动手能力非常强、开源文化深入骨髓的群体,绝大部分的解决方案都能找到开源项目,或者改几行代码就能实现了。一些大公司还时不时的开源一堆非常强悍的工具,所以面向这个群体的免费或开源工具很受欢迎,但收费工具却是非常难做的。 反而是如果你在非专业领域有一些更为大众的兴趣爱好,从那些方面来发现需求的话,难度就会下降很多。 需求的验证 另外要重复强调的就是,需求的验证不能以口头承诺甚至免费用户来验。做需求分析的时候你去问,很多都会说我觉得这个东西挺好的。但你让他们付钱的时候情况就完全不同了。 大家可以回想下自己在过去一年里边,为哪些软件或服务支付超过 100 元人民币。我之前发过一篇微博问我的粉丝(大部分是程序员),后来发现绝大部分都是一些资源型的服务,比如视频会员、云主机、网课、网盘;软件就非常少了。所以我们还是要尽可能的从更广泛的人群里去发掘更值钱的需求来做。 降低起始难度 上边并不是说程序员人群的需求不能做,而是说难度比较高。 作为副业,我们投入的精力是有限的,如果一上来就是玩 Hard 模式,失败的概率会非常高。如果经常失败的话,最后就变成一种习惯了,渐渐的,也就会不再想去做副业,甚至连创业的冲动也跟着没有了,这就非常可惜。","breadcrumbs":"优选资产 » 自有产品和服务 » 原生需求","id":"89","title":"原生需求"},"9":{"body":"先来说说「辞职创业」。 媒体很喜欢把创业宣传得一蹴而就,仿佛只要有一个独特的想法,就可以一夜暴富、咸鱼翻身。 程序员群体的理想主义趋向又比较明显,加上有无数包装出来的成功案例,所以这是程序员从E象限移动到B象限最常见的途径。 有激进派的,拿着自己的一点积蓄就英勇地加入的创业的队伍;有稳健点的,在搞定了天使投资以后再离职的。 但创业的光环在市场的面前毫无用处,要找到一个真正有商业价值的需求非常困难,往往要花很长的时间试错。而后,还要针对这个需求做出比现有方案至少好十倍的新方案。同时,还有大量公司管理、人力招聘、融资沟通方面的事务,这些都会让创业新手难以招架。 不少程序员朋友找我聊他们的创业想法,我发现他们真的只有想法 —— 完全没有进行过验证,他们并不了解B象限的生存法则。","breadcrumbs":"为什么副业特别重要 » 职业可能性 » 没有副业的职业 » E→B,辞职创业","id":"9","title":"E→B,辞职创业"},"90":{"body":"另一个路径是观察分析那些已经在挣钱的应用,阅读它的用户评论,发现可以改良的点,制作更好的产品。这个工作量还是很大的,所以也可以考虑直接购买一些分析报告。 这里的分析报告不是那种行业的通用报告,那是针对创业公司和大公司的,需要投入很多资源,以爆发式增长的方式去推动,并不适合副业。 最近在国外开始有一些专门针对副业和 Side project 的分析报告。他们收集整个市场的信息,然后针对大致一亿美金以下的细分市场做趋势分析。这种市场一般冲着上市去的创业公司看不上,所以留下了比较大的市场空间。 我最近读过报告的有两家,一家是 Trends.vc,另一家是 SoftwareIdeas.io。不过这两家本身也是初创或副业业务,不知道各位读到这本书的时候是否还在运营。这里最主要的还是给大家提供一种思路。 我们在做副业的时候,也需要慢慢来改变我们的一些习惯。比如说对于程序员来讲,绝大部分的东西都是可以自力更生的。所有能自己做的就自己做,不能自己做的,我们会找开源项目。这样我们会更有安全感,做的事情也会更加靠谱。但是我们在做商业的时候,尤其是在做副业的时候,遇到的问题就在于我们的精力是非常有限的,在价格适中、又有购买能力的情况下,更好的方式是通过购买而不是自己开发。","breadcrumbs":"优选资产 » 自有产品和服务 » 观察分析和阅读报告","id":"90","title":"观察分析和阅读报告"},"91":{"body":"picture 5 对于我们绝大部分程序员来讲,开发是自己的本职工作,所以都比较擅长。但是在做副业的时候,我们还不可避免地需要把自己的软件卖出去。而销售往往是我们的弱项,有没有一个办法让我们可以避免它呢? 答案就是应用商店。早期的应用商店是一个非常好的入口,它会分门别类的将软件陈列在上面,有需求的用户会通过分类浏览或者搜索查询的方式来安装或者购买。 但经过一段时间的发展,应用商店里边的软件已经越来越多,各种需求被满足得也越来越充分。 现在大部分的应用商店已经是红海市场,也就意味着说,即使你在应用商店上架了软件,也不等于其他的用户有机会看见它,因为软件实在是太太太多了。 所以,我们需要想办法在应用市场的应用海洋中获取流量。一般来讲免费获得流量的途径有两个。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 应用市场卖 APP","id":"91","title":"应用市场卖 APP"},"92":{"body":"一个是通过关键字搜索。一般应用商店都会有搜索入口,用户输入关键字,商店则会列出匹配的应用列表。如果我们指定的关键字被搜得更多,那就更容易覆盖到更多的人群。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 关键字搜索","id":"92","title":"关键字搜索"},"93":{"body":"另外一个途径是编辑推荐。一些看起来有创意、格调比较高的APP更容易被推荐。而同样功能但是界面不好看的应用,则很难被推荐。所以界面设计不光是用户体验的问题,甚至还直接影响我们的获客。 虽然现在应用市场很多,但是有强用户付费习惯的国内市场,其实也就是苹果商店,所以我们如果以挣钱为主要目标的话,就应该优先考虑苹果商店这个市场。Google 在国内没有商店业务,如果是面向全球市场的业务,可以上 Google Play。 下边来看看评分项。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 编辑推荐","id":"93","title":"编辑推荐"},"94":{"body":"从投入上来说,如果你本身不是 iOS 开发者,又没有苹果电脑,那么可能需要为 iOS APP 开发购买一些硬件,同时苹果开发者还有一个至少 699 的开发者年费。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低投入 ★★★","id":"94","title":"低投入 ★★★"},"95":{"body":"一旦进入市场某个分类排行前列,可以获得的流量还是很多的。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 高产出 ★★★★","id":"95","title":"高产出 ★★★★"},"96":{"body":"需要跟上操作系统的更新升级。应用市场会定期下架一些 SDK 版本过低的APP。大部分时候只重新编译就好了,但如果使用的一些库出现了兼容性问题,那么就需要有大量的维护工作了。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 可持续性 ★★★","id":"96","title":"可持续性 ★★★"},"97":{"body":"软件应用商店托管,数据同步可以用 iCloud 等,没什么特别风险。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低风险 ★★★★","id":"97","title":"低风险 ★★★★"},"98":{"body":"对移动客户端的开发者来讲,基本上没有门槛。其他开发者要进入这个市场,需要学习移动开发技能。当然也有桌面应用市场,但数据比移动市场差很多。","breadcrumbs":"优选资产 » 自有产品和服务 » 应用市场卖APP » 低门槛 ★★★","id":"98","title":"低门槛 ★★★"},"99":{"body":"","breadcrumbs":"精益副业 » 精益副业","id":"99","title":"精益副业"}},"length":252,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{"0":{"df":1,"docs":{"15":{"tf":1.0}}},"df":5,"docs":{"162":{"tf":1.0},"201":{"tf":1.0},"202":{"tf":1.0},"231":{"tf":1.0},"236":{"tf":1.0}}},"1":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.7320508075688772}},"万":{"df":0,"docs":{},"左":{"df":0,"docs":{},"右":{"df":0,"docs":{},"的":{"df":0,"docs":{},"人":{"df":0,"docs":{},"民":{"df":0,"docs":{},"币":{"df":0,"docs":{},"基":{"df":0,"docs":{},"本":{"df":0,"docs":{},"上":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"够":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"1":{"0":{"0":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}},"d":{"b":{"df":1,"docs":{"228":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"121":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"89":{"tf":1.0}},",":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"想":{"df":0,"docs":{},"加":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"改":{"df":0,"docs":{},"为":{"df":0,"docs":{},"大":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":0,"docs":{},";":{"df":0,"docs":{},"想":{"df":0,"docs":{},"减":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"小":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":1,"docs":{"227":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":5,"docs":{"107":{"tf":1.0},"126":{"tf":1.0},"177":{"tf":2.23606797749979},"189":{"tf":1.0},"228":{"tf":1.0}},"x":{"df":1,"docs":{"23":{"tf":1.0}}},"万":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"。":{"df":0,"docs":{},"以":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"它":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"能":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"花":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"。":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"想":{"df":0,"docs":{},"到":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"新":{"df":0,"docs":{},"办":{"df":0,"docs":{},"法":{"df":0,"docs":{},",":{"df":0,"docs":{},"把":{"df":0,"docs":{},"效":{"df":0,"docs":{},"率":{"df":0,"docs":{},"提":{"df":0,"docs":{},"升":{"df":0,"docs":{},"了":{"1":{"0":{"df":0,"docs":{},"倍":{"df":0,"docs":{},",":{"df":0,"docs":{},"那":{"df":0,"docs":{},"么":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"才":{"df":0,"docs":{},"能":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"的":{"df":0,"docs":{},"活":{"df":0,"docs":{},",":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"1":{"0":{"df":1,"docs":{"39":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}},"1":{"df":2,"docs":{"126":{"tf":1.0},"230":{"tf":1.0}}},"2":{"df":3,"docs":{"133":{"tf":1.0},"230":{"tf":1.0},"27":{"tf":1.0}}},"3":{"df":2,"docs":{"133":{"tf":1.0},"230":{"tf":1.0}}},"4":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"5":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"6":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"7":{"df":2,"docs":{"143":{"tf":1.0},"232":{"tf":1.0}}},"8":{"df":2,"docs":{"144":{"tf":1.0},"232":{"tf":1.0}}},"9":{"df":2,"docs":{"149":{"tf":1.0},"232":{"tf":1.0}}},"df":6,"docs":{"113":{"tf":1.0},"16":{"tf":1.0},"177":{"tf":1.0},"189":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0}}},"2":{"0":{"0":{"0":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"一":{"df":0,"docs":{},"个":{"df":0,"docs":{},"月":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"是":{"8":{"0":{"0":{"0":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"1":{"4":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}},"2":{"0":{"df":0,"docs":{},"年":{"4":{"df":1,"docs":{"13":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":4,"docs":{"149":{"tf":1.0},"191":{"tf":1.0},"234":{"tf":1.0},"41":{"tf":1.0}},"~":{"3":{"0":{"df":1,"docs":{"71":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"1":{"df":2,"docs":{"152":{"tf":1.0},"236":{"tf":1.0}}},"2":{"df":2,"docs":{"153":{"tf":1.0},"237":{"tf":1.0}}},"3":{"df":2,"docs":{"154":{"tf":1.0},"237":{"tf":1.0}}},"4":{"df":3,"docs":{"157":{"tf":1.0},"189":{"tf":1.0},"238":{"tf":1.0}}},"5":{"df":2,"docs":{"159":{"tf":1.0},"251":{"tf":1.0}}},"6":{"df":3,"docs":{"140":{"tf":1.0},"159":{"tf":1.0},"240":{"tf":1.0}}},"7":{"df":2,"docs":{"159":{"tf":1.0},"241":{"tf":1.0}}},"8":{"df":2,"docs":{"160":{"tf":1.0},"242":{"tf":1.0}}},"9":{"df":1,"docs":{"160":{"tf":1.0}}},"a":{"3":{"df":0,"docs":{},"r":{"df":4,"docs":{"121":{"tf":1.0},"175":{"tf":1.0},"176":{"tf":1.4142135623730951},"177":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":6,"docs":{"114":{"tf":1.0},"159":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0},"63":{"tf":1.0}},"~":{"3":{"df":1,"docs":{"57":{"tf":1.0}}},"df":0,"docs":{}}},"3":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"160":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"189":{"tf":1.4142135623730951},"243":{"tf":1.0}}},"1":{"df":2,"docs":{"160":{"tf":1.0},"244":{"tf":1.0}}},"2":{"df":2,"docs":{"161":{"tf":1.0},"246":{"tf":1.0}}},"3":{"df":1,"docs":{"161":{"tf":1.0}}},"4":{"df":1,"docs":{"161":{"tf":1.0}}},"5":{"df":2,"docs":{"10":{"tf":1.0},"162":{"tf":1.0}}},"6":{"df":1,"docs":{"162":{"tf":1.0}}},"7":{"df":1,"docs":{"162":{"tf":1.0}}},"8":{"df":1,"docs":{"163":{"tf":1.0}}},"9":{"df":1,"docs":{"169":{"tf":1.0}}},"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":3,"docs":{"116":{"tf":1.0},"224":{"tf":1.0},"69":{"tf":1.0}},"到":{"6":{"df":1,"docs":{"82":{"tf":1.0}}},"df":0,"docs":{}}},"4":{"0":{"df":2,"docs":{"118":{"tf":1.0},"169":{"tf":1.0}}},"1":{"df":1,"docs":{"170":{"tf":1.0}}},"2":{"df":1,"docs":{"176":{"tf":1.0}}},"9":{"df":1,"docs":{"191":{"tf":1.0}}},"df":3,"docs":{"117":{"tf":1.0},"224":{"tf":1.0},"75":{"tf":1.0}}},"5":{"0":{"0":{"df":1,"docs":{"189":{"tf":1.0}}},"df":2,"docs":{"123":{"tf":1.4142135623730951},"197":{"tf":1.0}}},"2":{"df":1,"docs":{"198":{"tf":1.0}}},"3":{"df":1,"docs":{"198":{"tf":1.0}}},"4":{"df":1,"docs":{"198":{"tf":1.0}}},"5":{"df":1,"docs":{"198":{"tf":1.0}}},"6":{"df":1,"docs":{"198":{"tf":1.0}}},"7":{"df":1,"docs":{"199":{"tf":1.0}}},"8":{"df":1,"docs":{"199":{"tf":1.0}}},"9":{"df":1,"docs":{"199":{"tf":1.0}}},"df":6,"docs":{"118":{"tf":1.0},"162":{"tf":1.0},"224":{"tf":1.0},"55":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}},"6":{"0":{"df":1,"docs":{"199":{"tf":1.0}}},"2":{"df":1,"docs":{"200":{"tf":1.0}}},"3":{"df":1,"docs":{"201":{"tf":1.0}}},"4":{"df":1,"docs":{"201":{"tf":1.0}}},"5":{"df":1,"docs":{"201":{"tf":1.0}}},"6":{"df":1,"docs":{"201":{"tf":1.0}}},"7":{"df":1,"docs":{"201":{"tf":1.0}}},"8":{"df":1,"docs":{"201":{"tf":1.0}}},"9":{"9":{"df":1,"docs":{"94":{"tf":1.0}}},"df":1,"docs":{"202":{"tf":1.0}}},"df":5,"docs":{"102":{"tf":1.0},"119":{"tf":1.0},"225":{"tf":1.0},"231":{"tf":1.0},"69":{"tf":1.0}}},"7":{"0":{"df":2,"docs":{"202":{"tf":1.0},"83":{"tf":1.0}}},"1":{"df":1,"docs":{"202":{"tf":1.0}}},"2":{"df":1,"docs":{"202":{"tf":1.0}}},"3":{"df":1,"docs":{"209":{"tf":1.0}}},"4":{"df":1,"docs":{"211":{"tf":1.0}}},"5":{"df":1,"docs":{"211":{"tf":1.0}}},"7":{"df":1,"docs":{"212":{"tf":1.0}}},"8":{"df":1,"docs":{"213":{"tf":1.0}}},"9":{"df":1,"docs":{"215":{"tf":1.0}}},"df":3,"docs":{"103":{"tf":1.0},"120":{"tf":1.0},"226":{"tf":1.0}},"×":{"2":{"4":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"8":{"%":{"df":0,"docs":{},"~":{"1":{"5":{"df":1,"docs":{"83":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"0":{"df":1,"docs":{"216":{"tf":1.0}}},"1":{"df":1,"docs":{"217":{"tf":1.0}}},"2":{"df":1,"docs":{"216":{"tf":1.0}}},"3":{"df":1,"docs":{"216":{"tf":1.0}}},"4":{"df":1,"docs":{"216":{"tf":1.0}}},"5":{"df":2,"docs":{"221":{"tf":1.0},"27":{"tf":1.0}}},"6":{"df":1,"docs":{"221":{"tf":1.0}}},"7":{"df":1,"docs":{"221":{"tf":1.0}}},"8":{"df":1,"docs":{"221":{"tf":1.0}}},"9":{"df":1,"docs":{"221":{"tf":1.0}}},"df":3,"docs":{"104":{"tf":1.0},"121":{"tf":1.0},"227":{"tf":1.0}}},"9":{"0":{"df":3,"docs":{"15":{"tf":1.0},"221":{"tf":1.0},"39":{"tf":1.0}}},"df":3,"docs":{"106":{"tf":1.0},"122":{"tf":1.0},"228":{"tf":1.0}}},"a":{"4":{"df":1,"docs":{"132":{"tf":1.0}}},"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":1,"docs":{"176":{"tf":1.0}}}}}},"b":{"c":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"一":{"df":0,"docs":{},"里":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"a":{"df":0,"docs":{},";":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"二":{"df":0,"docs":{},"中":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"b":{"c":{"df":1,"docs":{"210":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"103":{"tf":1.0}}}}}},"d":{"df":0,"docs":{},"o":{"b":{"df":4,"docs":{"157":{"tf":2.0},"158":{"tf":1.0},"223":{"tf":1.0},"228":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":1,"docs":{"156":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":2,"docs":{"133":{"tf":1.0},"41":{"tf":2.449489742783178}},"r":{"b":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"27":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"n":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"df":1,"docs":{"114":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"i":{"df":7,"docs":{"168":{"tf":1.4142135623730951},"169":{"tf":1.0},"170":{"tf":1.0},"174":{"tf":1.0},"238":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}},"p":{"df":9,"docs":{"166":{"tf":1.0},"172":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"27":{"tf":1.0},"91":{"tf":1.0},"93":{"tf":1.0},"94":{"tf":1.0},"96":{"tf":1.0}},",":{"df":0,"docs":{},"以":{"df":0,"docs":{},"每":{"df":0,"docs":{},"分":{"df":0,"docs":{},"钟":{"1":{"0":{"0":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"r":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":2,"docs":{"237":{"tf":1.0},"238":{"tf":1.0}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"159":{"tf":1.0}}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"、":{"df":0,"docs":{},"p":{"df":0,"docs":{},"h":{"df":0,"docs":{},"p":{"df":0,"docs":{},"和":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}}}}}},"u":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"228":{"tf":1.0},"230":{"tf":1.0}}}}},"df":4,"docs":{"230":{"tf":1.4142135623730951},"231":{"tf":1.0},"232":{"tf":1.0},"233":{"tf":1.0}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"160":{"tf":1.0}}}},"df":0,"docs":{}},"df":4,"docs":{"10":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":1.0}},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"d":{"df":0,"docs":{},"n":{"a":{"df":2,"docs":{"81":{"tf":1.0},"83":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"创":{"df":0,"docs":{},"业":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"和":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}}}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"163":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"56":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"或":{"df":0,"docs":{},"者":{"c":{"df":0,"docs":{},"m":{"d":{"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"d":{"b":{"df":1,"docs":{"231":{"tf":1.4142135623730951}}},"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":1,"docs":{"38":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"z":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"y":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"187":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":4,"docs":{"10":{"tf":1.0},"4":{"tf":2.0},"7":{"tf":1.0},"8":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.0},"9":{"tf":1.0}}},"df":2,"docs":{"10":{"tf":1.0},"12":{"tf":1.0}}},"、":{"df":0,"docs":{},"s":{"df":0,"docs":{},"、":{"b":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":1,"docs":{"3":{"tf":1.0}}}}},"df":0,"docs":{}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"移":{"df":0,"docs":{},"动":{"df":0,"docs":{},"到":{"b":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"220":{"tf":2.0},"221":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"1":{"0":{"8":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":1,"docs":{"15":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"154":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"154":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":2,"docs":{"19":{"tf":1.7320508075688772},"31":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{"df":3,"docs":{"186":{"tf":1.0},"238":{"tf":1.4142135623730951},"86":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"93":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"a":{"d":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},";":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"面":{"df":0,"docs":{},"向":{"df":0,"docs":{},"国":{"df":0,"docs":{},"内":{"df":0,"docs":{},"市":{"df":0,"docs":{},"场":{"df":0,"docs":{},"的":{"df":0,"docs":{},"话":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"使":{"df":0,"docs":{},"用":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"n":{"b":{"a":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"169":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"k":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"d":{"df":1,"docs":{"89":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"97":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":1,"docs":{"223":{"tf":1.7320508075688772}}}}}},"o":{"df":2,"docs":{"223":{"tf":1.0},"94":{"tf":1.4142135623730951}}},"p":{"a":{"d":{"df":2,"docs":{"137":{"tf":1.4142135623730951},"223":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"159":{"tf":1.0},"223":{"tf":1.0}},"e":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"a":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"是":{"df":0,"docs":{},"非":{"df":0,"docs":{},"常":{"df":0,"docs":{},"有":{"df":0,"docs":{},"用":{"df":0,"docs":{},"的":{"df":0,"docs":{},"。":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"将":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"和":{"df":0,"docs":{},"推":{"df":0,"docs":{},"广":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"放":{"df":0,"docs":{},"到":{"df":0,"docs":{},"真":{"df":0,"docs":{},"人":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"的":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"上":{"df":0,"docs":{},"面":{"df":0,"docs":{},",":{"df":0,"docs":{},"万":{"df":0,"docs":{},"一":{"df":0,"docs":{},"这":{"df":0,"docs":{},"个":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"离":{"df":0,"docs":{},"开":{"df":0,"docs":{},"团":{"df":0,"docs":{},"队":{"df":0,"docs":{},",":{"df":0,"docs":{},"之":{"df":0,"docs":{},"前":{"df":0,"docs":{},"的":{"df":0,"docs":{},"投":{"df":0,"docs":{},"入":{"df":0,"docs":{},"就":{"df":0,"docs":{},"废":{"df":0,"docs":{},"掉":{"df":0,"docs":{},"了":{"df":0,"docs":{},",":{"df":0,"docs":{},"甚":{"df":0,"docs":{},"至":{"df":0,"docs":{},"会":{"df":0,"docs":{},"变":{"df":0,"docs":{},"成":{"df":0,"docs":{},"竞":{"df":0,"docs":{},"争":{"df":0,"docs":{},"对":{"df":0,"docs":{},"手":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"。":{"df":0,"docs":{},"但":{"df":0,"docs":{},"是":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"采":{"df":0,"docs":{},"用":{"df":0,"docs":{},"虚":{"df":0,"docs":{},"拟":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"220":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"186":{"tf":1.0}}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"投":{"df":0,"docs":{},"资":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"是":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"有":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"定":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"本":{"df":0,"docs":{},"之":{"df":0,"docs":{},"后":{"df":0,"docs":{},"的":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"让":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"。":{"df":0,"docs":{},"在":{"b":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"里":{"df":0,"docs":{},",":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"创":{"df":0,"docs":{},"办":{"df":0,"docs":{},"企":{"df":0,"docs":{},"业":{"df":0,"docs":{},"来":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"这":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"。":{"df":0,"docs":{},"即":{"df":0,"docs":{},"使":{"df":0,"docs":{},"你":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"异":{"df":0,"docs":{},"常":{"df":0,"docs":{},"充":{"df":0,"docs":{},"沛":{"df":0,"docs":{},",":{"df":0,"docs":{},"同":{"df":0,"docs":{},"时":{"df":0,"docs":{},"运":{"df":0,"docs":{},"营":{"df":0,"docs":{},"三":{"df":0,"docs":{},"五":{"df":0,"docs":{},"家":{"df":0,"docs":{},"公":{"df":0,"docs":{},"司":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"到":{"df":0,"docs":{},"上":{"df":0,"docs":{},"限":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"df":0,"docs":{},"i":{"df":1,"docs":{"7":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":1,"docs":{"69":{"tf":1.0}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"198":{"tf":2.0},"200":{"tf":1.0},"201":{"tf":1.4142135623730951}}}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"208":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"2":{"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":6,"docs":{"150":{"tf":1.4142135623730951},"151":{"tf":1.4142135623730951},"152":{"tf":1.7320508075688772},"154":{"tf":1.0},"155":{"tf":2.6457513110645907},"161":{"tf":1.0}}}}}},"m":{"a":{"c":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.4142135623730951}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"111":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"p":{"df":3,"docs":{"111":{"tf":1.4142135623730951},"121":{"tf":1.0},"59":{"tf":1.0}}}}},"n":{"df":1,"docs":{"248":{"tf":1.0}},"o":{".":{"1":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"v":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"b":{"df":11,"docs":{"205":{"tf":1.0},"206":{"tf":2.0},"207":{"tf":1.0},"208":{"tf":1.4142135623730951},"209":{"tf":1.7320508075688772},"210":{"tf":1.4142135623730951},"211":{"tf":1.7320508075688772},"212":{"tf":1.0},"213":{"tf":1.0},"216":{"tf":1.0},"221":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"k":{"df":1,"docs":{"210":{"tf":1.0}}}},"p":{"a":{"df":0,"docs":{},"y":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{".":{"c":{"df":0,"docs":{},"n":{"df":1,"docs":{"168":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"c":{"df":1,"docs":{"140":{"tf":1.0}}},"d":{"df":0,"docs":{},"f":{"df":2,"docs":{"195":{"tf":1.0},"81":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"a":{"df":1,"docs":{"128":{"tf":1.0}}},"df":0,"docs":{}}}}}},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"105":{"tf":1.0}}}}}}}}},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"i":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":74,"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"104":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"134":{"tf":1.7320508075688772},"143":{"tf":1.0},"144":{"tf":1.0},"149":{"tf":1.4142135623730951},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.7320508075688772},"16":{"tf":1.0},"160":{"tf":2.0},"161":{"tf":1.7320508075688772},"162":{"tf":1.7320508075688772},"163":{"tf":1.0},"169":{"tf":1.4142135623730951},"170":{"tf":1.0},"176":{"tf":1.0},"191":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":2.23606797749979},"199":{"tf":2.0},"20":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":2.449489742783178},"202":{"tf":2.0},"209":{"tf":1.0},"211":{"tf":1.4142135623730951},"212":{"tf":1.0},"213":{"tf":1.0},"215":{"tf":1.0},"216":{"tf":2.0},"217":{"tf":1.0},"22":{"tf":1.4142135623730951},"221":{"tf":2.449489742783178},"224":{"tf":2.23606797749979},"225":{"tf":1.0},"226":{"tf":1.0},"227":{"tf":1.0},"228":{"tf":1.4142135623730951},"230":{"tf":1.7320508075688772},"231":{"tf":1.7320508075688772},"232":{"tf":1.7320508075688772},"234":{"tf":1.0},"236":{"tf":1.0},"237":{"tf":1.4142135623730951},"238":{"tf":1.0},"240":{"tf":1.0},"241":{"tf":1.0},"242":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"246":{"tf":1.0},"251":{"tf":1.0},"63":{"tf":1.0},"69":{"tf":1.4142135623730951},"75":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}}}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"114":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.0}}},"df":0,"docs":{}},"y":{"df":1,"docs":{"93":{"tf":1.0}}}},"df":0,"docs":{}},"m":{"df":0,"docs":{},"f":{"df":2,"docs":{"111":{"tf":2.0},"143":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"199":{"tf":1.4142135623730951},"200":{"tf":1.0},"202":{"tf":1.4142135623730951}}}}}}}}}}},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"194":{"tf":1.0}}}},"r":{"df":5,"docs":{"223":{"tf":1.7320508075688772},"224":{"tf":1.4142135623730951},"225":{"tf":1.4142135623730951},"226":{"tf":1.0},"230":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"(":{"df":0,"docs":{},"一":{"df":0,"docs":{},"般":{"df":0,"docs":{},"简":{"df":0,"docs":{},"称":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":1,"docs":{"223":{"tf":1.0}}}}}}}}}}}}}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":2,"docs":{"157":{"tf":1.0},"163":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}}}}},"s":{"d":{"df":1,"docs":{"105":{"tf":1.0}}},"df":0,"docs":{}}},"q":{"df":0,"docs":{},"q":{"df":3,"docs":{"120":{"tf":1.0},"170":{"tf":1.0},"75":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"154":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"s":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"96":{"tf":1.0}}}},"df":3,"docs":{"10":{"tf":1.0},"5":{"tf":1.7320508075688772},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"160":{"tf":1.0}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"157":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":1,"docs":{"90":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"236":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"186":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}}},"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"g":{"df":1,"docs":{"163":{"tf":1.4142135623730951}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"的":{"df":0,"docs":{},"缺":{"df":0,"docs":{},"点":{"df":0,"docs":{},"是":{"df":0,"docs":{},",":{"df":0,"docs":{},"收":{"df":0,"docs":{},"益":{"df":0,"docs":{},"未":{"df":0,"docs":{},"必":{"df":0,"docs":{},"能":{"df":0,"docs":{},"比":{"df":0,"docs":{},"e":{"df":1,"docs":{"5":{"tf":1.0}}}}}}}}}}}}}}}}},"t":{"a":{"b":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":3,"docs":{"154":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"v":{"c":{"df":1,"docs":{"90":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"125":{"tf":1.0}}},"u":{"c":{"a":{"df":0,"docs":{},"o":{".":{"df":0,"docs":{},"j":{"df":1,"docs":{"173":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"i":{"df":1,"docs":{"221":{"tf":1.0}}},"n":{"d":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"w":{"df":1,"docs":{"153":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"160":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"124":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"s":{"b":{"df":1,"docs":{"211":{"tf":1.0}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"111":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"238":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":1,"docs":{"56":{"tf":1.0}}}},"w":{"df":0,"docs":{},"e":{"b":{"df":2,"docs":{"172":{"tf":1.0},"249":{"tf":1.0}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}}},"x":{"d":{"df":5,"docs":{"157":{"tf":1.7320508075688772},"158":{"tf":1.0},"159":{"tf":1.4142135623730951},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"y":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"168":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"s":{"df":1,"docs":{"159":{"tf":1.0}}}}}},"breadcrumbs":{"root":{"0":{"0":{"df":1,"docs":{"15":{"tf":1.0}}},"df":5,"docs":{"162":{"tf":1.0},"201":{"tf":1.0},"202":{"tf":1.0},"231":{"tf":1.0},"236":{"tf":1.0}}},"1":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.7320508075688772}},"万":{"df":0,"docs":{},"左":{"df":0,"docs":{},"右":{"df":0,"docs":{},"的":{"df":0,"docs":{},"人":{"df":0,"docs":{},"民":{"df":0,"docs":{},"币":{"df":0,"docs":{},"基":{"df":0,"docs":{},"本":{"df":0,"docs":{},"上":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"够":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"1":{"0":{"0":{"0":{"df":1,"docs":{"27":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}},"d":{"b":{"df":1,"docs":{"228":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"121":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"89":{"tf":1.0}},",":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"想":{"df":0,"docs":{},"加":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"改":{"df":0,"docs":{},"为":{"df":0,"docs":{},"大":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":0,"docs":{},";":{"df":0,"docs":{},"想":{"df":0,"docs":{},"减":{"df":0,"docs":{},"速":{"df":0,"docs":{},",":{"df":0,"docs":{},"就":{"df":0,"docs":{},"小":{"df":0,"docs":{},"于":{"1":{"0":{"0":{"df":1,"docs":{"227":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":5,"docs":{"107":{"tf":1.0},"126":{"tf":1.0},"177":{"tf":2.23606797749979},"189":{"tf":1.0},"228":{"tf":1.0}},"x":{"df":1,"docs":{"23":{"tf":1.0}}},"万":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"。":{"df":0,"docs":{},"以":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"它":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"能":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"花":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"。":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"想":{"df":0,"docs":{},"到":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"新":{"df":0,"docs":{},"办":{"df":0,"docs":{},"法":{"df":0,"docs":{},",":{"df":0,"docs":{},"把":{"df":0,"docs":{},"效":{"df":0,"docs":{},"率":{"df":0,"docs":{},"提":{"df":0,"docs":{},"升":{"df":0,"docs":{},"了":{"1":{"0":{"df":0,"docs":{},"倍":{"df":0,"docs":{},",":{"df":0,"docs":{},"那":{"df":0,"docs":{},"么":{"df":0,"docs":{},"原":{"df":0,"docs":{},"来":{"1":{"0":{"0":{"df":0,"docs":{},"个":{"df":0,"docs":{},"小":{"df":0,"docs":{},"时":{"df":0,"docs":{},"才":{"df":0,"docs":{},"能":{"df":0,"docs":{},"完":{"df":0,"docs":{},"成":{"df":0,"docs":{},"的":{"df":0,"docs":{},"活":{"df":0,"docs":{},",":{"df":0,"docs":{},"现":{"df":0,"docs":{},"在":{"1":{"0":{"df":1,"docs":{"39":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}},"1":{"df":2,"docs":{"126":{"tf":1.0},"230":{"tf":1.0}}},"2":{"df":3,"docs":{"133":{"tf":1.0},"230":{"tf":1.0},"27":{"tf":1.0}}},"3":{"df":2,"docs":{"133":{"tf":1.0},"230":{"tf":1.0}}},"4":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"5":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"6":{"df":2,"docs":{"134":{"tf":1.0},"231":{"tf":1.0}}},"7":{"df":2,"docs":{"143":{"tf":1.0},"232":{"tf":1.0}}},"8":{"df":2,"docs":{"144":{"tf":1.0},"232":{"tf":1.0}}},"9":{"df":2,"docs":{"149":{"tf":1.0},"232":{"tf":1.0}}},"df":6,"docs":{"113":{"tf":1.0},"16":{"tf":1.0},"177":{"tf":1.0},"189":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0}}},"2":{"0":{"0":{"0":{"df":0,"docs":{},"块":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"一":{"df":0,"docs":{},"个":{"df":0,"docs":{},"月":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"是":{"8":{"0":{"0":{"0":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"1":{"4":{"df":1,"docs":{"3":{"tf":1.0}}},"df":0,"docs":{}},"2":{"0":{"df":0,"docs":{},"年":{"4":{"df":1,"docs":{"13":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":4,"docs":{"149":{"tf":1.0},"191":{"tf":1.0},"234":{"tf":1.0},"41":{"tf":1.0}},"~":{"3":{"0":{"df":1,"docs":{"71":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"1":{"df":2,"docs":{"152":{"tf":1.0},"236":{"tf":1.0}}},"2":{"df":2,"docs":{"153":{"tf":1.0},"237":{"tf":1.0}}},"3":{"df":2,"docs":{"154":{"tf":1.0},"237":{"tf":1.0}}},"4":{"df":3,"docs":{"157":{"tf":1.0},"189":{"tf":1.0},"238":{"tf":1.0}}},"5":{"df":2,"docs":{"159":{"tf":1.0},"251":{"tf":1.0}}},"6":{"df":3,"docs":{"140":{"tf":1.0},"159":{"tf":1.0},"240":{"tf":1.0}}},"7":{"df":2,"docs":{"159":{"tf":1.0},"241":{"tf":1.0}}},"8":{"df":2,"docs":{"160":{"tf":1.0},"242":{"tf":1.0}}},"9":{"df":1,"docs":{"160":{"tf":1.0}}},"a":{"3":{"df":0,"docs":{},"r":{"df":7,"docs":{"121":{"tf":1.0},"175":{"tf":1.7320508075688772},"176":{"tf":2.0},"177":{"tf":2.0},"178":{"tf":1.0},"179":{"tf":1.0},"180":{"tf":1.0}}}},"df":0,"docs":{}},"df":6,"docs":{"114":{"tf":1.0},"159":{"tf":1.0},"20":{"tf":1.0},"22":{"tf":1.0},"224":{"tf":1.0},"63":{"tf":1.0}},"~":{"3":{"df":1,"docs":{"57":{"tf":1.0}}},"df":0,"docs":{}}},"3":{"0":{"0":{"0":{"df":1,"docs":{"177":{"tf":1.0}}},"df":0,"docs":{}},"df":5,"docs":{"160":{"tf":1.4142135623730951},"177":{"tf":1.0},"179":{"tf":1.0},"189":{"tf":1.4142135623730951},"243":{"tf":1.0}}},"1":{"df":2,"docs":{"160":{"tf":1.0},"244":{"tf":1.0}}},"2":{"df":2,"docs":{"161":{"tf":1.0},"246":{"tf":1.0}}},"3":{"df":1,"docs":{"161":{"tf":1.0}}},"4":{"df":1,"docs":{"161":{"tf":1.0}}},"5":{"df":2,"docs":{"10":{"tf":1.0},"162":{"tf":1.0}}},"6":{"df":1,"docs":{"162":{"tf":1.0}}},"7":{"df":1,"docs":{"162":{"tf":1.0}}},"8":{"df":1,"docs":{"163":{"tf":1.0}}},"9":{"df":1,"docs":{"169":{"tf":1.0}}},"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":3,"docs":{"116":{"tf":1.0},"224":{"tf":1.0},"69":{"tf":1.0}},"到":{"6":{"df":1,"docs":{"82":{"tf":1.0}}},"df":0,"docs":{}}},"4":{"0":{"df":2,"docs":{"118":{"tf":1.0},"169":{"tf":1.0}}},"1":{"df":1,"docs":{"170":{"tf":1.0}}},"2":{"df":1,"docs":{"176":{"tf":1.0}}},"9":{"df":1,"docs":{"191":{"tf":1.0}}},"df":3,"docs":{"117":{"tf":1.0},"224":{"tf":1.0},"75":{"tf":1.0}}},"5":{"0":{"0":{"df":1,"docs":{"189":{"tf":1.0}}},"df":2,"docs":{"123":{"tf":1.4142135623730951},"197":{"tf":1.0}}},"2":{"df":1,"docs":{"198":{"tf":1.0}}},"3":{"df":1,"docs":{"198":{"tf":1.0}}},"4":{"df":1,"docs":{"198":{"tf":1.0}}},"5":{"df":1,"docs":{"198":{"tf":1.0}}},"6":{"df":1,"docs":{"198":{"tf":1.0}}},"7":{"df":1,"docs":{"199":{"tf":1.0}}},"8":{"df":1,"docs":{"199":{"tf":1.0}}},"9":{"df":1,"docs":{"199":{"tf":1.0}}},"df":6,"docs":{"118":{"tf":1.0},"162":{"tf":1.0},"224":{"tf":1.0},"55":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}},"6":{"0":{"df":1,"docs":{"199":{"tf":1.0}}},"2":{"df":1,"docs":{"200":{"tf":1.0}}},"3":{"df":1,"docs":{"201":{"tf":1.0}}},"4":{"df":1,"docs":{"201":{"tf":1.0}}},"5":{"df":1,"docs":{"201":{"tf":1.0}}},"6":{"df":1,"docs":{"201":{"tf":1.0}}},"7":{"df":1,"docs":{"201":{"tf":1.0}}},"8":{"df":1,"docs":{"201":{"tf":1.0}}},"9":{"9":{"df":1,"docs":{"94":{"tf":1.0}}},"df":1,"docs":{"202":{"tf":1.0}}},"df":5,"docs":{"102":{"tf":1.0},"119":{"tf":1.0},"225":{"tf":1.0},"231":{"tf":1.0},"69":{"tf":1.0}}},"7":{"0":{"df":2,"docs":{"202":{"tf":1.0},"83":{"tf":1.0}}},"1":{"df":1,"docs":{"202":{"tf":1.0}}},"2":{"df":1,"docs":{"202":{"tf":1.0}}},"3":{"df":1,"docs":{"209":{"tf":1.0}}},"4":{"df":1,"docs":{"211":{"tf":1.0}}},"5":{"df":1,"docs":{"211":{"tf":1.0}}},"7":{"df":1,"docs":{"212":{"tf":1.0}}},"8":{"df":1,"docs":{"213":{"tf":1.0}}},"9":{"df":1,"docs":{"215":{"tf":1.0}}},"df":3,"docs":{"103":{"tf":1.0},"120":{"tf":1.0},"226":{"tf":1.0}},"×":{"2":{"4":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"8":{"%":{"df":0,"docs":{},"~":{"1":{"5":{"df":1,"docs":{"83":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"0":{"df":1,"docs":{"216":{"tf":1.0}}},"1":{"df":1,"docs":{"217":{"tf":1.0}}},"2":{"df":1,"docs":{"216":{"tf":1.0}}},"3":{"df":1,"docs":{"216":{"tf":1.0}}},"4":{"df":1,"docs":{"216":{"tf":1.0}}},"5":{"df":2,"docs":{"221":{"tf":1.0},"27":{"tf":1.0}}},"6":{"df":1,"docs":{"221":{"tf":1.0}}},"7":{"df":1,"docs":{"221":{"tf":1.0}}},"8":{"df":1,"docs":{"221":{"tf":1.0}}},"9":{"df":1,"docs":{"221":{"tf":1.0}}},"df":3,"docs":{"104":{"tf":1.0},"121":{"tf":1.0},"227":{"tf":1.0}}},"9":{"0":{"df":3,"docs":{"15":{"tf":1.0},"221":{"tf":1.0},"39":{"tf":1.0}}},"df":3,"docs":{"106":{"tf":1.0},"122":{"tf":1.0},"228":{"tf":1.0}}},"a":{"4":{"df":1,"docs":{"132":{"tf":1.0}}},"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"r":{"df":1,"docs":{"176":{"tf":1.0}}}}}},"b":{"c":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"一":{"df":0,"docs":{},"里":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"a":{"df":0,"docs":{},";":{"df":0,"docs":{},"在":{"df":0,"docs":{},"场":{"df":0,"docs":{},"景":{"df":0,"docs":{},"二":{"df":0,"docs":{},"中":{"df":0,"docs":{},"显":{"df":0,"docs":{},"示":{"b":{"c":{"df":1,"docs":{"210":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}},"df":0,"docs":{}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"103":{"tf":1.0}}}}}},"d":{"df":0,"docs":{},"o":{"b":{"df":4,"docs":{"157":{"tf":2.23606797749979},"158":{"tf":1.4142135623730951},"223":{"tf":1.0},"228":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":8,"docs":{"156":{"tf":1.7320508075688772},"157":{"tf":1.0},"158":{"tf":1.0},"159":{"tf":1.0},"160":{"tf":1.0},"161":{"tf":1.0},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"i":{"df":2,"docs":{"133":{"tf":1.0},"41":{"tf":2.449489742783178}},"r":{"b":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"27":{"tf":1.7320508075688772}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"n":{"df":0,"docs":{},"k":{"df":0,"docs":{},"i":{"df":1,"docs":{"114":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"i":{"df":7,"docs":{"168":{"tf":1.4142135623730951},"169":{"tf":1.0},"170":{"tf":1.0},"174":{"tf":1.0},"238":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}},"p":{"df":13,"docs":{"166":{"tf":1.0},"172":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"27":{"tf":1.0},"91":{"tf":1.7320508075688772},"92":{"tf":1.0},"93":{"tf":1.4142135623730951},"94":{"tf":1.4142135623730951},"95":{"tf":1.0},"96":{"tf":1.4142135623730951},"97":{"tf":1.0},"98":{"tf":1.0}},",":{"df":0,"docs":{},"以":{"df":0,"docs":{},"每":{"df":0,"docs":{},"分":{"df":0,"docs":{},"钟":{"1":{"0":{"0":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"r":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":2,"docs":{"237":{"tf":1.0},"238":{"tf":1.0}}}}}},"df":0,"docs":{},"t":{"df":1,"docs":{"159":{"tf":1.0}}}},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"、":{"df":0,"docs":{},"p":{"df":0,"docs":{},"h":{"df":0,"docs":{},"p":{"df":0,"docs":{},"和":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":1,"docs":{"41":{"tf":1.0}}}}}}}}}}}},"u":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"228":{"tf":1.0},"230":{"tf":1.0}}}}},"df":4,"docs":{"230":{"tf":1.4142135623730951},"231":{"tf":1.0},"232":{"tf":1.0},"233":{"tf":1.0}}}},"b":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"160":{"tf":1.0}}}},"df":0,"docs":{}},"df":4,"docs":{"10":{"tf":1.0},"13":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":1.0}},"o":{"a":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"d":{"df":0,"docs":{},"n":{"a":{"df":2,"docs":{"81":{"tf":1.0},"83":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"r":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"22":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"创":{"df":0,"docs":{},"业":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"和":{"df":1,"docs":{"6":{"tf":1.0}}}}}}}}}}}},"c":{"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"t":{".":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"i":{"df":1,"docs":{"163":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"56":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"或":{"df":0,"docs":{},"者":{"c":{"df":0,"docs":{},"m":{"d":{"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"d":{"b":{"df":1,"docs":{"231":{"tf":1.4142135623730951}}},"df":2,"docs":{"159":{"tf":1.0},"162":{"tf":1.0}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":1,"docs":{"38":{"tf":1.0}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"23":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"z":{"df":1,"docs":{"38":{"tf":1.0}}}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"y":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"187":{"tf":1.0}}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.0}}}}},"df":4,"docs":{"10":{"tf":1.0},"4":{"tf":2.23606797749979},"7":{"tf":1.0},"8":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}},"df":2,"docs":{"10":{"tf":1.4142135623730951},"12":{"tf":1.4142135623730951}}},"、":{"df":0,"docs":{},"s":{"df":0,"docs":{},"、":{"b":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":1,"docs":{"3":{"tf":1.0}}}}},"df":0,"docs":{}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"移":{"df":0,"docs":{},"动":{"df":0,"docs":{},"到":{"b":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"45":{"tf":1.0}}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":2,"docs":{"220":{"tf":2.23606797749979},"221":{"tf":1.7320508075688772}}}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"1":{"0":{"8":{"0":{"df":0,"docs":{},"p":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":1,"docs":{"15":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}},"l":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"154":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"154":{"tf":1.0}},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":2,"docs":{"19":{"tf":2.0},"31":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"g":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"u":{"b":{"df":3,"docs":{"186":{"tf":1.0},"238":{"tf":1.4142135623730951},"86":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"93":{"tf":1.4142135623730951}}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"p":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"a":{"d":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},";":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"面":{"df":0,"docs":{},"向":{"df":0,"docs":{},"国":{"df":0,"docs":{},"内":{"df":0,"docs":{},"市":{"df":0,"docs":{},"场":{"df":0,"docs":{},"的":{"df":0,"docs":{},"话":{"df":0,"docs":{},",":{"df":0,"docs":{},"可":{"df":0,"docs":{},"以":{"df":0,"docs":{},"使":{"df":0,"docs":{},"用":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"n":{"b":{"a":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"169":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"b":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"k":{"df":1,"docs":{"198":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"d":{"df":1,"docs":{"89":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"i":{"c":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"d":{"df":1,"docs":{"97":{"tf":1.0}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"i":{"df":1,"docs":{"223":{"tf":1.7320508075688772}}}}}},"o":{"df":2,"docs":{"223":{"tf":1.0},"94":{"tf":1.4142135623730951}}},"p":{"a":{"d":{"df":2,"docs":{"137":{"tf":1.4142135623730951},"223":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"159":{"tf":1.0},"223":{"tf":1.0}},"e":{"df":0,"docs":{},"、":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"a":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}},"是":{"df":0,"docs":{},"非":{"df":0,"docs":{},"常":{"df":0,"docs":{},"有":{"df":0,"docs":{},"用":{"df":0,"docs":{},"的":{"df":0,"docs":{},"。":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"将":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"和":{"df":0,"docs":{},"推":{"df":0,"docs":{},"广":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"放":{"df":0,"docs":{},"到":{"df":0,"docs":{},"真":{"df":0,"docs":{},"人":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"的":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":0,"docs":{},"上":{"df":0,"docs":{},"面":{"df":0,"docs":{},",":{"df":0,"docs":{},"万":{"df":0,"docs":{},"一":{"df":0,"docs":{},"这":{"df":0,"docs":{},"个":{"df":0,"docs":{},"讲":{"df":0,"docs":{},"师":{"df":0,"docs":{},"离":{"df":0,"docs":{},"开":{"df":0,"docs":{},"团":{"df":0,"docs":{},"队":{"df":0,"docs":{},",":{"df":0,"docs":{},"之":{"df":0,"docs":{},"前":{"df":0,"docs":{},"的":{"df":0,"docs":{},"投":{"df":0,"docs":{},"入":{"df":0,"docs":{},"就":{"df":0,"docs":{},"废":{"df":0,"docs":{},"掉":{"df":0,"docs":{},"了":{"df":0,"docs":{},",":{"df":0,"docs":{},"甚":{"df":0,"docs":{},"至":{"df":0,"docs":{},"会":{"df":0,"docs":{},"变":{"df":0,"docs":{},"成":{"df":0,"docs":{},"竞":{"df":0,"docs":{},"争":{"df":0,"docs":{},"对":{"df":0,"docs":{},"手":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"源":{"df":0,"docs":{},"。":{"df":0,"docs":{},"但":{"df":0,"docs":{},"是":{"df":0,"docs":{},"如":{"df":0,"docs":{},"果":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"采":{"df":0,"docs":{},"用":{"df":0,"docs":{},"虚":{"df":0,"docs":{},"拟":{"df":0,"docs":{},"i":{"df":0,"docs":{},"p":{"df":1,"docs":{"220":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"u":{"df":1,"docs":{"186":{"tf":1.0}}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"是":{"df":0,"docs":{},"投":{"df":0,"docs":{},"资":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},",":{"df":0,"docs":{},"是":{"df":0,"docs":{},"在":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"有":{"df":0,"docs":{},"了":{"df":0,"docs":{},"一":{"df":0,"docs":{},"定":{"df":0,"docs":{},"的":{"df":0,"docs":{},"资":{"df":0,"docs":{},"本":{"df":0,"docs":{},"之":{"df":0,"docs":{},"后":{"df":0,"docs":{},"的":{"df":0,"docs":{},"一":{"df":0,"docs":{},"种":{"df":0,"docs":{},"让":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},"的":{"df":0,"docs":{},"方":{"df":0,"docs":{},"式":{"df":0,"docs":{},"。":{"df":0,"docs":{},"在":{"b":{"df":0,"docs":{},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"里":{"df":0,"docs":{},",":{"df":0,"docs":{},"我":{"df":0,"docs":{},"们":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"创":{"df":0,"docs":{},"办":{"df":0,"docs":{},"企":{"df":0,"docs":{},"业":{"df":0,"docs":{},"来":{"df":0,"docs":{},"挣":{"df":0,"docs":{},"钱":{"df":0,"docs":{},",":{"df":0,"docs":{},"这":{"df":0,"docs":{},"需":{"df":0,"docs":{},"要":{"df":0,"docs":{},"大":{"df":0,"docs":{},"量":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"。":{"df":0,"docs":{},"即":{"df":0,"docs":{},"使":{"df":0,"docs":{},"你":{"df":0,"docs":{},"的":{"df":0,"docs":{},"精":{"df":0,"docs":{},"力":{"df":0,"docs":{},"异":{"df":0,"docs":{},"常":{"df":0,"docs":{},"充":{"df":0,"docs":{},"沛":{"df":0,"docs":{},",":{"df":0,"docs":{},"同":{"df":0,"docs":{},"时":{"df":0,"docs":{},"运":{"df":0,"docs":{},"营":{"df":0,"docs":{},"三":{"df":0,"docs":{},"五":{"df":0,"docs":{},"家":{"df":0,"docs":{},"公":{"df":0,"docs":{},"司":{"df":0,"docs":{},"也":{"df":0,"docs":{},"就":{"df":0,"docs":{},"到":{"df":0,"docs":{},"上":{"df":0,"docs":{},"限":{"df":0,"docs":{},"了":{"df":0,"docs":{},"。":{"df":0,"docs":{},"i":{"df":1,"docs":{"7":{"tf":1.0}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"j":{"df":0,"docs":{},"s":{"df":1,"docs":{"69":{"tf":1.0}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"198":{"tf":2.23606797749979},"200":{"tf":1.0},"201":{"tf":1.7320508075688772}}}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"x":{"df":1,"docs":{"208":{"tf":1.0}}}}},"v":{"df":0,"docs":{},"e":{"2":{"d":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":7,"docs":{"150":{"tf":2.0},"151":{"tf":2.0},"152":{"tf":2.23606797749979},"153":{"tf":1.0},"154":{"tf":1.4142135623730951},"155":{"tf":2.8284271247461903},"161":{"tf":1.0}}}}}},"m":{"a":{"c":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.4142135623730951}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"111":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":1,"docs":{"15":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"p":{"df":3,"docs":{"111":{"tf":1.4142135623730951},"121":{"tf":1.0},"59":{"tf":1.0}}}}},"n":{"df":1,"docs":{"248":{"tf":1.0}},"o":{".":{"1":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"v":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}}}}},"o":{"b":{"df":11,"docs":{"205":{"tf":1.0},"206":{"tf":2.0},"207":{"tf":1.0},"208":{"tf":1.4142135623730951},"209":{"tf":2.0},"210":{"tf":1.4142135623730951},"211":{"tf":1.7320508075688772},"212":{"tf":1.0},"213":{"tf":1.0},"216":{"tf":1.0},"221":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"41":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}},"k":{"df":1,"docs":{"210":{"tf":1.0}}}},"p":{"a":{"df":0,"docs":{},"y":{"df":0,"docs":{},"j":{"df":0,"docs":{},"s":{".":{"c":{"df":0,"docs":{},"n":{"df":1,"docs":{"168":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"c":{"df":1,"docs":{"140":{"tf":1.0}}},"d":{"df":0,"docs":{},"f":{"df":2,"docs":{"195":{"tf":1.0},"81":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"a":{"df":1,"docs":{"128":{"tf":1.0}}},"df":0,"docs":{}}}}}},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"105":{"tf":1.0}}}}}}}}},"p":{"df":1,"docs":{"41":{"tf":1.0}}}},"i":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":74,"docs":{"102":{"tf":1.0},"103":{"tf":1.0},"104":{"tf":1.0},"106":{"tf":1.0},"107":{"tf":1.0},"113":{"tf":1.0},"114":{"tf":1.0},"116":{"tf":1.0},"117":{"tf":1.0},"118":{"tf":1.0},"119":{"tf":1.0},"120":{"tf":1.0},"121":{"tf":1.0},"122":{"tf":1.0},"126":{"tf":1.4142135623730951},"133":{"tf":1.4142135623730951},"134":{"tf":1.7320508075688772},"143":{"tf":1.0},"144":{"tf":1.0},"149":{"tf":1.4142135623730951},"152":{"tf":1.0},"153":{"tf":1.0},"154":{"tf":1.0},"157":{"tf":1.0},"159":{"tf":1.7320508075688772},"16":{"tf":1.0},"160":{"tf":2.0},"161":{"tf":1.7320508075688772},"162":{"tf":1.7320508075688772},"163":{"tf":1.0},"169":{"tf":1.4142135623730951},"170":{"tf":1.0},"176":{"tf":1.0},"191":{"tf":1.0},"197":{"tf":1.0},"198":{"tf":2.23606797749979},"199":{"tf":2.0},"20":{"tf":1.0},"200":{"tf":1.0},"201":{"tf":2.449489742783178},"202":{"tf":2.0},"209":{"tf":1.0},"211":{"tf":1.4142135623730951},"212":{"tf":1.0},"213":{"tf":1.0},"215":{"tf":1.0},"216":{"tf":2.0},"217":{"tf":1.0},"22":{"tf":1.4142135623730951},"221":{"tf":2.449489742783178},"224":{"tf":2.23606797749979},"225":{"tf":1.0},"226":{"tf":1.0},"227":{"tf":1.0},"228":{"tf":1.4142135623730951},"230":{"tf":1.7320508075688772},"231":{"tf":1.7320508075688772},"232":{"tf":1.7320508075688772},"234":{"tf":1.0},"236":{"tf":1.0},"237":{"tf":1.4142135623730951},"238":{"tf":1.0},"240":{"tf":1.0},"241":{"tf":1.0},"242":{"tf":1.0},"243":{"tf":1.0},"244":{"tf":1.0},"246":{"tf":1.0},"251":{"tf":1.0},"63":{"tf":1.0},"69":{"tf":1.4142135623730951},"75":{"tf":1.0},"81":{"tf":1.0},"91":{"tf":1.0}}}}}},"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"df":1,"docs":{"114":{"tf":1.0}}}}}},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"y":{"df":1,"docs":{"93":{"tf":1.0}}}},"df":0,"docs":{}},"m":{"df":0,"docs":{},"f":{"df":2,"docs":{"111":{"tf":2.0},"143":{"tf":1.0}}}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"197":{"tf":1.0},"199":{"tf":1.7320508075688772},"200":{"tf":1.0},"202":{"tf":1.7320508075688772}}}}}}}}}}},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"194":{"tf":1.0}}}},"r":{"df":5,"docs":{"223":{"tf":1.7320508075688772},"224":{"tf":1.4142135623730951},"225":{"tf":1.4142135623730951},"226":{"tf":1.0},"230":{"tf":1.4142135623730951}},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"(":{"df":0,"docs":{},"一":{"df":0,"docs":{},"般":{"df":0,"docs":{},"简":{"df":0,"docs":{},"称":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":1,"docs":{"223":{"tf":1.0}}}}}}}}}}}}}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"111":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":2,"docs":{"157":{"tf":1.0},"163":{"tf":1.0}},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}}}}},"s":{"d":{"df":1,"docs":{"105":{"tf":1.0}}},"df":0,"docs":{}}},"q":{"df":0,"docs":{},"q":{"df":3,"docs":{"120":{"tf":1.0},"170":{"tf":1.0},"75":{"tf":1.0}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"154":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"s":{"d":{"df":0,"docs":{},"k":{"df":1,"docs":{"96":{"tf":1.0}}}},"df":3,"docs":{"10":{"tf":1.0},"5":{"tf":2.0},"6":{"tf":1.0}},"e":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"160":{"tf":1.0}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":1,"docs":{"162":{"tf":1.0}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"87":{"tf":1.0},"90":{"tf":1.0}}}},"df":0,"docs":{}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"157":{"tf":1.0}}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"i":{"d":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":1,"docs":{"90":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"236":{"tf":1.0}}}},"t":{"a":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"f":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"186":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"m":{"df":2,"docs":{"220":{"tf":1.0},"221":{"tf":1.0}}}},"df":0,"docs":{},"w":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{}}}},"v":{"df":0,"docs":{},"g":{"df":1,"docs":{"163":{"tf":1.4142135623730951}}},"n":{"df":1,"docs":{"22":{"tf":1.0}}}},"象":{"df":0,"docs":{},"限":{"df":0,"docs":{},"的":{"df":0,"docs":{},"缺":{"df":0,"docs":{},"点":{"df":0,"docs":{},"是":{"df":0,"docs":{},",":{"df":0,"docs":{},"收":{"df":0,"docs":{},"益":{"df":0,"docs":{},"未":{"df":0,"docs":{},"必":{"df":0,"docs":{},"能":{"df":0,"docs":{},"比":{"df":0,"docs":{},"e":{"df":1,"docs":{"5":{"tf":1.0}}}}}}}}}}}}}}}}},"t":{"a":{"b":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":3,"docs":{"154":{"tf":1.0},"155":{"tf":1.0},"163":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}}},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"133":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}}}}}}}}}},"df":0,"docs":{}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"s":{".":{"df":0,"docs":{},"v":{"c":{"df":1,"docs":{"90":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"t":{"df":1,"docs":{"125":{"tf":1.0}}},"u":{"c":{"a":{"df":0,"docs":{},"o":{".":{"df":0,"docs":{},"j":{"df":1,"docs":{"173":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"i":{"df":1,"docs":{"221":{"tf":1.0}}},"n":{"d":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"w":{"df":1,"docs":{"153":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"160":{"tf":1.0}}}}},"df":0,"docs":{}},"df":1,"docs":{"124":{"tf":1.0}}}}},"df":0,"docs":{}}}}},"s":{"b":{"df":1,"docs":{"211":{"tf":1.0}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"111":{"tf":1.0}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"238":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"249":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":1,"docs":{"56":{"tf":1.0}}}},"w":{"df":0,"docs":{},"e":{"b":{"df":2,"docs":{"172":{"tf":1.0},"249":{"tf":1.0}}},"df":0,"docs":{}},"i":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":4,"docs":{"140":{"tf":1.0},"157":{"tf":1.0},"208":{"tf":1.0},"223":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"159":{"tf":1.0}}},"df":0,"docs":{}}}},"x":{"d":{"df":5,"docs":{"157":{"tf":2.0},"158":{"tf":1.4142135623730951},"159":{"tf":1.4142135623730951},"162":{"tf":1.0},"163":{"tf":1.0}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"a":{"df":0,"docs":{},"y":{".":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"168":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}}},"s":{"df":1,"docs":{"159":{"tf":1.0}}}}}},"title":{"root":{"2":{"a":{"3":{"df":0,"docs":{},"r":{"df":3,"docs":{"175":{"tf":1.0},"176":{"tf":1.0},"177":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"a":{"d":{"df":0,"docs":{},"o":{"b":{"df":2,"docs":{"157":{"tf":1.0},"158":{"tf":1.0}},"e":{"df":0,"docs":{},"x":{"d":{"df":1,"docs":{"156":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"p":{"df":1,"docs":{"91":{"tf":1.0}}}}},"b":{"df":1,"docs":{"6":{"tf":1.0}}},"df":0,"docs":{},"e":{"df":1,"docs":{"4":{"tf":1.0}},"→":{"b":{"df":2,"docs":{"13":{"tf":1.0},"9":{"tf":1.0}}},"df":2,"docs":{"10":{"tf":1.0},"12":{"tf":1.0}}}},"f":{"a":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":1,"docs":{"220":{"tf":1.0}}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"19":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":2,"docs":{"198":{"tf":1.0},"201":{"tf":1.0}}}}}}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"g":{"df":0,"docs":{},"o":{"df":3,"docs":{"150":{"tf":1.0},"151":{"tf":1.0},"152":{"tf":1.0}}}}}},"o":{"b":{"df":1,"docs":{"209":{"tf":1.0}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"n":{"b":{"df":1,"docs":{"16":{"tf":1.0}}},"df":0,"docs":{}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"199":{"tf":1.0},"202":{"tf":1.0}}}}}}}}}}}},"s":{"df":1,"docs":{"5":{"tf":1.0}}},"u":{"df":0,"docs":{},"g":{"c":{"df":1,"docs":{"53":{"tf":1.0}}},"df":0,"docs":{}}},"x":{"d":{"df":2,"docs":{"157":{"tf":1.0},"158":{"tf":1.0}}},"df":0,"docs":{}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}} ================================================ FILE: docs/tomorrow-night.css ================================================ /* Tomorrow Night Theme */ /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ /* Original theme - https://github.com/chriskempson/tomorrow-theme */ /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ /* Tomorrow Comment */ .hljs-comment { color: #969896; } /* Tomorrow Red */ .hljs-variable, .hljs-attribute, .hljs-tag, .hljs-regexp, .ruby .hljs-constant, .xml .hljs-tag .hljs-title, .xml .hljs-pi, .xml .hljs-doctype, .html .hljs-doctype, .css .hljs-id, .css .hljs-class, .css .hljs-pseudo { color: #cc6666; } /* Tomorrow Orange */ .hljs-number, .hljs-preprocessor, .hljs-pragma, .hljs-built_in, .hljs-literal, .hljs-params, .hljs-constant { color: #de935f; } /* Tomorrow Yellow */ .ruby .hljs-class .hljs-title, .css .hljs-rule .hljs-attribute { color: #f0c674; } /* Tomorrow Green */ .hljs-string, .hljs-value, .hljs-inheritance, .hljs-header, .hljs-name, .ruby .hljs-symbol, .xml .hljs-cdata { color: #b5bd68; } /* Tomorrow Aqua */ .hljs-title, .css .hljs-hexcolor { color: #8abeb7; } /* Tomorrow Blue */ .hljs-function, .python .hljs-decorator, .python .hljs-title, .ruby .hljs-function .hljs-title, .ruby .hljs-title .hljs-keyword, .perl .hljs-sub, .javascript .hljs-title, .coffeescript .hljs-title { color: #81a2be; } /* Tomorrow Purple */ .hljs-keyword, .javascript .hljs-function { color: #b294bb; } .hljs { display: block; overflow-x: auto; background: #1d1f21; color: #c5c8c6; padding: 0.5em; -webkit-text-size-adjust: none; } .coffeescript .javascript, .javascript .xml, .tex .hljs-formula, .xml .javascript, .xml .vbscript, .xml .css, .xml .hljs-cdata { opacity: 0.5; } .hljs-addition { color: #718c00; } .hljs-deletion { color: #c82829; } ================================================ FILE: src/01.md ================================================ # 为什么副业特别重要 在很多人的印象中,副业也许只是挣点零花钱补贴家用的小打小闹。但实际上,它对于我们的整个职业有非常大的影响,甚至会改变我们的人生。 本章我们将从「职业可能性」、「职业自由度」以及「职业成长性」三个方面来进行说明。 ================================================ FILE: src/0101.md ================================================ # 职业可能性 ================================================ FILE: src/010101.md ================================================ # 职业的四大象限 2014年的时候,我做过一个「程序员拍卖」的项目。听起来很神奇,其实就是将我们遴选过的优质程序员推送给各家在招聘的公司,让他们来竞价,从而帮程序员们找到一份满意的工作。 那两年,我们为上千名程序员找到了工作。后来我把从中学到的对于程序员职业的理解写成了一本小书,叫做[《程序员跳槽全攻略》](https://www.amazon.cn/dp/B00PJVX160)。 书里我创造了一个用来分析程序员职业的工具,叫做「方糖职业路线图」。它根据现金流将程序员的职业空间分布到了E、S、B、I 四个象限中,我们依次来说说。 ![](images/ch01-fangtangzhiyeluxiantu.jpg) ## E象限(雇员象限)、帮别人挣钱 E象限是雇员象限。别人给我们发工资,我们帮别人挣钱。这是风险最小的象限,我们的工作任务是别人分配的,只要认真完成,每个月都能得到预期中的收益。 在从开发走向高级开发后,往往就可以开始选择发展路线。E象限的典型的发展路线有两种,专家线和管理线。 E象限的优点是稳定,缺点是天花板非常明显。 ## S象限(自雇象限)、为自己挣钱 S象限是自雇象限,自己挣钱自己花,一般不雇用别人。比如做独立开发、组建工作室做外包和建站,甚至也可能做一些和编程没有关系的事情。 S象限最大的优点是,自己的业务自己做主,挣的钱也都是自己的。一个三五十万的外包做下来,一年的基本生活保障就有了。 S象限的缺点是,收益未必能比E象限多多少,而风险却高很多。光靠单纯的编程技能往往搞不定,还需要把接活拉活的能力、协调沟通的能力都培养起来。这些能力往往在程序员的舒适区外,需要花精力和时间去培养。因为收入是业务驱动的,所以行业的风险也会直接转嫁到我们这里。 ## B象限(创业象限)、让雇员挣钱 B象限是创业象限,和S象限最大的不同是我们不是自己干活,而是雇用其他人来帮我们干活挣钱。 它的优点在于,可以让我们从S象限的天花板中解脱出来,拥有规模化成长的可能性。 而缺点在于,它有一个比较大的固定成本。即使是对于轻资产的互联网公司来说,也是如此。比如人力成本。招聘、组建、培养一个团队是非常耗费时间和精力的,所以即使当业务不好的时候,我们还是需要支付大量的工资来维持团队,以便之后能快速恢复业务。 ## I象限(投资象限)、让钱挣钱 I象限是投资象限,是在我们有了一定的资本之后的一种让钱挣钱的方式。在B象限里,我们需要创办企业来挣钱,这需要大量的精力。即使你的精力异常充沛,同时运营三五家公司也就到上限了。I象限让我们以投资的方式参与到大量的公司中去,共享这些公司的增长,从而实现资产的增值。 在了解了四大象限以后,我们可以发现,如果赶不上公司上市这种可遇不可求的事情、或者能一路升迁做到大公司高层,先不说财务自由,光是要想在北上深买房安家,只留在E象限都是非常困难的 —— 我们必须向其他象限发展。 ================================================ FILE: src/010102.md ================================================ # 没有副业的职业 然而在没有副业的情况下,我们的职业就是单进程、只能做单选题。 我们在象限之间的移动,往往只能是突发式的。前一天还在E象限做雇员,第二天突然就辞职创业或者做外包去了。然而贸然进入一个新象限,将面临非常大的风险。因为每一个象限,它背后的商业模式是不同的,对人的能力、思维、精力的要求也都完全不一样。 ## E→B,辞职创业 先来说说「辞职创业」。 媒体很喜欢把创业宣传得一蹴而就,仿佛只要有一个独特的想法,就可以一夜暴富、咸鱼翻身。 程序员群体的理想主义趋向又比较明显,加上有无数包装出来的成功案例,所以这是程序员从E象限移动到B象限最常见的途径。 有激进派的,拿着自己的一点积蓄就英勇地加入的创业的队伍;有稳健点的,在搞定了天使投资以后再离职的。 但创业的光环在市场的面前毫无用处,要找到一个真正有商业价值的需求非常困难,往往要花很长的时间试错。而后,还要针对这个需求做出比现有方案至少好十倍的新方案。同时,还有大量公司管理、人力招聘、融资沟通方面的事务,这些都会让创业新手难以招架。 不少程序员朋友找我聊他们的创业想法,我发现他们真的只有想法 —— 完全没有进行过验证,他们并不了解B象限的生存法则。 ## E→S,回老家开工作室 S象限,在这里可以看成是 Easy 难度的B象限,因为自雇没有员工,可以不处理公司管理相关事务。 最熟悉的讨论就是回老家结婚,不,开工作室。我有不少北漂朋友都选择了这条路。本质上来说,这其实是一个好选择,但问题在于,如果没有做好前期准备,失败率也是非常高的。 在大公司工作的人容易产生一种幻觉,那就是把平台的能力当做自己的能力。以大公司的身份去和别人谈合作的时候,感觉都很容易。等到自己离完职才发现,同样的客户,你根本都见不到人。 我知道不少朋友都是因为高估了自己拉业务的能力,最后不得不又重返北上深。 加上全球经济放缓、美元投资减少,这种单线切换的方式又包含巨大的风险,所以很多程序员都选择了被锁死在E象限,成为永久的打工人。 我并不是说打工不好,但如果你不能较快地晋升到高级职位的话,就要仔细考虑如何应对正在形成的35岁新门槛。 ================================================ FILE: src/010103.md ================================================ # 副业带来的可能性 当我们有了副业,情况就完全不一样了。 因为我们从单进程变成了多进程,可以并行地进行尝试。最重要的是,这种尝试并不会影响我们的主业,不会降低我们的生活质量。 我们还是以上一节的两个例子来看。 ## E→S,回老家开工作室 采用副业的方式操作,我们在离开北上深之前就可以创立自己的工作室,并开始接活。一方面拓展客户,累积口碑,另一方面,我们还可以从客户的案例中提取重复需求,将其产品化、服务化。等到有了自己的客户和产品,我们在哪个城市已经不那么重要了,甚至可以在全国一个城市住上那么一两个月,一边旅行一边工作。 ## E→B,创业 有了副业,B象限等于完全开放了。不要纠结于是否成立了公司,那只是一个形式。真正驱动公司的是业务能力和运营公司的能力,而这些我们都可以通过副业练出来。 把创业想法以 Side Project 的方式来运作,以最简单的产品直扑最核心的需求。没有经验和所谓的产品感都不要紧,因为副业我们是输得起的。这个项目找不到需求,那么复盘以后开始下一个。那些创业公司花大价钱验证的认知,我们通过 Side Project 同样能获得,只是时间可能更长一些而已。 这种低风险的创业模式,也是非常契合当下的创业环境的。创新工场的汪华[在2020年4月的一场分享](https://www.chuangxin.com/index.php/home/aboutus/news_detail/id/393.html)中提到,移动互联网信息、交易等纯界面层的战争已经基本结束,那种靠想法和快速扩张的打法,已经很难奏效了。 所以通过副业的方式,扎扎实实地经营一家企业,靠对市场的理解、优质的产品、良好的管理和持续发展取胜,才是新时代更好的选择。 可以看到,引入副业后,我们可以以低风险、并行的方式在职业象限中移动,为职业的发展带来了无穷的可能性。 ================================================ FILE: src/0102.md ================================================ # 职业自由度 ================================================ FILE: src/010201.md ================================================ # 从中指备用金说起 前面说了副业给我们的职业带来了更多的可能性,接下来我们就来看,副业给我们的职业带来的更大的自由度。 首先是职业选择的自由。 这里我们先来讲一个比较有意思的概念,它叫做 F*** you money。这是国外的一个词,我们把它翻译成「中指备用金」。 它指的是一笔钱,数量大概是这个样子:突然有一天你跟老板闹翻了,你可以竖起中指,跟他讲说老子不干了,然后辞职回家。在这种情况下,你的生活质量也不会受到影响。 标准意义上的「中指备用金」,其实是和财务自由差不多额度的一笔钱,是以「不工作」为前提的。如果大家在北上深,要做到财务自由还是很难的。 我们这里要讲的是以「换工作」为前提的一个低配版本。也就是说,你可以随意裸辞,在找到下一份满意的工作之前,这段可能会长达半年甚至一年的时间里,没有任何收入,但你的生活品质不会受到太大影响。 很多年轻一点的同学可能觉得根本不需要这种备用金,因为现在的 90 后 00 后正是这么干的。但是当你的年龄稍微大一些,还着房贷车贷、养着老人小孩的时候,要是突然没有收入来源,压力实际上是非常大的。 而副业,恰恰可以为我们提供这么一笔钱。可能总额不大,但可以持续不断的提供。 比如我现在的课程放到网易云课堂上,即使自己不在微博去做主动的营销推广,通过网易平台上的自然流量进行的课程转化,也会有几千块钱。 我现在在重庆生活,这边房租非常的便宜,一个近七十平的小两居,房租每月不到两千。加上日常花销,也就几千块钱。所以现在即使不去上班挣钱,副业也可以在相当长的一段时间里保证我的基本生活不受影响。 这种情况下,我们就可以花更多的时间去思考自己的职业、未来和人生。去做一些短期内收入不明显,但长期收益巨大的决定。 这也就是副业带来的选择自由。 ================================================ FILE: src/010202.md ================================================ # PlanB和反脆弱 除了可以给我们的职业带来自由度,副业更可以为我们的职业引入反脆弱结构。 「反脆弱」这个概念,它来自塔勒布的书《反脆弱——从不确定性中获益》。 ![picture 1](images/08ddbed8247c27170ccbca8f3071454c792634310b94d14fcdb3b68f448df65f.png) 在书里边,塔勒布说,他之所以要专门造一个词,是因为大家往往对脆弱的反面有所误解,以为是「坚强」,也就是类似软件的「鲁棒性」。但事实上,反脆弱性比鲁棒性更棒。 什么意思呢?鲁棒性是说在风险来临的时候我们要做到不受影响。而反脆弱性更上一层楼,它说的是,当风险来临的时候,我们不但不受负面影响,还能从风险中受益,变得比原来更好。 具体到职业上,鲁棒性是说,万一现在公司发展不好,我们可以很容易地跳到平级的其他公司,继续我们之前的职业路线图。 而反脆弱性是说,当现在公司发展不好,我们可以很轻松的切换到另一个职业象限,实现跨越式的职业发展。 如果我们精心选择并发展合适的副业,它能带给我们的,正是后者。为什么这么说呢?这是由副业的天然特性决定的。因为它是我们用业余时间、在资源紧缺的情况下发展出来的。如果我们能把它转为主业,而它依然保留了对时间、资源需求不多的特性,那么这份工作就会极为舒适。 ================================================ FILE: src/010203.md ================================================ # 全新的工作自由度 接着上一节,我们来看看副业带来的、全新的工作自由度。这里我们多展望一下未来,主要是给大家鼓气。副业是很累的,要把别人用来休息的时间用到额外的工作上,多想想它的好处可以鼓励我们坚持下去。 当然,就像前边提过的,工作自由度最高当然是财务自由,上不上班都行,完全没有压力。我们这一节要讨论的是,在暂时还必须上班的情况下,我们可以取得的一些自由——我们就叫它「工作自由」吧。 我一般从三点上来看工作自由度: 1. 工作地点的自由 1. 工作时间的自由 1. 工作内容的自由。 不同的工作方式,有着不同的自由度。 ## 远程办公 比如最近新冠流行,很多公司都开始搞远程办公了,有些大公司甚至宣布员工可以永久远程办公。远程办公这种工作方式,就实现了工作地点自由。你可以去公司的办公室、也可以在自己的家里,甚至是在旅游的路上办公。 但是,远程办公并没有实现工作时间和工作内容的自由,你依然要和其他人同时办公,区别只是以前面对面,现在改成视频了而已。 ## freelancer freelancer,就是那种在网上接单并收取报酬的工作者。这种工作方式在工作地点上同样是自由的,而且经常全部内容都是自己做,需要和别人沟通协调的内容不多,客户主要卡交工时间,只要能赶上进度,时间是可以自己安排的。所以它还实现了工作时间自由。 但freelancer没有实现工作内容自由,因为工作内容都是由客户指定的,绝大部分情况下,都不是你自己想要开发的东西。 ## 独立开发 再来看独立开发这种工作方式。它通过售卖独立的软件、游戏或者在线服务来赚取收益。所以在工作地点、工作时间上都是自由的。 由于是自主售卖产品,它在工作内容上,也是自由的。 这里是举个例子,实际上还有很多在地点、时间和内容上都很自由的工作。比如网课讲师。 ![picture 2](images/3341e233a33a040b1593fb5243a5a1f32fe2086cc8b6d90ea57727443a6f4ade.png) 有意思的是,正是因为这些工作自由度高,所以适合作为副业来操作。反过来,一旦实际成熟,我们可以让副业反客为主,变成主业,从而随心所欲的掌控我们的日常工作。 ================================================ FILE: src/0103.md ================================================ # 职业成长性 ================================================ FILE: src/010301.md ================================================ # 新技术练兵场 前边说的都是当职业需要跨象限的时候,副业所提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,副业也能提供非常大的帮助。 首先,副业可以成为新技术的练兵场。 这个对我们程序员来讲非常重要,因为这个行业的知识和技术更新频次非常高。有一个段子说,某 iOS 大牛打算写一本 Swift 的书,但每次当他快写完的时候 Swift 就发布一个和之前完全不兼容的大版本,写了好几年这书都能没写完。这种高速迭代和快速淘汰的节奏,让程序员必须随时保证自己的技术栈最新才能有强的职业竞争力。 然而,绝大部分的中国互联网公司都不是纯粹的技术公司,技术在公司里只是起保驾护航的作用。往往是在最开始设计系统的时候,使用当时最新的技术栈,后续因为需求被满足,用户量增加,,更多的是在原有基础上去不断地进行各种优化。 这个时候如果再引入新技术、新框架,或者一些比较激进的架构方案的话,就会对线上的业务带来很大的风险。所以我们会发现,除了那些刚上线的业务,即使是一些很知名的公司,采用的技术栈其实也是相对老旧的。于是我们经常就在网上看到一些程序员抱怨自己的公司不使用新技术,让他学不到新的知识。 事实上公司是并不关心这些的,当前业务的稳定性对它来讲更重要。等到整个系统的技术债务累积到了一定的程度,就会选用当下时间点上,最先进的方案来重写一遍。 那些维护旧系统的人,如果技术栈不能跟上新系统,那么就很可能被淘汰掉。颇有又要马儿跑又不给马儿吃草的感觉。 所以在新技术面前,如果我们不主动去拥抱他们,而是跟随公司的节奏,躺在原来的技术舒适区里,那么最后就可能会变成用后即焚的螺丝钉。 这个时候,副业为我们打开了一扇门。它往往是可以并行的、可以接受失败的业务,所以我们可以在副业中去学习新的语言、去使用激进的架构方案,走在技术的最前沿。 [斯图尔特·布兰特说过](https://www.goodreads.com/author/quotes/18698.Stewart_Brand),当新技术迎面砸来,如果我们不能成为压路机,就只能成为铺路石。而副业正好提供了机会,让我们可以逃离被碾压的命运。不要轻易放过它。 ================================================ FILE: src/010301A.md ================================================ # 新技术练兵场 前边说的都是当职业需要跨象限的时候,副业能提供的可能性和自由度。但其实,即使你就想循规蹈矩地在一个固定的职业象限里发展,它也能提供非常大的帮助。 首先,副业可以成为新技术的练兵场。 现在社区里边吐槽得很多的一个现象是「面试造火箭,上班拧螺丝」。去面试一个前端岗位,问一些前端框架的最新版细节、底层原理,这是合理的,属于前端的业务范围。但如果把深度学习、大数据、云原生、容器编排、区块链甚至量子计算都拿来面试,就有点装了。 ![picture 1](images/c13ad9b2e654e7c6c14579a08c1eb3729544aaf71d17fe777c79a7ab7f7f6826.png) 但是面试本质上就不是合格考试,而是竞争考试 —— 是要在一群人中选择最好的,所以这也还可以理解。但最不好理解的是,当我们过五关斩六将入职以后,发现这家公司还在用十年前的技术栈,代码管理用的还是 SVN。 不光是小公司、也不光是传统行业;甚至在一些互联网行业的大公司的某些部门里,也会出现这种情况。吐槽规吐槽,但为什么这种情况相当普遍呢?这其实是由于「技术债务驱动的架构更新」导致的。 什么是「技术债务驱动的架构更新」? 把时间拉回五年前,现在有一个业务需要上线,于是我们用当下(也就是五年前)最新的技术构建了这套系统。然后,随着时间慢慢过去,新技术不断涌出,但是线上系统依然能用,业务团队要求稳定;产品团队需要的是不断添加新功能;根本没有机会对技术栈本身进行大幅更新。虽然技术栈逐渐变得陈旧,但是「又不是不能用,理解万岁」嘛。在这种想法下,技术债务不断累积,直到有一天,技术债务快把整个架构压垮了,甚至业务被迫中止一两天后,公司终于决定了 —— 要重新整套系统。于是,又会选用当前时间点最先进的技术来重新开发一套全新的系统。所以你会发现很多公司的系统,它并不是持续不断地更新、不是随时保持最新;而是在新旧之间反复横跳。 由于五年中,业务变动的可能性和幅度都非常大,所以对公司来讲,重写系统是可能比维护系统更合理的。但对于那些在五年里一直用原来技术栈持续不断地维护旧系统的同学来讲,他们的技术栈被迫变旧了。 而当决定开发新系统的时候,公司又希望使用当下最新的技术栈。这就要求原系统的程序员在一瞬间学会新技术,并开发出一套稳定的系统来。大部分人是做不到的,但从公司的角度讲没有关系,淘汰掉,招聘新人组建新团队就好了,说不定成本还能更低点呢。 ![picture 2](images/9463e3c45fb9044123af00e524869137f6cf5f92d9364f70e42fd49450135a4a.png) 所以在这种结构的架构更新里边,如果程序员自己不想办法去学新技术,不去找地方去应用新技术,那么就像温水里的青蛙,最后终会用后即弃。 我很喜欢一句话,它听起来有些残酷,但真实,也时时推动着我去学习最新的技术。 > 一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。 —— Stewart Brand 副业给了我们一个坐上压路机,避免被碾压的机会。程序员这个行业跟其他行业还不一样,它对新技术的要求并不只是认知,光知道新知识、了解新思路是不够的,还需要一个实打实的练手环境,花上相当长时间去踩坑,才能稳妥地做出一个稳定的方案。副业提供了一个真实业务,让我们可以把最新的技术用到上面,随时保持技术栈最新,增强主业的职业竞争力。 ================================================ FILE: src/010302.md ================================================ # 业务敏感度 除了技术,副业也可以帮助我们在业务上获得新认知,保持敏感性。 之前我们在做程序员职业成长服务的时候,发现了一个问题。很多初阶的程序员没法升到中高阶,有两个很大的非技术影响因素,一个是管理能力、另一个是业务理解能力。 管理能力比较好理解。每一个程序员即使把自己的潜力发挥到极致,成为十倍开发者( 10x developer),他可以处理的事情也是有限的。 但是如果管理能力好,他就可以培养出很多拥有和自己同等技能的人,这样就不只是十倍、而是可以成百上千倍地复制能力,为公司增加更多的生产力。 业务理解能力这一块,是因为在绝大部分的公司里,技术都是为业务服务的。所以需要针对业务的各种需求、各种流程来做解决方案。 如果对业务不了解,那么即使技术很不错,因为不知道某些业务细节,最后设计出来的方案可能也不是最优的。这就像我们小学时做应用题,有一个隐藏条件包含在业务逻辑中,如果忽视了它,即使数学再好,做出来的答案也是错的。 所以,程序员应该需要培养自己对业务的理解能力。但比较讽刺的是,很多公司的初阶程序员,恰恰没有机会去了解业务。尤其是一些比较大的公司,很多业务相关的问题都是在中高阶的技术决策层就已经解决掉了,分配到初阶程序员这里,就只剩下一些规划好的、待实现的技术方案了。 这就会形成职业上的一个断层,让初阶程序员无法变成行业专家。很多公司是无意的,也有极少数公司是有意为之。因为高阶的岗位是有限的,如果你成长起来后没有位置,就会跳槽了。所以,公司不培养我们的时候,我们就只能自己培养自己。 而副业正是磨练自己的好方法。我们可以做一个跟我们主业相关的副业,通过自己的项目来了解需求、理解业务,从而弄明白公司在做什么样的事情,怎样才能做得更好。将自己从一个纯粹的螺丝钉,变成独当一面的解决方案高手。 ================================================ FILE: src/02.md ================================================ # 如何优雅地做副业 ================================================ FILE: src/0201.md ================================================ # 想明白核心资源和核心优势 在通过大量章节充分了解了副业的重要意义之后,相信大家已经明白了「为什么」。下边我们开始来讲「是什么」和「怎么做」。 在做一件事情之前,我的习惯是要想明白它的本质,弄清楚它的核心资源,了解它的核心优势。 ================================================ FILE: src/020101.md ================================================ # 副业的核心资源 来看我们这本书的副标题 —— 「程序员如何优雅地做副业」。它有两个重点,一个是「优雅」、一个是「副业」。 既然是「副业」,就表明我们还有一份作为「主业」的正职工作。副业只是我们从本来已经很繁忙的工作、生活时间里面活活挤出来的一点时间精力去做的业务。 所以对于副业来讲,最核心、最宝贵的资源,就是我们的时间片。 为什么这么说呢? 因为对于一家企业来讲,它有足够多的资源可以调配。它可以通过雇人的方式,批量增加可用的时间片。但是对于我们处于「副业」状态的业务来讲,精力和资源都是非常有限的。 副业本来挣得就很少,如果还要去雇人的话,每一个人分下来就会更少,会有入不敷出的风险。另外,人多了以后,在沟通上、管理上的成本也会飙升。所以副业的人应该尽可能少。 于是,时间片就成为了整个副业中,最为有限、最难拓展的资源。我们应该围绕紧缺的核心资源来规划副业。 ================================================ FILE: src/020102.md ================================================ # 副业的核心优势 我们的目标读者是程序员。大部分的程序员要么是在写软件、要么是在写网站、要么是在写APP,通常属于软件或者互联网行业。 软件行业和互联网行业的竞争是非常激烈的。而我们在上一节里面说过,副业它有一个先天的特点,或者说是不足,也就是我们能在这个业务上可以投入的时间和精力是非常有限的。 市场是非常残酷的,它并不会管你这个产品的制作方是个人还是公司,开发它的程序员是全职还是兼职。最终用户会以同样的标准来看评判产品,优胜劣汰。 那在一个竞争如此激烈的市场里面,一个先天投入不足的业务,凭什么可以战胜其他的项目,获得成功呢?这是我们开始之前就要想明白的问题。只有想明白了这个问题,我们在做副业的时候才是有的放矢,而不是随波逐流。 这个问题困扰了我挺久,后来在读《[创业就是要细分垄断](https://item.jd.com/12157096.html)》时,里边一段话让我觉得非常有启发。 它大概意思是说,所谓的「快鱼吃慢鱼」,并不是说人家加班到晚上12点,你就天天逼着员工加班看凌晨四点的中关村。快鱼的快不是这种意义上的快,而是策略上的快。 书里还举了 AirBnb 的例子。它通过共享的方式来创造供应,AirBnb 增加一个民宿只需要几天,而连锁酒店可能要花上半年。就算连锁酒店的员工每天工作85 个小时,也赶不上 AirBnb 的速度。这就是策略上的快。 所以,回到副业上面来,如果想要我们的副业具备很强的竞争力,我们就必须根据其独有的特点,为其制定一个有竞争力的策略。 比如说,我们的副业项目往往规模不用做到特别大。因为如果我们想做到财务自由,那么1000万左右的人民币基本上也就够了。1000万这个数字对个人来讲可能很多,但是对于企业来讲,其实是一个非常小的市场。尤其对于一些以融资方式发展的创业公司和上市公司来讲,这种规模的市场根本就没有办法生存。所以,如果我们选择的目标市场足够好的话,是可以避免很大一部分公司的竞争的。 当然,即使是在一两千万的市场里边,仍然会有不少的竞争对手。我们仍然需要结合副业的特点来构造自己的优势。这里给大家介绍其中一种,叫做「副产品优势」。我们本身是有正职工作的,通过日常工作,会积累很多的经验知识和其他资源。如果我们把这些东西利用起来,把它做成副业的产品的话,它的成本是非常低的,而在深度上,往往又会有很高的门槛。 举一个实际的例子。 比如,我一个朋友是云平台的架构师,他的工作是专门为传统企业往云平台上做业务迁移提供解决方案,方便这些企业购买他所在公司的云计算产品。 但是在这个过程中,他接触了大量的、各行各业的公司的迁移需求,并为他们做了架构方案。这让他的架构能力突飞猛进,架构经验也远超旁人。 这个时候,如果他以副业的形式,开设讲授架构技巧的课程,对他来讲成本是非常低的。因为无论他做不做这个副业,都要投同样多的精力在这件事情上。 作为对比,如果一位全职网课讲师想要来做同样主题的课程,那么就需要从头开始学习完整的架构知识,并花足够长的时间,比如说几个月甚至几年,去接触大量的实际案例,最终才可能做出同样品质的课程。 而对专职讲师来讲,他的收益仅仅是课程收益,并不包含主业的薪资,所以最终收益甚至可能还赶不上他为了制作课程进行的投入。在这种情况下,全职反而成为了一种劣势,这就是我们所谓的副产品优势。 当然,我们还可以根据副业的其他特点,发掘出各种独特的竞争力。但只有围绕核心的稀缺资源进行规划,并从策略上建立我们的核心优势,才能真正做到优雅地做副业。 ================================================ FILE: src/0202.md ================================================ # 时间片 这一节开始,我们就来讲讲副业的核心资源——时间片。 ================================================ FILE: src/020201.md ================================================ # 时间片的销售 前边说过,时间片是我们副业的核心资源,所以直接把它以一个比较低的价格销售出去,是不划算的。这种方式和「优雅」这两个字不太匹配,但我们这里还是会简单介绍一下。 它不会作为我们这本书的重点,但大家有一个简单的了解也是好的,至少可以作为其他副业方式的对比。 ## 私单 不经任何加工直接销售时间片,最主要是以「私单」的方式来进行的。 ### 外包 传统的私单主要是外包模式。也就是说,一家公司有一个项目要做,它把这个独立项目完整的包给你。双方约定完成的时间、验收的标准和价格。大一点的项目,还会有阶段性的交付和付款。 除了这种完全线下的外包,还有基于网络的 freelancer 方式。大体上是基于网络接单,然后按发包方的要求进行开发。因为没有地域的制约,可以承接国外的业务。 目前的情况看,中国程序员在海外外包市场上并不占据优势,尤其是个人。因为现在海外接单平台上有大量的印度、巴基斯坦等国家的程序员,他们要价非常的低,而且平均而言,英文沟通能力比中国程序员要强一点。接这些单子会比较累。 做起来比较舒服、利润比较多、沟通上比较容易的私单,往往是通过行业人脉和开源项目来的。 ### 外包的坑 大部分的外包在我看来都是很痛苦的,因为它其实和程序员的技术栈不对应。 #### 沟通问题 我们平时在公司开发时,都是产品经理把需求梳理好,然后和程序员进行沟通,好一点的还有高保真原型。即使在这样的情况下,进行需求调整的时候,我们还是会很难受。大量的代码需要改动,如果上线时间表比较紧,我们就会被逼着加班。 而外包模式下,需求方往往就变成了外部的人群。因为个人的工作量有限,所以通常不会是特别大的单子,这就有可能遇到大量不靠谱的发包方。他们很可能并不了解开发的流程,也表达不清自己的需求。 这就要求我们有相当的沟通技巧。如果是基于网络的沟通,效率会进一步降低,问一句得等半天才能有响应。 甚至,很多时候我们会被迫去做需求分析工作,因为整个环节中缺失了产品经理 —— 很多发包方觉得根本不需要这个中间角色。 #### 尾款问题 即使熬过了开发阶段,还有一个尾款收取问题。新手容易因为太过信任对方先交工再收钱;老手也逃不掉那种开发完了对方的创业公司倒闭了的情况。 比较大的项目或者面向特定行业的项目,在签单之前可能会有招投标,然后可能会有层层的审批。在款项的时间预期上要有心理准备,经常会有项目都做完了审批还没有走完的情况。 项目全部由自己开发还好,如果需要其他人的配合,那我们就需要自己垫付资金。这些风险需要合理的控制。 #### 开票问题 个人做私单还有一个烦心的事情,就是大部分的单子都是需要开具发票的。这时候就只能去找一些公司代开。这种代开是有费用的,所以在定价的时候要把这些也考虑进去。 ### 按需雇用 正是因为这种整单外包的方式会带来各种麻烦,最近开始出现一个更加「简单粗暴」的私单方式,叫做「按需雇用」。这是面向发包方的说法,对于程序员来讲其实应该叫做「驻场开发」。 我们平时都有正职工作,但是如果不是去了黑心企业的话,周末的时间还是空出来的。这时候我们就可以到其他公司去上一两天班。通常是一些创业公司,去解决一些他们的开发没有能力或者精力解决的问题。 在这种模式下,费用是按时薪结算,沟通也更为顺畅。只要像平时一样多上一天班就可以获得好几倍的回报。而且当天晚上就可以获得收入,也没有尾款的烦恼。 所以如果非要销售时间片的话,我觉得这种方式更高效一些。 ## 更优雅的方式 但是正如我们前面所说的,你的时间片是非常有限的。像按需雇用这种方式,虽然收益看起来高一点,但它的天花板也是非常明显的。 我们可以很容易地算出来。假设我们每周末拿出一天,一个月也就只有四天而已。就算一天能挣2000块钱,一个月也就是8000块钱。 这是最理想的情况下,因为只能周末工作,所以往往并不是每周都会有活;同时,如果遇到开发内容不是特别熟悉的情况,可能还要花一点时间去学习相关的资料。 整体来讲,我们认为私单,尤其是按需雇用,属于一个中高收益、中低风险、但是也有明显的收入天花板的一个副业。 ================================================ FILE: src/020202.md ================================================ # 时间片的优化 时间片的优化有两个思路。 ## 提升单位时间的收益 提升单位时间的收益其实就是提升时薪(但并不一定局限于按时薪支付的副业,其他形式可以折算成时薪),有几个简单的思路。 ### 切换地域 「切换地域」就是说,我们同样是干活,但如果服务对象所在的位置不同的话,单位时间的收益也是不同的。 比如你在重庆,给本地公司去做一些外包,那整个项目的基础价格就是参照当地程序员的人工成本来进行比价的。但如果是在重庆可以给北京的公司做外包,那发包方就会更多地参照北京的各种成本来进行相应的股价,这样我们就可以把自己单位时间的收益提升上去。当然,需要考虑沟通的效率和成本。 把这个思路扩大一点,就变成在国内做国外的业务了。 因为和国内相比,国外的人力成本通常会贵很多,如果你在二三线城市,那么成本又更低。这样就出现了一个价格差,如果能控制好这个价格差,我们就能挣到更多的钱。 当然前边也说过,这里边有竞争和外语沟通的问题,需要根据自己的实际情况来选择。 ### 从外包到二次开发 在没有建立起自己的知名度之前,非常单纯地去做外包,面对的往往是价格战的红海。地球那么大,总有人的时间比你不值钱。 而且外包它是一个开放性的需求,如果真要把很多雇主的需求细细做好的话,对技术栈的广度要求还挺高的。因为每一个项目它要求的技术栈可能不一样。项目做的越多,用到的偏门技术就可能越多。 所以我们要想办法解决竞争的问题。细分市场就是一个很好的思路,比如说我们可以给一些标准化的开源产品做二次开发来挣钱。 这其实不是什么特别新的思路,早在个人站长时代就有人专门给 Discuz!这个开源论坛软件写插件和定制功能挣钱,而且还真养活了不少小公司。 现在我们可以把这个思路更扩展开一些,比如说我们把从「支持国内项目」变成「支持国际知名的项目」。 这样的话,我们就能解决掉出海接活面临的大部分起步问题。 你看: - 我们从什么地方来获得客户?直接从开源社区获取客户。 - 如何证明我们的开发能力? 可以写一些高质量的开源插件,给大家免费使用,并作为我们的demo。 - 如何来获取比较高的收益?专门给一个项目写插件的团队并不是太多,选择够好的话,就可以成为这个细分领域的No.1,获得一些品牌上的溢价。 ## 提升单位时间的效率 提升单位时间的效率对于按工作量支付的副业来说特别重要。 比如说我们现在有一个项目,交付后的收益是10万块钱。以原来的方式完成它,可能需要花100个小时。现在我们想到了一种新办法,把效率提升了10倍,那么原来100个小时才能完成的活,现在10个小时就能做完了,这就是效率的提升。 多出来的90个小时我们可以用到其他项目上,哪怕是用来休息,也是很好的。 ### 打鸡血难以奏效 当然,通过增强意志力来强迫自己去提升生产效率,其实是很难奏效的。 因为我们本来就是在利用工作之余的时间。在这个时间上,很难保证精力非常充沛。别说提升工作效率,能保证在做这些事情的时候尽可能的不被干扰,不让自己的生产效率降下去,已经是非常不错了。 ### 自动化 但是非常幸运的是,我们是程序员。我们从事的工作,它本身就有一部分是由机器来完成的,所以我们可以引入自动化来提升效率。机器是使用电来工作,它的效率提升空间是非常大的,而且它也不需要休息,可以7×24小时地进行工作。 #### 代码生成器 对于程序员的日常工作来说,最主要的自动化方式就是代码生成器。 但一说到代码生成器,就会听到很多反对声音。如果你用过一些比较早期的代码生成器产品,很可能你也会会有一些负面印象。 在大概十多年前吧,我当时所在的公司也就购买了一套代码生成工具。根据说明书,配置好业务逻辑,然后就可以同时生成ASP、PHP和JSP的代码。 公司买来以后就强制性行推广,但在硬推了两个月以后,发现推不动,只好放弃了。 最主要的原因是因为它没有办法处理我们特有的一些逻辑,加上每一个部门有自己独立的规范和周边库,在那个工具里边没法用上。之后很长的时间里,我们整个部门的人都对代码生成器非常反感。 但是后来还是经不住偷懒的诱惑,我自己一直在偷偷地不断尝试。渐渐地发现,其实要做一套全世界通用的代码生成系统可能会特别难;但是如果只是给自己做一个专用的代码生成工具却非常简单,只要遵循以下两个原则。 ##### 只为自己设计 第一个原则是「只为自己设计」。 因为每一个公司,每一个部门甚至每一个岗位它所面临的需求是千差万别的,很难通过一个通用工具来解决,所以我们也很难买到为自己量身定制的工具。 但如果自己来开发工具的话,就完全不同了。我们可以完全按照自己的工作流程、按照每天写代码的需求来进行设计。我们非常清楚写代码的时候,元数据是存放到什么地方的、通过什么样的方式进行加工、以及最终要生成怎样的代码。所以可以开发出非常好用的自用代码生成工具。 ##### 能自动化的自动化,不能自动化的半自动化 第二个原则是「能自动化的自动化,不能自动化的半自动化」,后半句特别重要。 很多程序员在设计代码生成工具的时候,往往太过完美主义,老想着要做一个系统把所有的工作都做完,最好点一下按钮后,什么事情都不用去做了。 这当然是最理想的方式,但是我们的开发环境和其他的办公软件之间不一定存在交互接口,很多软件只有图形界面,不支持通过 API 进行数据交换。所以,很多时候我们就没法做成全自动。完美主义或者叫强迫症的同学就会说,既然这个东西不能完全自动化,那就直接手动来处理吧。 但我们开发代码生成器的根本目标并不是要做一个完整的自动化产品,而是要提升我们的生产效率。所以,即使有一些地方不能做到完全的自动化,我们也可以把它做成半自动化。 半自动化有两个思路。第一个思路是,我们可以通过交互方式来解决一些不能自动化,或者需要花很多时间去处理的细节问题。 举一个例子,这个例子发生的年代比较久远,现在可能已经不适用了。 我们当初在做网站的时候,有很多的资料都是编辑给的。那个年代还没有产品经理,都是由网站编辑给我们资料。他们都使用 office 软件来存放数据。 当时是没有比较好的 office 格式解析包的,所以很多同学都放弃了数据的解析,改为手工输入。我给了一个解决方案,就是直接在 office 里复制数据表格,然后再粘贴到一个 textarea 里,最后用 PHP 分析 tab 和换行符号,把数据分离出来。为了防止分析错误,还做了一个界面来进行确认和手动修正。虽然没能实现全自动,但是比起手工输入数据,这个方案效率的提升是几十倍的。所以不要过分纠结于全自动化,有的解决方案不完美,但也可以很精彩。 另外一个思路是,只对小操作做自动化,用来生成代码片段。比如说,我们在写输入处理的时候,往往需要根据数据表字段来对输入进行验证,这往往是一个重复劳动。所以,我就写了一个命令行的小工具,它可以直接读取数据表里边的字段和对应的注释,根据注释里的标记来判断对应的字段的验证信息,最后会自动生成验证部分的代码。我把这些代码粘贴到编辑器后,再进行相应的修改,就可以很快的完成验证工作。这没有什么技术含量,但是它可以切实提高我们的生产效率。 这些只是我想到的思路,当然还有很多其他的。比如有的同学是通过工具链,通过命令行交互,来实现自动化。 #### 人工智能 代码模板呢,只能解决相对比较死板的规则。但最近随着人工智能的进步,在某些特定的场景下,原来很多低效率的人工操作其实可以交给 AI 了。 现在,AI 的正确率确实达不到和人类同等水平。但是,还是前边那句话,「不能完全自动化的,可以考虑做成半自动化」。针对 AI 正确率不高的场景,我们可以通过人机结合的方式来处理。 比如说,我们要进行图片分类,之前可能需要花上十几个小时的人工。现在使用 AI 进行分类,只需要十几秒。但是它可能有20%的图片分类是错的。 我们就可以先让 AI 来进行分类,然后再人工确认一遍。确认花的时间可能是两个小时,但即使这样,比起之前的十个小时来讲,效率也提升到了五倍。 最近很多人工智能接口的品质已经不错了。比如说,熟悉我微博的同学都知道,我经常会用语音的合成和识别服务来提升内容生产效率。 比如我经常会发一些技术视频,但是又不想自己录音,于是就会使用人工智能来生成语音。而大家正在看的这本书里,至少有一半的内容我是通过语音识别APP,以每分钟100多字的速度记录下来,然后再二次进行修改、校正完成的。 所以不管你对 AI 有什么看法,它现在已经在实实在在地改变着我们的生活。我们要思考的是,如何更好地利用它。 如果服务足够可靠,我们就可以做成自动化服务,直接提供给最终用户;如果服务还不够可靠,我们可以把它放到中间流程里来提升效率。 比如,同样是代码生成技术,如果我们把它做成面向不懂技术的人群的产品,服务不是很可靠的话,最终效果就会很惨;但同样品质的接口,如果我们把它做成面向开发者的服务,而且是在编辑器里面实时地进行代码补全和建议的工具,它就会显得非常好用,可以极大地提升生产效率。 ================================================ FILE: src/020203.md ================================================ # 突破时间片限制 前面我们讲了时间片的优化,敏锐的同学可能已经感受到了,时间片的限制其实是有办法突破的。下边我们就专门来讲一下怎么突破时间片限制。 ## 倍增 第一个思路叫「倍增」,就是让时间片的数量成倍的增加。但这里有一个前提,就是不能过多的增加我们的精力消耗和风险。 因为不考虑这个前提的时间片倍增非常容易,只需要增加雇员就可以了。但我们随时都要提醒自己,这是在做副业。 如果我们雇用全职人员,就需要有办公场地、还需要到现场进行人员管理。这对于有正职工作的同学来说,是很难分身的。除非你把办公场地放到正职工作的公司附近,用空闲时间去管理。但这依然有精力上的风险,搞不好既没做好副业,又影响了正职工作,这就本末倒置了。 既然雇用全职的路子走不通,我们就只能考虑雇用兼职。 ### 外包 主要的方式就是将部分业务外包。前边我们其实刚聊过外包,只不过在这里,我们从接单方变成了发包方。 外包的方式,可以将大块的业务交给别人去做,自己只需要花少量的时间片来做沟通和管理。等于接单方的时间片也为我们所用了,所以整体来看,时间片是倍增了。 外包还会带来一些潜在的风险。 我们的时间片是倍增了,但我们的成本也在成倍地增加,也就是说本身我们的项目需要有足够的利润空间才适合使用这种方式。如果控制不好,很可能最后整个项目做下来不挣钱甚至亏本。 另外,外包方式下,沟通和项目管理也是比较大的挑战。因为它不是那种每天在一起的沟通环境、也不是直接的上下级关系。只能以合同的形式来进行约束,很多时候甚至连合同都没有。这种情况下,其中某些环节出现问题,我们就需要为整个项目承担风险。 ### 众包 其实还存在其他的雇用兼职的方式,比如众包。众包和外包类似,但粒度更细,接单方更多,甚至我们都不知道接单方是谁。 一个典型的例子是 Facebook 的多语言翻译工作,他们提供了一个在线翻译工具,让懂该语言的用户每人来翻译几句,因为用户数量庞大,很快就能完成整个翻译工作。 众包的收益非常不错,一方面是成本上的,因为接单方多,所以会产生竞价。如果分摊的工作量非常小,甚至可以是免费的。另一方面是时间上的,同样因为接单方多,完成的速度会非常惊人。 不过,为了支持大量的接单方,我们的业务结构需要进行相应的调整。 比如说,通常我们可以把一个系统分成平台部分和扩展部分。平台部分,我们可以自己制作;扩展部分就可以把它设计成插件、扩展、中间件,将这些东西以众包的方式分出去。即使其中的组件出问题,对我们核心平台的影响也是小的。 这样对接单方来讲还有一个突出的好处,就是这种组件本身的逻辑和它的相关资源是闭合的,只需要知道输入输出,内部实现完全可以自己决定。组件开发者之间也不需要沟通,只需要跟平台以文档、API的形式来进行沟通,在使用细节上以工单的方式来进行反馈就可以了。这可以大幅度降低我们的管理成本。更进一步,我们可以开发工具来对众包进行支持,进一步提高效率。 所以,如果能培养起好的众包生态,我们是可以实现低投入的时间片倍增的。对于不想开公司、对时间片又需求大的业务来说,是非常值得尝试的。 ## 超卖 另外一个突破时间片限制的方式我叫它「超卖」,就是把一份时间片卖给多个人。 在很多非常个性化的业务里边,我们是为对方专门定制的服务和内容,所以一份时间片只能卖给一个人。但是,当我们业务做得足够久了之后,就会聚集起来很多有相同需求的人。 这时候我们就可以把他们的公共需求抽取出来,做一份面向这个公共需求的产品或者服务。这样的话,我们只需要花一份时间来做产品,就可以把它卖给多个人,也就间接地实现了时间片的超卖。 比较典型的例子是建站。这曾经是很多小公司赖以生存的业务。在最开始的时候呢,建站公司都是去跟客户谈,想建一个什么样的网站,然后找设计师进行界面设计,完了以后再进行开发。这种服务就是一对一的时间片售卖。 但后来很多公司发现其中重复的需求太多,于是就把建站的需求做成了一个系统。在这个系统上,客户可以自行选择模板,添加功能模块,输入内容,通过浏览器就可以很快地生成自己想要的网站。整个过程甚至不需要其他人参与。 从个性化服务到标准化服务,是实现时间片超卖的主要思路。 再举一个更明显一点的例子。熟悉我的同学都知道,网课是我一个很重要的业务。但和其他的机构不同,我从来不做直播课。所谓直播课是说,我提前准备好教学内容,等大家都上线了,然后我们在一个直播房间里边,一边讲课一边学习。相对的是录播课,是说我提前把这个内容录好,然后大家自己找时间去看视频就好了。 从讲师的角度来看呢,直播课就是一对一的时间片消耗模式,每讲一次,都要消耗一次我的时间片。而录播课则是一对多的时间片消耗模式,不管有多少学员,他们只需要去看录制好的视频就行,我付出的时间片不会增加。这也实现了时间片的超卖。 从上边的两个例子可以看出,时间片的超卖背后,实际上是商业模式的调整。 最理想的情况下,我们只需要付出一份时间片,然后即使我们什么都不做,它都可以持续不断地进行售卖。不管我们是在吃饭睡觉、看电影逛街、还是在旅行休假,这个产品都会持续不断地给我们带来收入。这种收入我们称为被动收入,能带来被动收入的东西,我们叫它资产。 ================================================ FILE: src/0203.md ================================================ # 资产和被动收入 ================================================ FILE: src/020301.md ================================================ # 什么是资产 资产的定义见仁见智了,我比较习惯用罗伯特·清崎在《穷爸爸富爸爸》里的定义,那就是「**能把钱放进你口袋的东西**」就是资产。换句话说,能产生**被动收入**的东西,其实就是资产。 《穷爸爸富爸爸》这本书很多人都读过,罗伯特·清崎后来还写了一个系列,核心是富人不为钱工作,而是**让钱为自己工作**。 在书里边,主要通过「购买」的方式来获得资产。这里是书中列出来的资产类型: * 股票 * 债券 * 能够产生收入的房地产 * 票据(借据) * 版税,如音乐、手稿、专利 * 其他任何有价值、可产生收入或者增值潜力且有很好销路的东西 这个系列后来就跑去教人投资和理财了。 其实投资也可以视为一种副业。优点很多,比如占用精力相对较少、没有收入天花板等;但也有两个明显的缺点。 最主要的缺点是风险高,且不易评估。还有一个缺点是,**投资你得先有资**、**理财你得先有财**。在风险可控的范围内,大部分投资理财的回报率差异不会特别大。如果你手上一百万都不到,可能折腾一年、背着挺大的风险也就是多挣了几万块钱。 投资理财是一门深奥的学问,我们不在本书中展开,大家可以阅读相关的专门书籍。 在罗伯特的资产清单中,还有一个可以无成本获得类别 —— 版税。但其实在中国因为书卖得特别便宜,而版权又普遍不受重视,一些大公司都堂而皇之地侵权,其实很难获得高收益。 如果没有初步的积累、或者不想背负过大的风险,怎样才能获得资产? ================================================ FILE: src/020302.md ================================================ # 资产的获得方式 资产最简单粗暴的获得方式当然是通过购买。但好的资产未必人家愿意卖,当然更可能的是,我们未必买得起。 但是除了购买,其实还有一个逐渐被遗忘的方式 —— 直接「创造资产」。对于很多传统行业的人来说,创造资产会大量的消耗精力,最后成本可能并不会比购买资产低多少。 但现在软件吞噬了世界,数字化业务已经茁壮成长,数字资产的生产资料日益廉价。而我们是程序员,正是那个可以通过自己的技能栈低成本、低风险的创造数字资产的群体。 并不是每个人都有我们这么幸运,其实大部分的程序员,离完整地做出一个商业产品,缺的可能只是一点美感和设计能力。 ================================================ FILE: src/020303.md ================================================ # 资产的量化评估 当然,并不是所有的数字资产都适合我们以副业的方式去创造。不过就像前面不断重复的,副业是一个资源和精力都非常缺乏的状态,我们也只能从庞大的可能性中,选择那些适合的产品和服务。 ## 适合副业的几个特征 说到底有哪些产品和服务适合副业呢?下边是我觉得值得留意的几个特征。 ### 自传播 首先是「**自传播**」,就是说这个东西做出来了以后,它本身有很强的感染力,它的用户会主动地去推荐给其他用户,这样的话我们就不用花很大的成本去做营销。 对于大部分程序员来讲,把程序写出来只是时间和精力问题。写不出来程序的程序员很少,但卖不出去程序的程序员非常多。所以,如果我们做的东西本身就能传播,那么我们就可以在零市场预算的情况下获得成长。 ### UGC 第二类叫做「**UGC**」,用户贡献内容,它其实可以理解为一种更广意义上的众包。核心也是突破时间片限制。比如说我现在经营一个原创博客,天天都是自己写,就会觉得自己累得都不行了。 但如果我们去做一个访谈类的博客,弄一个相对固定的问题列表,然后拿着这个列表去采访各行各业的人,把结果做成一期一期的内容。这样用户就贡献了至少一半的内容了。 如果我们再改成办一个杂志,每一期大家根据主题投稿,你就从主创变身成编辑了。虽然投稿里有好有坏,良莠不齐,但我们的主要任务已经变成去筛选了,只要贡献内容的用户足够的多,那整体质量还是有保证的。最主要是内容的量就上来了。一个人的话,不管你多么努力,总是有一个上限的,因为你毕竟是人类。 ### 自动化 「**自动化**」前边有提过。 就是说应用做起来以后,它所有的环节全部都可以由机器完成,我们什么都不用管,只需要把它扔到云平台上,然后定期给云平台打钱。当然这是一个理想的情况,意外总是会出现的,而且各种意外会约好在同一天出来逛街,别问我为啥知道。但是在绝大部分情况下,我们都可以不去管它,它都可以自动化运行。这种被动资产是非常适合副业来做的。 ## 量化评估标准 我们也可以更为量化地给资产定一个评估标准,确定好要考察的几个方面,每个方面做一个满分为5分的评分,对每一项评分就可以得到一个多边形,从而一目了然的看到各类资产的状况。 这个标准每个人的想法可能不同,这里分享的是我自己用得比较多的标准。 ### 投入 项目的一般投入都是三项:「人」、「钱」、「时间」。 「人」和「时间」不多说,通常就是我们自己和挤出来的那点时间了。 「钱」方面,我们也需要一点启动资金,但**不用花大钱去购买各种固定资产。这也是我们这个行业能自己动手创造资产的一个重要原因**。尤其是现在,云计算已经普及了。即使是很大访问量的网站,我们直接租用云服务,按用量付费,省钱又省心。我大学刚毕业的时候,要是做大点的网站,还要自己去买服务器,自己扛去机房托管。现在只需要点点鼠标就能买到一堆 vps ,其实是蛮幸福的。 要提醒大家的是,一定不要忘记维护成本。我们卖时间片的时候,活干完就完了,钱就拿到手了。 但是在自己创造资产的时候,资产的每个细节基本都得自己来 cover 的,所以**维护成本一定要算进去**。 维护成本往往不是那么显而易见。比如说吧,网课也是有维护成本的,尤其是技术类的,它的更新成本其实相当高。 ### 产出 在评估产出的时候,可以分为「一次性的回报」和「周期性的回报」。 一次性回报,比如我们给人家做技术顾问。可能就是在周三拿到一个邮件介绍说是什么样的一个需求,有什么问题要解答。我们花上2~3个小时来准备,在周末约一个时间,面谈一个小时,把之前准备的内容聊清楚,聊完了以后,回报就拿到手了。这就是一次性回报。 周期性回报,比如说我们在[掘金](https://juejin.cn/)上写了一个小册,那只要有人在购买,我们就会不停的有收益,这种收入一般按月结,所以每次看起来没多少,但加起来还是挺多的。我之前算了一下,发现**在我创造的各种资产中,掘金小册的投入产出比是最高的**。 ### 可持续性 持续性是以前忽略掉的评分项,后来被我追加上来。这其实是一个非常浅显的道理,**一个资产放在那个地方,它不可能一直就持续地挣钱**。就像电池光用不充电的话,总会有用光的一天(别和我提太阳能电池)。 这是因为我们创造这个资产的时候,它是面对一个市场需求的,而需求本身它会随时间变动。绝大部分的情况下,需求和我们提供的解决方案之间的契合度,会随着时间越来越差。最后就会变成,要么我们就不去管它,让它慢慢地随着时间去消亡;要么我们又要花成本去维护它,把它从偏差的地方给拉回来,重新覆盖到需求上面。把用户的满意度、用户的体验、市场的趋势给重新考虑进去,让我们资产的生命期变得更长。 对于不同的资产,只是过程的快慢会不一样,但整体来讲,都是会有这么一个过程的。 ### 风险 程序员创造产品最大的风险是「**没人用**」,因为虽然大部分科班出身的程序员都学过需求分析,但仍然各种喜欢拿着锤子找钉子。 当然,这对于没有做过独立开发或者自己产品的同学来讲,是一个必经的阶段。所以早期项目的风险都会非常高,但并不是说风险高我们就不做了,我们可以相对的调低投入,原来要投入三个月上线的产品,可以花三天做个最小可行产品(MVP,后文会说明)上线,测试到需求以后,再继续加码。这样也能慢慢的获取到一个平衡点。 ### 门槛 最后我加了一个评估标准叫做门槛。因为「副业」的关系,我们的各项资源都是受限的,这个评估标准体现了受限情况下创造资产的难度。 ================================================ FILE: src/03.md ================================================ # 优选资产 在这一部分,我们整理了大量的副业,并从中拿出适合程序员的来进行评估和讨论。 ================================================ FILE: src/0301.md ================================================ # 知识和人脉的变现 ================================================ FILE: src/030101.md ================================================ # 付费视频课 ![picture 2](images/cf2bb71a7ad1c5ed87ec8f5765df8e87dc27c176449ca83220d2a42d7039e821.png) 总体来讲,付费视频课是一个中等投入,然后产出极高的副业。 ## 低投入 ★ 前期需要做一些课程内容的准备;后期你需要对视频进行剪辑;录音还需要购买硬件。大部分的程序员并没有视频剪辑技能,所以这里有学习成本。硬件的话倒不算贵,便宜点的不到一千就能搞定。但是这是在我们赚到钱之前就要投入进去的。 ## 高产出 ★★★★★ 从产出上来讲,课程是一个非常好的品类。中国人有良好的为教育花钱的传统,大部分的用户都愿意为好的课程花钱。一些优质的、上百节的大课可以卖到几千甚至几万。相比其他的副业,它的产出是非常高的。 ## 可持续性 ★★ 我们是做技术类的课程。技术内容本身的变更是非常快的,除非我们做一些非常经典的基础课,比如说计算机原理、算法等等。 如果是跟语言、框架、实战相关的各种前沿课程,大概半年到一年就需要更新一次。如果我们使用屏幕录制方式来制作课程,在修改的时候,很可能需要重录相当部分,修改起来成本很高。 ## 低风险 ★★ 风险不低。如果做的课程比较长,比如几十上百集的大课,用业余时间来做可能会花上几个月甚至一两年,有时候做完技术都更新了。如果最终卖不出去的话,损失是很大的。 ## 低门槛 ★★★ 门槛不算高也不算低。如果经常在公司里面给团队做分享的话,那对你来讲这个门槛就很低。如果一直都是默默无闻地在做技术的话,可能就需要去练习一下怎么讲课。 因为我们最终是可以通过剪辑来进行调整的,所以也只是一个时间投入上的问题。讲得不好,你就多讲几遍;哪一句讲错了,就重新再讲。所以它本身的硬性门槛并不高。 关于风险和维护成本这两点,其实是有办法可以解决的,我们会在后续用专门的章节来讨论,这里就不展开了。 ================================================ FILE: src/030102.md ================================================ # 付费专栏 ![picture 3](images/64d06e2e0d9ae6ff5bf2d5f5f9365e7f7f465a6288ba9f89435ff513e3b71f97.png) 付费专栏就是付费的系列文章,绝大部分是技术教程,也有一些面向程序员的「心灵鸡汤」。我们可以简单地把它看成是传统出版的网络化。 对于技术内容来说,传统的纸书出版方式有一些明显的缺点。比如,不是彩页的话代码不能高亮,彩页的话书又特别贵。书里的代码也不能边看边调试。纸书的出品周期也较长,更新也慢,一些最新的技术会有一个较长的空白期。 而在线的付费专栏恰恰可以解决掉这些问题:它基于浏览器,自然可以通过 JS 来进行代码高亮;内容可以在线修改,几乎可以实时生效;做得细的技术专栏往往还内嵌了基于浏览器的调试环境,可以做到边学边练。 再加上原来技术博客的群众基础很好,于是技术平台和社区纷纷添加了付费专栏功能。这其中,做得比较好的应该算掘金的[小册](https://juejin.cn/books)。 ![picture 6](images/93c3caa937e9c177acbbb4d3f689ae111bc382fff03d5b53744ed5ec07890109.png) 下面我们来看一下付费专栏作为副业资产的各项评分。 ## 低投入 ★★★ 从投入上来讲,文字专栏比视频课程投入要低很多。但是技术内容比起其他文章的写作来讲,需要有技术实践作为基础,经常还要嵌入代码,调整格式,投入相对要高些。 ## 高产出 ★★★ 文字专栏的售价普遍比视频课程要低,像掘金小册的话,一般就在20~30块钱之间,还经常打折促销。 ## 可持续性 ★★★ 前面已经说过,技术内容一般更新频次高。但是图文专栏的更新成本很低,只需要编辑文字、加入新的内容就好,不需要像视频那样重新录制和剪辑。 ## 低风险 ★★★★ 文章的创作成本很低,而且我们可以通过发布短文来测试主题是否受欢迎,在确认后再开始系列文章的书写。 ## 低门槛 ★★★★★ 只要会写文章,就可以做付费专栏。 ================================================ FILE: src/030103.md ================================================ # 付费社群 ![picture 4](images/69d11fca7d29b6d8be3178b8d5b56508ffccd0fff46cd6b9ba21ff72f4ea8b12.png) 所谓付费社群就是指一些收费的微信群,QQ群或者付费可见的信息流、圈子类产品。 之所以把付费社群单独拿出来讲,是因为它更偏重于销售的不是内容本身,而是一种人脉关系、社区氛围或者互动型的服务。 像付费课程,通常是类似于出版。我提供内容,你来进行学习。通过文章评论和回复进行互动,时效性和效率比较低。 而在付费社群里边,大家互动起来会比较方便。比如在群里,你一句我一语很快就可以讨论起来。所以,付费课程和付费社群其实是有互补关系的两个产品。 我们可以把付费课程放到课程平台,然后把实时的学员答疑或者其他服务,再做成付费社群。 ## 低投入 ★★★★ 付费社群的投入是非常低的。如果我们要做课程的话,需要累积相当多的内容。但是付费社群它卖的不是内容本身,所以即使它没有内容,也可以立刻进行销售。 而且因为社群的互动环境在形式上比较随意,有个什么想法随时发一段文字或者几张照片都可以,内容创作的成本很低。 ## 高产出 ★★★ 产出方面就要看具体销售的是什么东西。氛围和讨论环境本身,通常不会特别值钱。但是如果能利用起来,价值就会非常高。比如用付费社群来做中高端猎头服务。 ## 可持续性 ★ 需要持续不断的有内容更新。当然也可以引导其他用户贡献内容。如果一段时间没有内容和话题,就很难维持社群的活跃,氛围会随着时间慢慢变冷,严重影响第二年的续费。 ## 低风险 ★★★★★ 没什么特别的风险。 ## 低门槛 ★★★★★ 会建群会聊天就可以开始。 ================================================ FILE: src/030104.md ================================================ # 图书出版 ![picture 5](images/d12bc8f1c00de8a3f3d67b90f873b38ea659eeeb75fe57f8b4102e096d6050e8.png) 如果把电子书也算进来,目前可以分发图书的方式大概有三类。 第一类是自己独立撰写图书,并生成 PDF 等电子书格式通过自己的渠道进行销售。这种更类似于数字商品售卖,所以并不包含在本节图书出版中。 第二类是通过出版商单独发行电子版。因为电子书不需要印刷,所以比起纸版图书门槛更低一些。我之前用 [BookDNA](http://bookdna.cn/) 出版过电子书,只需要将书提交给他们,就可以上架到亚马逊、苹果、京东、多看等多个平台。收入他们会代收,按分成结算回来。 第三类就是通过出版社出纸书,有时候也会同时把电子书版权签下来。一般纸版的门槛会高一些,需要有一定的影响力或者完成度已经较高的书稿作为参考。 ## 低投入 ★ 图书出版的投入非常大。一般至少需要花费3到6个月来编写初稿,加上审校印刷等环节,最后出版可能还需要花上半年,整个周期很长。 基于现有的内容,比如课程、文章整理创作书稿投入会相对较低,但仍有大量的工作要做。 ## 高产出 ★★★ 产出要把物质回报和非物质回报分开来看。 通过 BookDNA 等出版社专门出版电子书,可以按图书销售收入获得分成,大概在 70% ,还算不错。如果是纸版书,一般版税就只有 8%~15%,整体收入相当有限。 但纸版书对个人品牌提升的效果明显,而且可以通过线下书店等渠道获得读者,所以在非物质回报上比较高。 ## 可持续性 ★★★★ 图书的更新频次都很低,一般只有销售得不错,才会在再版时进行修订。所以我们可以认为它的可持续性还算不错。 ## 低风险 ★★★★ 主要还是时间投入,没有太多额外的风险。因为我们主要是出版技术书籍,内容方面的风险也非常小。 ## 低门槛 ★ 不管是电子版还是纸版,都要经过图书编辑审核,通过以后才能出版。尤其是纸书,要考虑至少收回印刷成本,所以门槛还是很高的。 如果在 GitHub 或者其他地方有发布电子书,且有较好的反馈,那么纸版的出版谈起来门槛就会低很多。 ================================================ FILE: src/030105.md ================================================ # 自媒体 - 低投入:★ 需要持续不断的创作内容 - 高产出:★★★★ 不火的时候没啥产出,火了就多了。另外粉丝也是资产 - 可持续性:★ 日更,最少周更 - 低风险:★★ 起步难,有内容没人看,越到后边风险越低 - 低门槛:★★★★★ 会写字就能开始 ## 经营个人品牌和媒体账号 ![](https://theseven.ftqq.com/20200407204938.png) 对于一个现代网民来讲,经营自己的个人品牌和媒体账号已经变成了一个非常非常基础的操作,不管你是程序员还是从事其他的行业,都离不开这些东西。 我以前在微博上说,现在是一个非常好的时代,网络的普及移动互联网的大规模覆盖,让过去本来很小众的群体,可以通过网络凝在一起。积少成多,小众群体就不那么小众了。 过去你一个很小众的爱好,是没有办法靠兴趣来养家糊口的,只能去一家大公司去从事一些自己不那么乐意去做的工作。 但在现在这个时代,全国、全世界的小众群体就不再小众,我们就可以从这个市场上得到足够多的收益来养活自己。 即使你不需要靠这个来生活,经营个人品牌也会在工作上给你带来很大的助力。一旦你在行业里,慢慢有了个人影响力,这些会跟着你从一家公司到另一家公司。而不是像那些基于公司和平台的影响力,一旦你离开,就和你再也没有关系。 就算单纯从锻炼写作和表达能力角度讲,它也会给你带来丰厚的回报。 所以从各种角度来讲,经营好个人品牌和媒体账号都是一件非常重要的事情。它还能顺便解决掉绝大部分程序员在创建资产时,遇到的那个最大的问题 —— 早期用户从哪儿来。 ## 带货变现 ![](https://theseven.ftqq.com/20200407205102.png) 经营得比较好的媒体账号是可以将流量和影响力进行变现的。 像我们程序员可以通过创造虚拟资产来进行变现。但并不是所有的行业有这么幸运。有些行业经营的是实体经济,它的制造需要工厂、需要工人,会有库存,需要物流,所以更多的媒体账号也靠带货来变现。 如果我们的核心目的不是经营个人品牌,而是带货的话,在品牌早期就应该选择和钱近的方向。比如数码、汽车、房地产、快消等,和花钱密切相关的领域,这样才更容易获得厂商的广告和赞助,自己组织货源以后才更好销售。 当然这个不是绝对的,如果你能和受众建立起很强的信任关系,那么也可能你卖啥他们都会买… ================================================ FILE: src/030106.md ================================================ # 付费咨询 ================================================ FILE: src/030107.md ================================================ # 猎头内推 ================================================ FILE: src/0302.md ================================================ # 自有产品和服务 那接下来我们就来聊聊程序员的专业领域 —— 通过开发自有的产品和服务、作为 side project 运营来变现。 ## 需求的发现 首先要说的是很多同学都很困扰的问题。 我以前以为最困扰的问题应该是如何抽出时间和精力来做一个项目,但后来发现还有一个同样甚至更为困扰大家的问题,那就是有了时间以后,不知道做什么。 通常来讲,解决方案有两种。 一种是通过日常的工作和生活发现原生需求;另一种是通过观察分析和阅读报告来发现。 ### 原生需求 最靠谱的方式就是,留意那些我们自己在日常的生活和工作中遇到的困扰,然后为它去做解决方案,最后把这个解决方案做成产品,出售给有同样需求的人。 这种需求叫做原生需求,不是我们因为有了某个技术而幻想出来的应用场景。原生需求不是等我我们去寻找,而是它会主动找到我们。这种需求非常真实可靠。 但有一个问题,我们程序员相对于整个大众来讲,其实是一个非常小众的人群。这个人群有一些独特的文化、行为和思考方式。所以程序员遇到的原生需求,很可能只适合程序员人群,而不适合其他更为大众的市场。这就让它的目标市场比较小。 而程序员又是一个动手能力非常强、开源文化深入骨髓的群体,绝大部分的解决方案都能找到开源项目,或者改几行代码就能实现了。一些大公司还时不时的开源一堆非常强悍的工具,所以面向这个群体的免费或开源工具很受欢迎,但收费工具却是非常难做的。 反而是如果你在非专业领域有一些更为大众的兴趣爱好,从那些方面来发现需求的话,难度就会下降很多。 #### 需求的验证 另外要重复强调的就是,需求的验证不能以口头承诺甚至免费用户来验。做需求分析的时候你去问,很多都会说我觉得这个东西挺好的。但你让他们付钱的时候情况就完全不同了。 大家可以回想下自己在过去一年里边,为哪些软件或服务支付超过 100 元人民币。我之前发过一篇微博问我的粉丝(大部分是程序员),后来发现绝大部分都是一些资源型的服务,比如视频会员、云主机、网课、网盘;软件就非常少了。所以我们还是要尽可能的从更广泛的人群里去发掘更值钱的需求来做。 #### 降低起始难度 上边并不是说程序员人群的需求不能做,而是说难度比较高。 作为副业,我们投入的精力是有限的,如果一上来就是玩 Hard 模式,失败的概率会非常高。如果经常失败的话,最后就变成一种习惯了,渐渐的,也就会不再想去做副业,甚至连创业的冲动也跟着没有了,这就非常可惜。 ### 观察分析和阅读报告 另一个路径是观察分析那些已经在挣钱的应用,阅读它的用户评论,发现可以改良的点,制作更好的产品。这个工作量还是很大的,所以也可以考虑直接购买一些分析报告。 这里的分析报告不是那种行业的通用报告,那是针对创业公司和大公司的,需要投入很多资源,以爆发式增长的方式去推动,并不适合副业。 最近在国外开始有一些专门针对副业和 Side project 的分析报告。他们收集整个市场的信息,然后针对大致一亿美金以下的细分市场做趋势分析。这种市场一般冲着上市去的创业公司看不上,所以留下了比较大的市场空间。 我最近读过报告的有两家,一家是 Trends.vc,另一家是 SoftwareIdeas.io。不过这两家本身也是初创或副业业务,不知道各位读到这本书的时候是否还在运营。这里最主要的还是给大家提供一种思路。 我们在做副业的时候,也需要慢慢来改变我们的一些习惯。比如说对于程序员来讲,绝大部分的东西都是可以自力更生的。所有能自己做的就自己做,不能自己做的,我们会找开源项目。这样我们会更有安全感,做的事情也会更加靠谱。但是我们在做商业的时候,尤其是在做副业的时候,遇到的问题就在于我们的精力是非常有限的,在价格适中、又有购买能力的情况下,更好的方式是通过购买而不是自己开发。 ================================================ FILE: src/030201.md ================================================ # 应用市场卖 APP ![picture 5](images/bcc287fbbd9b5f3db1ddb6ff977474fdca752c5ed7b5c138d600360deea83961.png) 对于我们绝大部分程序员来讲,开发是自己的本职工作,所以都比较擅长。但是在做副业的时候,我们还不可避免地需要把自己的软件卖出去。而销售往往是我们的弱项,有没有一个办法让我们可以避免它呢? 答案就是应用商店。早期的应用商店是一个非常好的入口,它会分门别类的将软件陈列在上面,有需求的用户会通过分类浏览或者搜索查询的方式来安装或者购买。 但经过一段时间的发展,应用商店里边的软件已经越来越多,各种需求被满足得也越来越充分。 现在大部分的应用商店已经是红海市场,也就意味着说,即使你在应用商店上架了软件,也不等于其他的用户有机会看见它,因为软件实在是太太太多了。 所以,我们需要想办法在应用市场的应用海洋中获取流量。一般来讲免费获得流量的途径有两个。 ## 关键字搜索 一个是通过关键字搜索。一般应用商店都会有搜索入口,用户输入关键字,商店则会列出匹配的应用列表。如果我们指定的关键字被搜得更多,那就更容易覆盖到更多的人群。 ## 编辑推荐 另外一个途径是编辑推荐。一些看起来有创意、格调比较高的APP更容易被推荐。而同样功能但是界面不好看的应用,则很难被推荐。所以界面设计不光是用户体验的问题,甚至还直接影响我们的获客。 虽然现在应用市场很多,但是有强用户付费习惯的国内市场,其实也就是苹果商店,所以我们如果以挣钱为主要目标的话,就应该优先考虑苹果商店这个市场。Google 在国内没有商店业务,如果是面向全球市场的业务,可以上 Google Play。 下边来看看评分项。 ## 低投入 ★★★ 从投入上来说,如果你本身不是 iOS 开发者,又没有苹果电脑,那么可能需要为 iOS APP 开发购买一些硬件,同时苹果开发者还有一个至少 699 的开发者年费。 ## 高产出 ★★★★ 一旦进入市场某个分类排行前列,可以获得的流量还是很多的。 ## 可持续性 ★★★ 需要跟上操作系统的更新升级。应用市场会定期下架一些 SDK 版本过低的APP。大部分时候只重新编译就好了,但如果使用的一些库出现了兼容性问题,那么就需要有大量的维护工作了。 ## 低风险 ★★★★ 软件应用商店托管,数据同步可以用 iCloud 等,没什么特别风险。 ## 低门槛 ★★★ 对移动客户端的开发者来讲,基本上没有门槛。其他开发者要进入这个市场,需要学习移动开发技能。当然也有桌面应用市场,但数据比移动市场差很多。 ================================================ FILE: src/030202.md ================================================ # 订阅式软件 - 低投入:★★ 基本功能免费、增值服务订阅,需要花不少时间和精力做免费功能 - 高产出:★★★★ 采用订阅模式,可以锁定用户,每个月都有收入 - 可持续性:★★ 需要定期更新大功能刺激用户续订 - 低风险:★★ 风险在于早期用户的获取,以及续订率 - 低门槛:★★★★★ 标准软件开发 ![](https://theseven.ftqq.com/20200407201150.png) 现在软件越来越难卖了,因为获取用户的成本正在变得越来越高。 但是软件订阅也正在兴起。什么是软件订阅呢? 以前,我们买的软件基本都是一次性付费的。从用户的角度看,这是很爽的,买完以后就可以一直用。 但是从软件开发者的角度去看,他需要不停的随着操作系统的升级和用户的需求去升级和修bug,有着大量的维护成本。同时,因为老用户已经花完钱了,所以还要不停的去寻找新用户。这样就牵扯了大量的精力。 软件订阅的方式,是说用户不用一次性付很多的钱,可以支付一点点,但会有使用期限制,如果你想一直使用,可能每个月都要花上一些钱。 这是一个很好的模式,但是软件订阅给客户带来了风险,比如说,突然有一天开发公司倒闭了,那么就没法续费了。所以也有很多用户是不愿意购买订阅服务的,我就是其中之一。 这里想说的是,订阅的服务一定要合理。比如有一些云端的功能我们要使用,那这个时候,订阅功能就是合理的。 你一个万年不更新的纯客户端,还要搞成订阅一个月收几块钱,就不合理了。 转订阅的软件很多,比如 Sketch,直接把之前买断的老用户扔了,强制让按年付费。也有良心一点的,比如 MindNode,之前买断的老用户可以一直用。但无论如何,订阅的软件是越来越多了。 说不定以后针对订阅软件,搞一个一次性买断的竞品,反而会很好卖 🤣 ================================================ FILE: src/030203.md ================================================ # 非订阅式软件 ================================================ FILE: src/030204.md ================================================ # 开源/免费+收费模式 ![picture 4](images/e3c6d128925437243ae6874001087bd84a414f7f9ccbdb026d94f9acfaa94b12.png) 我们前边有讲到,面向程序员群体提供产品和服务是一个难度很高的操作。但是,又提到了开源和免费的工具在这个领域是非常受欢迎的。这看似矛盾的背后,就衍生出来了一种商业模式,叫做开源/免费加收费的模式。 它的核心逻辑是说,既然开源或者免费的工具非常受欢迎,那么我们就可以利用它来获取大量的免费用户,在有了大量免费用户的基础上,再来提供增值服务进行变现。 虽然购买付费服务的用户比例不高,但如果我们免费用户数量庞大,那最终的收益还是会不错的。尤其是对于副业来讲,它对总收入的要求并不是特别高。所以,这个模式对于副业来讲,其实反而是一个很合适的方式。 我现在就在经营一个免费服务,叫做[server酱](http://sc.ftqq.com)。它是一个非常简单的 API,用来向微信推送通知。绑定以后只需要给一个 URL 发 HTTP 请求,微信上就会收到一条消息。 这个服务现在有10多万免费用户,免费服务是通过微信服务号来推送消息的。我们今年,在免费服务的基础上新增了基于测试号实现的推送功能,该功能是收费的。它收取的费用会用来补贴免费服务的服务器开销。 事实上,在免费服务刚上线半年时,我们就推出过一个付费服务,支付率非常低,后来就关掉了。 但在有了10万用户再来做付费服务的时候,我们发现它的效果就不一样了。运营了大概三个月左右,我们收到的费用就已经足以支撑本年度的整个免费+收费服务了。 这说明免费/开源,然后再加增值服务收费的模式是可行的,但它必须建立在不小的已有用户基础之上,否则是玩不转的。 下边来看评分项。 ## 低投入:★ 首先在硬件投入上,如果是独立的客户端软件,不依赖于服务器,那么做免费用户的时候,付出的成本是固定的,也就是软件的开发的人工成本,这个投入就会相对比较低。但如果是在线的服务,免费用户越多,付出的成本就越高,这个时候的投入其实是相当高的。 这里顺便跟大家分享一个趋势,随着 wasm 的发展,在浏览器里也能运行很多以前不能运行的程序了,比如视频转码工具 ffmpeg ,虽然还比较慢,但已经可以用了。这种技术一旦成熟,会大大地降低免费服务的成本,是一个值得留意的地方。 另外为了获取大量免费用户,它在很长一段时间内都难以挣钱,这部分投入很高。 ## 高产出:★★★★ 产出和规模、增值服务定价密切相关。考虑到整体转化率偏低,整体产出平均下来一般。但一旦成功,就可以获得不错的产出,并建立起比较高的竞争门槛。 ## 可持续性:★★★ 和一般软件服务的更新频次差不多。 ## 低风险 ★ 在获取免费用户阶段,只有投入没有收入。如果免费用户消耗的资源过多,而增值服务还没来及变现,整个业务就有挂掉的风险。 ## 低门槛:★★★★★ 会写代码就可以。 ================================================ FILE: src/030205.md ================================================ # 半成品市场 ![picture 3](images/20c0769a83b85b1b0dc6e28dc22822b403615c05754427db6caaaa4ccd245e63.png) 就像作家写书、音乐家作曲一样,其实程序员也可以创建有版权的数字内容,并通过售卖它来获得更好的收益。虽然我们之前聊过基于版权的市场在国内基本可以忽略,但是在全球范围,在英文市场里,还是有很大的交易额的。 比如 Envato 旗下的模板交易市场 [themeforest.net](https://themeforest.net) 和 代码插件交易市场 [codecanyon.net](https://codecanyon.net) 。 我们重点来说说 themeforest 吧。 ![picture 1](images/713394674c012d0ac06da878572241f5e3977ee6060ef54e6a6b78f3d0aa5221.png) 这个市场上有 47,000 多套 WordPress 和 HTML 的模板,最低的价格是两美金一套。 在国内,就算你做了一套好模板,其实也很难卖出去。即使有很少的用户购买,也会很快被分享出去,以盗版的方式到处传播。 在英文市场,用户的付费意识会比较强,会更愿意在付费市场里面去买一些价格合适、在版权上又没有隐患的模板或者插件。首先因为这对他们来说不贵,然后用盗版的话,受到的惩罚会贵很多。 我用 themeforest 主要是买模板,最开始以为这个市场不大,直到有一天无意间看到畅销榜的一个模板销量。这个模板本身做得很不错,内建了一套 page builder 系统,定价为 60 美金一套。 ![picture 2](images/7929cc167e1b68258139a79c714b61cf7891ee9fd7fa19f32bba7f94e1fd875c.png) 从2012年8月16号开始卖,截止到现在总共卖了58万5840套。 看到后我立马掏出计算器算了下,这是 3515 万美金,**大概2个多亿人民币**。这只是这家公司的一套模板,他们还有其他的模板。 所以啊,国内很多程序员老是觉得什么 PHP 不行了过时了,但是事实上**全球排名前1000万的网站里边,有三分之一是 WordPress 在支撑**,这依然是一个非常非常庞大的市场。 做模板和插件另一个比较有意思的地方是,它们通常是开发的副产品。比如我们做外包时做的模板系统、给自己博客写的插件,现在把它拿出来商品化,这样投入就会小很多。 下边我们来看评分项。 ## 低投入:★★★★ 通常是开发副产品,所以投入不算高,但需考虑推广成本。 ## 高产出:★★★★ 一旦找到位置,就可以持续销售,还是挣美金。 ## 可持续性:★★★ 根据平台的不同需要定期同步更新 ## 低风险:★★ 风险在于这部分主要是英文市场,如何获得关注、竖立品牌是难点 ## 低门槛:★★★★ 程序员的本职领域,前端可以做模板,后端可以写插件,全栈可以卖整站。 ================================================ FILE: src/04.md ================================================ # 精益副业 ================================================ FILE: src/0401.md ================================================ # 精益副业流程 ================================================ FILE: src/040101.md ================================================ # 什么是精益创业 「精益创业」是硅谷科技公司 IMUV 的联合创始人埃里克·莱斯提出的一个理念,他以此为主题出版了一本同名的书。 其实对于程序员来讲,尤其是熟悉敏捷开发的同学来讲,「精益创业」其实就是「精益开发」的增强版,它将精益的思想扩展到了产品的全生命期。 下边是它的一些核心思想: - 所有的战略都基于假设,只有经证实的认知才是可信的 - 对创业来讲,有两个核心假设很重要:价值创建假设和增长假设 - 通过实验来验证认知,通过创建 MVP(最小可行产品)来检测产品是否和市场契合 - 提出了三大常见的增长引擎,可用于验证增长假设 - 去掉虚荣指标,采用创新核算评估真实数据,决定是否转型 《精益创业》这本书非常好,但它更偏重于一些理念的阐述,没有形成一个完整好用的方法论。但幸运的是后来有其他的同学在这本书的基础上,出版了《精益创业实践》等其他周边书籍,逐渐形成了一个完整的创业方法论。 创业并不是我们的重点,所以留给大家自己去了解。但是我们从精益创业方法论中,针对资源紧缺的副业,精简出了一套「精益副业流程」。 ================================================ FILE: src/040102.md ================================================ # 精益副业:为副业优化的精益流程 虽然我们的副业也是一种创业,但是往往投入的精力比较小,而且局限在只有少数人,通常来讲只有1~2个人参加的情况。 所以,精益创业的标准流程,虽然它本身也是针对这种小企业起步时的创业方法论,在以副业的状态下来使用它时,也是需要进行一些优化的。 接下来,我们为大家讲解的,就是我自己在比较长时间的副业实践中经过多次优化的流程。除了流程本身,我们在后续会有两个非常大的章节,会以实例的方式来给大家讲解在做网课或者做独立开发的时候怎么将精益流程落地。 不过在开始流程之前,我们还是先来熟悉下精益副业中(从精益创业方法论体系中继承的)会用到的基本概念和工具。 ================================================ FILE: src/040103.md ================================================ # 价值主张及其设计 前边我们说到,在精益创业方法论里,有两个非常重要的假设。第一个就是「价值创建假设」,它其实就是说,我们提出一个价值主张,然后去测试这个主张针对的客户是否买单。 ================================================ FILE: src/040104.md ================================================ # 商业模式画布 前边我们说到,在精益创业方法论里,有两个非常重要的假设,第一个就是「价值创建假设」。 因为不管是向用户销售软件还是在线服务,它本质上来讲其实是一种价值交换。也就是我们「给什么样的客户」「提供什么样的服务」,然后「收多少钱」的一个简单逻辑。 而围绕着价值的定义、创造和传播,我们可以使用一个非常棒的工具来描述它,这个工具叫做商业模式画布。商业模式听起来是一个很高大上的名词,但它具体化以后就很容易理解。 商业模式画布是以价值为中心的一张图,让我们把所有和价值相关的内容都放到上面,从而可以一目了然地纵观全局。 那下面,我们就来看一下商业模式画布是怎么围绕核心价值,一层一层建立起来的。 ## 价值的定义 商业模式的核心,就是「价值主张」。也就是刚刚提过的,对谁,提供什么样的服务,收多少钱。 ![picture 6](images/258579e8f2115c650f38bba6054e42073651a6c3f47e83274730593daf94cf01.png) ## 创造价值 定义好价值以后,我们会从两方面来考虑它。首先是如何把这个价值给创造出来;然后是如何把这个价值给销售出去。 在价值创造这边,我们可以把它细化为三个方面。 ![picture 7](images/478eb3942f95f0163e1f4d6900360c1f6bfc5a142bb9b6b797ef02508aa041cb.png) 包括: - 我们需要进行什么样的活动?这里的「活动」是「activity」,其实也可以叫做动作。 - 我们需要什么样的资源? - 我们需要进行哪些合作? ## 销售价值 在价值销售这边呢,我们就要思考: ![picture 8](images/e064d34150f22ff80f2dc89dd9c3fd1b0c7065f493ef6da692de3bfd1c2d72e3.png) - 我们的价值主张定义得够不够好? - 我们的渠道通路是不是足够的通畅,到达是不是有效? - 我们的客户关系要怎么来建立和维系? 其实价值主张应该放到价值定义里边,但因为价值主张它直接涉及到了客户细分,又直接影响到了销售,所以我暂时把它放到销售这一边。 ## 分层结构 按前面的描述,我们比较容易把商业模式画布当成一张图。但事实上,它其实更类似于Photoshop 软件中 的 PSD 文件,是分层的。其中每一层针对一个细分人群。 这主要是因为我们提出的价值主张,很难同时覆盖多个人群。同样的价值主张对一类人来讲可能是非常棒的东西;而对于另一类人来讲可能就毫无用处。 所以,我们提出价值主张之前,就需要进行客户细分,把我们的客户分成几类典型的角色,再针对每一类角色来提出更为具体、更有针对性的价值主张。 ## 画布结构 下面我们就实际来看一下商业模式画布的布局。 ![picture 9](images/9750c7270996b4b3418ed4716e9108072b7b2676188813eced11e4796ebbb0d8.png) 在表格的最中间,就是我们的价值主张。在最右边,是客户细分。我们可以用不同颜色的文字,来代表不同的细分客户和针对他们的价值主张。 在价值主张表格的左边,是关于价值创造的区域,有「关键活动」、「关键资源」、「关键合作伙伴」;在价值主张表格的右边,是关于价值销售的区域,除了我们刚才已经说过的「客户细分」,还包含了「客户关系」和「渠道通路」。 表格的最下边一行,分成了两部分,左边是「成本构成」,右边是「收入来源」,它们都是根据我们上面的表格来进行计算的。一旦计算完,我们就可以预先知道这个项目做下来能不能挣钱,或者说挣钱的可能性有多大。 ## 价值主张画布 在整个商业模式画布里边,「价值主张」和「客户细分」是最为基础、也最为关键的地方。如果价值主张没定义好,其他的做得再好也没有用。 所以,为了更好地进行价值主张设计,我们还有一张专门针对这两个部分的、更为详尽的「价值主张画布」。 ![picture 10](images/40c7f0651751c07084942a525f4493f7f5722d10e4ad3c3043c2807b05b4f1a7.png) 上边这张图就是「价值主张画布」。它左边是「价值主张」,右边是「客户细分」。 ### 客户细分 在「客户细分」这里,它更为详尽地描述了客户的情况。 这个圆分为三部分,最右侧描述了客户想要进行的工作、要完成的业务;下方是他在完成这些工作的时候所感受到的痛苦;上方是在完成工作后可以得到的收益。 ### 价值主张 图左边的正方形就是我们的价值主张。可以看到,价值主张是针对需求提供的解决方案。比如:针对痛点,我们会提供「痛点缓释方案」,让客户在完成工作的过程中,没有那么痛苦;针对收益,提出「收益创造方案」,让收益变得更多。 在这两个方案的基础上,我们通过产品和服务的形式来将其落地,也就是正方形的左侧部分。 ### 契合 大家可以注意到,在「客户细分」的圆形和「价值主张」的方形中间,有两个正对着的箭头,它表示「价值主张」和「客户细分」之间要达成契合。 因为我们会把整个客户群体分成多个细分群体,所以价值主张画布,它其实也是多份的。针对每一个细分的客户群体,都会有一张自己的价值主张画布。 ================================================ FILE: src/040105.md ================================================ # 最小可行产品和产品市场契合 上一节讲了如何通过商业模式画布来规划商业逻辑,但是「所有的战略和规划都是假设」,只有被验证以后的认知才是可靠、可信的。所以接下来,我们就需要用实验的方式来对它们进行验证。 通常,我们会采用「最小可行产品」(Minimum Viable Product,缩写为 MVP)来进行验证。 「最小可行产品」有两个关键词。一个是「可行」,它其实并不是指用户拿过去能用,而是指它可以很好地验证我们的假设。 另一个关键词是「最小」。它是说,除了验证所必需的功能以外,其他的功能都应该先不做。那些功能应该在验证完成之后再去添加,不然如果我们验证失败的话,功能就白做了。在我们的精力非常有限的情况下,这种浪费是非常可惜的。 严格意义上来讲,我们可以针对整个商业规划里边的每一个假设来做一个最小可行产品对其进行验证。但是我们的精力是有限的,所以通常只对核心假设通过MVP来验证。这个核心假设就是我们之前提到过的「价值创建假设」。 一旦这个假设被证实了,我们就认为我们找到了「产品和市场之间的契合」(Product-Market Fit,缩写为 PMF)。 具体而言,我们会在验证假设之前,定下一些量化的指标。在我们验证的时候,进行相应的衡量。最后根据指标的数据,来判断是否达到了 PMF。如果是,就可以进一步的增加功能,往前推进;如果不是,则需要调整,甚至需要通过战略转型来重新找到 PMF。 这种转型可以是针对原有市场的细分市场重新提出价值主张;也可能是扩大需求,让它支持更广泛的人群。但无论如何,在找到 PMF 之前,我们都应该专注于价值假设的验证,而不是功能的丰富和市场的推广。 ================================================ FILE: src/040106.md ================================================ # 迭代和增长 ================================================ FILE: src/0402.md ================================================ # 精益网课变现实践 ================================================ FILE: src/040201.md ================================================ # 网课的精益流程 这一节开始,我们会将精益产品流程用到网课上。 ## 网课和互联网产品更接近 有同学可能会想,你用互联网产品常用的精益流程来独立开发,这很好理解,但是网络课程,它为什么也适合用这种流程在做呢? 让我们来仔细看看网络课程。 它其实是一种跨界的产物,我们把网络课程这个词拆开,它包含了「网络」,又包含了「课程」。提到「课程」,大家想得更多的是线下培训;而提到「网络」,大家往往第一反应就是互联网产品。 因为「网络课程」以「课程」结尾,我们可能从语感上觉得它离课程更近一些。然而到底是不是这样呢?我们来比较一下。 ![picture 11](images/8b3e525855e458d906d16e6652596cfe65a856e5820e13e5ae279ae7257c949e.png) - 从录制上来讲,网络课程使用电脑来制作,线下培训没有录制的这个环节。 - 学习上来讲,网络课程是在线进行学习,线下培训主要是现场教学。 - 从获客上来讲,网络课程主要是通过网络和社群来进行,线下培训主要依靠地面推广 - 从模式上来讲,网络课程通常是录制之后多次售卖,当然现在也有一些直播课;线下培训主要是按学期重复地进行讲授。 通过对比,我们可以看到网络课程和线下培训,不仅在学习方面有所差异,它们在最关键的获客和课程的模式上面有非常大的不同,而这两个环节会直接影响课程的销售。 我们接着再来对比一下网络课程和互联网产品。 ![picture 12](images/7cd2424338943f32c0edc38ee110e1a02d0a4194928d14ae54629bbc2b89de82.png) - 在制作上,网络课程是通过电脑进行制作;互联网产品也是通过电脑进行开发 - 在使用上,网络课程是在线进行学习;互联网产品通常也是在线进行消费 - 在获客上,它们都是通过社交网络推广,利用搜索引擎、社群互动来进行获客 - 在模式上,网络课程是一次录制多次售卖;互联网产品是开发完成之后持续地进行使用 通过对比我们可以发现,网络课程其实和互联网产品在形态上更为接近。 这其实是一件好事,因为它跟互联网产品接近,就意味着说它更容易像互联网产品那样爆发式的增长,它的潜力也会更大。这可能就是在线教育现在发展得很好的原因。 基于以上理由,我们把互联网产品常用的精益创业流程进行优化,最终用到了网络课程上。从一年多的实践看,是非常有效的。 ## 精益产品流程 这里我们复习一下上一节提到过的精益产品流程。 ![picture 14](images/5590d7f3ed2103969d586b1d21769ac4c9aabda62ca746c8465ec7ef324a6339.png) 首先第一步,是提出我们的价值主张。然后根据价值主张制作最小可行产品(MVP)。通过 MVP 去寻找产品市场契合(PMF)。如果达到了我们预定的契合目标,就开始迭代式的开发;产品上线稳定后,会开始做一些增长方向上的优化,来提升我们产品的数据。 这个流程放到网课制作上,要进行相应的调整和优化。 ![picture 15](images/ca3e9c69624594145b053722f8074399f5601b05183aa40d50c837bfce3ff716.png) - 提出价值主张,对应到选题和规划 - 制作 MVP ,对应到大纲 - 寻找产品市场的契合,对应到预售验证 - 迭代开发,对应到制作和后期 - 增长优化,对应到课程上线后的运营 看起来这个流程和传统课程制作流程没有特别大的差异,但是如果仔细观察,就会发现我们多了验证这个步骤,而且它放得非常靠前。 不要小看这个细节的改进,实际上它对我们的成本和风险的影响是非常大的。因为它可以在进入制作之前,就发现卖不掉的课程,帮我们省下大量的资源。 ![picture 16](images/9e1089c90e36aa190b02f8e3ed5afe003930f15293a78ba1479241c16a315f91.png) 从上边这张对比图可以看出,如果一个课程在规划和选题上存在问题,那么假设在大纲处开始验证,它损失的成本是 1;那么等到销售时才发现,它的损失将是 3 到 5。 这种风险控制对于副业来讲,是非常重要的。 ================================================ FILE: src/040202.md ================================================ # 如何确定选题的基本方向 网络课程既然是课程,我们就要有可以教授给别人的东西。为此,我们需要重新认识自己,弄明白我们拥有什么样的价值。 ## 认识自己 从网课的这个角度来讲,发现价值其实就是发现自身的专长,可以大致分成以下几类。 ### 专业技能专长 首先,想想自己有什么专业技能,比如说会不会编程、懂不懂设计、能不能做产品原型等。 ### 业务领域专长 然后,回顾下自己熟悉哪些业务。大学学的什么专业、毕业后进入的什么行业、对哪些业务特别熟悉?比如房产销售、心理咨询、职业规划等。 ### 兴趣爱好专长 前边是和工作相关的,我们也可以看一看自己的兴趣爱好,喜欢做的事里有什么做得比大多数人都要好。比如烘培、摄影、登山等。 ### 问题解决专长 前边几种专长都是显而易见的,但也有很多人不具备。是不是没有这些专长就没法做网课了呢?也不是。也有一些普通人就拥有的,但是往往很容易被忽略的专长。 比如说,问题解决专长。 什么叫问题解决专长呢?它是指善于发现并高效解决问题的专长。特别需要注意的是,你不需要对所有问题都擅长;只需要对解决某一个特定问题很精通就好。 比如,搬家。几乎所有的人都会搬家,但是如何搬家才更舒适、更划算、更安全,这就是一个问题。搬家的时候各种物品应该如何包装不容易坏;装箱时用多大的箱子、轻重如何搭配更省钱;搬运时找搬家公司、物流还是租车更划算。这些都是满满的细节。 搬家是很麻烦的事情,当我们不得不经历并想各种办法把它很好地解决后,我们就拥有了一些很有价值的实用知识。这些知识就是我们在这个问题上的专长。 ### 归纳表达专长 另一个不容易发现,但不少人都可以具备的,是归纳表达专长。它是说,我们通过阅读海量资料,进行整理,将其中最有价值的部分提取出来,作为一个精简的结果提供给时间和精力有限的受众。 一个典型的例子就是知识变现中的「讲书」,解读人花几天到几周时间读完一本书,把其中最核心、最精彩的部分提取出来,用几分钟的时间讲解。 问题解决专长和归纳表达专长背后的逻辑,其实都是帮学员节省时间和精力。它没有特别高的门槛,只要愿意在一个小问题上花足够多的时间,大部分人都能做到。所以当你没有明显的专长时,它们是值得优先去考虑和尝试的。 ### 跨界专长 如果你发现自己属于「泛而不精」的类型,对多个领域都有所涉猎,那么也可以思考下自己是否有跨界的专长。跨界专长的逻辑用曾经流行过一句话来讲就是,「比我漂亮的没我聪明,比我聪明的没我漂亮」。找到合适的交叉点,就可以建立起独特的价值壁垒。 比如说,我既做过程序员,又当过产品经理。那么我就可以出两个跨界的课程,一个给程序员讲产品;另一个给产品经理讲技术。这两个课程都是纯粹的程序员或者产品经理很难做好的。 所以大家不要觉得自己没有专长,其实「天生我材必有用」,很多时候只是缺少了发现自己专长的眼睛。花上几个小时,仔细回想自己的经历,你会找到你所拥有的独特价值的。 ================================================ FILE: src/040203.md ================================================ # 网课的商业模式设计 前边我们已经用过商业模式画布这个工具了,这次我们把它用到网课上。 这里,假设要将本书中的「精益网课变现」部分内容制作成一个付费视频网课(实际上还真的有这么一个课程,不过是在撰写本书之前制作的),我们来看看应该如何进行商业模式设计。 ## 价值主张和客户细分 首先肯定是要定义价值,这就离不开价值主张和客户细分。我们将课程的核心用户分为两类: 1. 做不出课程的人 1. 卖不掉课程的人 为了深入理解客户细分,我们之前使用了「用户画像」工具,这次使用「价值主张画布」来做分析吧。这个画布我们在前边讲商业模式画布时介绍过,忘了的同学可以先复习下。 ### 做不出课程的人的价值主张画布 #### 痛苦 什么样的人会做不出来课程呢?简单地分析一下,我觉得主要有两类: 1. 没有足够的时间和精力来做课程 1. 缺乏基本的知识和技能来做课程 于是我们把它写到右侧圆形的「痛苦」部分: 1. 没有足够的时间和精力 1. 不知道课程的制作流程 1. 不会音视频的后期 #### 工作 然后来看「客户的工作」。这里的工作,其实是一个广义的、泛化的概念,并不一定就非得是上班时要完成的任务,一些情绪上的、社交上的需求其实也都可以放到这个地方。所以我们写上: 1. 保持稳定的品质和产能持续制作课程 1. 获得成就感 #### 收益 再来看「收益」部分: 1. 学会快速做课的流程 1. 稳定的后期质量 1. 提升课程产出 这就是我们客户的情况。下边来看看如何针对这些情况提出价值主张。 #### 痛点缓释方案 先从痛点入手,来提供「痛点缓释方案」。 针对「不知道课程的制作流程」、「不会音视频的后期」的解决方案很直接,只需要提供详尽的流程和技能讲解就可以了。 而针对「没有足够的时间和精力」的问题,我们就要仔细想想了。首先,注意到「足够」这个词,它其实说明了两个问题,第一,客户还是有时间和精力在投入的,只是比较少。第二,学习做课以及实际做课需要消耗大量的时间和精力,与客户能投入的不匹配。 为了解决这个问题,我们有两种思路,一种是让客户增加投入,但在副业状态下不太现实。另一种思路,就是想办法大量削减学习做课和实际做课的时间和精力。 为了削减学习做课的时间和精力,据 8020 法则知道,在 80% 的时间里其实我们只会用到约 20% 的功能,那么我们可以只教授这 20% 最常用的部分功能,其他的知识可以在等学员遇到问题后,通过学员交流群或自行查找资料来解决。 而为了削减实际做课的时间和精力,我们则提供组队和众包服务。如果时间和精力不足以做完一个课程,那么可以几个人合作,拼起来完成一个课程。 #### 收益创造方案 再来看针对收益的创造方案。首先我们提供了基于精益副业的网课制作流程,速度更快、风险更小。然后我们可以引入人工智能和其他工具软件,提升课程的产出、稳定后期的质量。 组队和众包也可以进一步提升收益,所以我们也把它放到这里。 #### 产品和服务 有了「痛点缓释方案」和「收益创造方案」,我们需要把它们落地,这时候就需要具体的「产品和服务」。为了满足上边提到的需求,我们要提供的产品和服务如下: 1. 全流程覆盖的教学 1. 组队和众包群 1. 工具表格和提效技巧集 其中「工具表格和提效技巧集」可以包含在「全流程覆盖的教学」中。 最后,我们将价值主张归纳为一句话,那就是「多快好省地做课」。 ![picture 43](images/37960eb138377f3b6ace6d2403f2f157a180e6bc322c2e138b4c6921f89c39a9.png) 以上就是完整的,针对「做不出课程的人」的价值主张画布。 ### 卖不掉课程的人的价值主张画布 下边我们来看卖不掉课程的人。 #### 工作 很直接: 1. 卖掉课程 1. 赚取收益 #### 痛点 1. 风险:做完课程卖不掉 1. 入驻平台没有竞争力 1. 自己销售没有流量 这里的风险我是有切身体会的。之前大概花了三个月的时间来做一个课程,最后总共就卖出去了两套。不光是收益问题,在情感方面的打击也是非常大的,好久都不想再做课了。 #### 收益 1. 让制作的课程有竞争力 1. 拥有独立销售课程的渠道和能力 #### 痛点缓释方案 针对痛点,提出以下缓释方案: 1. 通过精益网课流程,将风险前置,卖不掉的课不进入制作 1. 提供市场分析工具和竞争力分析表格 1. 打造流量池进行二次销售 #### 收益创造方案 1. 精益网课流程让课程更具竞争力 1. 讲师流量互换、分销和流量池提升免费流量 #### 产品和服务 1. 精益网课流程中的验证流程 1. 市场分析工具和竞争力分析表格 1. 讲师群 我们将价值主张归纳为一句话,那就是「无风险、高收益地卖课」。 ![picture 45](images/3ae6358450603da7eb752ff8e82ac529fbabaa2ed525692ee118a9887e142c60.png) 以上是完整的,针对「卖不掉课程的人」的价值主张画布。 ## 关键活动 回到商业模式画布,将价值主张和客户细分填入对应的表格。然后将「产品和服务」中的内容合并后填入到「关键活动」。 ![picture 46](images/97bbbc9d7eebe663652557461971467c620f45c85b81b1274c8a7d0c6d87b4b1.png) 同时,不要忘了添加上支持这些产品和服务的基础工作,比如市场分析脚本编写等。 ## 关键资源 定义好了「关键活动」,我们就可以反推出「关键资源」。因为它其实就是为了实现「关键活动」所需要的人、钱和时间。 ## 关键合作伙伴 同时,我们把自己掌控不了的外部资源放到「关键合作伙伴」一格。这样关于价值创造部分的表格就填写完成了。 ## 渠道通路 然后我们来补充价值销售部分的表格,在「渠道通路」里,会填上课程平台,微信群和社交网络。 ## 客户关系 我们通过微信群来进行答疑,也会通过「兔小巢」来处理工单。 ## 成本构成和收入来源 最后,根据以上各个表格填写的内容来推算我们的成本和收益。 成本这边,这个课程大致会花掉我一个月的时间,这是最主要的人工成本。如果字幕要外包出去的话,还有成本。做这个课会用到幻灯片软件,我平时是用 Mac 系统下的 Keynote,但是为了课程的普适性,我还需要购买 Office。在硬件上,我之前已经购买过录音设备了,但很多刚开始做课的同学可能是没有的,要记得加上。 收入这边呢,主要就是课程销售。如果每套课程定价 100 元,卖掉 200 套,那么收入就是 2 万。 这时候我们就要评估下,用一个月的时间来挣这两万块钱是否划算。如果觉得合适,就可以编写大纲、准备预售。因为这里的两万完全是估计值,为了降低风险需要通过预售、众筹的方式来验证。 ================================================ FILE: src/040204.md ================================================ # 网课市场分析 在大部分的情况下,我们面对的是一个红海或者即将成为红海的市场,也就是说,你可以提出一个价值主张,但别人可以提出一样的或者类似的价值主张,那怎么样才能让我们的价值主张更具竞争力,这个就是本节我们要讨论的。 竞争就逃不掉对比,它是通过比较来得出的结论,所以我们需要对这个行业和竞争的基本情况有一个了解。下边分享下我们自己在用的方法,只是为不知道怎么分析的同学提供一个思路,并不是说不用这个方法就是错的。 ## 双层视角 我们一般会从两个视角来看待目标市场:一个是宏观的视角,也就是行业整体是什么样子;另一个是微观视角,也就是具体要做课的细分市场是什么样子。这里的细分市场会特别的细,比如 Vue 课程的市场。 ## 十万加不靠谱 说到了解行业的基本情况,很多同学都喜欢去找一些网红写的分析文章,或者一些营销号写的10万加,觉得读起来有一些行业里水很深的内幕,但事实上那种东西基本没有太多参考价值。 这类文章大多是消化过的东西,而往往又对数据的来源、分析和加工过程闭口不提。通常讲的都是一些结论,为了传播可能还会加油添醋。所以我认为不是可靠的信息源。如果把我们的产品建立在一个不可靠的原始认知上,那得出来的结论、做出来的产品自然不可靠的概率就会很高。 这里呢,我们建议大家去看行业报告。看报告也不是看里边的预测或者分析,最主要的是看里面的一些统计数据。因为预测和分析都是经过加工的,而统计数据是相对比较原始的认知,出问题的可能性比较小,所以可靠度更高。 ## 阅读行业报告 有一些咨询公司是专门做行业报告的,当然基本都是收费的。但最近几年有一些公司陆续以免费的形式开放了简版报告,比如[艾瑞咨询](https://www.iresearch.com.cn/)就提供了很多免费报告。 网上也有一些数据分析类的公众号会分享行业报告,大家可以自己搜索下。 ### 建立行业认知 在经过一番下载搜索后,你可能手上已经会有几十份报告了,这些报告怎么来看呢? 首先,要了解这个行业的概况,也就是说先要从整个行业的报告看起,建立对整个行业的认知。 比如我们的读者大概率是做编程课,它其实是属于职业教育的一种,我们就可以去找职业教育相关的报告,如果找不到细分到职业教育的报告,也可以直接找教育类的报告,它里面很可能会包含职业教育的这一部分。 报告的内容会很多,但我们也不用把报告全看完,通常在最开始的概要部分,就会介绍行业的相关情况,我们把各个报告最开始的部分进行综合,就可以逐渐建立起基本的认知。 ## 切换微观视角 当了解了行业概况以后,我们就需要切换到微观视角,来看一看我们要做课的细分市场是什么样子的。 因为我们要做的课往往非常具体,所以面对的市场其实容纳的课程数量并不会特别的多。这个时候就可以简单粗暴的通过批量收集数据并进行整理,最后得出精准的统计数据。 这种方式对程序员来讲非常简单,第一步是确定要考察的指标;第二步是搜集数据。这里我们给出一些常用的考察指标: 1. 课程类目 1. 定价、折扣价 1. 课时数 1. 学员数 1. 评分 1. 表面营收 1. 课时价 这里的表面营收是一个间接的考察项,它其实是折扣价和学员数的乘积。之所以要加上「表面」这两个字,这是因为这些学员不一定都是按当前的折扣价格购入课程,有可能一些学员是全价,也可能还有一些学员直接就是免费获得的。所以它并不是一个精准的营业收入,只是一个参考值。 另外一个间接考察项叫做课时价,它就是当前的折扣价格除以这一门课的课时数,也就是平均每一个课时多少钱。它对于我们的课程应该分多少个小节、分多少个课时,有很强的参考意义。如果还想做得更深入一些,对于视频课程来讲,还可以统计整个课程的视频时长,这样就可以算出每一分钟的价格,更为精准。 ================================================ FILE: src/040205.md ================================================ # 形成有竞争力的价值主张 了解了市场以后,就可以开始思考我们的竞争策略了。 ## 不竞争 孙子说过,不战而屈人之兵,才是最好的策略。所以,最好的竞争策略就是压根不参与竞争。这个听起来比较难,但还是有方法的。我们从两个方面来看: 1. 内容的独特性 1. 品牌的溢价 ### 内容的独特性 #### 新兴领域 要保持内容的独特性,我们可以去做新兴领域的课程。这个领域可能刚出来一个月到两个月,其他的讲师都还没来得及做,这时候我们的课程就是独特的,想学相关内容的同学就是没有选择的,所以我们也不用参与竞争。 像 Sketch 这个设计软件刚开始在硅谷流行时,国内相关课程是非常少的,全都还是 Adobe 系的课。这个时候去做 Sketch 的课的话,在一年左右就是没有什么竞争的。 #### 交叉领域 类似的,还有交叉领域。热门领域的竞争肯定比较激烈,但两个热门领域中间交叉的部分,做课的人就会非常少,这时候如果我们去做这个交叉领域的话,就会成为学员为数不多的选择,同样也可以避免竞争。 比如说现在有很多的课程有专门教怎么画漫画的,也有很多课程专门教怎么做网络营销的。但我们可以在它们的交叉领域中开发一个课程,教大家怎么做条漫进行营销。所谓条漫,就是微博上那种很长条的漫画。 面向专业人士的漫画课程,它需要很强的专业功底,而做运营的人,通常又不会有很强的手绘基础,但幸运的是,条漫对画面的细节要求不高,所以我们这个营销条漫的课程,就可以着重于普通人如何通过各种工具来制作营销条漫。这个课程就是一个典型的交叉领域课程。 前面两种方式都是通过调整我们对市场的选择来避免竞争,但我们同样要注意到,如果选的市场,它发展得不够大或者不够快,那最终我们就会面对学员不足最后挣不到钱的状况。 我们也要问自己,这个细分领域它没有竞争,到底是因为其他人没有看到没有来得及,还是因为没有充足的需求,原来的玩家都已经挂掉了。 这是要留意的注意事项。 #### 标准品的非标准化 我们从另一个角度来看不竞争的问题。我们知道,像电商平台它的竞争往往是很激烈的,比如买书时,我会在各个平台上比价,然后选价格最合适的平台购买。 这个行为的基础,在于图书它是一个标准化产品,我们在各个平台买到的图书,最终它是完全一样的。所以我们只需要进行价格的比较,就可以得出哪个平台好的结论。 反过来讲,如果我们为了避免课程被拿去比较,被动地参与竞争,我们就应该想办法把自己的课程从标准品变成非标准化产品。 ##### 内容上的非标准化 大家有时候会觉得,技术课程讲起来都差不多,比如我们要讲一种语言的基础课,总逃不掉语法、数据结构、条件分支流程、函数什么之类的。但即使这样,课程对应的实践环节却是完全不同的,我们可以将独创性放到实践里。 比如我们上一章讲独立开发时,用来贯穿全局的例子 —— 福利单词,就是一个非常独特的项目,足以和其他的同类课程区别开来。 ##### 体验上的非标准化 除了在内容上的非标准化,我们也可以在体验上进行非标准化,比如可以引入一些其他的媒体形式。在我们的方糖新全栈课中,就包含了一个网页版的角色扮演游戏,用来教大家网络基础知识。 ![picture 47](images/9fb98edc665299b82992b0a1911cf36a034ffb7dbf3e285091c82885b747813a.png) 这就带来了其它课程完全没有的体验。当然这个例子跨度有点大,更为常用的方式是引入互动式的编程环境,把只能看的视频变成边学边练的。 ### 品牌的溢价 品牌的溢价也是我们不竞争策略的一部分。它背后的逻辑是,因为品牌影响力比较好,所以同样的课程大家就会更信任我们,甚至只信任我们,起作用的实际上是品牌和用户之间的强信任关系。 这种关系主要来自于长时间的价值累积。 比如我的一些微博粉丝,可能关注我有好些年,他们不断通过我的微博获取有用的价值,长期的价值传输让他们和我之间建立了一种强信任关系。在这种信任关系上进行课程销售,转化率是非常高的。 除了免费内容可以建立强信任关系,甚至付费内容也可以建立强信任关系。免费内容的优点是门槛低,不需要付费就可以获取价值;付费内容的优点是,直接提供高性价比的产品,可以让客户体验到付费后的超值感,一旦这种感觉形成习惯,后期的购买就不需要进行比较。 ## 不得不竞争 下面我们来说一下不得不竞争的情况。即使我们在策略层次进行各种操作,但还是会面临到竞争的情况。 ### 理解比较优势 竞争是一个很高大上的词,但在课程购买的时候,就具体化到了我们的课程和其他课程之间的「比较优势」上。 那什么叫「比较优势」呢?课程本身的价值,其实是很难量化的,也很难一眼看出优劣。所以消费者在购买之前,会进行一个短时间的比较。而在这次比较中,如果我们能获取优势,就会赢得这一次销售。 「比较优势」并不等于真正的优势。因为用户在进行课程的比较时,有很大的时间和精力成本。绝大部分消费者,很难花几个小时去进行全面的系统的比较。所以影响他的往往是一些浅层次的、显而易见的优势。 在极端的情况下,我们甚至只在这些浅层次上建立优势,就有可能把平庸的课程卖出很好的销量。当然,课程本身的质量还是最重要的,因为这会影响口碑和二次销售。 比较常见的比较优势有以下几种: 1. 定价 1. 课时数 1. 附赠品 1. 承诺 #### 定价 很多同学可能会认为,定价当然是越低越好,不要钱最好。但事实上,因为现在大量的免费课程要么质量非常差,要么遍布各种广告营销内容和付费陷阱,让很多同学产生了逆反心理,他们宁愿购买一些价格适合的付费课程,这让他们觉得在品质和内容上更有保证。 #### 课时数 课程的内容多少主要看课时数。但网络课程的课时不是按一个小时或者 40 分钟来的,而是很随意的。所以严格地讲,应该看视频的累积时长。但目前大部分课程平台都不提供累计时长统计,这个时长是需要学员在购买之前去手工进行计算。这无疑增加了很大的比较成本,所以大部分的用户还是看课时数了事。 #### 附赠品 附赠品,就是买完课程以后我再给你送一个东西,这样会让这次购买看起来非常划算。适合课程送的附赠品包括: 1. 纸版参考图书 1. 源代码和素材 1. 软件授权 1. 免单和返现 #### 承诺 最后一种比较优势叫做承诺,它的本质上是说,我给你提供一些保证,你就不用再进行比较了。承诺通常包括就业承诺、推荐承诺(推荐实习)、达标承诺(不达标就重学)、退款承诺。 仔细分析竞品,建立比较优势,可以让自己的课程在不得不竞争时仍然具有很强的竞争力。 ================================================ FILE: src/040206.md ================================================ # 收益和成本预判 ![picture 48](images/01b9eb87ced0a30584b39bb19f83df6ddbcea3a712a04dc37786c75afdcb257a.png) 在讲商业模式设计的时候,我们用到了商业模式画布,在商业模式画布的最下边一行有两格分别是,成本结构和收入来源。 这一节我们就更为详细地聊聊,如何在课程之前怎么来预估成本和收益,从而知道我们这个课程它做出来能不能挣到钱,挣到钱的可能性有多大。 ================================================ FILE: src/040207.md ================================================ # 大纲的注意点 这一节我们来讲大纲。大纲大家都会做,所以我们不全面的展开,只挑其中一些需要注意的点和大家交流。 ## 条理性 最重要的一点,就是大纲一定要有条理性。如果在条例性上做得不够好,其他细节做得再好,这个课做出来在逻辑上也是乱的,最后学起来就会很别扭。 具体来说,我们要保证大纲的层次足够清楚,逻辑足够严密。有一个比较常用的结构推荐给大家,尤其适合知识性为课程。 ### 三段式 这个结构分成三段,是一个总、分、总的结构。 #### 总 在课程的最开始,我们会简明扼要地讲明白整个课程包含哪些内容;课程中的一些基础、原理也会放到这里。 #### 分 之后呢,我们就可以按照章节进行展开,对每一个部分进行详细地讲解。 #### 总 在最后我们会进行一个总结,同时放入一个大的实践章节。这样不但可以复习内容,还可以学以致用。当然在每一章结尾也可以安排小实践内容。 绝大部分以知识讲授为主的课程都可以采用这种总分总的结构,非常好用。 ### 提问式 我们也可以用问问题的方式来引出我们的每一部分结构。比如「是什么」——「为什么」——「怎么做」。这种结构可以是全局的,也可以是针对每一部分的。它会让我们的逻辑和层次更清晰。 ## 覆盖面 第二个需要注意的点是覆盖面。因为我们的课程往往是出于自己的实践经验,有时候会局限于我们所在的公司和所在的行业节点,它的覆盖不一定特别的全。所以我们的视角不一定能覆盖到所有的需求方。 有时候我们的课程是为了一类人做的,但另外一类人,实际上也可以学习我们的课程,就差一点点的周边知识。在这种情况下,如果我们可以注意到大纲的覆盖面,把缺少的那点知识补上,就可以扩大受众,让我们的销售变得更为容易。 那具体怎么保证大纲的覆盖面呢? 那首先大纲应该覆盖该领域的主要内容,这些内容通常来源于以下几个地方: 1. 官方文档:官方会处理几乎所有来自社区和其他客户的需求,即使一些边缘的需求,因为囤积的时间比较长,也会慢慢地累积起来,所以一般来讲官方资料的覆盖度是最为全面的 1. 行业的权威文档:虽然不是官方出品的,但因为日积月累它最后可能变成了事实标准,也是我们作为参考的一个主要来源 1. 图书:这也是大参考源,对于经典知识来讲,一些销量比较好的图书,会经过多次的再版,并会加入一些之前没有覆盖的内容。使用微信读书的无限卡,无需购买就可以直接搜索大量计算机图书,对查资料来讲非常好用 1. 同类课程:国外的同类课程往往也是非常好的参考,尤其是面向新技术的课程 然后呢,我们的大纲应该覆盖该领域最频繁出现的问题,那我们到什么地方找问题呢? 1. 搜索关键词 1. 专业问答网站,比如 stackoverflow.com 1. GitHub 的 issue 区 1. 课程平台的答疑区 ## 粒度 除了条例性和覆盖面,那我们最后,而且其实也是非常想强调的一个问题,就是大家一定要注意我们大纲的粒度。 大纲这名字听起来就像一个目录,很具备误导性。很多同学做大纲的时候,通常做两个层次就算是做得细的了。事实上,大纲的粒度越细,课程的品质就越可控,后期制作起来速度就越快。而且我们要拿大纲去做预售来验证需求,它越细,验证的效果就越好。 所以呢,建议大家把大纲至少细化到段落这个级别,同时把段落以下的一些知识点所涉及到的素材和资料,全部都整理到这个节点上去。 这里推荐大家使用 Dynalist 这种无限分级的树状笔记软件来做大纲,会特别方便。 ================================================ FILE: src/040208.md ================================================ # 大纲的细度 ================================================ FILE: src/040209.md ================================================ # 通过预售验证销量 ## 为什么要验证 > 随机抽样了某云课堂上近 500 门付费课程(通过搜索「课」字),其中销售不到 30 的有 24%,销售小于等于 1 的 10% 这是我之前分析某课程平台时的抽样数据,有十分之一的课程销量小于等于一,这个一还很可能是作者;而销售不到 30 套的课程约四分之一。 这些失败的课程背后,每一个都可能有几十几百个小时的制作时间,既然我们把宝贵的副业时间投入其中,就应该尽量避免重蹈覆辙。 ## 如何验证 回到我们这一节课的标题上来,「通过预售验证销量」。两个关键词「预售」,「销量」。 1. 预售,我们用什么来做预售?简单一点可以用「课程介绍」,复杂一些则可以提供「试学章节」,但我们测试下来最合适的是「课程大纲」。它能非常清楚的描述内容范围。 1. 销量,如何来评估?我们需要给自己设定一个达标的销售额,一般设定为比成本略高,预售结束时如果销售不达标,我们就退款,不制作这个课程了。 抓住这两个关键,就可以做好验证。在此基础上,可以扩展出一个完整的流程: 1. 准备课程介绍资料,主要是大纲和试学章节 1. 设定验证的目标,设定预售达标值 1. 开始预售 1. 每天统计销售量,并根据反馈调整介绍 1. 预售达标则进入课程制作 1. 预售不达标则进行退款,并反思价值主张 要支撑这个流程,我们大致有三种方案: 1. 通过众筹/预售平台来完成 1. 自建众筹/预售平台 1. 通过付费群简单解决下 下边我们分别来说: ### 众筹/预售平台 使用现成的众筹/预售平台是最省心的。其实最方便的是微博提供的众筹功能,集传播和销售于一体,很适合在微博有影响力的同学。 ![picture 49](images/2cd075474f662e50368b031e3b849b15684716429c31fd09f7979f3c804eef9b.png) 之前我用的时候还挺好找,现在这个功能藏得有点深,在微博的钱包二级菜单里。当然,其他的平台也是可以的。大体来讲,这类平台的问题在于操作相对麻烦,对个人的话,除了收取服务费,往往还会代扣 20% 左右的税。 另一方面,课程还不是实物商品,众筹完了可以直接寄送;我们众筹完以后,可能还要提供在线观看课程的功能。如果放到其他平台,还有一个账号统一的问题要解决。 ### 自建众筹/预售平台 对于我们程序员来讲,自建众筹/预售平台是很容易的事情。找不到满意的平台,当然是自己动手丰衣足食。功能开发上很简单,但这里有一个非技术因素,那就是支付接口往往需要公司资质来申请,个人很难申请下来。所以还没有搞定支付的同学们在动手前要留意,不要花几周写完系统要上线时才想起来。 ### 付费群 付费群就不需要任何的开发,交易完全走一对一支付,只要自己在年终走个税申报就行。它的缺点在于维护成本有点高,需要手工跟进整个众筹的流程;群功能也相对有限,甚至出现过仿冒老师的账号进行收款的事情。 这里也分享一个微信批量退款的小技巧:将要退款的同学拉到一个微信群中,然后发一个人数乘以金额的普通红包就可以了。注意是**普通**红包,不是**拼手气**红包。 综合以上,我们的建议是,早期通过付费群或者一对一付费就可以了。等到付费用户多了以后,再专门开发一个系统来做预售/众筹。 我们也做了一个众筹+课程托管的一体化平台自用,等成熟以后会考虑开放出来,感兴趣的同学可以关注下我的微博。 ================================================ FILE: src/040210.md ================================================ # 常见的课程片段类型 这一节开始我们来讲课程的制作。 我们将常见的课程分成四种片段: 1. 文稿讲义类:这是我们最熟悉的PPT+语音的形式 1. 屏幕录制类:在实战和演示时用得最多的形式 1. 真人出镜类:技术类课程用得较少,一般在右下角放一个小窗显示真人 1. 虚拟形象类:不想真人出镜时,可以用虚拟形象来代替 几乎所有的课程都是由以上四类课程片段组合而成,所以一旦学会了每种片段的制作,也就学会了几乎所有课程的制作。 ================================================ FILE: src/040211.md ================================================ # 文稿讲义类课程片段的制作 这里的文稿讲义,主要指使用幻灯片软件来进行播放的资料。如果是使用PDF这类材料,其实是属于「屏幕录制」类,我们会在下一节里详细讲解。 对于文稿讲义类课程片段,我们的画面、图文内容都已经做到了幻灯片里面,要录制的主要是声音。但我们有三种截然不同的方式来录制声音: 1. 第一种是最通用的,通过全局录屏来完成。不管是使用什么软件,只要在电脑里,都会被录下来。 1. 第二种是使用幻灯片软件自带的「演讲录制」功能来完成。 1. 第三种是最不为人知的,通过幻灯片软件的「导出为视频」来完成,这种方式有一个非常大的优点,可以极大地降低修改成本,在后文中会详细说明 下边我们分别说明。 ## 全局录屏 下一节会详细讲,这里就略过了。 ## 使用幻灯片软件自带的「演讲录制」功能 ![picture 50](images/c48467622504fd20139b9facb5c82bfeb47b520981cd8944945e3031eac8e3ea.png) 目前用得最多的幻灯片软件,分别是苹果公司的 Keynote 和微软的 PowerPoint。下边我们就以它们为例进行讲解。 首先,我们需要使用幻灯片软件将内容制作完成。课程完成度越高,修改起来成本就越高,所以要仔细检查有无错别字或其他疏漏,然后再进入音频录制阶段。 ### 如何使用 Keynote 的「录制幻灯片放映」功能生成视频课程 我们先来看在 Keynote 中如何录制。 在 Keynote 菜单「播放」里选择「录制幻灯片放映」 ![picture 52](images/4337caaa4668cfccc22d78f53e4c33aac4a153f59b19f2ec4784361c9f5e3a97.png) 然后我们就会进入一个深色背景的幻灯片录制的环境,在这个界面的最下方有一个红色的录制按钮。 ![picture 53](images/e3dbf39810582264b549713559ad74fbd61ca381ba4aafd8d184af01eb8846b9.png) 点击它就可以开始进行录音,可以随时暂停和停止。需要注意的是,这里录制的音频不是仅仅当前这页幻灯片的,而是整个幻灯片的。你可以来回切换幻灯片来录制音频,如果界面看到的有些不一样,可以通过调整预览界面的配置来修改。 当我们在录制环境中完成了整个课程的音频录制后,就可以回到主界面。从菜单中选择「文件」→「导出为」→「影片」。 ![picture 54](images/1ab07e080b3cca082ec91222ee89e257f7c0ed8659c93b1a1fb346a29059873e.png) 这样,Keynote 就会为刚才的录制生成视频。有一个需要特别注意的地方,就是导出窗口中,「播放」选项要选择为「幻灯片放映录制」。 ![picture 55](images/a981d56cac16f4c869c7a7e5a52c277a4a477140cdffff913f59e7ab51cf3f0d.png) 如果觉得导出的视频文件过大,可以使用[HandBrake](https://handbrake.fr/)来进行压缩。这是一款开源的视频压缩软件,默认的预置(比如 fast1080p )就很好用。 ![picture 56](images/45959232a5e2e9924bfcdf3f81d14c09ab15db29f72bc4e1ed0216271189e2ef.png) ### 如何使用 PowerPoint的「录制幻灯片演示」功能生成视频课程 下边我们来看 PowerPoint 中如何操作,其实很类似,只是菜单名称和个别细节不同。选择菜单「幻灯片放映」→「录制幻灯片演示」。 ![picture 57](images/6f07bd8227d02e9bda09e1bdd9c9a571a3cf9e1d3e737f92c1d35ce932b83042.png) 同样会进入一个暗色的录制界面。 ![picture 58](images/97d77635cb7d5df941eaa17ec58c146795d434c41adfc5062dca1a8695ad2254.png) 在左上角有一个时间正在走,在旁边有控制按钮,可以暂停。默认已经开始录制了,我们可以选择幻灯片进行讲解。全部讲解完成后,一样是导出视频。 ![picture 59](images/1191cf4a01b99611b66ed3c27c165b693fecb76bc0ca25ad9cae1499b572e22c.png) 在顶部菜单中选择「文件」→「导出」。 ![picture 60](images/cec3b12624048239067638dd44e72821651650923d900e37c6daf04b1a5827e7.png) 也有一个需要特别注意的地方,就是在导出窗口中要选中「使用录制时的计时和旁白」。 ## 幻灯片导出为视频 单从录制来讲,前一种方法就非常方便了,可以说是一气呵成。但如果录制完成后我们发现有几句话讲错了需要修改,那么就相当麻烦了。究其原因,主要在于虽然幻灯片是一页一页的,但音频却是整体录制的,所以音频出问题就只能重录。 那么我们能不能让音频也变成一段一段的,对应到每一页呢?这样我们以后再修改的时候,只需要重新录制那一页的音频。 ![picture 62](images/599b66d00f2ed6d594481f4709efdb806a286f5b3044451f085d305838fec595.png) 这就是我们第三种方案的思路。Keynote 和 PowerPoint 虽然没有提供分页录制的功能,但它们都能往幻灯片上添加音频,并将其合并到视频中统一输出。 所以我们要做的,就是在每一页幻灯片上,添加上语音讲解的音频。比较方便的地方是,这两个软件都支持直接录制语音讲解,而且一页幻灯片上可以录制多段,还能手工调整顺序。 下边我们来看具体如何操作。 ### 如何使用 Keynote 以「导出为视频」的方式生成视频课程 还是先来看 Keynote。第一步依然是制作好图文部分的内容,最好把要讲的文稿放到演讲者注释区域,这样录制的时候可以参考。 然后先选中要添加语音讲解的幻灯片,从菜单中选择「插入」→「录制音频」。 ![picture 63](images/a7a43110944657403e8d3b11d6be36697b61c99332d81b73de6ae0c49831c47e.png) 在弹出的小窗口中点击录音按钮就可以开始录音。 ![picture 64](images/a7a98dfa95345bbc1f26610f6bd7e3086a277651602c150e125e44c4f7c5f787.png) 录制完成可以试听,没问题后再插入到当前幻灯片。当一张幻灯片有多个音频时,可以选择右上角的「动画效果」菜单,再点击右下角的「构建顺序」就可以看到当前幻灯片中的音频列表了。被选中的时候,会有蓝色描边,通过拖拽可以很方便地调整顺序。 ![picture 65](images/b8c313f44cba666a1847fbd0c8824477450db40778a8469471aeb64a14525042.png) 导出和之前类似,还是通过「文件」→「导出为」→「影片」。 ![picture 66](images/07baab737938ac8bbd26763259987386c739c9ba24c0accd9f5c1ebd587d35de.png) 但需要注意的是,这次在导出窗口中,播放选项要选为「自动播放」。 ![picture 67](images/7bda56add02c02a8526ca07abdb920c4c529283ebe6407b45525d0bcae280a66.png) 同时,我们还要把下边两个等待时间设置为「0」秒钟。 ![picture 68](images/7c3bb0b3a981fbce8b2c90b499f54a91c83204a56800178a6b8db14998a1a62d.png) ### 如何使用 PowerPoint 以「导出为视频」的方式生成视频课程 再来看看 PowerPoint 里边的做法。给幻灯片添加语音讲义也在菜单「插入」→「音频」中。 ![picture 69](images/c0e9d9fb1f06855e29edd36169751807fd0a8b7603f3f5e6bbb7aa56e28f5520.png) 选择「录制音频」可以直接录制。 ![picture 70](images/b78f1919a9e4b1c5b454012ba3346219492b276c0d3be9de75e7c9add17c563f.png) 下边我们看看怎么调整多个音频的顺序。点击「动画」菜单,在右边会出现一个「动画窗格」,再点击它,在最右边就可以看到当前幻灯片上所有的音频的列表。 音频前边还有编号,可以一一对应到幻灯片上的音频。通过调节它们的上下顺序就可以手动的指定最终的音频播放顺序。 细心的同学可能会留意到这些音频都会被放到一个叫做动画的菜单里面,其实这个菜单的功能是指定动画播放的顺序,音频被当做动画的一种,所以也在里边了。通过同样的方式还可以控制插入的视频的播放顺序。 ![picture 71](images/72f5504455129efec0cab7ec832cf5c62aad5ec2062f1db56bdf920611a8ef68.png) 最后依然是通过「文件」→「导出」来生成视频,但是记得去掉「使用录制的计时和旁白」前的小勾,同时把「没有设置时间的每张幻灯片所用的秒数」设置为「0」。 ![picture 72](images/3afe2c5e9b362d4b072d0cfa530d38710724f8b1947c6968a08a0a1971f3cef7.png) ================================================ FILE: src/040212.md ================================================ # 屏幕录制类课程片段的制作 ## 屏幕录制的原理 屏幕录制软件的原理,是不停地截取屏幕画面,然后和音频合成为最终视频。屏幕录制的优点是可以把电脑屏幕上显示的所有东西都录下来,不管你在哪个应用里边,不受应用本身功能的限制。所以可以非常直观地向学员展示完整的操作。 ## 屏幕录制的软件 在试用了很多屏幕录制软件以后,我们选择了 OBS 。它的优点主要有: 1. 功能强大 1. 开源免费 1. 跨平台 ### 功能强大 OBS 不但可以录制屏幕,还有一个非常强大的功能就是直播。现在很多视频网站的直播都支持用 OBS 来进行推流。所以学会了它,不但可以录制屏幕,而且可以进行直播,一箭双雕、非常划算。 然后,OBS 可以非常容易地进行屏幕之间的叠加,比如画中画模式,这就非常适合我们马上要讲到的「真人出镜」和「虚拟形象」类型的课程片段。 同时呢,OBS 还支持通过快捷键在各个场景之间来回切换,在录制课程的时候可以非常方便的进行转场,这个功能不少收费软件都没有。 ### 开源免费 和那些昂贵的收费软件不同,OBS 是开源而且免费的,这意味着使用它没有任何版权风险。我们在制作付费课程的时候,需要特别留意版权方面的问题。因为平时以个人身份在免费文章和视频中用一些字体、图片是没问题的;但在收费的商业课程中,就可能面临被起诉索赔的风险。 ### 跨平台 再来说一下,为什么跨平台的特性非常重要。在课程中,尤其是编程类课程中,我们经常会遇到需要讲解某个工具软件在各个操作系统上的安装和使用的情况,这时候就需要在多个平台上录屏。 如果使用一个特有平台上的录屏软件,在录制其他平台上的课程内容时,就不能使用了。只能重新购买和学习一个新的录屏软件。这不但浪费钱,更浪费时间和精力。 而使用 OBS 就没有这种困扰,它不但支持 Windows 和 Mac 系统,连主流 Linux 系统都是支持的。 所以,在我们后续课程中,将以 OBS 为例进行讲解。 ## OBS 的层次逻辑 OBS 的功能非常强大,还有包含了直播相关的功能,所以需要理解它特有的一些概念后,用起来才会更加顺手。 像一般的屏幕录制软件,只需要启动后点击录制按钮,进行录制就完了。但 OBS 中,它有自己的层次逻辑。 ![picture 73](images/fe7d68123882cd29c483d63148609c52c3e2819f350c0ff110e4c8cc0c32647f.png) ### 场景 OBS 的第一个层次叫做「场景」,你可以把它理解为一种预设。 为什么需要场景?比如我们一个讲师,他每天上午要进行直播,这个时候视频的来源是摄像头和电脑屏幕;然后他每天下午要录制课程,这时视频的来源就只需要电脑屏幕,但他有两块屏幕,他希望都录进去。 如果没有场景这个概念,那我们每天上午到下午的时候,就需要不停的修改配置,非常麻烦。而有了场景以后,我们只需要把上午和下午定义成两个场景,使用的时候切换下就OK了。 你可能会想为什么要叫「场景」而不是直接叫「预设」呢?因为 OBS 中场景比预设更为常用和强大,它是可以实时切换的。 也就是说,如果我们有三个显示器ABC,可以在场景一里显示A;在场景二中显示BC;然后根据需求通过键盘快捷键来切换,甚至还能给它添加转场特效。 ### 来源 ![picture 74](images/c3487826ec95078a4402aa2385f0c298a0592022125125ff74d13800b61c1912.png) 在定义好「场景」以后,就可以往里面添加「来源」。最常用的来源其实就两类,也就是视频和音频。视频最主要的是显示器,也就是电脑屏幕,偶尔还有摄像头。音频的话主要就是麦克风。 ![picture 75](images/b48a709dcb64709426028df2286538024e9d87ade24217508db8dda346f79c4a.png) 来看一下 OBS 的来源菜单。 首先它提供了「图像」和「图像幻灯片放映」,如果我们想在视频上面显示一张固定的图片或者图片轮播可以用它。 比较有意思的是,我们还可以把一个场景指定为来源,这样就可以非常容易地实现场景嵌套。也可以把媒体作为一个来源,这样就会在画面上面播放另外一个视频。 文本来源这里可以输入一些文字,指定它的颜色、字号和字体,然后它就会显示到屏幕上方。可用来显示我们机构的品牌名称之类的。可以看到,一些本来是后期才进行处理的功能,在 OBS 里都可以通过来源来实现。 显示器采集也就是我们的屏幕;视频采集设备通常就是指摄像头;音频输入采集这里通常就是耳机、麦克风或者外接的USB声卡之类。 这里还有一个音频输出采集,可以用来做多层次的音频加工。比如说我们电脑上有一个软件,就像柯南的蝴蝶结一样,可以对输入的声音进行变声,那我们就可以把这个软件的输出作为来源接入到 OBS 里边,录制下来的声音就是变声后的效果。 ### 来源的层次 在多个来源之间,其实是有上下层级的概念的。打开 OBS 的来源小窗口,我们可以看见当前已经添加的所有来源。 来源是从上至下进行覆盖的。也就是说来源窗口的最上边一层,在最终视频中也会显示到最上面,上一层的内容会压住下边各层的内容。 ![picture 77](images/884e244f190702f1689ea4861962d1b910169673f70f4b17a663a57c26c8273d.png) 这个对于我们制作真人出镜类型的课程片段很重要,因为它通常是通过摄像头和显示器两个来源叠加得到的。摄像头的画面小、通常显示在右下角;显示器的画面大,往往覆盖整个视频画面。在来源窗口里,摄像头需要在显示器上层才看得见,不然会被显示器画面完全挡住。 ### 滤镜 ![picture 78](images/9a0f431f3b458776b65e37def67af4ad744972b41c994217c04b5146e82cc9bd.png) 如果通过来源采集的信息不是百分之百符合我们的需求,还可以通过滤镜来进行进一步加工。OBS带有两类滤镜,一类叫做「音视频滤镜」,可以对音视频进行处理,比如进行噪音的抑制或者把音量放大;另一类叫「效果滤镜」,包括各种各样的特效,比如「色度键」可以用来抠背景。 ================================================ FILE: src/040213.md ================================================ # 真人出镜类课程片段的制作 虽然前面其实已经陆续讲到了真人出镜类课程片段的基本原理,这里还是再明确下。 ## 什么是真人出镜类课程片段 「真人出镜」类的**视频**非常简单,只需要使用摄像头、手机或者摄影机直接录制就好了。而「真人出镜」类的**课程**反而要复杂一些。这是因为在课程中,讲师其实并不是主体,课程内容才是。所以我们往往会采用「画中画」的模式,将讲师的头像部分做成一个小方块放到画面中。 ![picture 79](images/2bb65857cb1e94b73eb35672ec1582159d2de7282f363c3dd1cd2a0da988e8af.png) 但这有一个小问题,就是这个方块会带背景。如果它的背景和作为主体的课程不搭,看起来就会比较别扭。要是能把背景变成透明的,它就能更好地融入到课程中。 ## 抠图 那么,怎么才能让背景变成透明的呢?答案是「抠图」。对于计算机来讲,将数字内容的一部分变成透明是非常简单的,真正的麻烦在于它不知道哪一些像素是背景、哪一些像素是讲师,所以我们需要一个方式来告诉计算机。 现在最常用的,也是最简单有效的一个办法,叫做「绿幕抠图」。就是在讲师身后放上绿色的背景布,再告诉计算机,绿色的部分都是背景,把它抠掉。这样就实现了背景的透明。 有同学可能会问说,为什么非要绿色,其他的颜色行不行?答案是可以的,但如果把背景设置成黑色,很多人的眼睛和头发都是黑色的,这些部分也会被透明,看起来会很灵异。 而绿色在日常生活中出现的频次比较低,所以一般默认用绿色来作为背景。但如果有天你穿了个绿色的衣裳,那就可以考虑换用蓝色的背景了。 ![picture 80](images/2c9537c8c7cbafd1b84d368347f5692b46ccec11fc30b8fb0bd3ac0057baec7f.png) 这一部分的具体操作是这样: 1. 在场景中添加一个「显示器采集」来源,选为我们想要录制的电脑屏幕,放到来源窗口最底层。 1. 在场景中再添加一个「视频采集设备」来源,选为摄像头,将其放置到屏幕右下方,在来源窗口中位于显示器之上。 1. 在摄像头来源的右键菜单中,选择「滤镜」,在「效果滤镜」中添加一个「色度键」滤镜,背景为默认的绿色。 1. 调整「相似度」和「平滑」的值,让背景消失得更为柔和。 ![picture 82](images/bbab1448b7d37b1e046150b3367a147328f9815255b23b4c6f99f8fd1021cad9.png) ![picture 83](images/dcad14fe668d4a01fb1ebf5fded6e8ba4a2dc2781fe621685ab9ef80e67dca63.png) 关掉滤镜窗口,这时候在 OBS 的预览界面上我们看到的摄像头画面背景就应该已经透明了。 ![picture 84](images/cbba508e0a684925ae8b47ba8c8f42908ce619c070fc957a9a63f15fdb7144c2.png) ## 真人出镜的其他细节 如果你是使用笔记本电脑,通常自带一个摄像头;如果是台式机,就需要自己装一个。摄像头需要对着讲师的脸,因为摄像头看到的,就是学员最后在课程里面看到的角度。 然后我们在讲师背后竖一个比较大的绿幕,充满整个摄像头的背景区域。一般两米宽高就够了,不够的话可以调整摄像头。 绿幕可以在电商网站输入「绿幕布」关键词搜索购买。有一些专业的幕布会比较贵,但我们早期可以买便宜的幕布来试水,一般几十块钱就能搞定。 为了让讲师和背景之间分离得更清晰一些,可以再通过光源进行补光。这里我们用手办做了个示意图给大家。这个灯的色温不能调,所以看起来稍微有点偏黄。实际录制的时候,可以用白色的灯来补光。 ![picture 81](images/fdaee0fcd650f2adfb41a10cac727a88f4292d03e893c6aa27d929de119786db.png) ================================================ FILE: src/040214.md ================================================ # 虚拟形象类课程片段的制作 ## 虚拟形象的原理 最后,我们再来看一下虚拟形象类课程片段的制作。虚拟形象实际上跟真人出镜差不多,但因为可以用卡通的形象来代表真人,所以形式上看起来会更加有意思,更适合年轻的同学。 在上一节里面,摄像头里拍到的是真实的画面,现在我们要想将真实的变成虚拟的,就要使用虚拟摄像头。 所谓的虚拟摄像头,就是其实并不存在这么一个物理上的摄像头,这个摄像头是用软件来模拟的。但是其他软件并不知道,它们会以为这个摄像头是真实的,于是它们之间就可以无缝地进行整合。 ## FaceRig 我们使用的是 FaceRig 这个虚拟摄像头软件,它提供了很多的3D模型,还支持导入 Live2D 这个游戏和动画用得较多的模型格式。如果是通过 Steam 购买的 FaceRig,那么在创意工坊里边可以看到全球玩家上传的各种模型,喜欢的可以直接订阅,它就会出现在我们的 FaceRig 里边。 当然,我们也可以制作自己的卡通形象,生成模型并导入。顺便说一下,对于多人参与的课程来讲,虚拟IP是非常有用的。如果我们将大量的精力和推广资源放到真人讲师的IP上面,万一这个讲师离开团队,之前的投入就废掉了,甚至会变成竞争对手的资源。但是如果我们采用虚拟IP,就完全没有这个问题。 ### 步骤 为了模拟摄像头,FaceRig 构造了一个 3D 空间。这个空间由「模型」和「背景」两部分组成。选好模型、配好背景,打开跟踪器让模型和我们的表情同步,就实现了用虚拟形象代替真人形象。 下边我们更为详细地讲述下步骤: 1. 购买和安装 1. 选择模型 1. 选择背景 1. 打开追踪器 1. 打开广播 #### 购买和安装 最方便的方式是在 [Steam](https://store.steampowered.com/app/274920/FaceRig/) 这个平台上进行购买,它会帮你自动安装各种依赖,确保能运行起来。如果想用 Live2D 的模型,还需要购买对应的插件。 ![picture 85](images/4c6974dfaf5bb709a66fd2da14c9b282ff89f82eaaa5dc166718ee6735fbad40.png) #### 选择模型 启动完成以后,点击顶部菜单最右边的UI按钮就可以切换右侧的面板;这个面板的第一格就是我们的模型。 点开以后可以选择喜欢的模型。 ![picture 86](images/1262fc4f766b7980120bc566aecc7b781c6a0a360bd56c11edd504f3c8eeb0ce.png) #### 选择背景 还是在右侧的面板,第二个图标就是。点开它可以看见预置的各种背景。如果想要最终背景透明,可以选择绿色背景方便下一步抠图。 ![picture 87](images/175e5c4dbcea21848f21d90f3598a0d814e9c0b1bfa89a255e757b212a55853e.png) #### 打开追踪器 现在虽然模型都有了,但它跟我们真人说话的表情语气没有关联起来,所以要打开追踪器。点击顶部导航,「切换追踪」按钮(图上画红圈的),摄像头就会通过人脸识别来捕捉我们的表情。这个时候我们摇脑袋和做出各种表情的话,就会同步到模型上。 ![picture 88](images/28a682f2c3fe4ef092341e5d37bc8394f5233a2ade1a04846bc371694ef53621.png) #### 打开广播 这些都做完了以后,一定要记得还有最后一步就是要**打开广播**。所谓广播就是 FaceRig 把画面虚拟成一个摄像头,并同步到整个系统里,其他的软件就会把它当做一个真实的摄像头。 ![picture 89](images/1e0d102e4f9bd47a16bdd26d57754ab22734369759234e58c736e5ced6688be9.png) 打开广播也非常简单,就是点击顶部的这个像电台一样的按钮。点击打开,再点一下关闭。 当广播打开后,在 OBS 里去添加一个新的视频捕捉设备的时候,就会发现有一个名字包含 FaceRig 的摄像头,把它作为来源,就可以引入和真人表情同步的虚拟形象了。 ![picture 90](images/daa3fd1ef8deed10a18db19b3fd8c5eff385b6d02a6ca437c3d7d8a6e41c7915.png) ================================================ FILE: src/040215.md ================================================ # 最常用的视频剪辑操作 视频剪辑是我们做课时用得非常多的技巧。剪辑是一门细节很多的技术,幸运的是,做课所需的只是非常基础的一些功能,所以我们才有可能花很少的时间学会。这也是我们这一节的内容。 ## 剪辑软件 视频剪辑的软件非常多,但整体功能上大同小异。经过一系列的试用,我个人用得最多的是这两个软件: 1. 苹果公司出品的 iMovie 1. Adobe 公司出品的 Premiere(一般简称PR) iMovie 是 Mac 专有的免费软件,完全可以胜任大部分的常规剪辑工作。后来苹果公司还开发了 iOS 版本,这样我们在 iPhone 和 iPad 上也能使用它。 如果我们只是想简单地调整下视频片段的顺序、删除某个片段、或者对某部分进行速度调整的话,iMovie 是个不错的选择。 PR 则是系统复杂、功能强大的专业剪辑软件,很多专业人士都在使用它。PR 是一个付费软件,但同时支持 Mac 和 Windows。 我们后续以 PR 为例进行讲解,在其他的剪辑软件里相关的操作也是非常类似的,往往只是菜单位置不同,大家可以自行摸索。 ## 视频片段的调整 视频片段的调整是最常遇到的需求。因为我们在录课的时候很可能其中有一段讲错了,会想把它去掉,再把后边的内容给接上去;或者讲课时有一部分内容讲丢了,在后边补讲的,想把它给挪到前面去。这些情况时常发生。 比如说我们现在有一段视频,希望删除其中红色的部分,应该怎么操作呢? ![picture 3](images/54868234aa276cbd83cf38593d3594c5f81c731e624874d142f211a9b7b484b5.png) 直观来讲,应该是选中一个片段然后按删除键。有一些编辑软件就是这样做的。但在 PR 中,这个操作通常被分两步:先分段、再删除。 ![picture 2](images/4bec1f048287d2357c924f1bfdfc5e7efcae06a7df22c731cf577b706e27d98a.png) 所以我们会先用剃刀工具将视频给切割成三段,切割的位置正好在红色部分的开始和结束,这样它就会变成一个独立的片段。 然后切换到选择工具,选择这个片段,再按删除键,片段就会被删除。 ![picture 4](images/60dd1974df913a05ad4a6008a7e2ee55e9abec63c5e13e636d2b2b43f2e3b263.png) 但我们会发现,视频中间空出来了一段空白。 ![picture 1](images/ad55711f24395cf46f5c4f15a4b6af6d3073533b82dd7d816c1ca0568052f1e6.png) 这是因为在 PR 里边,连续视频并不是一种常态,所以它没有自动去掉两个视频片段之间的空白。可以在这段空白上点右键,选择「波纹删除」,这样后边的视频就会自动补上来了。 ![picture 5](images/17c5b1e1a42aafd7ee79527b5cbb9a25c1f3fbab9236b1ed74add83012292b65.png) 当然,在删除视频的时候,如果不是直接按删除键,而是点击右键,选择「波纹删除」会更加方便一些。 ## 柔软的视频片段 这里有一个需要特别注意的概念。在我最初的想象中,视频片段应该是很「硬」的,当两个视频片段有重合时,后一个片段会自动后移并紧跟前一个视频对齐。但在 PR 中,视频片段是很「软」的,当两个片段重合的时候,重叠部分会被覆盖掉,再也分不开了。可以把它们想象成两个透明胶带,一旦粘上,就很难无损分开了。 ![picture 6](images/9577d988849747719afd334235d92f0496db625bc4ab22592122df6ada5fb7e0.png) 所以,对于不熟悉 PR 的新手来讲,想要两个片段紧密连接,最简单的方式还是分开放,然后「波纹删除」中间的空白来自动对齐。 ## 视频片段顺序的调整 正因为这些片段很「软」,当我们在进行顺序调整时,也要倍加小心。这里我们可以利用 PR 的多轨道。我们可以暂时把要移动的片段放到另一个轨道上,然后调整原来轨道上片段的顺序,挪出一个新的位置,再从外轨上把片段给挪回来。 ![picture 7](images/0f2a76e6e641d7fb2b6e95cedcde95d31c8aa9c37740cf24fbf2802b53dd7e3a.png) ## 视频片段速度的调整 速度调整在做课时也很常见,比如说我们通过网络安装软件的时候可能就很慢,得操作二三十分钟,但我们不可能让学员一直等二三十分钟。一个方式是直接减掉这个过程,但如果其中又包含了一些操作细节,我们可能就需要把这一段视频加速。 ![picture 8](images/a01fc217756195509b48c5778a3fa1df18912f6e5b75d46569f90919d915e817.png) 在需要调整速度的视频片段上边点击右键,选择「速度/持续时间」选项,会弹出设定窗口。 窗口上默认的速度是100,如果想加速,就改为大于100;想减速,就小于100。 有一个需要注意的问题,就是如果减速,视频片段会变长。如果前后有其他片段,就可能造成覆盖,所以这种情况下,最好放到另一个轨道上再调整速度。 另外,在加速的时候,原来的声音会变调,如果想要保持正常,记得选中「保持音频音调」。 ## 视频中的音频处理 这个操作也是很常见的,比如讲课中有几句讲错了,但是不方便删除视频,可以只删除这一部分的音频。 但是,默认情况下,音频和视频是绑定的。所以我们需要将要处理音频的部分切割成独立的片段,然后在右键菜单→「音频增益」中把它的音量调到听不到(比如-100dB)。 ![picture 9](images/41367bb938d065bdf82dba9e99a70c5edef1cf5dd0007ea6ce1eb51892d08e3a.png) 当然我们也可以通过选中片段后点右键菜单,选择「取消连接」来解除音频和视频的绑定。这样就可以随意编辑音频了。 除了像视频一样分段、调整顺序等,我们可能还需要对音频进行去噪、调音等更进一步的操作,这时候我们可以在对应的片段上点击右键,选择「在 Adobe Audition 中编辑剪辑」在另一个软件中来处理。具体的操作我们将放到下一节讲解。 ![picture 10](images/a4b18e138abe7cff903e023c74e0c34f9ea619e84b30b2e5f0fece9a8e3dafa3.png) ================================================ FILE: src/040216.md ================================================ # 最常用的音频处理操作 音频的后期处理和视频类似,也是非常专业的领域,所以我们这里也只讲最简单的处理。在我们做课时,经常会用到的技巧主要包括: 1. 去噪 1. 标准化 1. 混响 1. 去齿音和嘶声 下边我们依次来看看。 ## 去噪 「去噪」就是「去除噪音」。一般分为两个步骤: 1. 定义噪音 2. 去除噪音 为什么会有「定义噪音」这个步骤呢?因为对于计算机来讲,它并不知道哪一部分声音叫做噪音。 比如我们在录一首歌的时候,邻居家的猫在旁边叫,这个声音就算是噪音。但如果是想录一个宠物视频,猫在里面就不是噪音,它可能是主角。所以是否是噪音,是需要根据场景来进行定义的,计算机理解不了这点。 当然,这个例子比较特殊。通常来讲,要去掉的噪音叫做「底噪」。就是声音很小的背景噪音,比如电流声,远处汽车和行人的声音。这种时候,只需要选取一段只有这些背景音的音频,将其定义为噪音,那么软件就可以把和它类似的声音去掉。 音频处理也有很多软件能做,但因为我们视频剪辑用 PR,所以音频用 Audition(简称 AU )来做会更为方便。它在我们修改音频后,会自动更新 PR 里边的片段。 下边我们来看 AU 中具体怎么操作。首先选中一段只有背景噪音的音频,在顶部菜单中选择「效果」→「降噪/恢复」→「捕捉噪音样本」,就可以把它定义为噪音。 ![picture 11](images/cdbc5bd3b5132ebf7b3b24824d8c8d6d18594abc11f40f670702c3d0a1be5b32.png) 然后,在顶部菜单中选择「效果」→「降噪/恢复」→「降噪(处理)」,开始去噪。 ![picture 12](images/32c5db56439144f7f19e2929e863b8567bf0f9bec90ac5833dc727dd8b4a8c9c.png) 记得在弹出的窗口中点击「选择完整文件」,再点「应用」就会开始处理。 ![picture 13](images/743310601124a9987e6b23d73406ca68508a8b51db5de72508fcb78b624fd893.png) ## 标准化 标准化也是一个很有用的功能。我们录音的时候,尤其是换了场地和设备录音的时候,可能声音的范围(最高音和最低音)就不一致。这种时候,就需要通过「标准化」来将这个范围统一,这样听起来音量差异才不至于太大。 ![picture 14](images/54f674e11476375e1e10b0ede4e1d9f65701401b07b132911354c895861732cc.png) 在 AU 中的具体操作如下: 在顶部菜单中选择「效果」→ 「振幅与压限」→「标准化(处理)」。 ![picture 15](images/3246f43e9c9a9ea234abc9565857772bdabc05601b2e43a7f8335ad835222ffa.png) 然后在弹出的窗口中,可以将其标准化到 0 dB (如果觉得音量过大,也可以试试 -6 dB)。 ![picture 16](images/33a84af2f840cacf13e0a0eb15924a3ed7545a907928ffd6b198d78cb8fda6db.png) ## 混响 我不知道大家有没有这种感受,就是有时候听一些电脑生成的音频时,会觉得声音非常纯粹,很好听,但听起来不像是真的。而一些现场录制的音频,音质可能没那么好,但听起来却会有种非常强的空间感。 这是因为我们日常在说话的时候,声音会分成两个层次到达我们的耳朵。 ![picture 17](images/deac52fc3fe891da4f9ba34bf479ff1b0258123f560869cbce13118c6e13f905.png) 一个层次是直接从发声处传到了耳朵里,另一个层次是声波打到周围的环境上,比如墙面、地面、桌椅上,被反射后,有一些很弱的声音以稍微延迟一点的时间进入我们的耳朵。我们日常听到的多是这种叠加后的声音。 在电脑中生成的音频如果不特意处理,是没有这种叠加的。这就让声音有点「平」或者「干」。为了增强声音的空间感,很多编辑软件提供了叫做「混响」的功能。其原理就是模拟现实中的声音叠加,将一部分声音强制延迟后混音,这样的声音更有立体感。 下边我们看看在 AU 中怎么具体操作。 在顶部菜单中选择「效果」→ 「混响」→「混响」。 ![picture 18](images/014bee8ed73fda6b532f9efef30d1491c9f2ad590357dcb861492cc4ab42d26e.png) 在弹出窗口中,可以调节各项参数。点击播放按钮可以试听。 ![picture 19](images/bbaa6090bc7eb3c92a64c8b286af6ef1d77a6d9ed698331163eac12ac9987dd1.png) 选择好以后,点「应用」进行处理。 ## 齿音和嘶声 齿音是指我们说话时,呼入呼出的气流和嘴唇、牙齿之间摩擦产生的声音;嘶声则有些类似于广播电台中常听见的嘶嘶嘶的声音。这些声音混在音频中,可能听起来不那么舒服,所以 AU 也提供了工具来清除它们。这部分的操作很简单,这里就不详细说明了,这两个功能的菜单分别在: - 齿音:「效果」→「振幅与压限」→「消除齿音」 - 嘶声:「效果」→「降噪/恢复」→「降低嘶声」 ## 建议顺序 其实顺序并不是强制的,怎么都行。但考虑到标准化时有可能把底噪放大,所以我一般会按下图的顺序来进行各项音频处理操作。 ![picture 20](images/f444510b53f0c79dfc4cec4faf35b3ffce640864168a25d793889138ec6543a0.png) 整个过程中,去噪和标准化才是最重要的,其他的三项时间紧张时可以偷懒不做。 ================================================ FILE: src/040217.md ================================================ # 字幕的制作和自动生成 对于技术类课程来讲,字幕是非常有用的。一些技术名词光是读出来,有时候很难明白它是什么意思。而如果有字幕,就可以一目了然了。 ## 字幕及其格式 所谓字幕呢,是指我们在播放视频的时候,显示在屏幕下方的、和语音同步的文字。为了让计算机正确地显示出字幕,我们需要告诉它两个信息: 1. 这个字幕的文本是什么 2. 这个文本应该在什么时间开始显示,在什么时间结束 也就是说,最基本的字幕信息应该包含「文字本身」以及「文字显示的时间段」。 当我们把多条字幕的信息合并放到一起,就有了字幕文件。字幕文件可以是单独的文件,在播放视频时载入并显示,这种方式称为「外挂」;也可以在压制视频时直接压制到视频里,这样即使播放器不支持字幕功能,也可以正常显示。 字幕的格式有很多种,srt 格式是最简单的格式之一。 ![picture 21](images/62dc524776dc00af636cbaaf05bec313b51916178d77e02e0e116fd929e2a93f.png) 它由多段文本组成,每段文本分为三行: 1. 第一行是序号,一般从 0 开始递增 1. 第二行是显示时间段,中间用箭头分隔 1. 第三行是这个时间段应该显示的文字 ## 字幕编辑软件 我们使用的字幕编辑软件是 [ArcTime](https://arctime.org/),它是一款跨平台的免费软件。启动以后的界面是这样的: ![picture 22](images/165620d9e9ed2f1a0a834a832b61168f1939c29117f81b604ed6cacae77e4b7a.png) 左上部分区域是视频的预览区,可以从顶部菜单的「文件」→「导入音视频文件」载入要编辑字幕的视频。然后它就会显示预览区。 预览区下方就是字幕区,有根据音频生成的波形在上边。在这个区域点击右键,选择「插入空白字幕」,就会插入一个空白的字幕条,双击可以输入字幕,拖拽可以调整显示的时长和起止时间。 添加好字幕以后,点击预览区的播放按钮,可以实时地看到新添加的字幕效果。需要注意的是,目前的版本中,删除某条字幕的操作是不能撤销的。这可能是这个软件为数不多的缺点了。 整个视频的全部字幕添加完以后,点击顶部菜单中的「导出」→「字幕文件」就会将刚才编辑的字幕生成一个字幕文件了。 ![picture 23](images/747331b8341ef7ac9aa5a2dd1456fe0c54451519091c634b9df663bf118cacce.png) 如果想要把字幕直接压制到视频里边,则可以选择「快速压制视频」选项。 ## 字幕的自动生成 ArcTime 还内置了一个为视频生成字幕的功能,放置在「语音识别」菜单中,但这些功能是收费的。 对于程序员来讲,有一个更为廉价的方式获得同样的效果,那就是直接写代码去调用云服务商提供的 API。比如[阿里云](https://ai.aliyun.com/nls/filetrans?spm=5176.12061031.1228726.1.47fe3cb43I34mn)、腾讯云和[百度翻译平台](http://api.fanyi.baidu.com/api/trans/product/index)就提供了相关接口。 更有开发者已经在 [GitHub](https://github.com/wxbool/video-srt-windows) 上开源了基于这些接口的命令行和客户端软件。大家可以在 GitHub 搜索「VideoSrt」,自行安装试用。 ![picture 24](images/f422703492df26295513f51a08875ad5988fec98ed3d0eec6d5cc8f2844369df.png) ================================================ FILE: src/040218.md ================================================ # 流量池和二次购买 课程制作完成上线以后,并没有结束。长征才刚刚开始,我们需要不断得去运营它。这一节就来聊一聊流量池和二次购买。 ## 没有流量池的情况 先来看一下在没有流量池的情况下,课程转化是什么样子的。 ![picture 26](images/755371ed512e7344cd661dffb9e892a5ccb0abdb1b705d879ab86bfe702c6e90.png) 首先,我们将自有的或者购买的流量引导到课程页面,以触发销售转化。但如果我们没有采取更多措施,之后这个流量就走掉了。当上架新课时,又需要重新寻找或购买流量。 这种方式优点是简单,但今天操作起来问题很大,因为我们已经错过了之前流量爆炸的时代,现在流量已经很贵了,这么浪费太可惜。那么,能不能把流量囤起来,供以后使用呢? ## 学员池 ![picture 27](images/2ff942348109754e7fc16c31c2cc3ed29492662e53d8a4b577db90982582883f.png) 最简单的操作就是,把购买过课程的学员放到「学员池」里。当上架新课程以后,可以直接给他们发通知进行销售。这样就实现了流量的二次使用。很多同学觉得这是显而易见的,但事实上在操作的时候却很容易出问题。 比如说,很多讲师只是直接使用课程平台进行学员管理,而很多的平台不允许讲师给学员批量发送私信,甚至还会做关键字过滤。这种情况下,我们对学员的触达能力是非常弱的,需要建立更可控的流量池来替代。 ## 访客池 ![picture 28](images/da40ef4a001db5059cb2ad7691efefeb3492353f56ad7855419d0833d0260970.png) 学员池重用了已经购买过课程的流量,但更多的没有购买课程的访客流量还是流失了。所以我们还可以更进一步,来做访客池。 把我们课程中有意思、有传播点的内容做成免费的素材,进行多渠道分发,把用户吸引过来并放到这个池子里,以备以后发送通知、触发销售。 常用的渠道包括: 1. 搜索引擎 1. 社交网络 1. 媒体平台 1. 课程平台 1. 行业网站 学员池和访客池是我们最主要的两种流量池。 ## 构造流量池的工具 互联网发展到现在,各种产品已经极大的丰富,所以有大量的工具可以用来构造流量池。因为课程销售有非常明确的商业诉求,所以我们对流量池也有相对明确的评判标准。这里分享下我常用的三个标准: 1. 进入门槛低:最好能免除用户注册,尽快获得用户的基本信息和触达权限 1. 可触达率高:这样我们的销售信息才能被更多人看到 1. 触达免费或廉价:太贵了用不起 如果想要获取种子用户用来验证大纲,还需要考虑互动性。 针对微博、公众号、企业信号、微信群、自建 APP 这几种最常用的方案,我们整理了一个对比表格以供大家参考: ![picture 30](images/4ce9ddccfe59512284989cd5e423c0a94ea1b29efbafe68c1ab3d838266ba859.png) ## 多级流量池 各种流量池都有自己的优缺点,我们应该选取当前阶段最适合的来进行流量的存储。我们也可以分阶段、渐进式地建立多级流量池,以在投入和收益上获得平衡。 比如早期我们可以直接使用微博的关注、哔哩哔哩的订阅来做流量池;然后将一部分核心用户引导到微信群和企业微信一对一服务中。这样把微博的获客门槛低和微信的触达率高这两个优点结合起来了。 在用户规模大一些以后,我们再去开发自己的App,实现对用户流量更高级别的控制。 ![picture 31](images/90ad37e286fa20d68052f0a6d88468500b6d67bed707dd8ac5bd16ba322b80c9.png) ================================================ FILE: src/040219.md ================================================ # 如何有效地反盗版 ## 树立反盗版的正确思路 虽然几乎所有讲师都认为反盗版是必须做的,但未必都明白反盗版的意义,觉得就是少挣了钱。实际上并不是这么简单,盗版最大的问题,是对正版用户带来的不公平。同样的课程,有人花了几千块钱买过来,有人却一分钱不付就可以得到,这让正版用户显得很傻。 其次,很多讲师以为把课程放到课程平台上,平台就会帮着进行反盗版,自己就不用管了。事实上,大部分平台的反盗版措施都非常有限,通常只能由讲师提交盗版链接,他们投诉下架。如果对方将课程放到境外网站,连下架都做不到。而且有些平台每周定时收集处理一次盗版信息,还不如自己直接投诉效率高。所以我们不能把反盗版推给平台去做,他们只能起到辅助作用,我们自己还是要足够重视。 还有一个普遍的错误想法,就是很多程序员觉得盗版是不可能完全杜绝的,所以干脆就不防范了。我们的确没有办法从技术上来完全杜绝视频课的盗版,但却可以采取各种措施来降低被盗版的概率。 要从做盗版的人的经济收益的角度来思考盗版这件事情,如果我们的课盗版门槛很低,就可能导致大量盗版,因为不需要付出太多的代价。相反,如果我们课的盗版门槛很高,那就要花很多功夫才能盗版。 很多盗版手段是针对平台的,当我们课程的盗版门槛变高以后,盗版狗有两个选择,一个是投入时间和金钱去升级盗版手段,另一个选择是用原来的盗版方法继续盗版其他门槛低的课程。绝大部分情况下,它们会选择后者。 有同学可能会说,这样其实并没有解决盗版的问题。是的,从宏观上来讲,确实没有解决盗版问题;但从个体的角度来看,我们又的确避免了自己的课程被盗版。 要从宏观层面上去解决知识产权问题,需要国家、法律、以及社会各方面一起持续不断地推动,我们作为个体,积极响应国家的政策,并保护好自己的知识产权,就是在为这事添砖加瓦。 ![picture 32](images/098b5e2f63121115febdfdd6df9ff3b5a464b78d88fccd55b5178e67ee8a14a0.png) ## 如何有效地反盗版 所以反盗版其实就是要不断提升盗版的门槛,降低盗版狗的收益,让它们无利可图。我们自己实践过的方法中,最有效的可以归纳成四个字、两个词:卖空和卖多。 ### 卖空 卖空其实就是预售,还没有课程,就开始销售。你很难盗版一个还不存在的课程。而且在我们精益网课流程中,本来就是通过预售来验证需求的,所以做起来很顺手。 这个思路再扩展一下,比起一次性提供课程,连载课程的反盗版门槛更高。因为它每周只更新一到两节课程,持续时间很长。这样盗版的成本一下被提升了 N 倍。 卖空的思路很简单,但效果却非常明显,强烈推荐大家尝试。 ### 卖多 卖多是说,现在大家课程放到平台上,盗版门槛是一样高的。但是我们可以多提供一些平台没有的、盗版不了的服务来反盗版。这些服务可以包括: 1. 答疑 1. 督学 1. 社群 1. 线下服务 在进行这些服务的时候,我们可以先进行身份确认,无法提供购买证明的人就不能享受这些服务了。 更进一步,如果我们把课程中不可或缺的部分挪到这些服务中来,那么看盗版视频的人甚至不能完整的学完课程,这就让盗版课程失去了意义。 有一个不错的实践可以分享给大家。我们的主要课程是全栈课,既有前端又有后端。为了反盗版,我们开发了一个云端的编程环境,将后端课程放在其中,然后限制只有正版学员才能登录这个系统,采用这个系统的课程后来就再也没有被盗版过。 这个系统的开发很简单,只需要在云平台上启动一个基于容器的、带有桌面的系统,然后再运行一个基于 Web 的 VNC 去连接它,就可以实现在浏览器中远程操作桌面系统了。感兴趣的同学可以去了解下[NoVNC](https://novnc.com/info.html)这个开源项目。 ================================================ FILE: src/040220.md ================================================ # 使用网易云课堂进行免费分销 ================================================ FILE: src/0403.md ================================================ # 精益独立开发实践 前面我们给大家介绍了精益副业的基本概念,因为只有理论,所以看起来可能比较抽象。 从这一章开始,我们就以实际的副业实践为例,看看如何使用精益副业流程贯穿始终,多快好省地发展副业。我们安排了两个深度实践,一个是独立开发、一个是网课。下边我们开始第一部分。 ================================================ FILE: src/040301.md ================================================ # 独立开发的精益流程 ![picture 1](images/00441d19139213da4e96cf4c512c25e008b0cb9174d9ef87850d25e02f2241ff.png) 前面我们了解了精益创业的一些核心理念,接下来我们就在「独立开发」这个更为具体的副业活动中来看看如何应用精益流程。 这个流程和很多硅谷公司的产品流程很像,但是针对副业做了一些调整和优化。经过三年多时间的使用,我们自己用起来已经很顺手。 1. 首先定义价值主张,然后围绕着价值来设计商业模式画布。 1. 完成画布以后,我们把画布里的「客户细分」部分拿出来,做成「用户画像」。这是一个将细分客户具体化、变得有血有肉的工具 1. 有了画像,再据此还原用户使用产品的各个场景,他们是用电脑还是用手机、是在家里还是在车上使用等等。 1. 想象为了在上述场景下向用户传递价值,我们需要什么样的功能,这样就会得到一个功能列表 1. 功能列表会很长,不同功能的优先级也不同。所以我们会对功能进行分期,其中最重要也是最靠前的一个功能分期,就是用来开发「最小可行产品」的分期。 1. 当「最小可行产品」开发完成后,进行「产品市场契合」的验证,如果达不到设定的验证目标,就需要调整功能,甚至重新设计价值主张。 1. 当通过「产品市场契合」后,我们就可以按照分期迭代开发产品的其他功能了。 1. 在迭代过程中,我们会持续对新上线的部分功能进行增长优化,保证每一部分功能达到预定的目标。 以上就是我们为独立开发优化的精益流程,虽然讲起来比较多,但实际操作起来还是比较简单的。而且我们其实省略了不少大公司流程中的环节,比如用户访谈、焦点小组等。 下一节开始,我们将用一个具体的例子来讲解。 ================================================ FILE: src/040302.md ================================================ # 福利单词项目简介 先来介绍一下我们的实战项目 —— 福利单词。 它来自于我在学习过程中的一个原生需求。最开始我是使用 Anki 这个软件来背单词,软件很好用,但是每次都有一种逼着自己去背的感觉,背完以后如释重负。为了提醒自己不要逃避,我还定了一个闹钟每天催自己。 有一天,我又因为上[Pixiv](https://www.pixiv.net)(一个二次元内容创作社区)看图忘记了时间。突然间我想到,能不能把背单词和看图片这两个行为绑定到一起呢? 你看,背单词虽然有用,但让我痛苦,度日如年;看图片很欢乐,流连忘返,但似乎不是很「有用」。如果我们把两者结合到一起,一边看图一边背单词,是不是就可以让背单词不那么难受,可以持续不断地背下去了? 这就是福利单词的出发点。 接下来,我们就来看看,怎么从这个还有些模糊的想法中提出一个明确的价值主张,然后围绕它进行商业模式规划、功能和界面设计、验证和迭代开发,最终使其成为一个商业产品。 ![picture 2](images/d0111730a6a29b72746f8469e048f80812384b99f480ee0eff1d1f2f9a7ec0fb.png) 需要说明的是,开发过程很难在有限的篇幅中讲解清楚,也偏离了本书的主题,所以我们只会简略地提及一些需要注意的地方,并不会进行开发的教学。 ================================================ FILE: src/040303.md ================================================ # 福利单词的商业模式画布 前边我们已经讲解过商业模式画布,这一节我们就以「福利单词」为例,来看看怎么使用。 ## 价值主张 ![picture 3](images/cc1b6de8d096122e940d918cdcd55a861703ba4ef8145bb9432cd545ffc7c0a4.png) 首先来看一下价值主张。它的核心价值就是,让那些觉得学习起来很痛苦的人不那么痛苦,给一点糖,让其可以持续地、无痛地学习下去。它试图给学习过程添加一些乐趣来综合不是那么爱学习的人的痛苦,从而把一个短暂的、难以忍受的学习行为变成一个可以持续忍受、甚至通过习惯驱动可以持久化的行为。 所以我们在「价值主张」这一栏上写上两个关键字,一个叫「无痛学习」,一个叫「持久化的学习」,这是这个产品最核心的两个「价值主张」。 有了这个价值,我们就能帮助客户完成很多以前想学、但是因为各种原因没有办法学下去的东西,从而实现其个人成长和提升。 ## 客户细分 ![picture 4](images/e6b3f0d14c85c8a069a92c85afb3a1e06806bd65e244cf616e1e7ce7ce4a472c.png) 如果要具体化价值主张,就要来看客户细分。 因为是单词学习软件,所以客户群体往往还是跟学习英文需求相关的。具体划分下来,我觉得可以分成三大类。 1. 第一类是在学校要考英语四级或者六级的大学生。 1. 第二类是有留学或者移民需求,需要考雅思、托福的群体。 1. 第三类是需要专业英语来提升自己在职场的业务能力的上班族。 前两类群体是要备考应试的,后一类则更注重实用能力的提升。从学习的内容上来讲,只是题库的不同。所以如果我们的软件支持了「词库切换」或者「自定义词库」功能,就可以比较容易地覆盖他们的学习需求了。 ## 价值主张的细化 ![picture 5](images/84dd7a1afc00c0c29db15cacba045ea551822d9c0f9bf51db0e10b429fbfe254.png) 光是「有词库,你来背」这个主张和其他背单词软件并没有什么不同,所以我们需要在「价值主张」里再加上「糖」。 但是,对于不同的群体来讲,「糖」是不一样的。如果只是放一些二次元的萌妹子,只有喜欢动漫的人会觉得这是他们的「糖」,可以吸引着他们,每天都来看一看。对于其他一些二次元无感的人群来讲,这些图就毫无吸引力,于是我们需要增加「糖」的种类。 比方说有的妹子就喜欢看帅哥、有的粉丝就喜欢看偶像、有的铲屎官就喜欢看猫猫狗狗、有的吃货就喜欢看肉和甜点。这一部分,我们可以用多图库的方式来满足。 于是,针对不同的客户细分,我们提出三个更为细化的价值主张: 1. 「每天看40分钟妹子,一个月记住四六级词汇」 2. 「看着帅哥,把雅思托福词汇搞定」 3. 「一边云吸猫一边升职加薪」 现在听起来是不是就有吸引力多了? ## 渠道通路 ![picture 6](images/6993c0f0f27d97144b48b2f0c1d3871d4ed628c0aca2d3606567939861779dfd.png) 在「渠道通路」的这个方格里面呢,我们的种子用户主要由微博带过来的流量构成。 通过种子用户进行测试,一旦转化率达标,我们就可以开始对外去做一些合作,以及以微博为起点投放广告,观察广告投放的成本和其带来的流量的关系,以此判断下一步操作。 ## 客户关系 ![picture 7](images/fd6b8f048af9ff87d41bfd3e734681ae1c8448254bbc1a31964ce5fca9928e0c.png) 在「客户关系」这里,我们会通过腾讯提供的「兔小巢」这个产品来提供售后支持。它是类似于反馈板的免费工具。用户在上面提交问题,我们会收到微信或者QQ的通知,可以通过网页在电脑上或者手机上进行答复。 ## 关键活动 ![picture 8](images/32fe651a8ccd9a282e1e9316812dbec14bb0e8da0cff97ccc3c4cfae91aa0799.png) 接下来我们来看一下「关键活动」。 用来验证需求的最小可行产品(MVP),是一个简单网页,只包含 100 个单词、100 张图片和简单的输入文字切换图片功能即可。我们还需要一个统计数据,看看每一个访客到底背了多少个单词。这关系到我们价值主张里的「无痛」和「持久」。 当这个价值被验证后,就可以进入第一期开发。 虽然是一个全平台应用,我们第一期却只做网页版。具体业务包括:背单词的界面,以及选择词库的界面。这是最核心的业务功能。如果我们第一期想要有收入,那么就需要支付和订单系统。 为了对转化过程进行分析、更好地挣钱,我们还需要开发一个2A3R漏斗的统计,让用户从获客层顺利滑入付费层。如果需要通过分享裂变获取更多流量,我们也需要统计发起分享的用户数据。如果要允许用户自定义词库,我们就要提供对应的制作工具。 以上这些,构成了我们的关键活动。关键活动可以采用不同颜色的文字来标记不同的分期,也可以一期一期追加。 ## 关键资源 ![picture 9](images/ff4799c8d584c4b3a101ce2d5048d72705f0a4e7837bf6e28af6c6eadc1c5110.png) 在关键资源上,除了需要具备人、钱和时间以外,我们这个项目还有特有的资源需要考虑,那就是背单词所用的图片,这是一个非常值得注意的问题。 在最小可用产品中,因为不涉及到收费,我们可以使用的图片很多。一旦开始收费,如果还是不加识别地从网上下载各种版权不明的图片,放到自己软件里并以收费的方式进行售卖,很可能会出现侵权。 所以,我们就需要思考图片资源的解决方案。粗略分析后,有以下几种思路: 1. 作者授权 1. 换用无版权图片 1. 用户自行提供图片 ### 作者授权 直接找作者把图片买下来,然后作为付费词库卖给用户,这是最直接的方式。但有问题,那就是价格,光是大一点的词库就有超过一万个单词,也就是说我们要买一万多张图。如果按一张图 50 元计算,需要 50 万的投入。 在一分钱都还没挣之前就做出这么大的投入,风险还是很高的。这种方式更适合我们挣到钱以后,在扩大规模时使用。 ### 换用无版权图片 当然,我们也可以寻找无版权的图片来做图库。这样即使我们打包在软件里进行商业销售也不会有任何问题。互联网上已经有比较庞大的无版权高清图库了,比如 [Unsplash](https://unsplash.com/) 等。不过这些图库主要是风景和动物,人物类非常少。 ### 用户自行提供图片 本质而言,我们卖的是「看图背词」的工具,而不是图片本身。现在之所以在版权上有风险,是因为打包导致的。所以我们可以尝试着将付费的服务和免费的图片分离开。 比如我们可以给用户提供自定义图库的制作工具,让他们把自己收藏的图片导入进去。这样既能达到目的,又没有版权上的风险。 类似需要考虑的,还有背单词时用到的音频。最简单粗暴的方式是使用云平台的TTS(文字转语音)接口直接生成。 ## 成本收益 ![picture 10](images/2e137eb997a8f6335feaf2775de47e201fd4ed975f0bf76ec7301eeb4c063c46.png) 在填好这几个格子以后,我们就可以开始对成本和收益进行相应的预估,算出预期利润区间。 由于我们开发的项目相对比较小,用到的资源也不是特别的多,所以商业模式画布做得还不算细致。不过通常来讲,第一版的商业模式,画布本身也不会特别细。它是随着项目的进展不断被细化的。 最后我们来看看完整的商业模式画布: ![picture 11](images/67cc1dd4b774e8c37968a8d3cd2bb1e4c93fa4e927e2ea752b011a18e5cbca92.png) ================================================ FILE: src/040304.md ================================================ # 通过用户画像细化客户 ## 什么是用户画像 在商业模式画布里面,我们对客户进行了细分,把客户分成了不同的组,每一组代表一个独立的需求。 用户画像(persona)呢,就是给这些已经分好的组,每一组搞一个人设、建一个虚拟形象,让其变得有血有肉、有姓名有年龄有性别、有自己的身份有自己的爱好、有使用产品的场景。 这样当我们聊到这个用户画像的时候,就像在讲自己的朋友、同事一般熟悉的人一样。 把抽象的需求变成活灵活现的人,这样我们在进行产品设计的时候,就更容易还原到场景,带着画面去想象这个人的需求和行动,这就是用户画像的意义。 ## 福利单词的用户画像 接下来,我们就在福利单词的客户细分基础上,为每一类客户建立用户画像。 ### 四六级备考生 首先是备考四六级的大学生这个细分客户群。我们叫他王小康,设定为一个大三的男生。他现在有一个迫切的任务,就是一定要通过四级考试。这位同学是一个动漫宅,他喜欢看的图就是二次元的萌妹子。 ### 留学移民预备军 然后我们来给有留学移民需求、需要考雅思和托福的人群做一个用户画像。我们叫她章小留,她是一个大学刚毕业一年的女生,现在有出国留学的想法,正在准备雅思考试。这位同学是追星族,喜欢看的图片是韩国帅哥。 ### 专业提升小白领 第三个细分人群的用户画像,我们叫她卢小白,是一个毕业两年左右的女生。在生物公司从事技术相关的工作,她需要尽快熟悉大量的生物专业方向的英文单词,方便她更好地了解公司业务。她家里有猫,喜欢看的图片是萌宠和美食。 确定了这三个用户画像的基本资料以后,我们会给他们配上头像,写上他们的需求关键字,把它整理到一页A4纸上。 这样我们就可以把它打印出来,贴到墙上,在做产品设计的时候可以随时去看他们,就像看着我们身边的熟人一样。 ## 画像的头像制作 很多书里面都强调说,用户画像的头像要尽可能真实,最好用真人头像。但需要注意在网上乱找真人头像容易导致肖像权问题,这里给大家推荐一个通过AI生成真人头像的网站,叫做 thispersondoesnotexist.com。 ![picture 12](images/4e7df6ab08d030a7c0e4844562d87c3b48d65d3a131604bc1a9ecf314f6aa810.png) 不过这个网站生成的多是欧美人,对国内的产品来讲,反而各种违和。我更喜欢使用日系的动漫捏脸网站来做,比如 charat.me 这个网站。 ![picture 13](images/f632dfe03251e897f6ab4a780493f742fa9c790106b58dd73d1c6680b7bb998c.png) ## 最终的用户画像 有了头像,再配上角色的说明和需求关键字,我们就有了一个简单好用的用户画像。下边是我们制作好的三个画像: ![picture 14](images/e0b197cf51e2ee26cc27c69485b72a13d3379d6e1529c6cb52d6fbb6ee53a2c1.png) ![picture 15](images/939f370a51e5b0be322ff3c24ce92e4d6af27c05651ce4e5841cd16baf539a29.png) ![picture 16](images/221b764627378d0af87d5e5e468afa8cdff2faea551c8f357a434d3c9a6667d7.png) ================================================ FILE: src/040305.md ================================================ # 画像→场景→功能和分期 ## 使用场景分析 有了栩栩如生的用户画像,我们就可以从画像想象出场景,再由场景梳理出功能列表并进行分期。下边我们就具体来看下怎么分析使用场景。 ### 王小康的使用场景分析 首先是王小康的使用场景,包括在学生宿舍、在图书馆以及在课堂上。 在宿舍,他每天晚上八点到九点使用台式机。因为宿舍比较吵,他会戴着耳机学习。这时候他使用的是外接键盘。 晚上睡觉之前,他还会窝在被窝里玩一会儿手机,时间大概是晚上十一点半到十二点,也就是睡觉前的半个小时,这时候的使用场景就是用手机背单词。 图书馆也是一个典型场景,因为在这个环境里边,需要保持安静。所以你要么戴耳机,要么将设备调成静音。王小康一般是下午三点到五点去图书馆自习,这个时候他使用的是笔记本电脑和 iPad 。 需要注意的是使用 iPad 的时候是没有键盘的,所以在输入上面没有使用外接键盘方便,整体输入速度会下降很多。 图书馆和学生宿舍是两个相当不同的场景。宿舍里很可能有室友在玩游戏或者聊天,很容易分心,甚至连背单词这件事都很容易忘掉,所以我们需要有提醒。 相对而言,图书馆就是安静的沉浸式环境,没有人来打扰你,大家都在忙着学自己的东西。 ### 章小留的使用场景分析 下面我们来做章小留的场景分析。 她现在辞职在家,完全是备考的状态。每天上午会在家学网课、或者去线下的培训班学习,下午会在家学词汇。晚上的话,可能要看韩剧。 主要场景在学词汇的下午。因为是在家里边,她使用的是台式机,鼠标和键盘都是外接的。每天早上起床的时候可能也需要复习一下。 所以她的两个主要使用场景是使用电脑学习,以及早上起床时用手机进行复习。 实际上,这个场景和王小康在晚上用手机复习的场景非常类似,可以都写上,最后进行功能合并时,重复的内容会被合并掉。 同时,因为这两个用户都是在备考,所以他们其实还有「考试复习」这个特殊场景。 在这个场景里,它的词库是有范围的,不一定是整个词库。而背单词的时候,需要有一个考试模式,限时答题,并给出得分。这些需求我们不一定都要通过福利单词这个产品来满足,但可以先写下来。 ### 卢小白的使用场景分析 小白是上班族,所以学习时间是非常有限的,主要是在上下班通勤的时候学习,以及在周末的时候有一点空余时间。 通勤场景一般会在地铁上。运气好的时候就有座位,运气不好的时候还需要站立着。这时候她会使用手机和耳机来学习。 因为她的词汇学习主要是为了工作需要,所以在工作的时候可能还会有查词的需求,可以通过词典软件解决,但是她可能会想把生词加入到福利单词来记忆。 大部分时间地铁里是很挤的,有时候需要一个手扶住上面的吊环或者旁边的柱子,所以小白可能需要单手操作。 另外要意识到小白只是一个典型代表,她需要的是生物类的词汇,但是其他的上班族需要的词汇可能会覆盖各行各业,这部分的词库需要通过自定义词库来解决。 同时,小白很喜欢宠物,当她看见可爱的喵星人时,很可能希望将这个图片保存到相册。这里如果再结合到我们上面的考试模式的话,其实可以做得更游戏化一些。比如说我们可以加入一个图鉴,就是一个画册,里边有每一个单词对应的图。只有你对这个单词达到一定的熟练度以后,才能在里边看见。大体上这就是小白的使用场景。 ## 从场景到功能 现在我们三个用户画像的使用场景已经分析完了。接下来,我们就可以根据场景来确定功能了。也就是说,为了满足这些场景下的需求,我们在产品上需要提供哪些功能来支撑。 在确定功能的时候,有两类需要特别注意。一类是核心功能,没有它,所有画像都没法使用我们的产品。另一类是边界功能,没有它,某一个画像就没法使用我们的产品。核心功能是交集、边界功能是并集。 我们会根据画像的设定,将一些边界功能分配给他们。比如说,为什么卢小白她就会想保存图片到相册,章小留就不会呢?事实上章小留也会,但我们不需要把一个边界功能重复分配,因为最终都会覆盖到。 画像需要注意的是它特有的场景,比如考试模式是备考生的特有场景。对于不考试的同学来说有没有都无所谓,但是对考试的同学是非常有用的。 我们把边界功能标记出来以后,就可以框定一个大体的功能范围。 比如说,章小留使用的是苹果台式机,这就要PC版需要同时支持 Windows 和 Mac 两个操作系统。路小白上下班通勤的时候是单手操作,我们在手机上设计浮动键盘时,就要考虑到小屏幕手机上26键的全键盘单手时容易按错的问题。 对于卢小白来讲,她的空余时间不多,所以可能还会利用家务和健身的时间,这个时候如果她想复习单词,可能还有一个语音播报的需求。 章小留是追星族,那她在网上看韩剧的时候,会顺便把喜欢的偶像的图片给保存下来,制作成词库,甚至还会分享给同好。 这些都是边界功能。在早期设计的时候,可以先不考虑工期、开发量这些很现实的问题,我们可以先把它放进来思考,至于做不做、什么时候做,那是以后的事情。 我们要做的东西在早期应该尽可能的少,但是思考的范围却应该尽可能的广。我们是把很多东西都想明白了以后,选其中最核心的、最重要的来做。而不是说很多东西我压根就不想,只做眼前看到的那一丁点就开始做了。这样到项目中期,就会出现很多思考上的盲点,这些盲点甚至会导致我们的项目重做,所以需要尽可能避免。 ### 通过思维导图梳理功能 我们可以通过思维导图软件来梳理功能。 想象一下新用户从什么地方开始使用我们的软件,跟着他的使用流程来同步构建功能。 比如说,首先会需要有一个用户系统,这样我们才能识别用户。接着我们肯定需要有词库,不然就没有单词可以背了。我们肯定也需要有单词的背诵、管理,如果我们要收费的话,肯定还需要有支付。 用户系统里边,我们考虑使用微信登入,这是目前最简单的办法,不用做用户系统、也不用做密码找回。有了登入肯定也得有退出。 有了用户系统以后我们就可以保存用户背单词的进度了。在词库这边呢,既然我们要做一个可切换和自定义的词库,那肯定会有一个列表。 这个列表,首先是会有一个官方的或者叫内置的,然后我们在建立一个本地的列表,给自定义词库用的。 自定义词库这边,我们可能还需要给提供一个工具来制作词库。我们需要有一个单词表、需要生成对应的音频、需要有对应的解释,以及我们背单词的时候看的图片。这是词库的大体功能。 如果我们要做图鉴的话,就需要有词库的完成度数据。就是用户背了词库里面百分之多少的单词、以及对每一个单词的熟练度。在这个基础上我们还需要有一个相册,用来欣赏高清图片。 自定义词库制作完成以后,它还需要有一个分享方式。我们可以允许用户通过二维码分享,其他的用户通过二维码扫码导入。 接下来,我们来看背单词的功能。 首先它需要有一个地方来输入字母,我们会根据输入的字母动态地进行遮罩的调整。然后我们需要把用户输入的时间或者错误的次数统计起来,这代表着对这个单词的熟练程度。我们也还需要有一些辅助按钮,用来显示单词的意思、以及跳过不会的单词。 在最后,当正确地输入了单词以后,我们需要显示一个高清图片,让用户可以很完整地看见这张图片,这是对其的奖励。 另外我们也需要把用户的背单词成绩记录下来,为了能更清楚地看见这个成绩,可能还需要提供一个进度统计,告诉用户背了词库里面的百分之多少,各自的熟练度是多少。 还有支付部分别忘了。首先我们要显示可以付费的商品,当点击购买按钮以后,要把微信支付给呼叫起来。在微信支付完成以后,要进行确认。同时我们也需要维护一个订单列表来进行售后和退款。 ## 分期 确定好功能表以后,接下来就可以进行分期了。 ### 功能分期 因为我们现在的功能实际上已经非常多了,必须要把它分成不同的阶段来做。最小可行产品不太典型,这里我们以 PMF 验证完成后的第一个版本为例,来选择第一期的内容。第二期就是「以后再做」的功能,第三期就是「不知道啥时候做」的功能。 来看我们的功能列表: - 推送提醒:可以放到第一期。但为了实现推送,需要有消息系统。如果要做定时提醒的话,还需要做设置界面。因为用户设置过提醒以后,可能有一天不需要了,要能及时取消,不然天天推送还挺烦人的。 - 考试模式:放到第二期。虽然对备考生很重要,但是因为整个开发量比较大,在挣钱之前可以先不做。 - 虚拟键盘:放到第一期。为了支持单手操作,我们需要给背单词的界面添加在移动设备上的键盘界面。不同输入法的键盘可能会导致兼容性问题,所以我们直接通过一个虚拟键盘来解决它。 - 自定义词库分享:放到第二期。 - 图鉴模式:放到第二期,也可能是第三期。 - 语音回放:放到第二期。 ![picture 17](images/d25d02c6f99bb412e2c5b49358bbc1d9f358f9024d2e223d5179df83fbe610ab.png) 确定分期的时候,也要同时检查功能点是否都对应上了。比如支付里面,我们需要把「微信支付的对接」加上。 ### 功能归类到界面 确定好某一期的功能列表后,可以把各个功能归类到界面里。新建一个思维导图,写上显而易见的各个界面,然后把功能放到界面下去。 如果发现有功能没有界面放,恭喜你提前发现了做丢的界面,赶紧把这个界面也加进去吧。 ![picture 18](images/4961257f9fbfef01c15585619dfae50c19c2865a635784dee596f0b2e49852e6.png) 这一步完成以后,我们就可以开始进入设计阶段了。 ================================================ FILE: src/040306.md ================================================ # 什么是好的商业设计 这一节开始我们会讲一些设计方面的东西。和专业的设计课不同,我们主要着眼于如何让非专业设计人员也能做出七十到八十分的设计。 首先我们来和大家聊一聊,什么是好的商业设计。 ## 好设计的标准 要做好一件事,首先要弄明白好的标准是什么,而这恰恰是讨论设计时的一个难点。 为什么呢? 我们写程序做软件,好不好是有一个相对可以量化的指标的。比如:用了多少行代码,执行了多久时间,占用了多少内存、在一秒以内可以承受的并发请求数是多少。这些都可以很精确地衡量出一个程序是否写得好。 但是,对于设计来讲,它是一个很个人化的东西。同样一个设计,有的人会觉得它好,有的人会觉得它不好,还没法说谁对谁错。甚至有一些艺术家,他的作品可能在当时就没有人能够理解,隔了很多年大家又把它拿出来,才发现惊为天人。 这就造成了一个问题,设计到底应该按什么样的标准去衡量?不光是设计师本身需要思考这个问题,设计需求的提供方其实也需要去思考。 ## 商业设计 但是后来我们发现,如果把设计的范围给缩小一些,就可能得出一个部分适用的答案。 艺术这个东西它确实是千人千面的,因个人的感受而异。但是我们为商业产品做的设计它并不等价于艺术,大部分情况下它是为商业服务的,我们就叫它「商业设计」吧。 一个好的商业设计,其实就是要让尽可能多的客户喜欢它。因为,喜欢上我们设计的人,很可能也会喜欢上我们的品牌和产品,最终转变成商业价值。 至于这个设计在艺术上深刻不深刻,完全是另外一个领域的事情。 这里有一个比较极端、但大家也很熟悉的例子,那就是椰树椰汁的产品设计。它基本上是把美感给扔了,但换取了很好的识别度,这就是一种商业上的权衡。 我们写程序的时候,要从代码思维上走出来,回到商业思维的角度上来;我们做设计的时候也要从设计本身走出来,从整个商业链条的角度去思考。 通常来讲,我们会面临的抉择,往往是在两类截然不同的设计之间。一类剑走偏锋、足够深刻,能理解它的一类人特别地喜欢,而不理解的又特别讨厌它;另一类设计,看似中庸,然而平中见奇,不同层次的人都可以看到自己喜欢的点。 如果这个设计要拿去参加艺术大赛,可能前者更合适。但如果用于商业产品,那我觉得应该选择后者。因为归根结底,它是用来承载功能、向客户传递品牌质感的,而不是要体现它自身有多深刻,那样反而喧宾夺主了。 ## 简洁即美 每个人的兴趣和爱好都是不同的,要做一个设计或者塑造一种风格,让绝大部分人都喜欢上是很难的。但我们幸运的发现,设计如果足够简洁的话,就不容易包含太多触发各种反感的点,更容易获得绝大部分人的喜爱。 而对于副业来讲,简洁风格的方案所需要的设计和开发资源都相对较少,配合起来又比较容易协调,所以简洁风格是我们的首选。 ================================================ FILE: src/040307.md ================================================ # 人人能用的四大原则 界面设计是很多尝试自己开发完整产品的程序员非常痛苦的事情。很多时候,如果我们去问设计师,很多人虽然会设计,却讲不出背后的道理。只会说,「这样做感觉上更好一些」,「这就是经验/灵感」。 我以前也是这么认为的,直到读了一本书才明白,原来界面设计背后一样是有规律的。 界面的表层结构展现的正是它内部的逻辑。 一个界面上应该摆放哪些控件,哪几个应该离得近,哪几个应该离得远,哪些应该用同样的风格,哪些又应该区别开来,这些都源于它背后严密的逻辑关系,而不是因为设计师的一时兴起。 那本书就是《写给大家看的设计书》。在书里,作者提出了界面排版的四个基本原则,通过活用这四个原则,我们就能够把界面设计得美观大方。 这四个原则分别是「重复」,「对比」,「对齐」和「亲密性」。 - 「重复」原则强调「一致性」,它说的是「在逻辑上一致的物件,在视觉上也应该一致」。 - 「对比」原则强调「层次感],它说的是「逻辑上不同的物件,在视觉上也应该不同」。所以我们要想办法拉出距离来。 - 「对齐」原则强调的是「安定感」。均匀的留白能够营造出一种稳定的感觉。这正是产品质感的一种潜意识渗透。对齐虽然是很小的细节,但是如果处理不好,很容易会破坏产品整体质感,而且会给有强迫症的朋友带来莫大的压力。 - 「亲密性」原则,强调区块的关系,它说的是「逻辑上存在很近的关系,那么这个关系也应该表现在视觉上」。相关的项应该彼此靠近,不相关的项应该彼此远离。 书里有非常详尽的介绍和让人顿悟的例子,建议大家都去阅读下原书。 ![picture 19](images/8d4ce8c6b79ed6f915b7540a56935f631a7372e6f67b87d37e0fe54be20829ea.png) 四大原则回答了常见的一些界面问题。比如说,上图中,白色方块之间的间距为什么不能比第一个方块和页面边界的距离大。 如果从纯感性的角度来讲,可能会说「这样放不好看」。但是如果通过亲密性原则来思考的话,我们会发现在逻辑上,相对于页面边框,白色方块是一个整体。一个白色方块和另一个方块的关系,显然比它和页面边框近。所以这种深层关系表现在视觉上,就是它们之间的边距差异。 如果视觉关系和逻辑关系不一致,我们就会觉得「别扭」、「不直观」。这些原则为我们通过逻辑理解设计推开了一扇门,让之前仅存于「感觉」和「经验」的设计技巧变得有章可循。熟悉它们以后,只要多加练习,再配合上一些简洁、清爽风格的设计细节,我们就可以在大部分场景下做出七十到八十分的界面来。 ![picture 20](images/6cd891635db5171c0405707d8cf7d845ec05c8a0cb2cc290935c6476d1b9c9d8.png) ================================================ FILE: src/040308.md ================================================ # 独特Logo解决方案 接下来讲下,如何设计产品的 Logo 。 ## 为什么要自己设计 Logo 最简单的方式当然是请设计师来设计,我们只需要像产品经理那样在背后指指点点,改需求、当甲方就好了。但是,在做副业时,我们很可能没有足够的预算去雇佣专业的设计师。尤其是在软件还没有获得收益之前,如果花很多钱去请设计师设计,而产品本身又运营不起来的话,钱就白花了。 所以,学会自己做一些比较简单能用的 Logo 还是很重要的。等以后挣钱了,可以再花大钱请高手来重新设计。 ## 通过矢量软件绘制 Logo Logo 的设计还是有些考验绘画能力的,即使是相对简单的简笔画,对于很多没画过图的程序员来讲,也挺难绘制一个像样的出来。 如果你有一定的绘画基础,或者想发掘自己隐藏的天赋,那么我特别建议大家用矢量软件来绘制,对于像我这样手残的同学来讲特别有用。 我最开始画 Logo ,是给自己的开源项目。刚开始使用的是像素绘图软件。由于缺乏练习,即使使用数位屏,也很难绘制出光滑的线条。即使偶尔画出来了,要调整它时,又会花费大量的时间。 后来我发现了矢量绘图软件,在它里边,我们绘制的其实不是线条,而是一个个形状。线条是我们指定的形状的边界,可以通过描边自动生成。最棒的一点是,当我们改变形状时,线条就自动随之变动,无需再重新绘制。 只要熟悉了形状的画法,我们就可以通过矢量绘图软件来绘制一些简单的、线条光滑饱满的图案了。 ![picture 21](images/8b829b0a4c402ed46bc3a5074fb09a0f84a1165edbb87e639e67b21917814939.png) 作为对比,上图左边是我用像素绘图软件绘制的头像,右边是后来我用一个周末学习完矢量绘图软件后花一天时间重新绘制的。真的是好用太多了。 ## 免费和开放的矢量资源 当然,不是所有同学都有时间和精力去学习绘图的,所以我们还是回到适合更多人的方案上来。首先,我们可以使用网上的开源矢量资源。最近两年开始出现一些视觉效果非常不错的矢量插图网站。 ![picture 22](images/c13cdf64696d6fd190f4a14fa5315a5b46a8605da7dcfaab939db35d3d6e89c3.png) 比如 [unDraw](https://undraw.co/),它就提供大量的适合互联网和软件场景的开源矢量插图。更贴心的是,在网站右上角还提供了颜色按钮,通过调整颜色,我们可以得到和自己产品风格更为统一的矢量图。 一个需要注意的地方是,如果使用免费素材,一定要留意不要从国内那些没有注明作者和授权的网站上下载。因为这些来历不明的素材很可能给你带来版权风险,说不定哪天巨额索赔就找上你了。 ## 购买付费素材 如果没有好的免费备选,或者没有太多时间去各个网站上挑,我们还可以通过购买的方式来获取素材。 ![picture 23](images/ce1b14fcbeae1ba524a711f67361504b5d4658561031cfcc8d35da0af4d3bffd.png) 在购买素材的时候,要注意使用的限制。有的网站的素材是会限制使用的项目数、域名、甚至媒体类型的。我推荐大家优先购买采用「royalty-free」许可的网站。这种许可非常开放,往往只要付费就可以永久使用。 提供付费矢量图标的网站比较多,比如 flaticon.com ,thenounproject.com 都是比较有名的。我个人一直订阅的是后者,提供的图标够多,价格也比较便宜。它还提供了一个电脑客户端,可以很方便的搜索、复制粘贴图标文件。 这个网站目前提供的图标都是没有颜色的。当然这一点可能对我们来讲,并没有太大的影响。为什么呢,因为直接使用这些网站上的图标做 Logo ,会带来一个潜在的问题。 ## 将付费素材变成独有的 这种买断式授权的素材非常好用,但是既然我们可以花很少的钱来买这个设计,那同样的,其他人也可以来买这个设计拿去使用。正如许可中指出的,这种许可是非排他的。 如果这些图标只是用到界面上,多个应用之间相似甚至相同,可能还是好事,因为这降低了用户的学习成本。但如果用在 Logo 这种代表品牌的场景,就会出现多个应用 Logo 一样的尴尬场面。 只是从这种买断式素材网站上直接买一个素材就拿过来把它作为 Logo,那人家也可以从这个素材网站上买同样的素材作为它的 Logo。这种行为可能是无意的,也可能是有意的。这种情况下我们还不能说人家抄袭侵权,因为都是从同一个地方买的,你可以买,人家当然也可以买。除非你把这个图案拿去抢先注册了商标,否则就会存在潜在风险。 不过,我们可以通过混搭组合的方式,将 Logo 变得独一无二、且更贴近我们产品的本质。 你看,thenounproject.com 上有上百万的图标。我们单独使用,总有其他的用户和我们一样喜欢上某一个图标,并把它作为 Logo,这个时候我们两个产品就冲突了。 但是如果我们把这几百万的图标混搭组合起来,就会产生出上亿种组合,再要想重复,就变得非常困难了。而「从一个图案里边截取一部分,跟其他的地方拼合起来,构成一个新图案」的这种操作,即使对于一个没有绘画功底的同学来讲,只要能熟练地使用软件,也可以轻易完成。 另外,在增加识别度方面,除了混搭,还可以通过上色来实现。单色图标因为使用的颜色数少,往往比较单薄,看起来缺乏层次感。当我们把它作为产品 Logo 的时候,可能就不是那么耐看。这时候我们可以自己来给它上色。因为是矢量图标,所以调色和上色都非常简单。调色只要选中后改变线或者形状的颜色就可以。 ================================================ FILE: src/040309.md ================================================ # 使用AdobeXD设计界面 ## 什么是 Adobe XD ![picture 24](images/4ee6f6ee095f864dc96282525b69380c2f28d1b5bf5ea0414d3abf30fa4ecd25.png) Adobe XD是由 Adobe 开发的矢量设计工具,它和 Sketch 类似,既可以用来绘制矢量界面,又包含原型设计功能,还可以在手机上预览设计好的界面。XD 支持 Windows 和 Mac,是 Adobe 为数不多的可以免费使用的软件(当然你可以付费升级 pro 版本)。 ## 使用 Adobe XD 设计简单界面 软件的使用主要还是靠大家勤学多练,这里我们和大家演示下如何用它来设计背单词界面。 ### 理解画板 首先,我们在 XD 里新建一个画板(art board)。 画板是什么?它相当于 Word 里边的页面。一般的纯设计工具没有画板这个概念,但 XD 也包含了原型功能,有时候我们需要在多个界面之间来回切换,而一个画板往往就是一个界面。 点击左侧的菜单里面倒数第2个画板的按钮 ![picture 25](images/f6b522f7c0704ff048773475e8b4334a2124d20946afa33c7c01edc406451710.png) ,这时候在屏幕最右边就会出来一系列预置的画板尺寸。 ![picture 26](images/7693c976618197069e64c816967294f735d0e4c2ef4e630dc5dff9d4c3f93e7b.png) 它已经帮我们准备好了常用的规格,比如苹果的iPhone、iPad,谷歌的安卓机型,以及网页常见的尺寸。 我们只要从里边选择对应的尺寸就好了,当然也可以不选择它给你预置的,直接手工拖拽来画或者在属性里面调整画板的宽和高。那我们就新建一个iPhone Xs尺寸的画板好了。 然后按住 CTRL或者CMD + D,就可以直接复制画板。我们把第一个画板叫做背单词界面,然后开始设计。 ![picture 27](images/5941a5dce13909f4044ccfe800d42f713520a1084d0adf2d8015c38e1989cc80.png) ### 遮罩的制作 先来制作背单词时,字母没有输入完时显示的遮罩效果。选择左侧工具栏中的矩形 ![picture 29](images/12ae742ca490d93ce20f9c5aa96b494512bd0aca9e5df9c10d3f1c1128c675c8.png) 工具,画出一个覆盖全部画板的长方形。然后调节填充颜色为黑色,透明度为 30%。 ![picture 30](images/68d0fb889f33813c5b58f53dd088a35b2d2a74127a6deef8252e33c5b04d8d46.png) 然后我们到 unsplash.com 这个无版权网站上,找一只猫的图片,把它也放进来。 ![picture 28](images/26ce365a5cd2b48a7e9926feec288fc4ec36c555d2bcbdcf137fb9609cc6118c.png) 这时候猫是在遮罩上方的,所以它挡住了遮罩。 ![picture 31](images/3fd45f459adc6bf0949a9a25498fffe39927996eccac6bf0342c5fbdc815c495.png) 点击右键,选择「Send to back」将它放到遮罩后,我们就可以看到被半透明遮罩挡住的猫了。 ### 单词释义和输入框 接下来,在遮罩上边,我们来放上单词释义和输入框。点击最左侧工具栏中的 ![picture 33](images/67fb978bc2912408fb6e347eab440d3da5d161b8c1f6dd21738d5769d8c8695b.png) 图标,切换到文字工具。 然后输入文字释义。 ![picture 32](images/36e31721ae40e108f0ba3b4fcb5cdf44e63263686f02acbe0282d587b53675bf.png) 在右侧的属性面板里,我们可以调节文字的字体、大小、颜色和对齐。 然后我们放上之前设计好的 Logo,加上单词输入框。 ![picture 34](images/21aaded8aee1a6683c5ed1f76958bcbadcdd40d79e61dea141d7e6328c0614d8.png) 注意这个输入框不一定非要是「框」,比如我们这里也可以把它做成下划线。 ### 虚拟键盘 ![picture 35](images/cd7edb97da404b395f2f3821ffbbdb7e42ed1f20904943525d4ed429fd9a7896.png) 虚拟键盘的制作在 XD 中也很简单,直接用矩形工具绘制就行。需要注意的是圆角的做法。 ![picture 36](images/b258617ad1104a072548cda70c147292a862e06c3046c3b3e44b8d5a3a286cd1.png) 其实很简单,在右侧的属性设置里边,把圆角从0 改为 5 就可以了。在做好一个按钮后,我们可以按住 Shift 同时选中按钮和上边的文字,在右键菜单中将其编组(Group);然后按 CTRL或者CMD + D 就可以复制按钮。 ![picture 37](images/18349a2006555ddc932fa806936d801a93b9fb43f88fe9146026a7fbaa5311aa.png) 当按钮多起来之后,要对齐它们还挺费事的。其实选中多个按钮后,可以在菜单 Object → Align 中来自动对齐;也可以在 Object → Distribute 中让它们自动均匀分布。 ### 矢量图标 再下来,我们需要在界面中引入图标。既然是矢量界面,当然是矢量图标最好。前边我们已经介绍过 thenounproject.com 了,它还为 pro 用户提供了一个客户端。在这个客户端里边可以非常方便的复制图标。 ![picture 38](images/8c11c4cd1362d30f45d5056462f130adfc819fe1348c03748855602868e07e04.png) 当我们通过关键字搜索到图标后,可以通过下载并将其拖拽到 XD 的方式引入;也可以直接在客户端中右键选择 Copy as SVG,然后直接粘贴。因为是 SVG 格式,调整完大小后可以很方便地更换颜色。 最后我们再微调一下输入框和单词释义的位置,背单词界面就做完了。其他界面的制作非常类似,就不在这里累述了。 ================================================ FILE: src/040310.md ================================================ # 个人支付解决方案 略过开发环节,我们来讲讲变现。绝大部分的支付方案都是面向企业的,面向个人的正规支付方案非常少。那么对于没注册公司的个人,怎么样才能比较安全地收款呢? ## 常见的几种个人收款方式 ### 个人收款码 市面上最简单粗暴的个人收款方案,就是利用微信或者支付宝的个人收款码来做。 具体的说,就是生成一张二维码,在这个二维码上面添加一个付款的备注,让用户备注中补充上特定的消息后(比如订单号)支付。当完成支付以后,我们就会通过APP或者网站,得到备注里面填的消息,通过识别,我们就能定位到订单,从而自动发货。也有不用备注,用支付金额来识别的。 这个方式淘宝店家已经用了很多年,它的问题就在于,从用户端的体验来讲,它需要填写额外的消息或者发送不确定的金额。从商家端的体验来讲,它需要有一个常驻的服务,随时去监测收款的相关消息,这就会有相当的不稳定因素在里边。 ### 二次封装接口 另一种解决方案,就是由那些有资质的企业申请到接口权限后,二次封装后提供给个人来用。这种方案的问题在于,钱是支付给提供接口的企业的,我们只能定期找他们结算提款。万一对方跑路了,我们的钱也就没了。这种方式风险非常高,不推荐。 ### 小微商户 「小微商户」是支付平台针对个人、也就是大量没有企业资质的用户推出的一个解决方案。最开始推出的时候,是为了帮助一些线下的店面,快捷地接入支付而存在的一个服务,然后又扩展到了网上的网店和商家。 一些银行和微信都有这个服务。但是微信并没有给它做专门的后台页面,所以我们在支付平台的后台里是看不见它的,它只有API。 微信把这一部分业务,交给了微信开放平台上的服务商。由服务商去调用这些接口来帮助个人接入到微信的支付服务里面来,同时服务商会提供后台的页面帮个人用户进行管理、也是服务商封装API供个人使用。 这种方案它的好处在于,它是完全合规的,而且这个钱是从微信直接打到小微商户的银行卡里边,不经过中间服务商,所以非常安全。 目前国内有名一点比如 xorpay.com 和 payjs.cn 。他们都是收费服务,前者的费用似乎更为便宜一些。这两个业务我们了解不多,大家使用之前请自行判断其靠谱系数。 ## 数字内容销售平台 如果我们就是写一个软件,想简单地进行销售获得收入的话,我们还可以使用一些现成的数字内容销售平台。面向国外市场的话,可以使用Gumroad.com;如果面向国内市场的话,可以使用mianbaoduo.com。 ![picture 39](images/4fa2ce0a1d95a2aae0099970b1d580f12e571adf1e68cef076bbdab9d822eded.png) 逻辑上讲,所有的网店都能解决我们卖软件的需求,但相对而言,面包多这类专门面向数字商品的平台提供了更低的手续费和更为全面的 API 接口。 ![picture 40](images/a79a80cfb44f3a354f3de91fde1fb92f1815c9a446d77d27b1f7a24a44ff7239.png) ================================================ FILE: src/040311.md ================================================ # 使用「兔小巢」处理用户反馈 市面上管理用户反馈的产品很多,不过大部分都是收费的;这里我们介绍下自己在用的、腾讯出品的免费工具「兔小巢」。 ![picture 41](images/9572f9155ff6e9695889a15e4deb94f8aab726f5658ae3ad652559c2f0b79877.png) 这个产品最大的用户就是腾讯自己,原来叫「吐个槽」,最近才升级并更名为「兔小巢」。我们已经使用了几个月,用下来感受很不错。 从用户端来讲,它支持微信和QQ登入,能及时地推送回复通知;从运营端来讲,用起来明显可以感受到这是一款看似简单,功能却相当强大的产品。比如它可以设置移动端的展示方式;可以适配大型产品和通用产品;默认发帖可以隐藏,也就可以当做工单使用;甚至还配备了团队博客和知识库。 不足的地方是提供的 API 比较少,但也够在自己产品中展示用户反馈了。有了它,我觉得大部分情况下,就不用再去购买同类的付费产品了。 ## 整合说明 下边分享一些整合细节,供大家参考。 ### 链接跳转 兔小巢提供的是非常浅的整合,不管是在 Web 还是 APP 中,都是通过网页转向的方式来进行。通过设置,在反馈区上方可以显示一个链接,供用户返回到产品中。 ### 状态登入 但是通过链接跳转会遇到一个问题,就是在我们的产品和兔小巢之间,用户的登录状态会丢失,这样我们就不知道那个反馈是哪一个用户提交的了。 为此,兔小巢提供了一个[tucao.js](https://txc.qq.com/helper/configLogonState),让我们可以在跳转时传递用户的登录态,从而实现用户的统一。 ### 反馈数据整合 在默认的模式下,我们只能点击链接后,在单独的页面上才能看到反馈信息。但通过兔小巢提供的 [API](https://txc.qq.com/helper/usrFetchAPIGuide),我们可以直接在产品中显示反馈内容。 ================================================ FILE: src/040312.md ================================================ # 2A3R漏斗和增长优化 ## 什么是 2A3R 漏斗 2A3R 漏斗,又叫 AARRR 漏斗,是一个用来描述用户转化的结构。 ![picture 42](images/50235337647e114f8f3cbcbd57e52728ff49ed4c5875dabd31f9d5c13c50361e.png) 它是一个五层结构,分别是: 1. 获客层 1. 激活层 1. 留存层 1. 推荐层 1. 付费层 用户由上至下逐步转化,直至完成付费。其中,留存层、推荐层和付费层可以是并列的,因为用户激活以后,立刻就可以付费、推荐好友。 ## 使用 2A3R 漏斗进行业务优化 2A3R 漏斗的现实意义在于,它促使我们从结果出发,去反向优化前边各个环节的转化率。比如说,如果我们福利单词的销售额定为 1000 套,那么就是说最终到达付费层的用户有 1000 人。而在付费层上至少还有获客层、激活层。 这里我们把获客指标定义为「访问网站」;把激活指标定义为「用户登入」。假设每一层的转化率是 10%,那么访问我们产品的用户数需要达到 1000 乘以 100 等于 10 万人。 优化方向包括: 1. 我们可以加大推广力度,让访问人数从十万变成一百万,这样就能卖掉一万套软件了。 1. 我们可以优化「用户登入」环节,在微信里边做成自动登录,这样把原来 10% 的激活转化提高为 30%,这样即使依然是 10 万访客,销售额也会变为 3000 套。 1. 我们可以强化「付费转化」环节,给第一次访问的用户一个限时折扣,比如 1 个小时内购买,买一送一。如果能拉升 10% 的支付转化,我们的销售也会上升。 ## 留存层优化 留存层优化主要用于一些基于高粘度增长引擎的业务,或者免费+付费模式的产品。在这些模式下,用户需要经过很长时间的使用,才会付费。如果留存做不好,用户熬不到付费那天。 对于福利单词而言,留存层优化可以通过推送通知、定时提醒等功能来做。因为背单词本来就是一个周期性行为,所以我们有足够的理由去召回用户。 ## 推荐层优化 现在的流量已经是非常贵的了,所以我们必须珍惜每一滴流量。通过旧用户带来新用户,可以为我们提供免费流量;如果做得足够好,流量甚至能像滚雪球一样不断变大。这就是推荐层优化要做的事情。 在我们的应用中,我们可以选择几个用户情绪高涨的点来做分享触发: 1. 完成当天的背单词目标,比如背了 100 个单词 1. 完成有挑战的任务,比如连续 30 个单词不出错 1. 看到赏心悦目的图片,比如看到超级呆萌的猫 在这些时刻,我们都可以引导用户通过海报来分享他们的激动心情,同时为我们带来新的用户。 ## 推荐阅读 关于增长优化,这里给大家推荐两本书。一本是肖恩·埃利斯的《增长黑客》,系统化地讲述了如果建立增长实验机制并从中受益;另一本是《病毒循环》,记录了众多流量传奇。它们中很多细节和技巧,都可以用到我们的副业当中。 ================================================ FILE: src/040313.md ================================================ # 分享页面和裂变海报 ================================================ FILE: src/0404.md ================================================ # 进一步提升副业的鲁棒性 ================================================ FILE: src/040401.md ================================================ # 网课+独立开发的双引擎副业模式 前面我们通过两个大章节的实践课程,为大家详细讲解了怎么通过独立开发和网络课程制作来发展副业。之所以会选择这两个方向,除了它们非常典型、有很高的投入产出比,还有一个原因 —— 它们之间可以形成非常好的互补。 目前看来,在国内要通过独立开发赚到一流企业程序员的年收入(大致三十到五十万),还是比较困难的。免费加收费模式虽然后期收益巨大,但前期需要长时间的投入。 相对而言,网络课程的售卖更容易带来现金收益。如果我们把独立开发的整个过程完整的录制下来,并加工成网络课程进行销售,那么即使独立开发项目最终难以通过销售软件和服务来赚取足够多的收益,我们还可以通过网络课程获得收入。 而且,不管对于课程学员还是独立软件/服务使用者来讲,都更有益。课程的学员可以学到更为真实、更贴近一线、且经过事实验证的开发技巧;软件/服务使用者则可以获得详尽的文档、架构说明,更有机会进一步深入了解整个规划、设计、开发过程,充分理解业务,甚至因此变成代码贡献者。 从流量上讲,软件/服务可以给课程带来学员;课程可以给软件/服务带来用户。两者互相促进,为我们的副业更添了一层保障。 ![picture 25](images/e0d3f636b6cf6ee45d51e9e9d41283940a9a0d84c6f7f067d8cd6e2f56446547.png) 最终,我们就可以实现一个多次利用「副产品优势」的三级收入模式。在这个模式下,我们首先通过主业赚取最核心的收益,以供日常生活和基本发展。然后,我们在主业工作中积累的知识、经验、人脉基础上,开发我们的副业,比如独立软件或服务。在独立开发的过程中,我们再次把它的副产品——制作过程,录制成课程进行售卖。最终,我们可以分别从主业、独立开发以及课程三个渠道获取收益。 这样即使某些收入源不是特别好,我们的整体收入还是相对高的,这就让我们有足够的时间和资源去修正这些错误,让整体发展得越来越好。 ================================================ FILE: src/README.md ================================================ # 精益副业 ================================================ FILE: src/SUMMARY.md ================================================ # Summary * [精益副业](README.md) * [为什么副业特别重要](01.md) * [职业可能性](0101.md) * [职业的四大象限](010101.md) * [没有副业的职业](010102.md) * [副业带来的可能性](010103.md) * [职业自由度](0102.md) * [从中指备用金说起](010201.md) * [PlanB和反脆弱](010202.md) * [全新的工作自由度](010203.md) * [职业成长性](0103.md) * [新技术练兵场](010301A.md) * [业务敏感度](010302.md) * [如何优雅地做副业](02.md) * [想明白核心资源和核心优势](0201.md) * [副业的核心资源](020101.md) * [副业的核心优势](020102.md) * [时间片](0202.md) * [时间片的销售](020201.md) * [时间片的优化](020202.md) * [突破时间片限制](020203.md) * [资产和被动收入](0203.md) * [什么是资产](020301.md) * [资产的获得方式](020302.md) * [资产的量化评估](020303.md) * [优选资产](03.md) * [知识和人脉的变现](0301.md) * [付费视频课](030101.md) * [付费专栏](030102.md) * [付费社群](030103.md) * [图书出版](030104.md) * [自有产品和服务](0302.md) * [半成品市场](030205.md) * [开源/免费+收费模式](030204.md) * [应用市场卖APP](030201.md) * [精益副业](04.md) * [精益副业流程](0401.md) * [什么是精益创业](040101.md) * [精益副业:为副业优化的精益流程](040102.md) * [商业模式画布](040104.md) * [最小可行产品和产品市场契合](040105.md) * [精益独立开发实践](0403.md) * [独立开发的精益流程](040301.md) * [福利单词项目简介](040302.md) * [福利单词的商业模式画布](040303.md) * [通过用户画像细化客户](040304.md) * [画像→场景→功能和分期](040305.md) * [什么是好的商业设计](040306.md) * [人人能用的四大原则](040307.md) * [独特Logo解决方案](040308.md) * [使用AdobeXD设计界面](040309.md) * [个人支付解决方案](040310.md) * [使用「兔小巢」处理用户反馈](040311.md) * [2A3R漏斗和增长优化](040312.md) * [精益网课变现实践](0402.md) * [网课的精益流程](040201.md) * [如何确定选题的基本方向](040202.md) * [网课的商业模式设计](040203.md) * [网课市场分析](040204.md) * [形成有竞争力的价值主张](040205.md) * [大纲的注意点](040207.md) * [通过预售验证销量](040209.md) * [常见的课程片段类型](040210.md) * [文稿讲义类课程片段的制作](040211.md) * [屏幕录制类课程片段的制作](040212.md) * [真人出镜类课程片段的制作](040213.md) * [虚拟形象类课程片段的制作](040214.md) * [最常用的视频剪辑操作](040215.md) * [最常用的音频处理操作](040216.md) * [字幕的制作和自动生成](040217.md) * [流量池和二次购买](040218.md) * [如何有效地反盗版](040219.md) * [进一步提升副业的鲁棒性](0404.md) * [网课+独立开发的双引擎副业模式](040401.md)