├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── 0216 └── input │ └── input.txt ├── 0217 └── input │ └── input.txt ├── 0218 └── input │ └── input.txt ├── 0219 └── input │ └── input.txt ├── 0220 ├── input │ └── input.txt └── merged │ └── list.txt ├── 0221 └── input │ └── input.txt ├── 0223 └── input │ └── input.txt ├── 0224 └── input │ └── input.txt ├── 0225 └── input │ └── input.txt ├── bili └── input.md ├── fonts ├── _思源黑体SourceHanSansCN-Bold.otf └── font.otf ├── index.js ├── merged └── result.srt ├── package-lock.json ├── package.json ├── readme.md ├── src ├── addBgm.js ├── addJpg.js ├── addText.js ├── baiduSpeech.js ├── exec.js ├── init.js ├── mergeMP3.js ├── randomBgCopy.js ├── readText.js ├── text2svg.js └── utils.js ├── srt └── result.srt ├── templete └── input │ └── input.txt └── tools └── request.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | result/ 3 | mp3/ 4 | mp4/ 5 | bg/ 6 | test/ 7 | *.jpg 8 | *.jpeg 9 | *.png 10 | *.svg 11 | *.mp3 12 | *.mp4 13 | *.wav 14 | *.srt -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "启动程序", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceFolder}\\index.js" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.disableLanguages": [ 3 | "vue" 4 | // "javascript", 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /0216/input/input.txt: -------------------------------------------------------------------------------- 1 | 尊敬的连叔: 2 | 3 | 您好。 4 | 5 | 刚开始关注您的时候看过您给一位初中生的一篇回信, 6 | 看那篇的时候不知道为什么深有体会。 7 | 8 | 我今年初三,学习也还行。 9 | 但让我苦恼的是我和家人的关系。 10 | 11 | 我的父亲去世了,母亲和姐姐供我上学,经常会吵架, 12 | 可能是我的情绪很不好控制, 13 | 只要母亲说的不如我意我就会生气。 14 | 我也会在反思自己。 15 | 16 | 但昨天我和母亲吵架, 17 | 母亲和姐姐说我没有资本和她们吵架, 18 | 他们如果不养我,我就会成为一个野孩子自身自灭。 19 | 20 | 那时我崩溃了,觉得我就像一个项目对我投资只是等回报。 21 | 我很好奇,一个母亲为什么要生孩子。 22 | 母亲对我很好,可我真的接受不了她这样的话。 23 | 24 | 致此 25 | 祝你健健康康 26 | 一个初三生 27 | 28 | 29 | 一个初三生: 30 | 31 | 我想,你并非不知道妈妈姐姐供你辛苦, 32 | 因为爸爸去世了,你可能还知道得特别深刻。 33 | 34 | 感激(或者爱),这种情感很难表达, 35 | 尤其在你这个年纪,需要一个学习过程。 36 | 37 | 有些孩子选择常态的表达,懂事、温柔、成绩好, 38 | 用“我的任务完成得很好”表达出爱。 39 | 40 | 更多的孩子选择非常态的表达,他们也会悄悄努力, 41 | 希望成为一个特别厉害的人,回报爱自己的人。 42 | 43 | 在他们还没有实现这个理想的时候, 44 | 又不想表现得软弱, 45 | 反而会有攻击性,攻击的目标或是自己, 46 | 47 | 严重的进入自毁状态,或是那些爱你的人, 48 | 因为他们彻底心死,放弃你,你就没有情感压力了。 49 | 50 | 只有极少数人会发展得很极端, 51 | 绝大多数人只是通过吵架表达出 52 | “虽然你爱我,可我没有强迫你爱我”, 53 | 有一点点不认账的意思,这样可以暂时减轻一点压力。 54 | 55 | 同样,妈妈与姐姐和你吵架,也在释放她们的压力。 56 | 57 | “如果不养你,你就会成为一个野孩子自身自灭”, 58 | 59 | 这句话翻译一下,意思是: 60 | 凭我们两个女人的力量养一个孩子,真的很辛苦, 61 | 62 | 接下来更艰巨,高中,大学,工作,一直到他能够养活自己, 63 | 真是希望他瞬间自立啊。 64 | 65 | 她们害怕无法完成这个任务,有时太累了,也会想放弃, 66 | 但这个念头又产生道德愧疚,折磨她们。 67 | 68 | 这一切压力,都容易导致吵架。 69 | 70 | 你的妈妈和姐姐,她们或许不够强大,在教育上也有缺失, 71 | 72 | 如果她们对你有足够的信心,也知道成长需要等候, 73 | 她们的压力就不会那么大,对你更忍耐, 74 | 不至于说出说出伤你自尊的话,似乎不养你你就会饿死。 75 | 76 | 这句话有很糟的暗示,一个孩子,听多了,听得没脾气, 77 | 以后一辈子心安理得等人养。 78 | 79 | 你听了这句话生气,是好事。 80 | 从你的邮件看不出你的性别。 81 | 82 | 如果你是男孩,这是男人角色的轻微觉醒。 83 | 如果你是女孩,这也是责任感的轻微觉醒。 84 | 85 | 你意识到了,她们需要有人保护。 86 | 当然,如果哭哭啼啼,放弃进取,甚至狠狠伤这两个女人的心, 87 | 就听不见这内心的觉醒,好事无法继续。 88 | 89 | 你只一个初三孩子,你有理由担心自己保护不了她们, 90 | 91 | 确实,10年后强大的你,更能履行家长的职责, 92 | 你镇静地说,没事,有我。她们就不再害怕。 93 | 94 | 现在的你,精神上也能做到, 95 | 当她们开始和你吵架时,你要知道, 96 | 97 | 那是她们在害怕,害怕自己照顾不好你,害怕你会被这个世界吞噬。 98 | 只要简单抱抱她们,说,我会努力的。 99 | 100 | 她们就不会那么害怕。而且,你自己也真的会更努力。 101 | 人就是这么神奇,只要你意识到必须对人负责,你就会飞速成长。 102 | 103 | 祝开心。 104 | 连岳 -------------------------------------------------------------------------------- /0217/input/input.txt: -------------------------------------------------------------------------------- 1 | 疫情时期,高三学生还没回校复课,教学依靠网络。 2 | 昨天有位高三老师说到, 3 | 她感觉学生比老师还焦虑,让谈谈这事。 4 | 5 | 教学方式变化,学习节奏打乱, 6 | 是今年所有学生面临的挑战, 7 | 对高三学生影响尤其大, 8 | 毕竟他们要迎接学习生涯中最重要的高考。 9 | 10 | 高三可能是许多人人生中效率最高的一年, 11 | 它具备几个条件: 12 | 13 | 一是艰巨而无法延迟的考核任务; 14 | 二是师长严厉的监督,这是最高等级的他律; 15 | 三是自律最严; 16 | 四是同学努力带来的激励, 17 | 这是最高等级的同侪压力。 18 | 19 | 这些高三的宝贵资源,在以后的人生中, 20 | 可用来迎接挑战,拿出你高三强度的一半,事都不是什么事。 21 | 22 | 可惜的是,多数人高三毕业后, 23 | 把这资源像旧课本一样扔了,暴殄天物。 24 | 25 | 无论你成绩好坏,都要记住自己高三全力以赴的模样, 26 | 成绩不拔尖的同学,尤其要记住, 27 | 因为人生定论不终结在高考, 28 | 你需要这种精神在后面一次又一次无形的考试挺住,并且成功。 29 | 30 | 很多人为何无法保住高三资源? 31 | 那是因为高三的诸条件消失了。 32 | 33 | 任务变模糊了,可以无限拖拉; 34 | 他律消失了;同侪压力也不大,人群的多样, 35 | 身边总有懒散的人、不负责任的人、愚笨的人, 36 | 37 | 让你产生“我很努力”的错觉,看不见自己其实在退步。 38 | 自律,变得极其重要。 39 | 40 | 很多孩子害怕上网课,迫切希望回到真实的课堂 41 | ,那是他们需要一个他律的环境以免自己迷失。 42 | 43 | 怎么度过这段特殊的高三? 44 | 这是我的建议: 45 | 46 | 一、接受事实。老想着回校复课,那就是不接受现实。 47 | 变化是计划的平台,自己在家学习,上网课,都是变化, 48 | 谁适应变化快,谁的计划成功率高。 49 | 50 | 我们那些有难度的、时间跨度长的计划,必然被扰乱。 51 | 就像一场伟大战役,有时气候不对,有时失去补给, 52 | 有时战友阵亡,有时自己受伤, 53 | 善战者根据变化不停调整行动,以保证计划的完成。 54 | 55 | 变化发生时,最好的应对就是马上接受变化, 56 | 不要回忆,不要抱怨。 57 | 58 | 二、告诉自己:所有同学面临同样处境,并非针对我。 59 | 所有人担心同样的事,那就没什么好担心的。 60 | 61 | 三、屏蔽疫情消息,你只要记住, 62 | 疫情得到了控制,世界很快会恢复正常。 63 | 64 | 四、恢复学校的作息。 65 | 在家,由于不要通勤,你可能会睡迟一点, 66 | 吃饭磨蹭一点,甚至随时吃点零食。 67 | 恢复到原来常规的作息,包括这种作息带来的一定的疲惫感, 68 | 这是在找回节奏,节奏可带着你跑,让你跑得更远。 69 | 70 | 五、建立仿真角。 71 | 有条件的用一房间,没条件的用一角落,学习环境 72 | 布置得像你学校的课桌一样,我也建议你上网课时 73 | 穿上校服。这仪式感能让你迅速进入角色。 74 | 75 | 六、除学习必要,锁上手机,或交由家长保管, 76 | 每日设定使用手机的时段与时长,能少尽量少。 77 | 78 | 七、每日完成固定的锻炼,冥想、卷腹、俯卧撑、 79 | 马步、站桩……总有一项或几项适合你。 80 | 81 | 八、家人做好配合。 82 | 高三学生的学习,是此里家里最重要的任务,其他一切退让。 83 | 这意味着,尽量保持家里的安静, 84 | 85 | 尤其是孩子在学习时,电视关掉, 86 | 手机静音,不吵不闹,别没完没了议论疫情, 87 | 设立一个固定的交流区域,你们有事去那儿说。 88 | 89 | 最好也趁这段时间,带着任务看看书, 90 | 体验一下孩子的学习,自己也可精进。 91 | 学习有时是整个家庭的竞争,当下最可证明这点。 92 | 93 | 如果你渴望胜利,你不会害怕变化, 94 | 变化只是让你多了赢的机会。 95 | 加油。 -------------------------------------------------------------------------------- /0218/input/input.txt: -------------------------------------------------------------------------------- 1 | “我家有一个高三的,完全不像我们意义上的样子, 2 | 其他人着急的很,自己还好像小学生一样, 3 | 白天上网课,晚上手游刷剧,1点多才睡! 4 | 5 | 对于这样的孩子该怎么办?现在这个年纪, 6 | 已经不能打不能骂了,我们只能忍着看着吗?” 7 | 这是一位家长的焦急留言。 8 | 9 | 我想,分两种情况,一是这位高三生的成绩极好, 10 | 那么,我们只能说,他有自己一套独特方法, 11 | 他想怎么学就怎么学。 12 | 13 | 一个永远拿第一的高三生,玩手游刷剧, 14 | 不做作业,迟睡迟起,在其他学生身上, 15 | 是坏毛病,对他来说,却是正常的。 16 | 17 | 虽然这种可能性极小,但我们也不能排除, 18 | 如果是这样的孩子,那么家长最好不要打扰他, 19 | 让他用自己的方法读书好了, 20 | 不要因为他与别人不一样而着急。 21 | 22 | 有实力的人,有特权。 23 | 这是人类社会的残酷而真实的规则之一。 24 | 25 | 乔丹在更衣室有训斥 26 | (传言还说殴打)队友的特权; 27 | 乔布斯有对员工脾气暴躁的特权。 28 | 29 | 能力一般的人,即使姓乔, 30 | 友善待人也是必须遵守的规则。 31 | 当然,你是天才,有特权, 32 | 友善也是更好的选择,没必要非得暴躁。 33 | 34 | 很多高中生,独立意识已经强烈,对师长的教导排斥。 35 | 我觉得最好的办法就是展示实力, 36 | 亮出一手好成绩,师长自然少烦你。 37 | 38 | 否则依靠父母生存,成绩又不好, 39 | 还各种坏毛病和不服气, 40 | 这怎么说都与独立挂不上钩, 41 | 一点也不酷,纯粹就是忘恩负义嘛。 42 | 43 | 这位家长的焦急,极大的可能是这孩子习惯不好, 44 | 成绩也不好。这也是很多家长相同的困境。 45 | 46 | 高三孩子,肯定不能打了, 47 | 一是可能打不过他,二是此时再打已无作用。 48 | 49 | 我们知道,现在立法者重新把适当的体罚权 50 | 还给了教育者,那就是意识到,没有这种纠偏手段, 51 | 有些孩子遵守规则的能力建立不起来。 52 | 53 | 当然,体罚只能适当,滥用了,孩子打皮了, 54 | 教育者权威尽失,只会起反作用。 55 | 骂除了发泄情绪,引起抵触,也无更多意义。 56 | 57 | 只剩下真诚的交流了。可以明确且温和地表达你的意见, 58 | 也请孩子说说自己的想法与计划, 59 | 让他制订自己的手机使用纪律,彼此达成共识,写下来。 60 | 61 | 这并不意味着他以后就不玩手机了,他一定会玩, 62 | 甚至纪律只可能维持一两天, 63 | 因为他的自控力只有这么多, 64 | 65 | 你要预见到这点,否则你就得情绪失控,悲观绝望: 66 | 明明说好的,怎么转眼又破功? 67 | 这时才需要你帮助他:你控制不住自己,我们一起来, 68 | 再调整计划,到了某个时间点,手机交由家长代管。 69 | 70 | 家庭教育就是大量的交流。一次谈话, 71 | 一篇文章,一阵感动,一天努力,功效都有限, 72 | 需要重复一千次,几千天,累积功效, 73 | 直到他成为一个自律、勤奋、负责任的人。 74 | 75 | 家长必须有耐心,必须保持沟通的顺畅, 76 | 孩子尊重你,乐于和你说话,你才有持续教育他的机会。 77 | 从这点来看,打骂是坏选择, 78 | 一不小心,就摧毁了沟通渠道。 79 | 80 | 孩子有了好习惯,甚至奇迹发生, 81 | 在高三时脱胎换骨,是不是意味着高考必胜? 82 | 不是的,最好别抱这种期待,他高考大概率还是输的。 83 | 84 | 一是高考成功者本来就是少数; 85 | 二是高考是所有原因的结果, 86 | 一个自律、勤奋、负责任的孩子, 87 | 成绩就是不好,常有的事。 88 | 89 | 但已经没有关系了,自律、勤奋、负责任, 90 | 这用来应对之后人生的所有挑战,绰绰有余。 91 | 这不就是教育的主要目的吗? 92 | 93 | 所以家长不能有这样的心思:我这孩子, 94 | 反正成绩不可能好,高考没什么指望,随他去吧。 95 | 反而要珍惜教育中孩子暴露出的种种缺点,逐一调整。 96 | 97 | 天才孩子极少,普通孩子是多数,普通人何苦为难普通人, 98 | 家长只有发自内心接纳自己的普通孩子, 99 | 才能保持耐心和友善,这样, 100 | 高考失败就不会等于教育失败,更不是孩子人生的失败。 -------------------------------------------------------------------------------- /0219/input/input.txt: -------------------------------------------------------------------------------- 1 | 上证指数这两天已经收复2月3日开市时的大跌,恢复且超过节前收市的高度。换言之,开市当日敢于买入的人,短期内已有不错收益。恭喜,这是他们该得的。 2 | 3 | 市场是真正的投票机,你的每一个决定,都押上了自己的钱。判断正确,盈利,判断错误,亏损。事实不为你的意志转移。我尊重一切在市场上投票的人,无他,就是因为他们不是随便说说,错了真要被惩罚,亏损是酷刑。 4 | 5 | 当一件大事发生时,比如新冠肺炎,不同的人群,由于自己的立场、见识或掌握的事实不同,有不同的观点,这很正常。都听听。如果你是一个投资者,你想成功,就会寻求很多声音,以求得出最合情合理的结论。 6 | 7 | 经商使人客观,人应该从事一点商业活动。中国商业发达的东南沿海地区,这次疫情各阶层体现出来的竞争力,就是一个例子。政府在防疫的同时,比较容易纠正非常状态下的错误与过激反应,官员敢于冒险第一时间鼓励企业恢复生产,民众也不喜欢层层加码的戏码,不那么恐慌,努力回归正常生活。主流的思维是商业思维,自己养活自己的人多,则成本意识是第一反应。我最近的任务是去附近每家恢复营业的餐馆大吃一顿,一是表示对他们的敬意,二是贪吃。 8 | 9 | 时至今日,疫情得到控制并且可以战胜,已是显然之事,而一些批评家依然认为中国要完蛋,情绪悲愤,以泪洗面。如果是真诚的话,这不利于自己的健康,情绪长期低落,免疫力也会降低,还是建议他们平静一点。 10 | 11 | 不能说他们的议论的事没一点依据,官员的不作为乱作为;民众科学素养不足,妖孽四起;借防疫之名出现的故意伤害,非法拘禁;对企业经营的粗暴干涉,都是事实。这些事情若成不可逆的燎原之势,中国当然会完蛋。批评家,尤其是不那么善意的,容易直接跳跃到中国完蛋论。这悲愤得比较有气势,虽然逻辑不成立。 12 | 13 | 但投资者愿意去查证,纠偏有没发生?当然有,湖北从基层官员到省委书记,撤换了一堆;全国医疗精英支持湖北,多有殉职,他们的高贵精神与职业荣誉感,令人动容;这几天,各地抢人复工的新闻频出,也是非常积极的信号。这些,批评家可能会忽视,投资者绝不会。所以,中国政府也要加倍珍惜这个国家的企业家与投资者,他们最容易看见政府的功劳,是真金白银的爱国者。 14 | 15 | 要学会从投资者的眼睛看中国,看世界,这样情绪与财务都比较健康。2月3日开市时,我的判断是疫情只有短期冲击,长期来看,对中国经济没有多大影响,而且,“政府与政府比,中国政府搞经济是一流的。这么说难免被激愤的人扣帽子,那无所谓的。”事后果然被扣了帽子。 16 | 17 | 没人喜欢被扣帽子,所以,芒格最近对中国经济的判断,还是直接引用好了:“没有人能以如此快的速度领先一个国家。中国做得非常好,很欣赏中国在过去25年中取得的成就,让大家看到了巨大的增长繁荣,使8亿人摆脱贫困。美国应该与中国和睦相处。”“美国可能是全球最大的经济体,但中国目前拥有更强大的公司。……中国公司比美国强大,并且增长更快。” 18 | 19 | 中国人这么说,“五毛”的帽子少不了。你是一个企业家,一个投资者,也没必要非得在朋友圈里,在舆论场上说真实的想法,一下成“汉奸”,一下成“五毛”,左右不是人。知道事实,各自用钱下注就是了。 20 | 21 | 曾有朋友问我:你看好中国的未来,如果中国再次闭关锁国,取消市场,关你,没收你的财产,怎么办? 22 | 23 | 我的答案是:一、这种事情发生的概率极低,趋近于零;二、真发生,我就认,愿赌服输;三、建议你别把自己吓得半死,好好投资中国,好好享受当下。 24 | -------------------------------------------------------------------------------- /0220/input/input.txt: -------------------------------------------------------------------------------- 1 | 我们会对医生护士好吗? 2 | 3 | 废话!当然。肯定会得到这个答案。现在医护人员最受尊重爱戴,人们不吝啬把赞美倾泻给他们。 4 | 5 | 但是疫情结束以后呢?那一天很快会到来,人们回归正常生活,医生护士不再是谈论焦点,我们慢慢忘掉他们此时的无畏与专业。这是记忆的规律。在那个时候,我们会对医生护士好吗?答案就没那么肯定了。 6 | 7 | 现代医疗有两个“弊端”,将永远存在: 8 | 9 | 一是成本高昂。大到尖端医疗设备的发明生产,新药的研制,耗资惊人。小到医生个人的成长,教育成本不是小数字。看电视剧就知道,无论中西,富人家的孩子,读医学院是首选。并非穷人家不爱这个职业,主要是承担不起昂贵的教育费用。穷孩子咬紧牙关当上医生,也被认为是阶层跃升,命运有了大转折。 10 | 11 | 二是疾病和死亡最终一定胜出。除了极少数的幸运儿,无疾而终,一觉不醒。绝大多数人生命的最后阶段,是在医院度过的,穷尽一切手段,宣告不治。 12 | 13 | 这两个因素结合在一起,则形成不好的消费体验:我花了很多钱,人还是死了。 14 | 15 | 人的理性,可以压抑,进而理解这种“不好”感觉。成本高的商品与服务,享受的价格一定高。否则,别人为何要那么努力地精进?本质上就是为了收入与地位高一点。努力与懒惰的结果一样,没人会努力。理解这点,需要市场经济的常识。 16 | 17 | 而任何一次治疗,都是不同的。同样的病,你好了,我没好,可能是你体质好,心态好,医生水平高,用的设备也先进。甚至纯粹就是运气好。同样的流感,年轻人轻松自愈,却吹灭老年人微弱的生命烛火。每个人,每个年龄段,每种状态,治愈率都不同。理解这点,需要一点概率常识。 18 | 19 | 一个理想的社会,当然人人有市场常识与概率常识。 20 | 21 | 可惜这样的理想社会并不存在。以后也不会存在,无论如何教育,有市场常识与概率常识的人,只会有一部分。决策者,精英阶层有,那就是谢天谢地的好事,国家必将繁荣。 22 | 23 | 很多人永远不会有这些常识,即使受了大学教育,也没有。从这点来看,医生并不是一个好职业。你提升医术的成本高,那是你的事。你要用医术挣我的钱,我就得骂你。至于医疗的价格怎么才合适呢?那得由我这个病人说了算,免费最好。我这个愿望不能实现?原因自然是政府无能,医生黑心。平时大量的仇医舆论,就是这种无知驱使的。一些偏执的人,仇医舆论听多了,有伤医杀医的行动,也就不稀奇了。 24 | 25 | 前不久,有人卖口罩,即使只是收了合理的利润,也被举报和处罚,叫好的人还挺多,理由就是这个时候你还赚钱,真是坏了良心。不为赚钱,人家像你一样,躺在家里骂人,不挺舒服,为何要受累呢?没人受累,口罩从哪里来?还好普通口罩,技术含量低,生产起来容易,中国这个生产魔王,很快也就让口罩不那么稀缺。 26 | 27 | 但医生不是口罩,不是说有就有的。当医生普遍心生倦意,觉得地位与收入都不体面,有点正常人物质上的想法,就得被攻击。这就会影响医生的供给,想当医生的人变少,好医生也变少。 28 | 29 | 我觉得,现在防疫一线的医护人员,也不要只送高帽子,这些他们已经够多了,以后被骂,也不能拿出来对冲,不如趁大家爱他们,在这精英与民粹都一致的奇妙时刻,简单粗暴地给他们猛提一大截工资。这也是最好的激励与教育,做得好的人,首先应该体现在收入上。这么想,这么做的人多了,就是一个好社会。 -------------------------------------------------------------------------------- /0220/merged/list.txt: -------------------------------------------------------------------------------- 1 | file 'cover.mp4' 2 | file 'final.mp4' -------------------------------------------------------------------------------- /0221/input/input.txt: -------------------------------------------------------------------------------- 1 | 最近,多地出台为一线防疫医务人员子女中考加分的政策,引起了一些争论。 2 | 3 | 有人说这不公平,学生考试用分数说话,和他们父母做了什么有何关系? 4 | 5 | 我有两点想法: 6 | 7 | 一、它并非不公平。 8 | 9 | 这些孩子,还是未成年人,父母去防疫一线,归期未知,甚至有生命危险,对他们的学习、生活与心理,都将产生不小的冲击,这可能会影响成绩。适当加点分,弥补这损失,我觉得是公平的。 10 | 11 | 况且,这符合天理人情。假想这些孩子就住在我们隔壁,在一群孩子里,我们肯定对他们更关照,就像对自己的孩子一样,这才是人正常的反应。中国人传统的价值观,认为一个人若是英雄义士,他的功德可以庇护子孙。现代的中国人,也会认同这个传统价值。 12 | 13 | 我不怀疑这种政策朴素的善意。我也愿意看到各地政府努力出政策褒奖一线抗疫的医务人员,他们已经被架得很高,无法再提报酬与补偿。其他人,尤其是政府,应该主动想这个问题,不然的话,就演变成专门欺负老实正派人,我知道你不好意思说,我也假装不知道,这事就这么过去了。这种“惩善扬恶”的事,我们平时见得可不少, 14 | 15 | 二、它不够聪明。 16 | 17 | 应该奖励一线抗疫的医务人员,这不会有什么争议。但这加分政策一出来,争议就来了,说明这政策不聪明,有漏洞。 18 | 19 | 对很多人来说,公平或不公平很难分辨,一项政策,需要不停去解释,逻辑绕几个弯,它大概率就是失败的政策。决策者的力量、智慧、善意,真要追求直击心灵的表述力,所以好的政治家都是表达大师,不会怪别人水平低,听不懂他的话。好的政策应该具有好的表述能力。 20 | 21 | 对一线抗疫的医务人员来说,加分政策也显得古怪,因为它无法普适。还没孩子的,没有结婚的,甚至还没有恋爱的,这些一线抗疫医务人员,子女加分政策就和他们没关系。产生一点委屈和失望,再正常不过吧?都在拼命,我就不需要爱护?这是生造出了矛盾。 22 | 23 | 什么是最普适的奖励?那就是钱,钱可以给每一个抗疫医务人员,每一个人也可用钱做自己最想做的事,这种奖励的效用最大,而且,反对的人最少。 24 | 25 | 真要表彰和感谢一线抗疫的医务人员,有诗吟得好:赞美诚可贵,金钱价更高,英雄不愿提,我们得有数。 -------------------------------------------------------------------------------- /0223/input/input.txt: -------------------------------------------------------------------------------- 1 | 连叔, 2 | 3 | 我们也被迫请阿姨了,她今天就要过来了。不知道为什么心理很忐忑,可能是第一次请?也可能是对她不放心?最大的可能是因为不知道怎么和一个陌生人相处。 4 | 5 | 如果相处的不错,两个孩子上学放学接送问题都要交给她了。老是各种担心,而且冒出一些没发生的极端的想法,本来是请来减轻我们两个的家务,做饭,带孩子的压力的,反而自己精神更紧张了。 6 | 7 | Jill 8 | 9 | 10 | Jill: 11 | 12 | 一个人生活要好,离不开阿姨。这是生活富裕后必然的社会分工。我一直认为,家政业大有前途,它没有门槛,技术难度不大,但好的阿姨又很抢手,收入不低。一个阿姨得到了雇主的信任,她一生的稳定性甚至超过许多雇主,可以同甘,不必共苦,雇主若事业发达,她的收入水涨船高,雇主若家道中落,用不起阿姨,她很快可以找到新东家。 13 | 14 | 阿姨这个行业,可信任度其实比别的行业高,那就是因为,这一行的核心竞争力是取得信任,并不在于家务做得特别出色。一个阿姨想保住工作,建立口碑,提升收入,只有通过雇主的信任这条路,其他行业可以取巧,这行却无旁门左道。 15 | 16 | 好阿姨的工作是不需要监督的,你越信任她,她做得越好。这是我几十年请阿姨的经验。她们最后都有我家的大门锁匙或密码,自行进出。 17 | 18 | 当然,我不是建议你盲目信任,我也遇过不靠谱的阿姨,客客气气把工钱结清,编个理由让她有台阶下,换人就是了,不是什么大事。我从小见识过人性恶,也活了半辈子,知道人性其实很靠不住,自己不强大,指望人性中善良友爱来帮助你,那希望渺茫。 19 | 20 | 但人性也是符合正态分布的,绝大多数人不好不坏,只是他人与环境的镜像,环境好一些,你信任他,他就呈现出善的人性;反之他就人性恶一些。基于这个事实,默认设置为相信他人,对自己有利,这样可以引发人性善,自己身边的小环境就更好。这么做,肯定要承担风险,不瞒你说,连叔这样的老江湖,偶尔还是要被坑,复盘找原因,都是因为太容易信任对方。有个大坑,去年底才爬出来,早先合作时,对方托了好朋友的关系,我完全放弃合同该有的制约,结果对方钱越欠越多,越多越不想给。 21 | 22 | 未来还会有坑,可这种风险是值得的,因为它的收益更大,没有信任的风险,就没有信任的收益。无法信任他人与世界,生活就会变得极为简陋。以请阿姨这事为例,有些人对这行充满偏见,他们认定阿姨一定会偷懒,手脚必然不干净,他们越是不停请阿姨,偏见越深,因为他们制造出了极端的小环境,好阿姨一看雇主这德性,迅速托辞离开,只有没人雇的坏阿姨才愿意留下斗智斗勇。他们于是如愿得到很糟糕的事实:阿姨要么不安心工作,要么就真是坏阿姨,所以不请阿姨是对的。这样的话,再多钱,他也无法享受生活,甚至烦恼更多,他得自己做一切家务,房子越大,家务越多。 23 | 24 | 无法信任,则无法合作。任何一个真有能量的人,从好阿姨到好企业家,你不是真心信任他,他都不愿与你合作,你也就无法借用他们的优秀成就自己,无法信任他人,必然是简陋的、痛苦的,将发展成受迫害幻想症。一个丰盛的人,在于他的生态是丰盛的,通过信任的联结,他为别人创造价值,别人也为他创造价值,螺旋型上升。 25 | 26 | 人的本能容易恐惧,信任他人,这也是学习过程。我们排除一个不值得信任的人,成本有限,你拒绝的同时,损失就停止。得到一个可以信任的人,收益无限,可以合作一生,可以享受他的成长。 27 | 28 | 祝开心。 29 | 30 | 连岳 -------------------------------------------------------------------------------- /0224/input/input.txt: -------------------------------------------------------------------------------- 1 | 昨天说到人性是正态分布的,不好不坏的人占多数。 2 | 3 | 正态分布是个很有用的概念,画成图就是钟形曲线,类似“几”字形。当我们知道某事的绝大多数的状态时,判断才准确。 4 | 5 | 钟形曲线有两种,一是两边封口,比如人的身高,不可能低于0米,也不可能高于3米。另一种两边不封口,极端事例虽然极少,但无限延伸,这叫做长尾正态分布。理解这种形态,在认知中更为重要。 6 | 7 | 人性就是长尾正态分布,多数人不好不坏,可好可坏,好坏杂糅,在好环境里,富足状态下,他更容易变好,在坏环境里,匮乏状态下,他更容易变坏。但有人纯粹极坏,只能从伤害毁灭他人中得到快乐;有人又纯粹极好,把他扔到任何环境,他都像天使一样。 8 | 9 | 长尾正态分布,还可以证明我们应该对人类的未来抱以乐观。是不是很神奇? 10 | 11 | 证明过程是这样的: 12 | 13 | 一、人类社会是知识驱动的,有了新知识,就有新产品。 14 | 15 | 二、人类的智力呈长尾正态分布,永远存在极少数极其聪明的人,他们在最前沿学习、思考、创造,他们得到新知识。 16 | 17 | 三、绝大多数人具有学习能力,新知识很快可以普及。比如天才才能发明轮子,但学习制造轮子并不难。如果没有图灵,人类可能现在也没有电脑,但只要有了他,电脑就成最常用的工具。人类可以凭借天才的发现,迅速实现整体的跃升。 18 | 19 | 未来永远都有新难题。这是事实,有人因此悲观。但是更要知道,这些难题人类可以解决,因为智力的长尾上有天才。就像新冠肺炎是新难题,但你知道有科学家一定可以找到药物和疫苗。 20 | 21 | 当新问题出现,即使你没有办法,也不要惊惶失措,最好的应对是镇定地等候。 22 | 23 | 曾有个哲学家被国王判处死刑。他请求缓刑,再给他两年时间。 24 | 25 | 国王问他理由。他说,我有奇能,两年内可教会陛下的爱马说话。 26 | 27 | 国王于是准了。 28 | 29 | 哲学家的好友不解,虽然你是伟大的哲学家,也不可能让马说话。 30 | 31 | 哲学家说,重点不在这里,重点在两年时间,这存在很多可能:国王可能死了,我可能死了,国王可能改变主意了,我可能逃跑了,还有,马可能真会说话了。 32 | 33 | 现在的难题,两年后都不是什么事,两年后,人们甚至都不太记得这次新冠肺炎。任何难题出现时,只要坚持住,都有办法,人类作为一个整体,是极其聪明的,智力有无限长尾,没有什么问题,解决不了。 34 | 35 | 悲观才是最大的问题,永远不要悲观。 -------------------------------------------------------------------------------- /0225/input/input.txt: -------------------------------------------------------------------------------- 1 | 因为“抢”口罩,大理一批官员被查处。 2 | 3 | 2月初,一批从云南运往重庆等地的口罩物资,被云南大理州下辖的大理市以“紧急征用”的方式扣留。 4 | 5 | 据云南省纪委监委官方网站2月24日通报,大理市委书记高志宏受到党内严重警告处分、免职处理,市长杜淑敢和副市长娄增辉受到撤销党内职务,政务撤职处分。共有地方两级党委、政府的8名责任人被问责。 6 | 7 | 这么严厉,有点在我意料之外。 8 | 9 | 不是说这严厉不对,它很对,这个“抢”口罩的行为,性质是侵犯产权,藐视法律。一切权利都是产权的延申,产权是权利之母。侵犯产权就是动摇文明社会的根基。但是“抢”口罩表面上看起来又显得轻微,事件刚发生时,一些人,尤其是大理人,还对这种行为表示支持,赞其“硬核”,“抢”别人的口罩给自己人用,够剽悍,他自己也没得好处,不是贪污受贿,似乎还是“爱民”之举。我也以为,这种“错误”,会被轻轻放过。 10 | 11 | 疫情发生以来,为人赞美的“硬核”举动,不少都在侵害人身权与财产权,把法律当废纸。但似乎又可以收获民心,因为一般人的认识水准,觉得是“好事”,把人的家门焊死,随意打砸、捆绑,是防止你传染他人,是为了彰显防疫的决心。“抢”几个口罩,更不算什么事。 12 | 13 | 他们说,非常时期,就不要拘泥于法律了。 14 | 15 | 可是,一到非常时期就被抛弃的法律,怎么配叫法律?就像一个人,平时像君子,一到非常时期,就是强盗和小偷,当然只是伪君子。 16 | 17 | 我担心这种行为,远甚于担心疫情。 18 | 19 | 疫情听起来可怕,但是现代医学一定能够找到办法控制它。疫情属于天灾的一种,人类的进化史,也伴随着一次次与疫情的搏斗,将来我们不乱吃野生动物,社会文明,生活健康,也还会有疫情。 20 | 21 | “抢”口罩,侵犯产权,却是标准的人祸。中国的地方主官,书记市长,权力很大。这是双刃剑,有抱负,有见识,想作为的,真可以提升辖区的水准,造福一方人。但是胡作非为的效率也一样高。我觉得,一个人当到了书记市长,能力肯定不弱,也属于仕途比较幸运,应该有格局,有尊严,有操守。产权,无知者才不尊重,盗贼才会去侵犯。地方大员,一急起来,就去侵犯产权,那是自甘堕落成盗贼。这种行为,也只能讨好那些无知的民众,真有见识的人,看了心里发凉。 22 | 23 | 疫情期间,似乎不止大理一地“抢”口罩的侵犯产权,但愿他们都被问责。这个国家的法律,官员率先违反,杀伤力比疫情厉害多了。 -------------------------------------------------------------------------------- /bili/input.md: -------------------------------------------------------------------------------- 1 | # 流言 2 | 3 | 今天是 2019 年 12 月 31 日,明天就是跨年了! 4 | 晚上有各大卫视跨年演出, 5 | 可是喜欢的偶像不在同一台,看谁呢? 6 | 我是武汉某大学的大二学生萨曼萨, 7 | 今年考试和过年都要早一些。 8 | 但是由于一些其他安排和春运订票困难, 9 | 只预订到了大年二十九的回家机票。 10 | 好想早点回家啊! 11 | “嗡嗡~”,微信群有新消息提示: 12 | “华南水果海鲜市场确诊了 7 例非典” 13 | 看到这条消息,我苦笑了一下。 14 | 那不就是在汉口吗,离我们就这十几公里。我感觉…… 15 | 16 | ## 无感 17 | 18 | 每天微信群的假消息也太多了吧。 19 | 不知道哪里闲人每天编造各种谣言。 20 | 是不是又是吸引眼球的自媒体求关注啊? 21 | 最烦这种毫无技术含量的假消息了。 22 | 一看又是闲聊群,只好退群保智商了。 23 | 24 | ## 疑虑 25 | 26 | 非典?当时我还在上小学。 27 | 我家虽然不是疫区,但是当年谣言可传的很厉害。 28 | 当时大家都挺害怕的,学校也停了一段时间课。 29 | 虽然记不太清情况,但是这个病应该是传染挺厉害的。 30 | 还是小心为妙,别去人多的地方玩了。 31 | 32 | # 辟谣 33 | 34 | 今天是 2020 年 1 月 2 日。 35 | 之前和几个好朋友约好今天去火锅餐厅。 36 | 天气又冷又潮,吃火锅最好了~ 37 | 好点早点回到北方啊,真怀念家里舒服的暖气。 38 | 39 | 微博上突然刷到了一条武汉公安局的通报。 40 | 8 人因散布“武汉肺炎”不实信息,被警方依法处理。 41 | 幸好自己没有随意转发。 42 | 以后可要注意了,微信还是不能乱发。 43 | 44 | 回忆起那条“谣言”,心里又打了下鼓。 45 | 火锅店的人可不少。 46 | 我们这个饭局是继续还是取消呢? 47 | 48 | ## 继续 49 | 50 | 谣言什么的最可恶了。干扰了我享受美食的好心情。 51 | 既然辟谣了有什么可怕的。 52 | 冬季流感和肺炎那么多,我们还能不吃饭了啊? 53 | 美味火锅走起~ 54 | 55 | ## 取消 56 | 57 | 这几天我又查了下非典的相关资料。 58 | 真是一看吓一跳啊。 59 | 呼吸道传染的疾病真是防不胜防。 60 | 连医生都有不少染病和致死的。 61 | 治愈后的后遗症也那么可怕。 62 | 63 | 算了多一事不如少一事。 64 | 还是取消聚餐,等放假回家再海吃补回来吧。 65 | 66 | # 人传人 67 | 68 | 今天是 2020 年 1 月 21 日。 69 | 这两天戴口罩的人多起来了。 70 | 我也去药店看了一下,并没有货。 71 | 好像是因为钟南山宣布肺炎存在人传人情况。 72 | 结果大家就有点过度紧张了。 73 | 我看了下通报的患病人数是两百多人。 74 | 武汉人口可是超一千万的啊。 75 | 才这么点比例怎么可能正巧在我身边传染我? 76 | 算了出门时戴个围巾凑合下吧。 77 | 反正后天我就回家啦! 78 | 79 | # 封城 80 | 81 | 今天是 2020 年 1 月 23 日。 82 | 怎么搞得怎么搞得,天还没亮起来准备去赶飞机。 83 | 突然看到个封城公告是闹哪样? 84 | 上午 10 时起机场火车站不让离开武汉, 85 | 连公交地铁长途也停止运营?? 86 | 我还从没听过历史上有这种封城的操作啊! 87 | 这是要肺炎要爆发的节奏吗? 88 | 这两天已经人心惶惶了,我想回家! 89 | 90 | 打电话给航空公司说我 9 点 55 的航班还可以安排值机。 91 | 但是能不能走不敢保证,政策太突然了。 92 | 但是十点前可以免手续费退机票款。 93 | 我去,怎么办呢? 94 | 95 | ## 冒险去机场 96 | 97 | 谁知道什么时候才解封?我要逃出去! 98 | 没心情收拾洗漱了,赶紧拎东西出发。 99 | 临时翻出一个旧的布口罩戴上, 100 | 拖上行李就赶往机场。 101 | 虽然打车难,路上也有些堵,还是安全上了飞机。 102 | 拜拜啦武汉,明年见。 103 | 104 | ## 退票另想办法 105 | 106 | 糟透了,我买的可是春运的高价机票。 107 | 要是冲过去机场,飞不回去又退不掉可麻烦了。 108 | 而且机场和飞机上全是人,密闭环境那么长时间共处接触, 109 | 我还没有专业口罩用,风险太高了。 110 | 保险起见还是退票吧。 111 | 还得给家里打电话好好说说…… 112 | 113 | # 双黄连 114 | 115 | 今年是 2020 年 2 月 1 日。 116 | 今年的春节过的太可怕了。 117 | 情况急转直下,人人自危。 118 | 老家的除夕团聚和互相拜年活动都取消了。 119 | 昨天有消息说双黄连可以抑制新冠病毒, 120 | 本来我还没当回事,但是后来央视新闻都报道了。 121 | 怎么办,要不要去备一些来预防呢? 122 | 123 | ## 出去买药 124 | 125 | 这么多日子没见到人山人海的景象了。 126 | 药店都在排长队疯抢,很多已经断货了。 127 | 跑到第三家时终于有货了,虽然限购一盒。 128 | 排队时后面的大爷带着黑口罩,咳嗽个不停。 129 | 还要有好朋友匀给了我一个 N95 口罩。 130 | 拿到药感觉安全多了。 131 | 回家赶紧吃上预防吧。 132 | 133 | ## bad end 1 134 | 135 | 今天是 2020 年 2 月 11 日。 136 | 确诊第三天了。 137 | 本来发烧头疼的症状都不算严重, 138 | 可是今天状况一下子糟糕了。 139 | 身体一点动不了,发不出任何声音。 140 | 好急躁好生气啊。 141 | 后悔了无数次,为什么这么大意。 142 | 状况这么危险还凑热闹染上了病。 143 | 这些神奇的中药吃了那么多,到底管了什么用…… 144 | 我的生命真的要这么着急的结束吗? 145 | 心里大声呼喊着: 146 | 妈妈!爸爸!妈……妈…… 147 | The end。 148 | 149 | ## 不去买 150 | 151 | 我信了你的邪。 152 | 发现和确证都要花那么久。 153 | 一晚上就能研究出神奇药物吗? 154 | 而且又是成品中药, 155 | 非典时候就靠板蓝根收割了一波了。 156 | 这些人怎么那么有脸。 157 | 158 | 中药奸商就不提了, 159 | 法律和媒体怎么也各种给中药乱开绿灯。 160 | 对人体和药物认识不够的时候, 161 | 只能靠什么神神鬼鬼或者个人经验主义。 162 | 现在不是有科学严格的药物测试和临床验证流程吗? 163 | 为啥还破不掉这些不做研究不做验证的中药迷信。 164 | 敢让它们随便上市随便进病人的嘴。 165 | 166 | 我是绝对不会发疯去抢的。 167 | 这个时候去药店挤,怕是没病都要染上病吧。 168 | 169 | ## 求助他人 170 | 171 | 感觉中药很不靠谱,还是不冒险出去买了。 172 | 正好隔壁的朋友抢回来 2 大袋,分给我一盒。 173 | 虽然不一定管什么用,吃点也没啥坏处吧。 174 | 图个心安,还是每天吃一点看看能否预防吧。 175 | 真希望疫情能快点过去啊…… 176 | 177 | # 出现症状 178 | 179 | 今天是 2020 年 2 月 11 日。 180 | 181 | 喉咙发干,想咳嗽,体温一量 38 度,头疼无力。 182 | 我应该是感染了吧。 183 | 回顾一下前几日的行程。 184 | 在超市有人咳嗽,在小区门口登记时有排长队。 185 | 186 | # 未完待续 187 | 188 | 本故事未完待续,逐步更新。 189 | 互动视频制作不易,求关注求三连求分享~ 190 | 非常感谢! 191 | -------------------------------------------------------------------------------- /fonts/_思源黑体SourceHanSansCN-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/todokku/tinyVideoFromText/2482d1b8c1370ffc704f3ddb423e231e5ebe6a98/fonts/_思源黑体SourceHanSansCN-Bold.otf -------------------------------------------------------------------------------- /fonts/font.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/todokku/tinyVideoFromText/2482d1b8c1370ffc704f3ddb423e231e5ebe6a98/fonts/font.otf -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { bgRename, renameBot } = require("./src/utils"); 2 | 3 | const { initPath, clearPreviousFiles } = require("./src/init"); 4 | const { stringToPng } = require("./src/text2svg"); 5 | const { readAll } = require("./src/readText"); 6 | const { merge } = require("./src/mergeMP3"); 7 | const { randomBgCopy } = require("./src/randomBgCopy"); 8 | const { addBgm, generateBGM } = require("./src/addBgm"); 9 | const { addJpg } = require("./src/addJpg"); 10 | const { addText } = require("./src/addText"); 11 | 12 | async function main() { 13 | global.config = initPath("./0226"); //写入全局配置文件 14 | let time = 250.956; 15 | clearPreviousFiles(); 16 | await readAll(); 17 | time = await merge(); 18 | await generateBGM(time); 19 | await addBgm(time); 20 | await randomBgCopy(time); 21 | bgRename(); 22 | await addJpg(time); 23 | await addText(); 24 | } 25 | 26 | main(); 27 | -------------------------------------------------------------------------------- /merged/result.srt: -------------------------------------------------------------------------------- 1 | 1 2 | 00:00:00,000 --> 00:00:02,556 3 | 疫情之后,房价会如何? 4 | 5 | 2 6 | 00:00:02,556 --> 00:00:05,363 7 | 这是近几天多起来的读者问题。 8 | 9 | 3 10 | 00:00:05,363 --> 00:00:09,179 11 | 房价最终是经济的体现,经济发达则房价高。 12 | 13 | 4 14 | 00:00:09,179 --> 00:00:13,644 15 | 判断疫情对房价的影响,得先判断疫情对经济的影响。 16 | 17 | 5 18 | 00:00:13,644 --> 00:00:17,460 19 | 有极端悲观者,认为中国经济从此将垮掉。 20 | 21 | 6 22 | 00:00:17,460 --> 00:00:23,112 23 | 如果你是一个容易悲观的人,最近密集接受坏消息的轰炸,可能会有这种假想: 24 | 25 | 7 26 | 00:00:23,112 --> 00:00:27,108 27 | 几个月后,企业大规模倒闭,企业主先倒霉; 28 | 29 | 8 30 | 00:00:27,108 --> 00:00:31,608 31 | 这产生大量的失业,再过一段时间,失业者耗尽积蓄, 32 | 33 | 9 34 | 00:00:31,608 --> 00:00:34,847 35 | 发现自己的命运是和企业主捆绑在一起的, 36 | 37 | 10 38 | 00:00:34,847 --> 00:00:38,159 39 | 开始还不起房贷,生活费都成问题; 40 | 41 | 11 42 | 00:00:38,159 --> 00:00:43,559 43 | 而政府由于没有企业可以收税,国库空虚,失去救援民众的能量。 44 | 45 | 12 46 | 00:00:43,559 --> 00:00:49,751 47 | 这种情况发生,房价当然一泄千里,覆巢之下,每个人的蛋都要摔破。 48 | 49 | 13 50 | 00:00:49,751 --> 00:00:51,407 51 | 但它不会发生。 52 | 53 | 14 54 | 00:00:51,407 --> 00:00:57,275 55 | 即使疫情不结束,一个月后,农民戴着口罩种田,工人戴着口罩生产, 56 | 57 | 15 58 | 00:00:57,275 --> 00:01:01,775 59 | 两三个月后,政府急迫地鼓励(极端的甚至强制)企业开工, 60 | 61 | 16 62 | 00:01:01,775 --> 00:01:04,043 63 | 生存问题升格为第一问题, 64 | 65 | 17 66 | 00:01:04,043 --> 00:01:07,679 67 | 毕竟,只要持续饿,死亡率是100%, 68 | 69 | 18 70 | 00:01:07,679 --> 00:01:11,387 71 | 比新冠肺炎厉害多了,两害相权取其轻。 72 | 73 | 19 74 | 00:01:11,387 --> 00:01:19,919 75 | 何况,疫情很快将会结束。它对中国经济的影响,只是一个短期冲击,长期来看,只是一个小波澜。 76 | 77 | 20 78 | 00:01:19,919 --> 00:01:27,947 79 | 在这个短期内,你的企业撑得住,你的积蓄用不完,你甚至会获得优势,因为不幸的倒闭者让出了市场份额。 80 | 81 | 21 82 | 00:01:27,947 --> 00:01:33,995 83 | 这样,我们可以得出结论:疫情对房价的影响是短期的,改变不了大趋势。 84 | 85 | 22 86 | 00:01:33,995 --> 00:01:44,363 87 | 短期内,有些负债率极高的房企,不得不亏本抛售,有些赌徒式的购房者,也只能割肉,可能会有一些便宜捡,不过那是零星事件。 88 | 89 | 23 90 | 00:01:44,363 --> 00:01:51,095 91 | 而疫情中出现的一些变化,对房价的助推作用,过比较长的一段时间后,才会显现。 92 | 93 | 24 94 | 00:01:51,095 --> 00:02:01,859 95 | 一是货币投放的增加。灾难之后,用货币放水刺激经济,这是现代政府的标准动作(在这里不探讨是否符合市场规律,只描述现实)。 96 | 97 | 25 98 | 00:02:01,859 --> 00:02:07,007 99 | 目前为止,政府投放的货币,以万亿计了。后续还有更多。 100 | 101 | 26 102 | 00:02:07,007 --> 00:02:14,747 103 | 钱增加得快,物增长得慢,价格就得涨,尤其是好物,涨得更快,好房子,就是好物中的好物。 104 | 105 | 27 106 | 00:02:14,747 --> 00:02:21,407 107 | 二是观念的改变。所谓的租售同权出台后,很多人欢呼,以为不用当房奴了。 108 | 109 | 28 110 | 00:02:21,407 --> 00:02:26,735 111 | 可是一个租户,在这次疫情中,假期归来,被挡在小区大门之外。 112 | 113 | 29 114 | 00:02:26,735 --> 00:02:34,799 115 | 不少地方出台政策,对有房户与租户区别对待,租户进不了房,酒店又都停业,一下变成了流浪者。 116 | 117 | 30 118 | 00:02:34,799 --> 00:02:40,199 119 | 这种政策,当然不合理,简单粗暴,反映出极低的管理水平。 120 | 121 | 31 122 | 00:02:40,199 --> 00:02:44,987 123 | 不过,倒也让人清醒地知道,有房与无房,是两个阶级。 124 | 125 | 32 126 | 00:02:44,987 --> 00:02:52,548 127 | 在灾难之中,先被动的,先受害的,是无房阶级。这次很多人会下决心拥有自己的房子。 128 | 129 | 33 130 | 00:02:52,548 --> 00:02:57,264 131 | 安心拥有你的房子,或者,认真开始实行你的购房计划。 132 | 133 | 34 134 | 00:02:57,264 --> 00:03:02,052 135 | 有自己一间房子,再小,都更能保障自己的安全与权利。 136 | 137 | 35 138 | 00:03:02,052 --> 00:03:05,724 139 | 繁荣时,可升值,灾难时,可避难。 140 | 141 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "video", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "13.7.1", 9 | "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-13.7.1.tgz?cache=0&sync_timestamp=1581452012338&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-13.7.1.tgz", 10 | "integrity": "sha1-I46zSmZDG3HSqt3qp9sWbyWXGg0=" 11 | }, 12 | "ajv": { 13 | "version": "6.11.0", 14 | "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.11.0.tgz", 15 | "integrity": "sha1-w2B8vIrjktilpTbyWyH45fP4f+k=", 16 | "requires": { 17 | "fast-deep-equal": "^3.1.1", 18 | "fast-json-stable-stringify": "^2.0.0", 19 | "json-schema-traverse": "^0.4.1", 20 | "uri-js": "^4.2.2" 21 | } 22 | }, 23 | "ansi-regex": { 24 | "version": "2.1.1", 25 | "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", 26 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 27 | }, 28 | "aproba": { 29 | "version": "1.2.0", 30 | "resolved": "http://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz", 31 | "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=" 32 | }, 33 | "are-we-there-yet": { 34 | "version": "1.1.5", 35 | "resolved": "http://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz", 36 | "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", 37 | "requires": { 38 | "delegates": "^1.0.0", 39 | "readable-stream": "^2.0.6" 40 | } 41 | }, 42 | "asn1": { 43 | "version": "0.2.4", 44 | "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", 45 | "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", 46 | "requires": { 47 | "safer-buffer": "~2.1.0" 48 | } 49 | }, 50 | "assert-plus": { 51 | "version": "1.0.0", 52 | "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", 53 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 54 | }, 55 | "async": { 56 | "version": "3.1.1", 57 | "resolved": "https://registry.npm.taobao.org/async/download/async-3.1.1.tgz", 58 | "integrity": "sha1-3TVC2wPeg3l5yeu8pkygGwbcmN8=" 59 | }, 60 | "asynckit": { 61 | "version": "0.4.0", 62 | "resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", 63 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 64 | }, 65 | "aws-sign2": { 66 | "version": "0.7.0", 67 | "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", 68 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 69 | }, 70 | "aws4": { 71 | "version": "1.9.1", 72 | "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.9.1.tgz", 73 | "integrity": "sha1-fjPY99RJs/ZzzXLeuavcVS2+Uo4=" 74 | }, 75 | "baidu-aip-sdk": { 76 | "version": "2.4.5", 77 | "resolved": "https://registry.npm.taobao.org/baidu-aip-sdk/download/baidu-aip-sdk-2.4.5.tgz", 78 | "integrity": "sha1-DHKG/gMZCBOR5VEndKlF6bOc5NA=", 79 | "requires": { 80 | "debug": "^2.6.0", 81 | "iconv-lite": "^0.4.15", 82 | "keep-alive-agent": "0.0.1", 83 | "mocha": "^4.0.1", 84 | "request": "^2.79.0", 85 | "should": "^13.2.0", 86 | "underscore": "^1.8.3" 87 | } 88 | }, 89 | "balanced-match": { 90 | "version": "1.0.0", 91 | "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz", 92 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 93 | "optional": true 94 | }, 95 | "bcrypt-pbkdf": { 96 | "version": "1.0.2", 97 | "resolved": "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", 98 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 99 | "requires": { 100 | "tweetnacl": "^0.14.3" 101 | } 102 | }, 103 | "bl": { 104 | "version": "3.0.0", 105 | "resolved": "https://registry.npm.taobao.org/bl/download/bl-3.0.0.tgz", 106 | "integrity": "sha1-NhHsAFef0YVhdUNgsh6feEUA/4g=", 107 | "requires": { 108 | "readable-stream": "^3.0.1" 109 | }, 110 | "dependencies": { 111 | "readable-stream": { 112 | "version": "3.6.0", 113 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-3.6.0.tgz", 114 | "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", 115 | "requires": { 116 | "inherits": "^2.0.3", 117 | "string_decoder": "^1.1.1", 118 | "util-deprecate": "^1.0.1" 119 | } 120 | } 121 | } 122 | }, 123 | "boolbase": { 124 | "version": "1.0.0", 125 | "resolved": "http://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz", 126 | "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" 127 | }, 128 | "brace-expansion": { 129 | "version": "1.1.11", 130 | "resolved": "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", 131 | "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", 132 | "optional": true, 133 | "requires": { 134 | "balanced-match": "^1.0.0", 135 | "concat-map": "0.0.1" 136 | } 137 | }, 138 | "browser-stdout": { 139 | "version": "1.3.0", 140 | "resolved": "https://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.0.tgz", 141 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 142 | "optional": true 143 | }, 144 | "caseless": { 145 | "version": "0.12.0", 146 | "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", 147 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 148 | }, 149 | "cheerio": { 150 | "version": "1.0.0-rc.3", 151 | "resolved": "https://registry.npm.taobao.org/cheerio/download/cheerio-1.0.0-rc.3.tgz", 152 | "integrity": "sha1-CUY21CWy6cD065GkbAVjDJoai/Y=", 153 | "requires": { 154 | "css-select": "~1.2.0", 155 | "dom-serializer": "~0.1.1", 156 | "entities": "~1.1.1", 157 | "htmlparser2": "^3.9.1", 158 | "lodash": "^4.15.0", 159 | "parse5": "^3.0.1" 160 | } 161 | }, 162 | "chownr": { 163 | "version": "1.1.4", 164 | "resolved": "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz", 165 | "integrity": "sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs=" 166 | }, 167 | "code-point-at": { 168 | "version": "1.1.0", 169 | "resolved": "http://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", 170 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 171 | }, 172 | "color": { 173 | "version": "3.1.2", 174 | "resolved": "https://registry.npm.taobao.org/color/download/color-3.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolor%2Fdownload%2Fcolor-3.1.2.tgz", 175 | "integrity": "sha1-aBSOf4XUGtdknF+oyBBvCY0inhA=", 176 | "requires": { 177 | "color-convert": "^1.9.1", 178 | "color-string": "^1.5.2" 179 | } 180 | }, 181 | "color-convert": { 182 | "version": "1.9.3", 183 | "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", 184 | "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", 185 | "requires": { 186 | "color-name": "1.1.3" 187 | } 188 | }, 189 | "color-name": { 190 | "version": "1.1.3", 191 | "resolved": "http://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz", 192 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 193 | }, 194 | "color-string": { 195 | "version": "1.5.3", 196 | "resolved": "http://registry.npm.taobao.org/color-string/download/color-string-1.5.3.tgz", 197 | "integrity": "sha1-ybvF8BtYtUkvPWhXRZy2WQziBMw=", 198 | "requires": { 199 | "color-name": "^1.0.0", 200 | "simple-swizzle": "^0.2.2" 201 | } 202 | }, 203 | "combined-stream": { 204 | "version": "1.0.8", 205 | "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", 206 | "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", 207 | "requires": { 208 | "delayed-stream": "~1.0.0" 209 | } 210 | }, 211 | "commander": { 212 | "version": "2.11.0", 213 | "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.11.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.11.0.tgz", 214 | "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=" 215 | }, 216 | "concat-map": { 217 | "version": "0.0.1", 218 | "resolved": "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz", 219 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 220 | "optional": true 221 | }, 222 | "console-control-strings": { 223 | "version": "1.1.0", 224 | "resolved": "http://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz", 225 | "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 226 | }, 227 | "core-util-is": { 228 | "version": "1.0.2", 229 | "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", 230 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 231 | }, 232 | "css-select": { 233 | "version": "1.2.0", 234 | "resolved": "https://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz", 235 | "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", 236 | "requires": { 237 | "boolbase": "~1.0.0", 238 | "css-what": "2.1", 239 | "domutils": "1.5.1", 240 | "nth-check": "~1.0.1" 241 | } 242 | }, 243 | "css-what": { 244 | "version": "2.1.3", 245 | "resolved": "https://registry.npm.taobao.org/css-what/download/css-what-2.1.3.tgz", 246 | "integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI=" 247 | }, 248 | "dashdash": { 249 | "version": "1.14.1", 250 | "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", 251 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 252 | "requires": { 253 | "assert-plus": "^1.0.0" 254 | } 255 | }, 256 | "debug": { 257 | "version": "2.6.9", 258 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", 259 | "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", 260 | "requires": { 261 | "ms": "2.0.0" 262 | } 263 | }, 264 | "decompress-response": { 265 | "version": "4.2.1", 266 | "resolved": "https://registry.npm.taobao.org/decompress-response/download/decompress-response-4.2.1.tgz?cache=0&sync_timestamp=1572616776694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdecompress-response%2Fdownload%2Fdecompress-response-4.2.1.tgz", 267 | "integrity": "sha1-QUAjzHowLaJc4uyC0NUjjMr9iYY=", 268 | "requires": { 269 | "mimic-response": "^2.0.0" 270 | } 271 | }, 272 | "deep-extend": { 273 | "version": "0.6.0", 274 | "resolved": "http://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz", 275 | "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=" 276 | }, 277 | "delayed-stream": { 278 | "version": "1.0.0", 279 | "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", 280 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 281 | }, 282 | "delegates": { 283 | "version": "1.0.0", 284 | "resolved": "http://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", 285 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" 286 | }, 287 | "detect-libc": { 288 | "version": "1.0.3", 289 | "resolved": "http://registry.npm.taobao.org/detect-libc/download/detect-libc-1.0.3.tgz", 290 | "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" 291 | }, 292 | "diff": { 293 | "version": "3.3.1", 294 | "resolved": "https://registry.npm.taobao.org/diff/download/diff-3.3.1.tgz", 295 | "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=", 296 | "optional": true 297 | }, 298 | "dom-serializer": { 299 | "version": "0.1.1", 300 | "resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.1.tgz", 301 | "integrity": "sha1-HsQFnihLq+027sKUHUqXChic58A=", 302 | "requires": { 303 | "domelementtype": "^1.3.0", 304 | "entities": "^1.1.1" 305 | } 306 | }, 307 | "domelementtype": { 308 | "version": "1.3.1", 309 | "resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz", 310 | "integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8=" 311 | }, 312 | "domhandler": { 313 | "version": "2.4.2", 314 | "resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz?cache=0&sync_timestamp=1564708909977&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomhandler%2Fdownload%2Fdomhandler-2.4.2.tgz", 315 | "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=", 316 | "requires": { 317 | "domelementtype": "1" 318 | } 319 | }, 320 | "domutils": { 321 | "version": "1.5.1", 322 | "resolved": "https://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz", 323 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", 324 | "requires": { 325 | "dom-serializer": "0", 326 | "domelementtype": "1" 327 | } 328 | }, 329 | "ecc-jsbn": { 330 | "version": "0.1.2", 331 | "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", 332 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 333 | "requires": { 334 | "jsbn": "~0.1.0", 335 | "safer-buffer": "^2.1.0" 336 | } 337 | }, 338 | "end-of-stream": { 339 | "version": "1.4.4", 340 | "resolved": "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz?cache=0&sync_timestamp=1569416272686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fend-of-stream%2Fdownload%2Fend-of-stream-1.4.4.tgz", 341 | "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", 342 | "requires": { 343 | "once": "^1.4.0" 344 | } 345 | }, 346 | "entities": { 347 | "version": "1.1.2", 348 | "resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz", 349 | "integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=" 350 | }, 351 | "escape-string-regexp": { 352 | "version": "1.0.5", 353 | "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", 354 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 355 | "optional": true 356 | }, 357 | "expand-template": { 358 | "version": "2.0.3", 359 | "resolved": "https://registry.npm.taobao.org/expand-template/download/expand-template-2.0.3.tgz", 360 | "integrity": "sha1-bhSz/O4POmNA7LV9LokYaSBSpHw=" 361 | }, 362 | "extend": { 363 | "version": "3.0.2", 364 | "resolved": "http://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", 365 | "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" 366 | }, 367 | "extsprintf": { 368 | "version": "1.3.0", 369 | "resolved": "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", 370 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 371 | }, 372 | "fast-deep-equal": { 373 | "version": "3.1.1", 374 | "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz", 375 | "integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ=" 376 | }, 377 | "fast-json-stable-stringify": { 378 | "version": "2.1.0", 379 | "resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz", 380 | "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=" 381 | }, 382 | "fluent-ffmpeg": { 383 | "version": "2.1.2", 384 | "resolved": "https://registry.npm.taobao.org/fluent-ffmpeg/download/fluent-ffmpeg-2.1.2.tgz", 385 | "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=", 386 | "requires": { 387 | "async": ">=0.2.9", 388 | "which": "^1.1.1" 389 | } 390 | }, 391 | "forever-agent": { 392 | "version": "0.6.1", 393 | "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", 394 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 395 | }, 396 | "form-data": { 397 | "version": "2.3.3", 398 | "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", 399 | "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", 400 | "requires": { 401 | "asynckit": "^0.4.0", 402 | "combined-stream": "^1.0.6", 403 | "mime-types": "^2.1.12" 404 | } 405 | }, 406 | "fs-constants": { 407 | "version": "1.0.0", 408 | "resolved": "https://registry.npm.taobao.org/fs-constants/download/fs-constants-1.0.0.tgz", 409 | "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=" 410 | }, 411 | "fs-minipass": { 412 | "version": "2.1.0", 413 | "resolved": "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-2.1.0.tgz", 414 | "integrity": "sha1-f1A2/b8SxjwWkZDL5BmchSJx+fs=", 415 | "requires": { 416 | "minipass": "^3.0.0" 417 | } 418 | }, 419 | "fs.realpath": { 420 | "version": "1.0.0", 421 | "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", 422 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 423 | "optional": true 424 | }, 425 | "gauge": { 426 | "version": "2.7.4", 427 | "resolved": "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz", 428 | "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", 429 | "requires": { 430 | "aproba": "^1.0.3", 431 | "console-control-strings": "^1.0.0", 432 | "has-unicode": "^2.0.0", 433 | "object-assign": "^4.1.0", 434 | "signal-exit": "^3.0.0", 435 | "string-width": "^1.0.1", 436 | "strip-ansi": "^3.0.1", 437 | "wide-align": "^1.1.0" 438 | } 439 | }, 440 | "getpass": { 441 | "version": "0.1.7", 442 | "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", 443 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 444 | "requires": { 445 | "assert-plus": "^1.0.0" 446 | } 447 | }, 448 | "github-from-package": { 449 | "version": "0.0.0", 450 | "resolved": "https://registry.npm.taobao.org/github-from-package/download/github-from-package-0.0.0.tgz", 451 | "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" 452 | }, 453 | "glob": { 454 | "version": "7.1.2", 455 | "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.2.tgz", 456 | "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", 457 | "optional": true, 458 | "requires": { 459 | "fs.realpath": "^1.0.0", 460 | "inflight": "^1.0.4", 461 | "inherits": "2", 462 | "minimatch": "^3.0.4", 463 | "once": "^1.3.0", 464 | "path-is-absolute": "^1.0.0" 465 | } 466 | }, 467 | "growl": { 468 | "version": "1.10.3", 469 | "resolved": "https://registry.npm.taobao.org/growl/download/growl-1.10.3.tgz", 470 | "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=", 471 | "optional": true 472 | }, 473 | "har-schema": { 474 | "version": "2.0.0", 475 | "resolved": "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", 476 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 477 | }, 478 | "har-validator": { 479 | "version": "5.1.3", 480 | "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz", 481 | "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=", 482 | "requires": { 483 | "ajv": "^6.5.5", 484 | "har-schema": "^2.0.0" 485 | } 486 | }, 487 | "has-flag": { 488 | "version": "2.0.0", 489 | "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-2.0.0.tgz", 490 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", 491 | "optional": true 492 | }, 493 | "has-unicode": { 494 | "version": "2.0.1", 495 | "resolved": "http://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz", 496 | "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" 497 | }, 498 | "he": { 499 | "version": "1.1.1", 500 | "resolved": "http://registry.npm.taobao.org/he/download/he-1.1.1.tgz", 501 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 502 | "optional": true 503 | }, 504 | "htmlparser2": { 505 | "version": "3.10.1", 506 | "resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz", 507 | "integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=", 508 | "requires": { 509 | "domelementtype": "^1.3.1", 510 | "domhandler": "^2.3.0", 511 | "domutils": "^1.5.1", 512 | "entities": "^1.1.1", 513 | "inherits": "^2.0.1", 514 | "readable-stream": "^3.1.1" 515 | }, 516 | "dependencies": { 517 | "readable-stream": { 518 | "version": "3.6.0", 519 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-3.6.0.tgz", 520 | "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", 521 | "requires": { 522 | "inherits": "^2.0.3", 523 | "string_decoder": "^1.1.1", 524 | "util-deprecate": "^1.0.1" 525 | } 526 | } 527 | } 528 | }, 529 | "http-signature": { 530 | "version": "1.2.0", 531 | "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1572997300808&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz", 532 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 533 | "requires": { 534 | "assert-plus": "^1.0.0", 535 | "jsprim": "^1.2.2", 536 | "sshpk": "^1.7.0" 537 | } 538 | }, 539 | "iconv": { 540 | "version": "2.3.5", 541 | "resolved": "https://registry.npm.taobao.org/iconv/download/iconv-2.3.5.tgz", 542 | "integrity": "sha1-X5uWEvWxUxMoZ0jQMMb/Ke/e+jM=", 543 | "requires": { 544 | "nan": "^2.14.0", 545 | "safer-buffer": "^2.1.2" 546 | } 547 | }, 548 | "iconv-lite": { 549 | "version": "0.4.24", 550 | "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1579334008444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz", 551 | "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=", 552 | "requires": { 553 | "safer-buffer": ">= 2.1.2 < 3" 554 | } 555 | }, 556 | "inflight": { 557 | "version": "1.0.6", 558 | "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz", 559 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 560 | "optional": true, 561 | "requires": { 562 | "once": "^1.3.0", 563 | "wrappy": "1" 564 | } 565 | }, 566 | "inherits": { 567 | "version": "2.0.4", 568 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz?cache=0&sync_timestamp=1560975547815&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finherits%2Fdownload%2Finherits-2.0.4.tgz", 569 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" 570 | }, 571 | "ini": { 572 | "version": "1.3.5", 573 | "resolved": "http://registry.npm.taobao.org/ini/download/ini-1.3.5.tgz", 574 | "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" 575 | }, 576 | "is-arrayish": { 577 | "version": "0.3.2", 578 | "resolved": "http://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.3.2.tgz", 579 | "integrity": "sha1-RXSirlb3qyBolvtDHq7tBm/fjwM=" 580 | }, 581 | "is-fullwidth-code-point": { 582 | "version": "1.0.0", 583 | "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", 584 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 585 | "requires": { 586 | "number-is-nan": "^1.0.0" 587 | } 588 | }, 589 | "is-typedarray": { 590 | "version": "1.0.0", 591 | "resolved": "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", 592 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 593 | }, 594 | "isarray": { 595 | "version": "1.0.0", 596 | "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz?cache=0&sync_timestamp=1562592125418&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisarray%2Fdownload%2Fisarray-1.0.0.tgz", 597 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 598 | }, 599 | "isexe": { 600 | "version": "2.0.0", 601 | "resolved": "http://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", 602 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 603 | }, 604 | "isstream": { 605 | "version": "0.1.2", 606 | "resolved": "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", 607 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 608 | }, 609 | "jsbn": { 610 | "version": "0.1.1", 611 | "resolved": "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", 612 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 613 | }, 614 | "jschardet": { 615 | "version": "2.1.1", 616 | "resolved": "https://registry.npm.taobao.org/jschardet/download/jschardet-2.1.1.tgz", 617 | "integrity": "sha1-r2+P0LOw9dRqj9lhSk/OSQV1wYQ=" 618 | }, 619 | "json-schema": { 620 | "version": "0.2.3", 621 | "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", 622 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 623 | }, 624 | "json-schema-traverse": { 625 | "version": "0.4.1", 626 | "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", 627 | "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=" 628 | }, 629 | "json-stringify-safe": { 630 | "version": "5.0.1", 631 | "resolved": "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", 632 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 633 | }, 634 | "jsprim": { 635 | "version": "1.4.1", 636 | "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", 637 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 638 | "requires": { 639 | "assert-plus": "1.0.0", 640 | "extsprintf": "1.3.0", 641 | "json-schema": "0.2.3", 642 | "verror": "1.10.0" 643 | } 644 | }, 645 | "keep-alive-agent": { 646 | "version": "0.0.1", 647 | "resolved": "https://registry.npm.taobao.org/keep-alive-agent/download/keep-alive-agent-0.0.1.tgz", 648 | "integrity": "sha1-RIR8o5TOjWtSGuhYFr1kUJlCs4U=" 649 | }, 650 | "lodash": { 651 | "version": "4.17.15", 652 | "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz", 653 | "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=" 654 | }, 655 | "mime-db": { 656 | "version": "1.43.0", 657 | "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.43.0.tgz?cache=0&sync_timestamp=1578281193492&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.43.0.tgz", 658 | "integrity": "sha1-ChLgUCZQ5HPXNVNQUOfI9OtPrlg=" 659 | }, 660 | "mime-types": { 661 | "version": "2.1.26", 662 | "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.26.tgz?cache=0&sync_timestamp=1578282566609&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.26.tgz", 663 | "integrity": "sha1-nJIfwJt+FJpl39wNpNIJlyALCgY=", 664 | "requires": { 665 | "mime-db": "1.43.0" 666 | } 667 | }, 668 | "mimic-response": { 669 | "version": "2.0.0", 670 | "resolved": "https://registry.npm.taobao.org/mimic-response/download/mimic-response-2.0.0.tgz", 671 | "integrity": "sha1-mWpRxgrfEsuKh9f7jvJMLz1eu0Y=" 672 | }, 673 | "minimatch": { 674 | "version": "3.0.4", 675 | "resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz", 676 | "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", 677 | "optional": true, 678 | "requires": { 679 | "brace-expansion": "^1.1.7" 680 | } 681 | }, 682 | "minimist": { 683 | "version": "0.0.8", 684 | "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz", 685 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 686 | }, 687 | "minipass": { 688 | "version": "3.1.1", 689 | "resolved": "https://registry.npm.taobao.org/minipass/download/minipass-3.1.1.tgz?cache=0&sync_timestamp=1571953003467&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminipass%2Fdownload%2Fminipass-3.1.1.tgz", 690 | "integrity": "sha1-dgfOd4RyoYWtbYkIKqIHD3nO3NU=", 691 | "requires": { 692 | "yallist": "^4.0.0" 693 | } 694 | }, 695 | "minizlib": { 696 | "version": "2.1.0", 697 | "resolved": "https://registry.npm.taobao.org/minizlib/download/minizlib-2.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminizlib%2Fdownload%2Fminizlib-2.1.0.tgz", 698 | "integrity": "sha1-/VLGRTAe8JpjosIJaXwpTGzgLPM=", 699 | "requires": { 700 | "minipass": "^3.0.0", 701 | "yallist": "^4.0.0" 702 | } 703 | }, 704 | "mkdirp": { 705 | "version": "0.5.1", 706 | "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz", 707 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 708 | "requires": { 709 | "minimist": "0.0.8" 710 | } 711 | }, 712 | "mocha": { 713 | "version": "4.1.0", 714 | "resolved": "https://registry.npm.taobao.org/mocha/download/mocha-4.1.0.tgz", 715 | "integrity": "sha1-fYbPvPNcuCnidUwy4XNV7AUzh5Q=", 716 | "optional": true, 717 | "requires": { 718 | "browser-stdout": "1.3.0", 719 | "commander": "2.11.0", 720 | "debug": "3.1.0", 721 | "diff": "3.3.1", 722 | "escape-string-regexp": "1.0.5", 723 | "glob": "7.1.2", 724 | "growl": "1.10.3", 725 | "he": "1.1.1", 726 | "mkdirp": "0.5.1", 727 | "supports-color": "4.4.0" 728 | }, 729 | "dependencies": { 730 | "debug": { 731 | "version": "3.1.0", 732 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz", 733 | "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", 734 | "optional": true, 735 | "requires": { 736 | "ms": "2.0.0" 737 | } 738 | } 739 | } 740 | }, 741 | "ms": { 742 | "version": "2.0.0", 743 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", 744 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 745 | }, 746 | "nan": { 747 | "version": "2.14.0", 748 | "resolved": "https://registry.npm.taobao.org/nan/download/nan-2.14.0.tgz", 749 | "integrity": "sha1-eBj3IgJ7JFmobwKV1DTR/CM2xSw=" 750 | }, 751 | "napi-build-utils": { 752 | "version": "1.0.1", 753 | "resolved": "https://registry.npm.taobao.org/napi-build-utils/download/napi-build-utils-1.0.1.tgz", 754 | "integrity": "sha1-E4Gg+Sw51mvxmFLnhzQy/CEj5Qg=" 755 | }, 756 | "node-abi": { 757 | "version": "2.15.0", 758 | "resolved": "https://registry.npm.taobao.org/node-abi/download/node-abi-2.15.0.tgz", 759 | "integrity": "sha1-UdVcxxG9nkokpXKs4TuSMZRcyxA=", 760 | "requires": { 761 | "semver": "^5.4.1" 762 | }, 763 | "dependencies": { 764 | "semver": { 765 | "version": "5.7.1", 766 | "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1581458265183&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", 767 | "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=" 768 | } 769 | } 770 | }, 771 | "noop-logger": { 772 | "version": "0.1.1", 773 | "resolved": "https://registry.npm.taobao.org/noop-logger/download/noop-logger-0.1.1.tgz", 774 | "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" 775 | }, 776 | "npmlog": { 777 | "version": "4.1.2", 778 | "resolved": "http://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz", 779 | "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", 780 | "requires": { 781 | "are-we-there-yet": "~1.1.2", 782 | "console-control-strings": "~1.1.0", 783 | "gauge": "~2.7.3", 784 | "set-blocking": "~2.0.0" 785 | } 786 | }, 787 | "nth-check": { 788 | "version": "1.0.2", 789 | "resolved": "http://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz", 790 | "integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=", 791 | "requires": { 792 | "boolbase": "~1.0.0" 793 | } 794 | }, 795 | "number-is-nan": { 796 | "version": "1.0.1", 797 | "resolved": "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", 798 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 799 | }, 800 | "oauth-sign": { 801 | "version": "0.9.0", 802 | "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", 803 | "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=" 804 | }, 805 | "object-assign": { 806 | "version": "4.1.1", 807 | "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz", 808 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 809 | }, 810 | "once": { 811 | "version": "1.4.0", 812 | "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz", 813 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 814 | "requires": { 815 | "wrappy": "1" 816 | } 817 | }, 818 | "opentype.js": { 819 | "version": "0.11.0", 820 | "resolved": "https://registry.npm.taobao.org/opentype.js/download/opentype.js-0.11.0.tgz", 821 | "integrity": "sha1-MQ8/uF8JymzyKsjPVA32e0GMM1E=", 822 | "requires": { 823 | "string.prototype.codepointat": "^0.2.1", 824 | "tiny-inflate": "^1.0.2" 825 | } 826 | }, 827 | "parse5": { 828 | "version": "3.0.3", 829 | "resolved": "https://registry.npm.taobao.org/parse5/download/parse5-3.0.3.tgz?cache=0&sync_timestamp=1573036827948&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-3.0.3.tgz", 830 | "integrity": "sha1-BC95L/3TaFFVHPTp4Gazh0q0W1w=", 831 | "requires": { 832 | "@types/node": "*" 833 | } 834 | }, 835 | "path-is-absolute": { 836 | "version": "1.0.1", 837 | "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", 838 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 839 | "optional": true 840 | }, 841 | "performance-now": { 842 | "version": "2.1.0", 843 | "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", 844 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 845 | }, 846 | "prebuild-install": { 847 | "version": "5.3.3", 848 | "resolved": "https://registry.npm.taobao.org/prebuild-install/download/prebuild-install-5.3.3.tgz", 849 | "integrity": "sha1-70BSuqxg1GX1umvwA8nB3nm52o4=", 850 | "requires": { 851 | "detect-libc": "^1.0.3", 852 | "expand-template": "^2.0.3", 853 | "github-from-package": "0.0.0", 854 | "minimist": "^1.2.0", 855 | "mkdirp": "^0.5.1", 856 | "napi-build-utils": "^1.0.1", 857 | "node-abi": "^2.7.0", 858 | "noop-logger": "^0.1.1", 859 | "npmlog": "^4.0.1", 860 | "pump": "^3.0.0", 861 | "rc": "^1.2.7", 862 | "simple-get": "^3.0.3", 863 | "tar-fs": "^2.0.0", 864 | "tunnel-agent": "^0.6.0", 865 | "which-pm-runs": "^1.0.0" 866 | }, 867 | "dependencies": { 868 | "minimist": { 869 | "version": "1.2.0", 870 | "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", 871 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 872 | } 873 | } 874 | }, 875 | "process-nextick-args": { 876 | "version": "2.0.1", 877 | "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz", 878 | "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=" 879 | }, 880 | "psl": { 881 | "version": "1.7.0", 882 | "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.7.0.tgz", 883 | "integrity": "sha1-8cTEeo75cWfepda79IFtc26ISjw=" 884 | }, 885 | "pump": { 886 | "version": "3.0.0", 887 | "resolved": "http://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz", 888 | "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", 889 | "requires": { 890 | "end-of-stream": "^1.1.0", 891 | "once": "^1.3.1" 892 | } 893 | }, 894 | "punycode": { 895 | "version": "2.1.1", 896 | "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz", 897 | "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew=" 898 | }, 899 | "qs": { 900 | "version": "6.5.2", 901 | "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz", 902 | "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=" 903 | }, 904 | "rc": { 905 | "version": "1.2.8", 906 | "resolved": "http://registry.npm.taobao.org/rc/download/rc-1.2.8.tgz", 907 | "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=", 908 | "requires": { 909 | "deep-extend": "^0.6.0", 910 | "ini": "~1.3.0", 911 | "minimist": "^1.2.0", 912 | "strip-json-comments": "~2.0.1" 913 | }, 914 | "dependencies": { 915 | "minimist": { 916 | "version": "1.2.0", 917 | "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", 918 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 919 | } 920 | } 921 | }, 922 | "readable-stream": { 923 | "version": "2.3.7", 924 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz", 925 | "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=", 926 | "requires": { 927 | "core-util-is": "~1.0.0", 928 | "inherits": "~2.0.3", 929 | "isarray": "~1.0.0", 930 | "process-nextick-args": "~2.0.0", 931 | "safe-buffer": "~5.1.1", 932 | "string_decoder": "~1.1.1", 933 | "util-deprecate": "~1.0.1" 934 | }, 935 | "dependencies": { 936 | "safe-buffer": { 937 | "version": "5.1.2", 938 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", 939 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" 940 | } 941 | } 942 | }, 943 | "request": { 944 | "version": "2.88.0", 945 | "resolved": "http://registry.npm.taobao.org/request/download/request-2.88.0.tgz", 946 | "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=", 947 | "requires": { 948 | "aws-sign2": "~0.7.0", 949 | "aws4": "^1.8.0", 950 | "caseless": "~0.12.0", 951 | "combined-stream": "~1.0.6", 952 | "extend": "~3.0.2", 953 | "forever-agent": "~0.6.1", 954 | "form-data": "~2.3.2", 955 | "har-validator": "~5.1.0", 956 | "http-signature": "~1.2.0", 957 | "is-typedarray": "~1.0.0", 958 | "isstream": "~0.1.2", 959 | "json-stringify-safe": "~5.0.1", 960 | "mime-types": "~2.1.19", 961 | "oauth-sign": "~0.9.0", 962 | "performance-now": "^2.1.0", 963 | "qs": "~6.5.2", 964 | "safe-buffer": "^5.1.2", 965 | "tough-cookie": "~2.4.3", 966 | "tunnel-agent": "^0.6.0", 967 | "uuid": "^3.3.2" 968 | } 969 | }, 970 | "safe-buffer": { 971 | "version": "5.2.0", 972 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.0.tgz", 973 | "integrity": "sha1-t02uxJsRSPiMZLaNSbHoFcHy9Rk=" 974 | }, 975 | "safer-buffer": { 976 | "version": "2.1.2", 977 | "resolved": "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz", 978 | "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=" 979 | }, 980 | "semver": { 981 | "version": "7.1.3", 982 | "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.1.3.tgz?cache=0&sync_timestamp=1581458265183&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.1.3.tgz", 983 | "integrity": "sha1-5DRc5zBxxT8zZEXPwZ77HDEd8qY=" 984 | }, 985 | "set-blocking": { 986 | "version": "2.0.0", 987 | "resolved": "http://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", 988 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 989 | }, 990 | "sharp": { 991 | "version": "0.24.1", 992 | "resolved": "https://registry.npm.taobao.org/sharp/download/sharp-0.24.1.tgz", 993 | "integrity": "sha1-+FP59JXf3gXUUhebT58x38QA9Mo=", 994 | "requires": { 995 | "color": "^3.1.2", 996 | "detect-libc": "^1.0.3", 997 | "nan": "^2.14.0", 998 | "npmlog": "^4.1.2", 999 | "prebuild-install": "^5.3.3", 1000 | "semver": "^7.1.3", 1001 | "simple-get": "^3.1.0", 1002 | "tar": "^6.0.1", 1003 | "tunnel-agent": "^0.6.0" 1004 | } 1005 | }, 1006 | "should": { 1007 | "version": "13.2.3", 1008 | "resolved": "https://registry.npm.taobao.org/should/download/should-13.2.3.tgz", 1009 | "integrity": "sha1-ltjlrPPpe0nYm1H+qlro0H71jxA=", 1010 | "optional": true, 1011 | "requires": { 1012 | "should-equal": "^2.0.0", 1013 | "should-format": "^3.0.3", 1014 | "should-type": "^1.4.0", 1015 | "should-type-adaptors": "^1.0.1", 1016 | "should-util": "^1.0.0" 1017 | } 1018 | }, 1019 | "should-equal": { 1020 | "version": "2.0.0", 1021 | "resolved": "https://registry.npm.taobao.org/should-equal/download/should-equal-2.0.0.tgz", 1022 | "integrity": "sha1-YHLPgwRzYIZ+aOmLCdcRQ9BO4MM=", 1023 | "optional": true, 1024 | "requires": { 1025 | "should-type": "^1.4.0" 1026 | } 1027 | }, 1028 | "should-format": { 1029 | "version": "3.0.3", 1030 | "resolved": "https://registry.npm.taobao.org/should-format/download/should-format-3.0.3.tgz", 1031 | "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", 1032 | "optional": true, 1033 | "requires": { 1034 | "should-type": "^1.3.0", 1035 | "should-type-adaptors": "^1.0.1" 1036 | } 1037 | }, 1038 | "should-type": { 1039 | "version": "1.4.0", 1040 | "resolved": "https://registry.npm.taobao.org/should-type/download/should-type-1.4.0.tgz", 1041 | "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", 1042 | "optional": true 1043 | }, 1044 | "should-type-adaptors": { 1045 | "version": "1.1.0", 1046 | "resolved": "https://registry.npm.taobao.org/should-type-adaptors/download/should-type-adaptors-1.1.0.tgz", 1047 | "integrity": "sha1-QB5/M7VTMDOUTVzYvytlAneS4no=", 1048 | "optional": true, 1049 | "requires": { 1050 | "should-type": "^1.3.0", 1051 | "should-util": "^1.0.0" 1052 | } 1053 | }, 1054 | "should-util": { 1055 | "version": "1.0.1", 1056 | "resolved": "https://registry.npm.taobao.org/should-util/download/should-util-1.0.1.tgz", 1057 | "integrity": "sha1-+w1xM49TKjoUkhNjni0yy+qLyyg=", 1058 | "optional": true 1059 | }, 1060 | "signal-exit": { 1061 | "version": "3.0.2", 1062 | "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz", 1063 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 1064 | }, 1065 | "simple-concat": { 1066 | "version": "1.0.0", 1067 | "resolved": "https://registry.npm.taobao.org/simple-concat/download/simple-concat-1.0.0.tgz", 1068 | "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" 1069 | }, 1070 | "simple-get": { 1071 | "version": "3.1.0", 1072 | "resolved": "https://registry.npm.taobao.org/simple-get/download/simple-get-3.1.0.tgz", 1073 | "integrity": "sha1-tFvgYkNeUNFZVAtXYgLO7EC5xrM=", 1074 | "requires": { 1075 | "decompress-response": "^4.2.0", 1076 | "once": "^1.3.1", 1077 | "simple-concat": "^1.0.0" 1078 | } 1079 | }, 1080 | "simple-swizzle": { 1081 | "version": "0.2.2", 1082 | "resolved": "http://registry.npm.taobao.org/simple-swizzle/download/simple-swizzle-0.2.2.tgz", 1083 | "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", 1084 | "requires": { 1085 | "is-arrayish": "^0.3.1" 1086 | } 1087 | }, 1088 | "sshpk": { 1089 | "version": "1.16.1", 1090 | "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", 1091 | "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", 1092 | "requires": { 1093 | "asn1": "~0.2.3", 1094 | "assert-plus": "^1.0.0", 1095 | "bcrypt-pbkdf": "^1.0.0", 1096 | "dashdash": "^1.12.0", 1097 | "ecc-jsbn": "~0.1.1", 1098 | "getpass": "^0.1.1", 1099 | "jsbn": "~0.1.0", 1100 | "safer-buffer": "^2.0.2", 1101 | "tweetnacl": "~0.14.0" 1102 | } 1103 | }, 1104 | "string-width": { 1105 | "version": "1.0.2", 1106 | "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz?cache=0&sync_timestamp=1573488535785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-1.0.2.tgz", 1107 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1108 | "requires": { 1109 | "code-point-at": "^1.0.0", 1110 | "is-fullwidth-code-point": "^1.0.0", 1111 | "strip-ansi": "^3.0.0" 1112 | } 1113 | }, 1114 | "string.prototype.codepointat": { 1115 | "version": "0.2.1", 1116 | "resolved": "https://registry.npm.taobao.org/string.prototype.codepointat/download/string.prototype.codepointat-0.2.1.tgz", 1117 | "integrity": "sha1-AErUTIr8cnUnsQjNRitNlxzUabw=" 1118 | }, 1119 | "string_decoder": { 1120 | "version": "1.1.1", 1121 | "resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz?cache=0&sync_timestamp=1565170823020&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring_decoder%2Fdownload%2Fstring_decoder-1.1.1.tgz", 1122 | "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", 1123 | "requires": { 1124 | "safe-buffer": "~5.1.0" 1125 | }, 1126 | "dependencies": { 1127 | "safe-buffer": { 1128 | "version": "5.1.2", 1129 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", 1130 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" 1131 | } 1132 | } 1133 | }, 1134 | "strip-ansi": { 1135 | "version": "3.0.1", 1136 | "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz?cache=0&sync_timestamp=1573280549549&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-3.0.1.tgz", 1137 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1138 | "requires": { 1139 | "ansi-regex": "^2.0.0" 1140 | } 1141 | }, 1142 | "strip-json-comments": { 1143 | "version": "2.0.1", 1144 | "resolved": "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz", 1145 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" 1146 | }, 1147 | "supports-color": { 1148 | "version": "4.4.0", 1149 | "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-4.4.0.tgz?cache=0&sync_timestamp=1569557271992&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-4.4.0.tgz", 1150 | "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", 1151 | "optional": true, 1152 | "requires": { 1153 | "has-flag": "^2.0.0" 1154 | } 1155 | }, 1156 | "tar": { 1157 | "version": "6.0.1", 1158 | "resolved": "https://registry.npm.taobao.org/tar/download/tar-6.0.1.tgz?cache=0&sync_timestamp=1580272793579&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftar%2Fdownload%2Ftar-6.0.1.tgz", 1159 | "integrity": "sha1-ezvWwxPLbgFTdwEI+NcKwphgfvo=", 1160 | "requires": { 1161 | "chownr": "^1.1.3", 1162 | "fs-minipass": "^2.0.0", 1163 | "minipass": "^3.0.0", 1164 | "minizlib": "^2.1.0", 1165 | "mkdirp": "^1.0.3", 1166 | "yallist": "^4.0.0" 1167 | }, 1168 | "dependencies": { 1169 | "mkdirp": { 1170 | "version": "1.0.3", 1171 | "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-1.0.3.tgz", 1172 | "integrity": "sha1-TPLjCtRZWd3epTrZfVGLbIIF4eo=" 1173 | } 1174 | } 1175 | }, 1176 | "tar-fs": { 1177 | "version": "2.0.0", 1178 | "resolved": "https://registry.npm.taobao.org/tar-fs/download/tar-fs-2.0.0.tgz", 1179 | "integrity": "sha1-Z3cA/AyLM3p4vuNiP9wjXyHXr60=", 1180 | "requires": { 1181 | "chownr": "^1.1.1", 1182 | "mkdirp": "^0.5.1", 1183 | "pump": "^3.0.0", 1184 | "tar-stream": "^2.0.0" 1185 | } 1186 | }, 1187 | "tar-stream": { 1188 | "version": "2.1.0", 1189 | "resolved": "https://registry.npm.taobao.org/tar-stream/download/tar-stream-2.1.0.tgz", 1190 | "integrity": "sha1-0aqjZh8Fs4tazJtwIO/cpReaLMM=", 1191 | "requires": { 1192 | "bl": "^3.0.0", 1193 | "end-of-stream": "^1.4.1", 1194 | "fs-constants": "^1.0.0", 1195 | "inherits": "^2.0.3", 1196 | "readable-stream": "^3.1.1" 1197 | }, 1198 | "dependencies": { 1199 | "readable-stream": { 1200 | "version": "3.6.0", 1201 | "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz?cache=0&sync_timestamp=1581623021561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-3.6.0.tgz", 1202 | "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=", 1203 | "requires": { 1204 | "inherits": "^2.0.3", 1205 | "string_decoder": "^1.1.1", 1206 | "util-deprecate": "^1.0.1" 1207 | } 1208 | } 1209 | } 1210 | }, 1211 | "text-to-svg": { 1212 | "version": "3.1.5", 1213 | "resolved": "https://registry.npm.taobao.org/text-to-svg/download/text-to-svg-3.1.5.tgz", 1214 | "integrity": "sha1-STkT1w6uGxIkCzCVR9ZNeH7BHlc=", 1215 | "requires": { 1216 | "commander": "^2.11.0", 1217 | "opentype.js": "0.11.0" 1218 | } 1219 | }, 1220 | "tiny-inflate": { 1221 | "version": "1.0.3", 1222 | "resolved": "https://registry.npm.taobao.org/tiny-inflate/download/tiny-inflate-1.0.3.tgz", 1223 | "integrity": "sha1-EicVSUkToYBRZqr3yTRnkz7qJsQ=" 1224 | }, 1225 | "tough-cookie": { 1226 | "version": "2.4.3", 1227 | "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.4.3.tgz", 1228 | "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=", 1229 | "requires": { 1230 | "psl": "^1.1.24", 1231 | "punycode": "^1.4.1" 1232 | }, 1233 | "dependencies": { 1234 | "punycode": { 1235 | "version": "1.4.1", 1236 | "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", 1237 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1238 | } 1239 | } 1240 | }, 1241 | "tunnel-agent": { 1242 | "version": "0.6.0", 1243 | "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", 1244 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1245 | "requires": { 1246 | "safe-buffer": "^5.0.1" 1247 | } 1248 | }, 1249 | "tweetnacl": { 1250 | "version": "0.14.5", 1251 | "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&sync_timestamp=1581364183265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz", 1252 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1253 | }, 1254 | "underscore": { 1255 | "version": "1.9.2", 1256 | "resolved": "https://registry.npm.taobao.org/underscore/download/underscore-1.9.2.tgz", 1257 | "integrity": "sha1-DI1vU21vN4pa8mSnL3vsUP63zy8=" 1258 | }, 1259 | "uri-js": { 1260 | "version": "4.2.2", 1261 | "resolved": "http://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz", 1262 | "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", 1263 | "requires": { 1264 | "punycode": "^2.1.0" 1265 | } 1266 | }, 1267 | "urlencode": { 1268 | "version": "1.1.0", 1269 | "resolved": "https://registry.npm.taobao.org/urlencode/download/urlencode-1.1.0.tgz", 1270 | "integrity": "sha1-HyuibwE8hfATP3o61v8nMK33y7c=", 1271 | "requires": { 1272 | "iconv-lite": "~0.4.11" 1273 | } 1274 | }, 1275 | "util-deprecate": { 1276 | "version": "1.0.2", 1277 | "resolved": "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", 1278 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1279 | }, 1280 | "uuid": { 1281 | "version": "3.4.0", 1282 | "resolved": "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1579209051695&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", 1283 | "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=" 1284 | }, 1285 | "verror": { 1286 | "version": "1.10.0", 1287 | "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", 1288 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1289 | "requires": { 1290 | "assert-plus": "^1.0.0", 1291 | "core-util-is": "1.0.2", 1292 | "extsprintf": "^1.2.0" 1293 | } 1294 | }, 1295 | "which": { 1296 | "version": "1.3.1", 1297 | "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-1.3.1.tgz", 1298 | "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", 1299 | "requires": { 1300 | "isexe": "^2.0.0" 1301 | } 1302 | }, 1303 | "which-pm-runs": { 1304 | "version": "1.0.0", 1305 | "resolved": "https://registry.npm.taobao.org/which-pm-runs/download/which-pm-runs-1.0.0.tgz", 1306 | "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" 1307 | }, 1308 | "wide-align": { 1309 | "version": "1.1.3", 1310 | "resolved": "http://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz", 1311 | "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", 1312 | "requires": { 1313 | "string-width": "^1.0.2 || 2" 1314 | } 1315 | }, 1316 | "wrappy": { 1317 | "version": "1.0.2", 1318 | "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", 1319 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1320 | }, 1321 | "yallist": { 1322 | "version": "4.0.0", 1323 | "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz?cache=0&sync_timestamp=1569874223546&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyallist%2Fdownload%2Fyallist-4.0.0.tgz", 1324 | "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=" 1325 | } 1326 | } 1327 | } 1328 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "video", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "baidu-aip-sdk": "^2.4.5", 13 | "cheerio": "^1.0.0-rc.3", 14 | "fluent-ffmpeg": "^2.1.2", 15 | "iconv": "^2.3.5", 16 | "jschardet": "^2.1.1", 17 | "request": "^2.88.0", 18 | "sharp": "^0.24.1", 19 | "text-to-svg": "^3.1.5", 20 | "urlencode": "^1.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 文章自动制作视频 2 | 3 | ## 用法 4 | 5 | ### 1.首先第一步就是注册百度 AI。 6 | 7 | [注册申请方法](https://ai.baidu.com/ai-doc/SPEECH/jk38y8gno) 8 | 9 | 按照文档,注册账号,新建应用,获取 APP_ID, API_KEY, SECRET_KEY。 10 | 11 | 然后填入`src\baiduSpeech.js`中第 7 行的 client 参数。**切记本条,因为百度朗读 AI 有并发限制。** 12 | 13 | ``` 14 | var client = new AipSpeechClient(APP_ID, API_KEY, SECRET_KEY); 15 | ``` 16 | 17 | ### 2.准备输入文件和参数 18 | 19 | 执行 `npm i` 安装依赖。还需要安装 ffmpeg 并配置系统变量 path,至命令行窗口输入 `ffmpeg` 能找到程序为止。 20 | 21 | 复制 templete 目录并粘贴,重命名为如'0225'目录,修改其中的 input/input.txt 为你想要制作的文章。(如示例段落间放一个空行方便分段)。 22 | 23 | 然后拷贝若干横版 jpg 图片(最好 16:9)放入 0225/pic 目录用于轮播制作视频。**也支持从图库中随机抽选**:修改 `src/init.js` 中间中的图库地址 `let picAllSourceFolder = path.resolve("/picall");` ,将你的图库中绝对路径填入,替换 `/picall` (我的代码在 d 盘,图库地址为'D:/picall/'),当然要先清空在项目 0225/pic 文件夹,程序会抽选并拷入。 24 | 25 | 如需替换背景音乐请重命名并替换 `input/bgm.mp3`,会根据视频时长循环播放。 26 | 27 | ### 3.生成视频 28 | 29 | 生成就简单了。修改 index.js 中 `global.config = initPath("./0226");`中的为你重命名后的目录如'./0225',然后 `node index.js`。生成的结果视频为 `0225/merged/final.mp4`。 30 | 31 | ## ffmpeg 命令 32 | 33 | #### 多图制作视频 34 | 35 | 音频加图片,图片循环结束后一直为最后一张 36 | 37 | ``` 38 | ffmpeg -y -r 30 -i ./bg%04d.jpg -i result.mp3 -absf aac_adtstoasc output.mp4 //开头超快 100ms 39 | ffmpeg -y -r 10 -i ./bg%04d.jpg -i result.mp3 -absf aac_adtstoasc output.mp4 //超快 100ms 40 | ffmpeg -y -r 1 -i ./bg%04d.jpg -i result.mp3 -absf aac_adtstoasc output.mp4 //黑屏 41 | ffmpeg -y -r 0.1 -i ./bg%04d.jpg -i result.mp3 -absf aac_adtstoasc output.mp4 //从40秒开始有图,10秒一换,前40不能拖进度 42 | ffmpeg -y -r 0.1 -i ./bg%04d.jpg -i result.mp3 output.mp4 43 | ``` 44 | 45 | 仅视频 46 | 47 | ``` 48 | ffmpeg -y -loop 1 -f image2 -r 0.3 -i ./bg%04d.jpg -vcodec libx264 -t 20 output2.mp4 //前几秒不正常,后面对了 49 | ffmpeg -y -loop 1 -f image2 -r 0.5 -i ./bg%04d.jpg -vcodec libx264 -r 20 -t 10 output2.mp4 //前后都加r后正常。前面为切换间隔 后面为渲染帧数 50 | ffmpeg -y -loop 1 -f image2 -r 0.3 -i ./bg%04d.jpg -vcodec libx264 -r 25 -t 180 output2.mp4 //完全正常 51 | ``` 52 | 53 | 本部分测试完成,bg0001.jpg 开始连续,而且第一张的图片有问题的话视频不能播放。 54 | 根据第一张图片的分辨率决定了视频分辨率。太大的话视频也会很大。 55 | 代码 56 | 57 | ``` 58 | let picPath = path.join(__dirname, "../bg/bg%04d.jpg"); //bg0001.jpg开始 59 | ffmpeg() 60 | .input(picPath) 61 | .inputOptions("-r 0.5") 62 | .loop(time) 63 | .fps(25) 64 | .size("200x?") //输出分辨率,规定了比例和一边(对大小和容量修改) 65 | .aspect("4:3") 66 | .input(mergedPath) 67 | .save(outputPath); 68 | ``` 69 | 70 | #### 合并音频 71 | 72 | ``` 73 | ffmpeg -y -i result.mp3 -i input1.mp3 -filter_complex amerge -ac 2 -c:a libmp3lame -q:a 4 output.mp3 //可以正常合并,长度为短的那个 74 | 75 | ffmpeg -y -i result.mp3 -filter_complex "amovie=input1.wav:loop=0,asetpts=N/SR/TB[input1];[0][input1]amix=duration=shortest,volume=1" out.mp3 //可以合并,将短的重复合并到长的。但是音量为总体控制,1为100% 76 | 77 | ffmpeg -y -i input1.mp3 -af volume=-15dB input1.wav //降低音量 78 | 79 | ffmpeg -y -i result.mp3 -i input1.mp3 -filter_complex amix=inputs=2:duration=longest:dropout_transition=3 amix.mp3 //简单合并,已最长为时长,有3秒的过渡退出效果 80 | ``` 81 | 82 | 字幕调整 83 | 84 | ``` 85 | ffmpeg -y -i AudioAndPic.mp4 -filter_complex "subtitles=result.srt:force_style='MarginV=100,Fontsize=35'" output.mp4 86 | 87 | 给test.mp4添加字幕,同时字幕字体的大小为11px,如果还需要设置字幕的位置,字体,阴影等可以直接在Fontsize=11后面直接拼接即可。Shadow=0,MarginV=20代表阴影为1,距离下边距为20px 88 | 89 | ffmpeg -y -i AudioAndPic.mp4 -filter_complex "subtitles=result.srt:force_style='MarginL=10,MarginR=10,PrimaryColour=&H22EEEEEE,SecondaryColour=&H22e7da75,OutlineColor=&H22e7da75,BackColour=&H22e7da75,Spacing=1,Alignment=10,Outline=2'" output.mp4 90 | 91 | 居中可以,描边颜色不对 92 | 93 | ``` 94 | 95 | 参数中不能包含空格!!!!和中文逗号 96 | 97 | test: 98 | 99 | ``` 100 | ffmpeg -y -i AudioAndPic.mp4 -filter_complex "subtitles=result.srt:force_style='Fontsize=22,PrimaryColour=&H11FFFFFF,OutlineColour=&H440000EE,Alignment=10,BorderStyle=1,Outline=1,Shadow=0,Spacing=1'" output.mp4 101 | 102 | ``` 103 | 104 | Alignment=7 为右上角 =10 为中间 105 | 106 | 封面单图生成视频: 107 | 108 | ``` 109 | 110 | ffmpeg -loop 1 -f image2 -i cover.png -vcodec libx264 -r 24 -t 1 cover.mp4 111 | ``` 112 | 113 | 视频拼接: 114 | 115 | ``` 116 | ffmpeg -f concat -i list.txt -c copy out.mp4 117 | 118 | 3个拼接的demo 119 | ffmpeg -i input1.mp4 -i input2.webm -i input3.mov \ 120 | -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[outv][outa]" \ 121 | -map "[outv]" -map "[outa]" output.mkv 122 | 123 | ffmpeg -i cover.mp4 -i final.mp4 -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output4.mp4 124 | 125 | ffmpeg -i cover.mp4 -i final.mp4 -filter_complex "[0:0][1:0][1:0]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output4.mp4 126 | 127 | ffmpeg -i cover.mp4 -i final.mp4 -filter_complex '[0:0] [0:1] [0:2] [1:0] [1:1] [1:2] concat=n=2:v=1:a=2 [v] [a1] [a2]' -map '[v]' -map '[a1]' -map '[a2]' output.mkv 128 | 129 | ffmpeg -f concat -i list.txt -c copy -map 0:v:0 -map 1:v:0 -map 1:a:0 output.mp4 130 | ``` 131 | 132 | ## todo 133 | 134 | - [ ] 美化字幕,最好动画 135 | 136 | - [x] 字幕超长遮挡 137 | 138 | - [x] 文章自动断句。 139 | 140 | - [ ] 文章自动抓取分析。 141 | 142 | - [x] 多图 143 | 144 | - [ ] 多图切换和滤镜 145 | 146 | - [ ] 片头 水印 和片尾 147 | 148 | 用什么方式: 149 | 150 | 1. 将片头图片作为背景图的一张。需要保证图片不循环,同时添加固定一张图片为片头。标题文字用 drawtext 或者是图片通过 svg 叠加生成。语音和字幕增加固定秒数的偏移量。(现在图片结果为 7 秒,做片头太长。) 151 | 152 | 2. 将图片生成同尺寸视频,然后视频拼接。(图像压制多一次,性能差)。 153 | -------------------------------------------------------------------------------- /src/addBgm.js: -------------------------------------------------------------------------------- 1 | const ffmpeg = require("fluent-ffmpeg"); 2 | const path = require("path"); 3 | const fs = require("fs"); 4 | 5 | // let bgmSourcePath = path.join(__dirname, "../merged/input1.mp3"); 6 | 7 | // let mergedPath = path.join(__dirname, "../merged/result.mp3"); 8 | // let bgmPath = path.join(__dirname, "../merged/bgm.mp3"); 9 | 10 | // let outputPath = path.join(__dirname, "../merged/result_bgm.mp3"); 11 | 12 | var generateBGM = function(time = 180, vol = -15) { 13 | let { bgmInput, pathBgmReduced } = global.config; 14 | return new Promise((resolve, reject) => { 15 | ffmpeg.ffprobe(bgmInput, function(err, metadata) { 16 | let duration = metadata.format.duration; 17 | let nLoop = Math.floor(time / duration) + 1; 18 | ffmpeg() 19 | .input(bgmInput) 20 | .audioFilters([ 21 | { 22 | filter: "volume", 23 | options: vol + "dB" 24 | }, 25 | { 26 | filter: "aloop", 27 | options: { loop: nLoop, size: 2e9 } 28 | } 29 | ]) 30 | .duration(time) 31 | .on("end", function() { 32 | console.log("Bgm generate succesfully"); 33 | resolve(); 34 | }) 35 | .on("error", function(err) { 36 | console.log("Bgm generate an error happened: " + err.message); 37 | reject(); 38 | }) 39 | .save(pathBgmReduced); 40 | }); 41 | }); 42 | }; 43 | 44 | var add = function(time = 20) { 45 | let { pathMergedVoices, pathBgmReduced, pathVoiceAndBgm } = global.config; 46 | return new Promise((resolve, reject) => { 47 | ffmpeg() 48 | .input(pathMergedVoices) 49 | .input(pathBgmReduced) 50 | .complexFilter( 51 | [ 52 | { 53 | filter: "amix", 54 | options: { inputs: 2, duration: "longest", dropout_transition: 3 }, 55 | outputs: "output" 56 | } 57 | ], 58 | "output" 59 | ) 60 | .on("end", function() { 61 | console.log("addBgm succesfully"); 62 | resolve(); 63 | }) 64 | .on("error", function(err) { 65 | console.log("addBgm an error happened: " + err.message); 66 | reject(); 67 | }) 68 | .save(pathVoiceAndBgm); 69 | }); 70 | }; 71 | exports.addBgm = add; 72 | exports.generateBGM = generateBGM; 73 | -------------------------------------------------------------------------------- /src/addJpg.js: -------------------------------------------------------------------------------- 1 | const ffmpeg = require("fluent-ffmpeg"); 2 | 3 | var add = function(time = 20) { 4 | let { pathPicTemple, pathVoiceAndBgm, pathAudioAndPic } = global.config; 5 | return new Promise((resolve, reject) => { 6 | ffmpeg() 7 | .input(pathPicTemple) 8 | .inputOptions("-r 0.15") 9 | .loop(time) 10 | .fps(24) 11 | 12 | .input(pathVoiceAndBgm) 13 | .videoCodec("libx264") 14 | .size("1280x720") 15 | .aspect("16:9") 16 | .on("end", function() { 17 | console.log("jpgPlusMp3 succesfully"); 18 | resolve(); 19 | }) 20 | .on("error", function(err) { 21 | console.log("jpgPlusMp3 an error happened: " + err.message); 22 | reject(); 23 | }) 24 | .save(pathAudioAndPic); 25 | }); 26 | }; 27 | exports.addJpg = add; 28 | -------------------------------------------------------------------------------- /src/addText.js: -------------------------------------------------------------------------------- 1 | const ffmpeg = require("fluent-ffmpeg"); 2 | 3 | 4 | //导入字幕 5 | var add = function() { 6 | let { pathAudioAndPic, pathFinal, pathSrtComplex } = global.config; 7 | // pathSrt = "d\\:\\\\wsNodejs\\\\video\\\\test\\\\merged\\\\result.srt"; 8 | 9 | return new Promise((resolve, reject) => { 10 | ffmpeg() 11 | .input(pathAudioAndPic) 12 | .complexFilter( 13 | "subtitles='" + 14 | pathSrtComplex + 15 | "':force_style='Fontsize=22,PrimaryColour=&H11FFFFFF,OutlineColour=&H440000EE,Alignment=10,BorderStyle=1,Outline=1,Shadow=0,Spacing=1'" 16 | ) 17 | //MarginV=100,TertiaryColour=333333 18 | // .complexFilter("subtitles=./merged/result.srt") 19 | .on("end", function() { 20 | console.log("addText succesfully"); 21 | resolve(); 22 | }) 23 | .on("error", function(err) { 24 | console.log("addText an error happened: " + err.message); 25 | reject(); 26 | }) 27 | .save(pathFinal); 28 | }); 29 | }; 30 | 31 | exports.addText = add; 32 | -------------------------------------------------------------------------------- /src/baiduSpeech.js: -------------------------------------------------------------------------------- 1 | let AipSpeech = require("baidu-aip-sdk").speech; 2 | let fs = require("fs"); 3 | const path = require("path"); 4 | const { delay } = require("./utils"); 5 | 6 | // 务必替换百度云控制台中新建百度语音应用的 Api Key 和 Secret Key 7 | let client = new AipSpeech( 8 | "18439020", 9 | "rrGNNPHqf5P3VfnorrUTtmAS", 10 | "GCAR6b0s0YSgRLw0mevrAkNFfVgti9NK" 11 | ); 12 | 13 | let voice = function(text = "待朗读文字", name = "tts") { 14 | let tempVoiceFolder = global.config.tempVoiceFolder; 15 | return new Promise((res, rej) => { 16 | client.text2audio(text, { spd: 6, per: 111 }).then( 17 | async function(result) { 18 | if (result.data) { 19 | console.log("语音合成成功,文件保存到" + name + ".mp3,打开听听吧"); 20 | fs.writeFileSync( 21 | path.join(tempVoiceFolder, name + ".mp3"), 22 | result.data 23 | ); 24 | await delay(0.6); 25 | res(); 26 | } else { 27 | // 合成服务发生错误 28 | console.log("语音合成失败: " + JSON.stringify(result)); 29 | res(result); 30 | } 31 | }, 32 | function(err) { 33 | console.log(err); 34 | rej(err); 35 | } 36 | ); 37 | }); 38 | }; 39 | 40 | exports.voice = voice; 41 | -------------------------------------------------------------------------------- /src/exec.js: -------------------------------------------------------------------------------- 1 | var exec = require("child_process").exec; 2 | 3 | var cmdStr = "ffmpeg"; 4 | 5 | exec(cmdStr, function(err, stdout, stderr) { 6 | if (err) { 7 | console.log("cmd exec error:" + stderr); 8 | } else { 9 | var data = JSON.parse(stdout); 10 | 11 | console.log(data); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /src/init.js: -------------------------------------------------------------------------------- 1 | const utils = require("./utils"); 2 | const path = require("path"); 3 | 4 | function clearPreviousFiles() { 5 | let tempVoiceFolder = global.config.tempVoiceFolder; 6 | utils.rmAllFiles(tempVoiceFolder); 7 | // utils.rmAllFiles("../srt"); 8 | console.log("清除临时文件成功"); 9 | } 10 | 11 | function initPath(dir = path.join(__dirname, "..")) { 12 | let mainPath = path.resolve(dir); 13 | let bgmInputFolder = path.join(mainPath, "input"); 14 | let bgmInput = path.join(bgmInputFolder, "bgm.mp3"); 15 | let picInputFolder = path.join(mainPath, "pic"); 16 | let picAllSourceFolder = path.resolve("/picall"); 17 | let tempVoiceFolder = path.join(mainPath, "result"); 18 | let tempResultFolder = path.join(mainPath, "merged"); 19 | let pathPicTemple = picInputFolder + "/bg%04d.jpg"; 20 | let pathFont = path.join(mainPath, "fonts", "font.otf"); 21 | let pathInputTxt = path.join(bgmInputFolder, "input.txt"); 22 | let pathInputCover = path.join(bgmInputFolder, "cover.jpg"); 23 | let pathSrt = path.join(tempResultFolder, "result.srt"); 24 | let pathSrtComplex = formatComplexPath(pathSrt); 25 | let pathMergedVoices = path.join(tempResultFolder, "mergedVoice.mp3"); 26 | let pathBgmReduced = path.join(tempResultFolder, "bgmReduced.mp3"); 27 | let pathVoiceAndBgm = path.join(tempResultFolder, "voiceAndBgm.mp3"); 28 | let pathAudioAndPic = path.join(tempResultFolder, "AudioAndPic.mp4"); 29 | let pathFinal = path.join(tempResultFolder, "final.mp4"); 30 | 31 | function formatComplexPath(abPath) { 32 | let a = abPath.replace(/\\/g, "\\\\"); 33 | let formatPath = a.replace(new RegExp(":", "g"), "\\:"); 34 | return formatPath; 35 | } 36 | 37 | const config = { 38 | mainPath, 39 | bgmInputFolder, 40 | bgmInput, 41 | picInputFolder, 42 | picAllSourceFolder, 43 | tempVoiceFolder, 44 | tempResultFolder, 45 | pathInputCover, 46 | pathFont, 47 | pathInputTxt, 48 | pathPicTemple, 49 | pathSrt, 50 | pathSrtComplex, 51 | pathMergedVoices, 52 | pathBgmReduced, 53 | pathVoiceAndBgm, 54 | pathAudioAndPic, 55 | pathFinal 56 | }; 57 | checkPathAndCreate(config); 58 | 59 | function checkPathAndCreate(config) { 60 | utils.mkdir(config.tempVoiceFolder); 61 | utils.mkdir(config.tempResultFolder); 62 | utils.mkdir(config.bgmInputFolder); 63 | utils.mkdir(config.picInputFolder); 64 | } 65 | 66 | console.log(config); 67 | return config; 68 | } 69 | 70 | exports.initPath = initPath; 71 | exports.clearPreviousFiles = clearPreviousFiles; 72 | -------------------------------------------------------------------------------- /src/mergeMP3.js: -------------------------------------------------------------------------------- 1 | //顺序合并多个音频并输出。如果加了图像做视频,用save的话只有一个音频。 2 | const ffmpeg = require("fluent-ffmpeg"); 3 | const path = require("path"); 4 | const { readdir, readFile, writeFile, readdirSync, statSync } = require("fs"); 5 | const { getStringList } = require("./readText"); 6 | 7 | function pReadFile(filepath) { 8 | return new Promise((resolve, reject) => { 9 | readdir(filepath, (err, files) => { 10 | let filenames = []; 11 | files.forEach(file => { 12 | if (path.extname(file).toLowerCase() === ".mp3") { 13 | filenames.push(file); 14 | } 15 | }); 16 | 17 | function sortNumber(a, b) { 18 | //升序 19 | a = a.replace(".mp3", ""); 20 | b = b.replace(".mp3", ""); 21 | return a - b; 22 | } 23 | filenames.sort(sortNumber); // 排序 24 | resolve(filenames); 25 | }); 26 | }); 27 | } 28 | 29 | function mergeAllMp3(srtOffset = 0) { 30 | let tempVoiceFolder = global.config.tempVoiceFolder; 31 | let pathMergedVoices = global.config.pathMergedVoices; 32 | return new Promise(async (resolve, reject) => { 33 | let filenames = await pReadFile(tempVoiceFolder); 34 | let proc = ffmpeg(); 35 | let lists = []; 36 | for (let index = 0; index < filenames.length; index++) { 37 | let file = path.join(tempVoiceFolder, filenames[index]); 38 | proc.input(file).ffprobe(function(err, data) { 39 | // console.log("file metadata:", data.format.duration); 40 | let obj = { 41 | duration: data.format.duration, 42 | filename: filenames[index].replace(".mp3", "") 43 | }; 44 | lists[index] = obj; 45 | }); 46 | } 47 | // console.log(lists) 48 | proc 49 | .on("end", function() { 50 | let total = formatLists(lists, srtOffset); 51 | console.log("files have been merged succesfully. "); 52 | resolve(total); 53 | }) 54 | .on("error", function(err) { 55 | console.log("an error happened: " + err.message); 56 | }) 57 | .mergeToFile(pathMergedVoices); 58 | }); 59 | } 60 | 61 | async function formatLists(lists, offset = 0) { 62 | let total = offset; 63 | let strResult = ""; 64 | let content = getStringList(); 65 | for (let index = 0; index < lists.length; index++) { 66 | const row = lists[index]; 67 | row.content = content[index]; 68 | row.start = total; 69 | total += row.duration; 70 | row.end = total; 71 | row.index = index + 1; 72 | strResult += `${row.index} 73 | ${formatSecend(row.start)} --> ${formatSecend(row.end)} 74 | ${row.content} 75 | 76 | `; 77 | } 78 | // console.log(lists); 79 | await writeSrt(strResult); 80 | total = Math.round(total * 1000) / 1000; 81 | console.log("总时长秒数:" + total); 82 | return total; 83 | } 84 | 85 | function writeSrt(str) { 86 | let pathSrt = global.config.pathSrt; 87 | return new Promise(async (resolve, reject) => { 88 | writeFile(pathSrt, str, function(err) { 89 | if (err) { 90 | console.error(err); 91 | reject(err); 92 | } 93 | console.log("----------新增成功-------------"); 94 | resolve(); 95 | }); 96 | }); 97 | } 98 | 99 | function formatSecend(secend) { 100 | function p(s) { 101 | return s < 10 ? "0" + s : s; 102 | } 103 | var hours = secend / 60 / 60; 104 | var hoursRound = Math.floor(hours); 105 | var minutes = secend / 60 - 60 * hoursRound; 106 | var minutesRound = Math.floor(minutes); 107 | var seconds = secend - 60 * 60 * hoursRound - 60 * minutesRound; 108 | var secondsRound = Math.floor(seconds); 109 | var micro = Math.floor((secend - Math.floor(secend)) * 1000); 110 | 111 | if (micro === 0) { 112 | micro = "000"; 113 | } else if (micro > 0 && micro < 10) { 114 | micro = "00" + micro; 115 | } else if (micro >= 10 && micro < 100) { 116 | micro = "0" + micro; 117 | } 118 | 119 | var time = 120 | p(hoursRound) + ":" + p(minutesRound) + ":" + p(secondsRound) + "," + micro; 121 | return time; 122 | } 123 | 124 | exports.merge = mergeAllMp3; 125 | -------------------------------------------------------------------------------- /src/randomBgCopy.js: -------------------------------------------------------------------------------- 1 | //顺序合并多个音频并输出。如果加了图像做视频,用save的话只有一个音频。 2 | const path = require("path"); 3 | const { 4 | readdir, 5 | copyFileSync 6 | } = require("fs"); 7 | 8 | function pReadFile(filepath) { 9 | return new Promise((resolve, reject) => { 10 | readdir(filepath, (err, files) => { 11 | let filenames = []; 12 | files.forEach(file => { 13 | if (path.extname(file).toLowerCase() === ".jpg") { 14 | filenames.push(file); 15 | } 16 | }); 17 | 18 | // function sortNumber(a, b) { 19 | // //升序 20 | // a = a.replace(".mp3", ""); 21 | // b = b.replace(".mp3", ""); 22 | // return a - b; 23 | // } 24 | // filenames.sort(sortNumber); // 排序 25 | resolve(filenames); 26 | }); 27 | }); 28 | } 29 | 30 | function randomBgCopy(time = 240, picFrame = 0.15) { 31 | let picAllSourceFolder = global.config.picAllSourceFolder; 32 | let picInputFolder = global.config.picInputFolder; 33 | return new Promise(async (resolve, reject) => { 34 | let check = await pReadFile(picInputFolder); 35 | if (check.length) { 36 | resolve(); 37 | return; 38 | } 39 | 40 | let filenames = await pReadFile(picAllSourceFolder); 41 | let lists = []; 42 | let picsCount = Math.floor(time * picFrame) + 10; 43 | let groupSize = Math.floor((filenames.length - 1) / picsCount); 44 | for (let index = 0; index < picsCount - 1; index++) { 45 | let random = Math.floor(Math.random() * groupSize); 46 | let file = filenames[index * groupSize + random]; 47 | 48 | lists.push(file); 49 | } 50 | for (let index = 0; index < lists.length; index++) { 51 | const file = lists[index]; 52 | let res = copyFileSync( 53 | path.join(picAllSourceFolder, file), 54 | path.join(picInputFolder, file) 55 | ); 56 | } 57 | resolve(); 58 | }); 59 | } 60 | 61 | exports.randomBgCopy = randomBgCopy; 62 | -------------------------------------------------------------------------------- /src/readText.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { voice } = require("./baiduSpeech"); 3 | const jschardet = require("jschardet"); 4 | const Iconv = require("iconv").Iconv; 5 | 6 | let str = `疫情之后,房价会如何? 7 | 这是近几天多起来的读者问题。 8 | 9 | 房价最终是经济的体现,经济发达则房价高。 10 | 判断疫情对房价的影响,得先判断疫情对经济的影响。 11 | 12 | 繁荣时,可升值,灾难时,可避难。`; 13 | 14 | function readTxt(filepath) { 15 | let txt = fs.readFileSync(filepath, "utf-8"); 16 | // let t = jschardet.detect(txt); 17 | // console.log(t.encoding); 18 | // if (t.encoding !== "utf-8") { 19 | // let iconv = new Iconv(t.encoding, "utf-8"); 20 | // txt = iconv.convert(txt); 21 | // } 22 | console.log(txt); 23 | return txt.replace(/\r/g, ""); 24 | } 25 | 26 | let getStringList = function() { 27 | let { pathInputTxt } = global.config; 28 | str = readTxt(pathInputTxt); 29 | let arr = str.split(/\n\n/); 30 | let content = []; 31 | 32 | content = arr; 33 | 34 | content = content.filter(ele => !ele.match(/^[ ]*$/)); //去除空行和纯空格行 35 | 36 | content = splitText(content); 37 | console.log(content); 38 | return content; 39 | }; 40 | 41 | function splitText(content, singleLineLimit = 26, linesLimit = 4) { 42 | function danjuchaiduan(str) { 43 | let tempStr = ""; 44 | const oneSentence = str; 45 | let beishu = oneSentence.length / singleLineLimit; 46 | for (let j = 0; j < beishu; j++) { 47 | let raw = oneSentence.slice( 48 | j * singleLineLimit, 49 | (j + 1) * singleLineLimit 50 | ); 51 | tempStr += raw + (j >= beishu - 1 ? "" : "\n"); 52 | } 53 | return tempStr; 54 | } 55 | 56 | function duojuchaiduan(str) { 57 | let n = str / (singleLineLimit * linesLimit); 58 | let arr = []; 59 | for (let index = 0; index < n; index++) { 60 | let one = oneSentence.slice( 61 | index * singleLineLimit * linesLimit, 62 | (index + 1) * singleLineLimit * linesLimit 63 | ); 64 | one = danjuchaiduan(one); 65 | arr.push(one); 66 | } 67 | return arr; 68 | } 69 | 70 | let paraCac = []; 71 | for (let index = 0; index < content.length; index++) { 72 | const para = content[index]; 73 | if (para.length > singleLineLimit * linesLimit) { 74 | let sentences = para.split(/。/); 75 | 76 | let mycak = []; 77 | for (let i = 0; i < sentences.length; i++) { 78 | if ( 79 | sentences[i] !== "" && 80 | sentences[i] !== "\n" && 81 | sentences[i] !== "。" && 82 | sentences[i] !== "," && 83 | sentences[i] !== "、" && 84 | sentences[i] !== ":" && 85 | sentences[i] !== "?" && 86 | sentences[i] !== '"' && 87 | sentences[i] !== "'" && 88 | sentences[i] !== "“" && 89 | sentences[i] !== "”" && 90 | sentences[i] !== "." && 91 | sentences[i] !== "?" && 92 | sentences[i] !== ")" && 93 | sentences[i] !== ")" 94 | ) { 95 | const oneSentence = sentences[i] + "。"; 96 | 97 | if (oneSentence.length <= singleLineLimit + 1) { 98 | paraCac.push(oneSentence); 99 | } else { 100 | if (oneSentence.length > singleLineLimit * linesLimit) { 101 | let halfSentences = oneSentence.split(/,/); 102 | for (let haIndex = 0; haIndex < halfSentences.length; haIndex++) { 103 | const halfSentence = halfSentences[haIndex]; 104 | if (halfSentence.length < singleLineLimit) { 105 | paraCac.push(halfSentence); 106 | } else { 107 | if (halfSentence.length > singleLineLimit * linesLimit) { 108 | let arr = duojuchaiduan(halfSentence); 109 | paraCac.push(...arr); 110 | } else { 111 | let tempStr = danjuchaiduan(halfSentence); 112 | paraCac.push(tempStr); 113 | } 114 | } 115 | } 116 | } else { 117 | let tempStr = danjuchaiduan(oneSentence); 118 | paraCac.push(tempStr); 119 | } 120 | } 121 | } 122 | } 123 | 124 | // let suoyin = 1; 125 | // let cacone = ""; 126 | // let cacArr = []; 127 | // for (let k = 0; k < mycak.length; k++) { 128 | // if (k < suoyin * linesLimit) { 129 | // cacone += mycak[k]; 130 | // if (k === mycak.length - 1) { 131 | // cacArr.push(cacone); 132 | // } 133 | // } else { 134 | // cacArr.push(cacone); 135 | // cacone = mycak[k]; 136 | // suoyin++; 137 | // } 138 | // } 139 | // paraCac.push(...cacArr); 140 | } else { 141 | let tempStr = ""; 142 | 143 | tempStr = danjuchaiduan(para); 144 | paraCac.push(tempStr); 145 | } 146 | } 147 | 148 | return paraCac; 149 | } 150 | 151 | let readAll = async function() { 152 | let content = getStringList(); 153 | for (let index = 0; index < content.length; index++) { 154 | const element = content[index]; 155 | await voice(element, index); 156 | } 157 | console.log("朗读全部完成"); 158 | }; 159 | 160 | // getList() 161 | 162 | exports.getStringList = getStringList; 163 | exports.readAll = readAll; 164 | -------------------------------------------------------------------------------- /src/text2svg.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const TextToSVG = require("text-to-svg"); 3 | const sharp = require("sharp"); 4 | 5 | function stringToPng(str = "hello") { 6 | let pathFont = path.join(__dirname, "..", "fonts", "font.otf"); 7 | let pathInputCover = global.config.pathInputCover; 8 | const textToSVG = TextToSVG.loadSync(pathFont); 9 | const attributes = { 10 | fill: "white", 11 | stroke: "black", 12 | width: 800, 13 | height: 600 14 | }; 15 | const options = { 16 | x: 0, 17 | y: 0, 18 | fontSize: 72, 19 | anchor: "top", 20 | attributes: attributes 21 | }; 22 | let svg = textToSVG.getSVG(str, options); 23 | 24 | console.log(svg); 25 | 26 | let buffer = Buffer.from(svg); 27 | 28 | sharp(buffer) 29 | // .png() 30 | .jpeg({ 31 | quality: 90, 32 | chromaSubsampling: "4:4:4" 33 | }) 34 | .toFile(pathInputCover) 35 | .then(function(info) { 36 | console.log(info); 37 | }) 38 | .catch(function(err) { 39 | console.log(err); 40 | }); 41 | } 42 | 43 | exports.stringToPng = stringToPng; 44 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | function delay(secends = 1) { 5 | return new Promise(resolve => { 6 | setTimeout(() => resolve(), secends * 1000); 7 | }); 8 | } 9 | 10 | function mkdir(dir) { 11 | let absoluteDir = path.resolve(dir); 12 | if (!fs.existsSync(absoluteDir)) { 13 | fs.mkdirSync(absoluteDir); 14 | } 15 | } 16 | 17 | function getAllFile(dir) { 18 | let files = fs.readdirSync(dir); 19 | return files; 20 | } 21 | 22 | function isPic(file) { 23 | let ext = path.extname(file).toLowerCase(); 24 | return ext === ".jpg" || ext === ".jpeg" || ext === ".png" || ext === ".gif"; 25 | } 26 | function numberFormatZero(num, n) { 27 | return (Array(n).join(0) + num).slice(-n); 28 | } 29 | 30 | //批量重命名子文件夹下所有文件名。增加一个时间戳。 31 | function renameBot(dir) { 32 | let absoluteDir = path.resolve(dir); 33 | let files = fs.readdirSync(absoluteDir); 34 | for (let index = 0; index < files.length; index++) { 35 | const fold = files[index]; 36 | let absoluteFold = path.join(absoluteDir, fold); 37 | let isFold = fs.statSync(absoluteFold).isDirectory(); 38 | if (isFold) { 39 | let time = Date.now(); 40 | let pics = fs.readdirSync(absoluteFold); 41 | for (let index = 0; index < pics.length; index++) { 42 | const file = pics[index]; 43 | let absoluteFile = path.join(absoluteFold, file); 44 | let isFile = fs.statSync(absoluteFile).isFile(); 45 | if (isFile) { 46 | let newname = time + file; 47 | fs.renameSync(absoluteFile, path.join(absoluteFold, newname)); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | function bgRename(dirPath) { 55 | let absoluteDir = dirPath 56 | ? path.resolve(dirPath) 57 | : global.config.picInputFolder; 58 | let files = fs.readdirSync(absoluteDir); 59 | if (!files.length) { 60 | console.error("未找到背景图片,之后进行随机挑选"); 61 | 62 | return; 63 | } else { 64 | let existBgArr = files.filter(file => file.substring(0, 2) === "bg"); 65 | let time = Date.now(); 66 | for (let index = 0; index < existBgArr.length; index++) { 67 | const exfile = existBgArr[index]; 68 | let absoluteexfile = path.join(absoluteDir, exfile); 69 | let isexFile = fs.statSync(absoluteexfile).isFile(); 70 | if (isexFile) { 71 | let newname = time + exfile; 72 | fs.renameSync(absoluteexfile, path.join(absoluteDir, newname)); 73 | } 74 | } 75 | } 76 | 77 | files = fs.readdirSync(absoluteDir); 78 | let numFileCount = 1; 79 | for (let index = 0; index < files.length; index++) { 80 | const file = files[index]; 81 | let absoluteFile = path.join(absoluteDir, file); 82 | let isFile = fs.statSync(absoluteFile).isFile(); 83 | if (isFile) { 84 | let newname = 85 | "bg" + 86 | numberFormatZero(numFileCount, 4) + 87 | path.extname(file).toLowerCase(); 88 | fs.renameSync(absoluteFile, path.join(absoluteDir, newname)); 89 | numFileCount++; 90 | } 91 | } 92 | console.log( 93 | "目录'" + absoluteDir + "'中的图片已经重命名完毕。格式为bg0001.jpg.." 94 | ); 95 | } 96 | 97 | function rmAllFiles(dirPath) { 98 | let absoluteDir = path.resolve(dirPath); 99 | let files = fs.readdirSync(dirPath); 100 | for (let index = 0; index < files.length; index++) { 101 | const file = files[index]; 102 | let absoluteFile = path.join(absoluteDir, file); 103 | let isFile = fs.statSync(absoluteFile).isFile(); 104 | if (isFile) { 105 | fs.unlinkSync(absoluteFile); 106 | } 107 | } 108 | console.log("已清空目录 " + absoluteDir); 109 | } 110 | 111 | exports.delay = delay; 112 | exports.mkdir = mkdir; 113 | exports.rmAllFiles = rmAllFiles; 114 | exports.bgRename = bgRename; 115 | exports.renameBot = renameBot; 116 | -------------------------------------------------------------------------------- /srt/result.srt: -------------------------------------------------------------------------------- 1 | 1 2 | 00:00:00,000 --> 00:00:02,556 3 | 疫情之后,房价会如何? 4 | 5 | 2 6 | 00:00:02,556 --> 00:00:05,363 7 | 这是近几天多起来的读者问题。 8 | 9 | 3 10 | 00:00:05,363 --> 00:00:09,179 11 | 房价最终是经济的体现,经济发达则房价高。 12 | 13 | 4 14 | 00:00:09,179 --> 00:00:13,644 15 | 判断疫情对房价的影响,得先判断疫情对经济的影响。 16 | 17 | 5 18 | 00:00:13,644 --> 00:00:17,460 19 | 有极端悲观者,认为中国经济从此将垮掉。 20 | 21 | 6 22 | 00:00:17,460 --> 00:00:23,112 23 | 如果你是一个容易悲观的人,最近密集接受坏消息的轰炸,可能会有这种假想: 24 | 25 | 7 26 | 00:00:23,112 --> 00:00:27,108 27 | 几个月后,企业大规模倒闭,企业主先倒霉; 28 | 29 | 8 30 | 00:00:27,108 --> 00:00:31,608 31 | 这产生大量的失业,再过一段时间,失业者耗尽积蓄, 32 | 33 | 9 34 | 00:00:31,608 --> 00:00:34,847 35 | 发现自己的命运是和企业主捆绑在一起的, 36 | 37 | 10 38 | 00:00:34,847 --> 00:00:38,159 39 | 开始还不起房贷,生活费都成问题; 40 | 41 | 11 42 | 00:00:38,159 --> 00:00:43,559 43 | 而政府由于没有企业可以收税,国库空虚,失去救援民众的能量。 44 | 45 | 12 46 | 00:00:43,559 --> 00:00:49,751 47 | 这种情况发生,房价当然一泄千里,覆巢之下,每个人的蛋都要摔破。 48 | 49 | 13 50 | 00:00:49,751 --> 00:00:51,407 51 | 但它不会发生。 52 | 53 | 14 54 | 00:00:51,407 --> 00:00:57,275 55 | 即使疫情不结束,一个月后,农民戴着口罩种田,工人戴着口罩生产, 56 | 57 | 15 58 | 00:00:57,275 --> 00:01:01,775 59 | 两三个月后,政府急迫地鼓励(极端的甚至强制)企业开工, 60 | 61 | 16 62 | 00:01:01,775 --> 00:01:04,043 63 | 生存问题升格为第一问题, 64 | 65 | 17 66 | 00:01:04,043 --> 00:01:07,679 67 | 毕竟,只要持续饿,死亡率是100%, 68 | 69 | 18 70 | 00:01:07,679 --> 00:01:11,387 71 | 比新冠肺炎厉害多了,两害相权取其轻。 72 | 73 | 19 74 | 00:01:11,387 --> 00:01:19,919 75 | 何况,疫情很快将会结束。它对中国经济的影响,只是一个短期冲击,长期来看,只是一个小波澜。 76 | 77 | 20 78 | 00:01:19,919 --> 00:01:27,947 79 | 在这个短期内,你的企业撑得住,你的积蓄用不完,你甚至会获得优势,因为不幸的倒闭者让出了市场份额。 80 | 81 | 21 82 | 00:01:27,947 --> 00:01:33,995 83 | 这样,我们可以得出结论:疫情对房价的影响是短期的,改变不了大趋势。 84 | 85 | 22 86 | 00:01:33,995 --> 00:01:44,363 87 | 短期内,有些负债率极高的房企,不得不亏本抛售,有些赌徒式的购房者,也只能割肉,可能会有一些便宜捡,不过那是零星事件。 88 | 89 | 23 90 | 00:01:44,363 --> 00:01:51,095 91 | 而疫情中出现的一些变化,对房价的助推作用,过比较长的一段时间后,才会显现。 92 | 93 | 24 94 | 00:01:51,095 --> 00:02:01,859 95 | 一是货币投放的增加。灾难之后,用货币放水刺激经济,这是现代政府的标准动作(在这里不探讨是否符合市场规律,只描述现实)。 96 | 97 | 25 98 | 00:02:01,859 --> 00:02:07,007 99 | 目前为止,政府投放的货币,以万亿计了。后续还有更多。 100 | 101 | 26 102 | 00:02:07,007 --> 00:02:14,747 103 | 钱增加得快,物增长得慢,价格就得涨,尤其是好物,涨得更快,好房子,就是好物中的好物。 104 | 105 | 27 106 | 00:02:14,747 --> 00:02:21,407 107 | 二是观念的改变。所谓的租售同权出台后,很多人欢呼,以为不用当房奴了。 108 | 109 | 28 110 | 00:02:21,407 --> 00:02:26,735 111 | 可是一个租户,在这次疫情中,假期归来,被挡在小区大门之外。 112 | 113 | 29 114 | 00:02:26,735 --> 00:02:34,799 115 | 不少地方出台政策,对有房户与租户区别对待,租户进不了房,酒店又都停业,一下变成了流浪者。 116 | 117 | 30 118 | 00:02:34,799 --> 00:02:40,199 119 | 这种政策,当然不合理,简单粗暴,反映出极低的管理水平。 120 | 121 | 31 122 | 00:02:40,199 --> 00:02:44,987 123 | 不过,倒也让人清醒地知道,有房与无房,是两个阶级。 124 | 125 | 32 126 | 00:02:44,987 --> 00:02:52,548 127 | 在灾难之中,先被动的,先受害的,是无房阶级。这次很多人会下决心拥有自己的房子。 128 | 129 | 33 130 | 00:02:52,548 --> 00:02:57,264 131 | 安心拥有你的房子,或者,认真开始实行你的购房计划。 132 | 133 | 34 134 | 00:02:57,264 --> 00:03:02,052 135 | 有自己一间房子,再小,都更能保障自己的安全与权利。 136 | 137 | 35 138 | 00:03:02,052 --> 00:03:05,724 139 | 繁荣时,可升值,灾难时,可避难。 140 | 141 | -------------------------------------------------------------------------------- /templete/input/input.txt: -------------------------------------------------------------------------------- 1 | 疫情时期,高三学生还没回校复课,教学依靠网络。 2 | 昨天有位高三老师说到, 3 | 她感觉学生比老师还焦虑,让谈谈这事。 4 | 5 | 教学方式变化,学习节奏打乱, 6 | 是今年所有学生面临的挑战, 7 | 对高三学生影响尤其大, 8 | 毕竟他们要迎接学习生涯中最重要的高考。 9 | 10 | 高三可能是许多人人生中效率最高的一年, 11 | 它具备几个条件: 12 | 13 | 一是艰巨而无法延迟的考核任务; 14 | 二是师长严厉的监督,这是最高等级的他律; 15 | 三是自律最严; 16 | 四是同学努力带来的激励, 17 | 这是最高等级的同侪压力。 18 | 19 | 这些高三的宝贵资源,在以后的人生中, 20 | 可用来迎接挑战,拿出你高三强度的一半,事都不是什么事。 21 | 22 | 可惜的是,多数人高三毕业后, 23 | 把这资源像旧课本一样扔了,暴殄天物。 24 | 25 | 无论你成绩好坏,都要记住自己高三全力以赴的模样, 26 | 成绩不拔尖的同学,尤其要记住, 27 | 因为人生定论不终结在高考, 28 | 你需要这种精神在后面一次又一次无形的考试挺住,并且成功。 29 | 30 | 很多人为何无法保住高三资源? 31 | 那是因为高三的诸条件消失了。 32 | 33 | 任务变模糊了,可以无限拖拉; 34 | 他律消失了;同侪压力也不大,人群的多样, 35 | 身边总有懒散的人、不负责任的人、愚笨的人, 36 | 37 | 让你产生“我很努力”的错觉,看不见自己其实在退步。 38 | 自律,变得极其重要。 39 | 40 | 很多孩子害怕上网课,迫切希望回到真实的课堂 41 | ,那是他们需要一个他律的环境以免自己迷失。 42 | 43 | 怎么度过这段特殊的高三? 44 | 这是我的建议: 45 | 46 | 一、接受事实。老想着回校复课,那就是不接受现实。 47 | 变化是计划的平台,自己在家学习,上网课,都是变化, 48 | 谁适应变化快,谁的计划成功率高。 49 | 50 | 我们那些有难度的、时间跨度长的计划,必然被扰乱。 51 | 就像一场伟大战役,有时气候不对,有时失去补给, 52 | 有时战友阵亡,有时自己受伤, 53 | 善战者根据变化不停调整行动,以保证计划的完成。 54 | 55 | 变化发生时,最好的应对就是马上接受变化, 56 | 不要回忆,不要抱怨。 57 | 58 | 二、告诉自己:所有同学面临同样处境,并非针对我。 59 | 所有人担心同样的事,那就没什么好担心的。 60 | 61 | 三、屏蔽疫情消息,你只要记住, 62 | 疫情得到了控制,世界很快会恢复正常。 63 | 64 | 四、恢复学校的作息。 65 | 在家,由于不要通勤,你可能会睡迟一点, 66 | 吃饭磨蹭一点,甚至随时吃点零食。 67 | 恢复到原来常规的作息,包括这种作息带来的一定的疲惫感, 68 | 这是在找回节奏,节奏可带着你跑,让你跑得更远。 69 | 70 | 五、建立仿真角。 71 | 有条件的用一房间,没条件的用一角落,学习环境 72 | 布置得像你学校的课桌一样,我也建议你上网课时 73 | 穿上校服。这仪式感能让你迅速进入角色。 74 | 75 | 六、除学习必要,锁上手机,或交由家长保管, 76 | 每日设定使用手机的时段与时长,能少尽量少。 77 | 78 | 七、每日完成固定的锻炼,冥想、卷腹、俯卧撑、 79 | 马步、站桩……总有一项或几项适合你。 80 | 81 | 八、家人做好配合。 82 | 高三学生的学习,是此里家里最重要的任务,其他一切退让。 83 | 这意味着,尽量保持家里的安静, 84 | 85 | 尤其是孩子在学习时,电视关掉, 86 | 手机静音,不吵不闹,别没完没了议论疫情, 87 | 设立一个固定的交流区域,你们有事去那儿说。 88 | 89 | 最好也趁这段时间,带着任务看看书, 90 | 体验一下孩子的学习,自己也可精进。 91 | 学习有时是整个家庭的竞争,当下最可证明这点。 92 | 93 | 如果你渴望胜利,你不会害怕变化, 94 | 变化只是让你多了赢的机会。 95 | 加油。 -------------------------------------------------------------------------------- /tools/request.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var request = require("request"); 3 | 4 | var src = "https://www.google.com.hk/images/srpr/logo3w.png"; 5 | var writeStream = fs.createWriteStream("image.png"); 6 | var readStream = request(src); 7 | readStream.pipe(writeStream); 8 | readStream.on("end", function() { 9 | console.log("文件下载成功"); 10 | }); 11 | readStream.on("error", function() { 12 | console.log("错误信息:" + err); 13 | }); 14 | writeStream.on("finish", function() { 15 | console.log("文件写入成功"); 16 | writeStream.end(); 17 | }); 18 | --------------------------------------------------------------------------------