小丸工具箱入门操作教程

      1 Comment on 小丸工具箱入门操作教程

本教程为小丸工具箱入门操作教程,仅对小丸工具箱的重要功能作详细解释。可能某些功能通过小丸的后续更新变得有些不同,所以仅供学习参考。
本次以236版来讲解

选项页1:视频


这里是压制视频的地方
通常来说,你把视频添加到“单视频压制操作范围”里面,在“通用参数”里调试你所要的参数,点击压制即可。
批量压制同理,不过它点的是右下角的压制。
普通的压制只需要调一调CRF的数值和视频的分辨率即可,不需要搞其他更深奥的东西。
需要注意的是,小丸会自动识别跟视频在同一个文件夹的同名字幕文件,在“单视频压制操作范围”增加视频后,它会自动添加同文件名的字幕文件上去。
而在批量压制的框框里,视频文件名会变成蓝色,跟上图的效果一样,再勾上右边的“内嵌字幕”,就可以压进去了。如果字的颜色是黑的,那么就说明没关联到字幕。

视频选项详细解说

编码器

无论是32位还是64位,都无所谓,跟着系统走就行了。(压制4K或以上最好用64位编码器,否则容易出现爆内存)
而“X264_GCC”,是用GCC编译的X264版本。
至于怎么选择都没必要纠结,一般压制是没区别的。

音频模式:

小丸这里分为3个模式:复制、压制、无音频流。
复制模式:顾名思义就是直接复制过来,使用这个模式之前,你需要考虑原视频的音频是否能封装进你所压制好的容器里。
压制模式:该选项的设置在“音频”选项页中,设置是通用的。
无音频流 :那就是没有音频了。

分离器:

这里一般选项为auto,没啥事不要动它。
压制视频出来画音不同步,有很大一部分都是分离器出问题,要是出现这个问题,请提供压制日志到论坛或交流群内报错。

起始帧和编码帧数:

该选项默认为0,如果你只需要压制该视频的其中一小段,那么你只要在“起始帧”设置从第几帧开始压制,在“编码帧数”上设置要压多少帧即可。
需要注意的是,使用该功能一定要“无音频”压制

压制模式

CRF:

该参数的质量范围一般为1-51,一般设置21-25之间就可以,此值越大码率范围越低。21可以压制出高码率。网络播放则设为24即可。
质量是x264参数中的 CRF(Constant Rate Factor),这种码率控制方式是非常优秀的,以至于可以无需2pass压制,即使1pass也能实现非常好的码率分配利用。很多人在压片的时候不清楚应该给视频压到多少码率才比较好。CRF就是按需要来分配码率的。

2Pass:

一般是给控制体积和码率用的,压出来的画质好与坏,得看你定下了多少码率和你的片需要多少码率。
2pass正是有“压制需要两遍,浪费时间”、“出问题的概率多”、“压制出来的效果不太好”等缺点,我们一般都不推荐大家使用。

自定义:

就是给你写自己的参数用的,会直接覆盖掉小丸所有内置的X264参数。但不包括编码器、音频模式、起始帧和编码帧数这4个选项。
使用之前,请确定你对X264的参数知识有一定了解,不要无脑复制别人的压制参数就直接压。

选项页2:音频


无论是音频还是视频,都可以从这里处理成一个单独的音频文件
只要选择不同的编码器即可。
需要注意的是,这里的设置跟视频页的“压制音频”通用,单独压其他音频后,记得改回AAC编码器,否则会造成视频压制失败。
音频合并功能有点小问题,凑合能用,但不推荐用。

选项页3:常用


此选项页有3大功能
1. 一图流
2. 视频无损截取
3. 视频方向旋转

一图流

音频码率

压制音频到所填写的码率,如果不需要压制请勾选复制音频即可。
在勾选了“复制音频流”的情况下,请不要直接使用AAC格式音频,得把它封装成M4A或MP4格式才能正常运行。

FPS

最好填上23或者30比较常用的帧数,如果直接用1的话,调戏进度条会比较困难。

CRF

跟压制的CRF同理,默认就好。

时间

把音频拖进去后,小丸会自动识别该音频有多少秒,如识别有误,可手动更改。

其他

起始时刻和结束时刻

起始时刻和结束时刻:时间格式为 时:分:秒,设定时间只需要结束时刻大于起始时刻点击“截取”即可。
截取之后总时间可能会有点误差,属于正常现象,不影响使用。
根据ffmpeg的无损截取原理,是无法做到准确到秒来截取的,只能准确到该时间的关键帧来截取。
需要准确到秒,请使用PR或爱剪辑等编辑软件或者通过ffmpeg重编码的方式来准确截取。

Transpose

你要把画面怎样旋转,就选哪个,选好点击“旋转”即可。
该设置也得重编码。

选项卡4:封装

合并成MP4

可以把单独的H264和AAC文件封装到一起

FPS和PAR

万年不用该的选项,可以不理。

替换音频

可以把视频里的音频替换成添加进来音频

合并成MKV

这里仅提供一些基础的MKV封装功能,如需要用其他复杂功能,建议你使用MKVExtractGUI等软件

批量封装

视频只要是AVC+AAC格式的,都可在这里批量封装成MP4/MKV/FLV/AVI等格式。
需要注意的是,音频不是AAC格式的都会被转成AAC格式。

选项卡5: AVS

我就不多介绍了,会用的基本都懂,不懂的教起来也复杂,还是找个AVS教程看看吧。

选项卡6:MediaInfo

用来查看视频信息,报错必备。

选项卡7:设置

界面语言

支持简、繁、英、日 4种。

托盘模式

该功能仅仅是压制时托盘有个小丸图标,在图标中悬停会有简要的压制进度信息,并且压制完成后会弹出提示。

X264优先级

这个选项可以设置程序的优先级,不会大幅度提升或降低压制速度,顶多是能让你一边凑合着玩游戏一边压制。

X264线程

一般来说小丸的X264只能利用到16线程,所以让它auto就可以。如果需要限制线程,那就根据自己最大的框框数量,减去需要保留的框框数量,得出来的和就是X264的线程。

X264自定义命令行

这个自定义,它不会把小丸的界面参数全部覆盖掉,只会覆盖掉内置参数。
即保留--crf 24.0 --threads 16这两项参数。

预览播放器

可以在这里指定AVS的预览播放器。

退出程序时删除所有临时文件

该功能开启后,在退出软件时,../MarukoToolbox/tools文件夹里的批处理等临时文件会自动删除。

启动X265

勾上了就可以用X265了,该功能还在测试中,所以默认不开启。

还原默认设置

小丸被玩坏了可以点这里。゚∀゚)σ

查看日志

点击即可查看最新的日志文件,如果要查找以往的日志文件,可以去 ../ MarukoToolbox/logs 文件夹里查找。

删除日志

点击后整个logs文件夹被删除。

From anywhere to AWS Lambda in one line with Zappa

The problem

We always want to do continus integration and deployment with our repo. Bitbucket comes with handy build function.
Version releasing with Zappa is easy: zappa update xxx will make a release, and zappa rollback xxx -n 3 would revert the changes.
But Zappa is currently broken on Python 3.7 as Zappa is using async as package name, while Python 3.7 shall use async and await as reserved names.
Locally I use Python 3.7 with macOS, but I have to support Windows + macOS + Ubuntu + CentOS: how can I quickly make release everywhere?

Solution

Local

Refer to blog.zappa.io/posts/docker-zappa-and-python3.
LambCI has made a couple of Docker images that would simulate AWS Lambda, located at github.com/lambci/docker-lambda , which provides handy shell access.

With CI

With some hacking we can make a Docker image for release, as in blog.zappa.io/posts/simplified-aws-lambda-deployments-with-docker-and-zappa . But this image only supports Python 2.7.
A Python 3.6 version is located at cloud.docker.com/repository/docker/cnbeining/zappa3 . And we can have a one-liner:
docker run -e AWS_SECRET_ACCESS_KEY=xxxxxxxxx -e AWS_ACCESS_KEY_ID=AKXXXXXXXXXXX -e AWS_DEFAULT_REGION=us-west-2 -v $(pwd):/var/task --rm cnbeining/zappa3 bash -c "virtualenv -p python3 docker_env && source docker_env/bin/activate && pip install -r requirements.txt && zappa update && rm -rf docker_env"
This command will create a environment, attach your current folder, install all the requirements, update the version, and remove all the garbage.
One note: DO NOT SET profile in zappa_settings.json. This image will automatically login with your key.

Reference:

blog.zappa.io/posts/continuous-zappa-deployments-with-travis

Flask from Docker to Lambda with Zappa: the more-or-less complete guide

TLDR

Step-by-step guide of how FleetOps migrate the Docker-based Flask API to AWS Lambda.

History

At FleetOps.ai we use Docker extensively when building APIs. Our API is built on Flask, with microservices supporting async features.
Since we are moving microservices to AWS Lambda ... What if the main API could also run on Lambda?

AWS Lambda & Serverless

Serverless is probably the hottest word in the DevOps world in 2018. Does not sound very interesting?
Compared to SaaS(Google App Engine, Heroku, Openshift V2, Sina App Engine, etc.): serverless does not have severe vendor lock-in problem. Most of the time you do not need to edit ANYTHING to migrate to serverless. You CAN choose to write the code in a SaaS way: and if you don't fancy that a DIY approach is still available. In this case I did not make any change to the original codebase!
Compared to Docker: although Docker is more flexible and you have access to a full Linux OS within the VM, it's still hard to manage when scaling. Kubernetes is good: but the burden for DevOps is dramatic. At FleetOps we do not want to put so much energy into DevOps: not to say hobby project.
Compared to Web Hosting: serverless supports more languages(Java, Node, etc.) which are not possible to get in the Hosting world.

Problem/limits with AWS Lambda

To name a few:

  • Does not support ALL the languages like Docker, and definitely not ALL the versions of Python. AWS is working on super lightweight OS image so maybe we can see something different?
  • Have to bring your binary/library should you want to use any special software, and they have to be statically linked, while with Docker you can do anything you want. Well, does not sound very bad, but:
  • The size limit of code: if you love 3rd party library it may be very hard to put everything into one zipball. Well technically you can grab them on the fly upon function invoked from S3, BUT:
  • Cold start problem: you have absolutely no control the life cycle of those function. God bless you if your function needs 10s to start.
  • Hard max runtime: 900s is the limit. Maybe you can get it raised but YMMV.
  • Stateless: Like container committing suicide after every invoke.
  • No access to special hardware, like GPU.
  • No debugger: do some print()s instead.
  • Confusing networking: I will try to sort out this issue in this article.

So if your task is:

  • not require any special technology, and uses the most common stack
  • stateless, or is able to recover state from other services(which should be the standard for every API - at least in FleetOps we ensure that every API call shall be stateless)
  • one task does not run forever and does not consume lots of memory
  • not really benefiting from JIT or similar caching
  • not super huge
  • not using fancy hardware
  • having an uneven workload

Then you could benefit from AWS Lambda.

The Guide

1. Get ready

We use Python 3.6 for the API for now.
Get a requirement.txt ready. Not there yet? pip freeze > requirements.txt.
On your dev machine, make a virtual environment: (ref: docs.python-guide.org/dev/virtualenvs/)

pip install virtualenv
virtualenv venv
source venv/bin/activate

Install Zappa(https://github.com/Miserlou/Zappa ): pip install zappa
Get your AWS CLI ready: pip install boto3 and refer to steps in pypi.org/project/boto3/ . Make sure that account has full access to S3, Lambda, SQS, API Gateway, and the whole network stack.

2. Some observations and calculations:

  • Where is your main function? Make a note of that.
  • How much memory do you need? If you cannot provide a definite number yet, let it here.
  • What is your target VPC & security group? Note their IDs.
  • What 3rd party binary do you need? Compile them with statically linked library - you cannot easily call apt-get on the remote machine!
  • Do you need any environment variables? There are different ways of setting them, and I am using the easiest approach - putting them in the config JSON.

3. Get the Internet right!

Further reading: gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7
Quote from @reggi 's article:

So it might be really unintuitive at first but lambda functions have three states.
1. No VPC, where it can talk openly to the web, but can't talk to any of your AWS services.
2. VPC, the default setting where the lambda function can talk to your AWS services but can't talk to the web.
3. VPC with NAT, The best of both worlds, AWS services and web.

Use 1. if you do not need this function to access any AWS service, or you only need the function to access them via the Internet. Use 2. if you are building a private API. And for FleetOps, we are going down path 3.
Note that not all the AWS services are accessible by VPC: e.g., S3 and RDS are accessible by VPC, while SQS and DynamoDB would require Internet access, even you are calling from within Lambda.
My recommended step is:

  1. Create Internet Gateway.

  1. Create 4 subnets.

  1. Create NAT Gateway.

  1. Create Route table.




Take note of the 3 private-faced subnet ids.
We will use Zappa to configure the networking. Note if you want to deploy the function to multiple AZ, you may need to do the steps multiple times, once at each AZ.

4. Wrap it up

Get back to your virtual env, and active it.
Do a zappa init. You will be asked the following questions:

Your Zappa configuration can support multiple production stages, like 'dev', 'staging', and 'production'.
What do you want to call this environment (default 'dev'):

Use whatever name: and you can carry on the stage's configuration for further stages.

Your Zappa deployments will need to be uploaded to a private S3 bucket.
If you don't have a bucket yet, we'll create one for you too.
What do you want to call your bucket? (default 'zappa-xxxxxxxxxx'):

By default, Zappa will only use this bucket when uploading/updating the function.

It looks like this is a Flask application.
What's the modular path to your app's function?
This will likely be something like 'your_module.app'.
We discovered: jinjaTemplates.app_template.app, v2.app.app
Where is your app's function? (default 'jinjaTemplates.app_template.app'):

Put in the entrance function.

You can optionally deploy to all available regions in order to provide fast global service.
If you are using Zappa for the first time, you probably don't want to do this!
Would you like to deploy this application globally? (default 'n') [y/n/(p)rimary]: n

Depends on your use case.
Now you may want to edit the zappa_settings.json: all the arguments are at github.com/Miserlou/Zappa#advanced-settings but this is the basic one that get our API running:

{
    "dev": {
        "app_function": "v2.run.app", // entrance function
        "profile_name": null, // boto3 profile
        "project_name": "FleetOpsAPI", // a name
        "runtime": "python3.6",  // Refer to AWS for list. Zappa only supports Python 2.7 and 3.6 for now.
        "s3_bucket": "zappa-xxxxxx",  // code temp bucket
        "memory_size": 256,  // Memory. You will pay for per second memory use so choose wisely!
        "environment_variables": {  // Everything that used to live in export
            "ENV": "dev",
           ..........
        },
        "vpc_config": {
            "SubnetIds": ["subnet-xxxxxxxx"],  // Put down your subnet IDs. We use all 3 zones within the same AZ and I recommend you do the same.
            "SecurityGroupIds": ["sg-xxxxxx"]  // Security group for access of other AWS service.
        },
    }
}

There are TONS of settings Zappa provides but I am not using all them: You can use a selective set of feature to make sure you do not have vendor lock-in. For example, Lambda can handle URL routing by itself but I am not using it to avoid any kind of lock-in. By doing so you can easily take the code and put them back on the container if you wish.
Zappa does provide some exciting feature:

  • Setting AWS Environment variables: If you prefer to put the secret key in another place
  • Auto packing huge project: if your project is >50M, Zappa will handle that.
  • Keep warm: Use CloudWatch to make sure there is one function running.

Save zappa_settings.json.

5. PROFIT!

Do a pip install -r requirement.txt to install all the packages.
Now do a zappa deploy.
You would see:

Downloading and installing dependencies..
 - pymongo==3.7.2: Using locally cached manylinux wheel
 - pycrypto==2.6.1: Using precompiled lambda package
 - protobuf==3.6.1: Using locally cached manylinux wheel
 - msgpack==0.6.0: Using locally cached manylinux wheel
 - markupsafe==1.1.0: Using locally cached manylinux wheel
 - greenlet==0.4.15: Using locally cached manylinux wheel
 - gevent==1.3.7: Using locally cached manylinux wheel
 - sqlite==python36: Using precompiled lambda package
Packaging project as zip.
Uploading xxxxxx-dev-1546239781.zip (22.9MiB)..
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 24.0M/24.0M [00:00<00:00, 77.6MB/s]
Updating Lambda function code..
Updating Lambda function configuration..
Uploading xxxxxxx.json (1.6KiB)..
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.63K/1.63K [00:00<00:00, 84.7KB/s]
Deploying API Gateway..
Scheduling..
Unscheduled xxxxxx-dev-zappa-keep-warm-handler.keep_warm_callback.
Scheduled xxxxx-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Your updated Zappa deployment is live!: https://xxxxxx.execute-api.us-west-2.amazonaws.com/dev

And you now have a serverless API ready to serve!

6. Clean up

You want to do the following tasks to save $$$, boost performance and secure the setup:

  • View some CloudWatch log and set the memory to a reasonable value afterwards.
  • Adjust warmer period.
  • Adjust API Gateway caching.
  • Setup cronjobs if you have them: either with Zappa or with CloudWatch.
  • Change the scope of IAM user for Zappa: the default one is super powerful.
  • Adjust X-Ray if you need it.

Conclusion

Migrating Flask API to serverless could be painless. I did not adjust one single line of code: and there is no vendor lock-in as every step can be reproduced by Dockerfile.
Good luck with your journey with serverless!

备忘:SOCKS和SOCKS/HTTP代理的连接

      1 Comment on 备忘:SOCKS和SOCKS/HTTP代理的连接

Use case:

  • 直接SOCKS肯定过不去GFW
  • 公有的SS看Google会跳验证码或者IP黑掉
  • Chrome的SOCKS代理不支持密码验证

方法:

  1. 本地安装Proxifier。配置好SS 不要使用全局模式,只监听某个端口。准备好可以使用的SOCKS/HTTP代理。
  2. 在Proxifier中分别配置好两个代理。
  3. 如图设置:

  1. 在Proxifier中,对浏览器使用这个chain,如图所示(例子是curl):

  1. 现在你的浏览器走SS翻墙 但是IP换了。

$ curl "http://ip-api.com/json"
{"as":"AS32489 Amanah Tech Inc.","city":"Toronto","country":"Canada","countryCode":"CA","isp":"Amanah Tech","lat":43.6683,"lon":-79.4205,"org":"Amanah Tech","query":"184.75..xxx","region":"ON","regionName":"Ontario","status":"success","timezone":"America/Toronto","zip":"M6G"}

数据说话:出国旅游,Visa还是MasterCard?

进入2018年,免货转(no-FX)信用卡突然大行其道。毕竟消费降级,大家囊中羞涩,传统信用卡2.5%的货币转换费简直等于给信用卡公司上税。
Brim Financial的Brim (WE)MC靠免货转的旗号,靠PPT收割了十几万个人信息然而发卡还是遥遥无期;Rogers推出了屌丝三宝之一的Rogers WEMC,外币返现4%;Scotiabank的Passport Visa Infinite正式成为丰业银行旗下的主打旅游卡产品;Home Bank的Preferred Visa仗着免年费可刷美国Costco成为了不错的抽屉卡;Prepaid卡的选择也有很多。
常逛小黄网的观众应该都知道,Visa和MasterCard肯定不会好心到按中间价进行兑换。那么到底高多少?交易群普遍认为是0.5%。有这么多吗?
这个问题greedyrates有过研究(https://www.greedyrates.ca/blog/mastercard-or-visa-foreign-purchases-better-canadians/) :但是数据量比较少,只对每周进行了取样,而汇率这个东西是瞬息万变的。这次的研究希望可以解决之前研究的缺陷。
研究方法:
数据源:Visa,MasterCard(下称MC),和中间价数据。文中所有单位都为基点(百分比)。数据的日期范围是报告日(2018年9月8日)前364天(2017年9月10日)至报告日,因为MasterCard只提供一年的历史数据。

  • Visa的汇率来自https://usa.visa.com/support/consumer/travel-support/exchange-rate-calculator.html 。其中有9天没有数据:使用后一天的数据填充。
  • MasterCard的汇率来自https://www.mastercard.us/en-us/consumers/get-support/convert-currency.html 。
  • 中间价数据来自https://openexchangerates.org/ 。数据是当日closing价格的中间价。在处理数据中,可能有小于千万分之一的误差。

所有的数据由爬虫得到。每种数据抽样5次检查爬虫工作情况。爬虫源代码公开。
结论:
先上一张全家福:

眼花缭乱?我们一点点分析:

上图是按时间排列,Visa卡比MasterCard汇率高出的基点数。可以看出,总体而言,Visa的汇率要高于MasterCard。
计算得出,Visa平均比MasterCard高0.209个基点,然而标准差是0.438,意味着差异统计上不显著:因为在去年中,MasterCard只比Visa优秀271天。
下图更加清楚:

大部分情况下,MasterCard的汇率都会比Visa好那么一点的。

Visa比中间价高那么0.449个基点:标准差是0.611。所以单单是免货转的Visa卡是不够的:在极端条件下,1%的返现会被吃光。

比起Visa,MasterCard就没那么心黑:多收0.240个基点,标准差0.454。大部分的免货转MC都不用担心赔钱了:Rogers WEMC即使在最惨的情况会剩下个0.8%的。
结论:

  1. Home Trust的Visa慎用,有可能赔钱;Scotiabank Passport VI可用。
  2. 大部分的MasterCard都不会赔钱。
  3. 无脑刷MC吧,除非不让。

本次研究没能解决的问题:

  1. Visa和MC都有连续几天汇率不变的情况,然而国际汇市是不可能不波动的。Visa的问题更加明显。不知道是Visa的系统抽风还是Visa的交易员比较懒。
  2. AMEX的数据实在没有找到:希望有这部分数据的观众进行补充。
  3. 由于XE的数据太贵了,这次研究使用了openexchangerates的数据作为中间价,有可能精度不如XE:但是应该不会有颠覆性影响。

附:

  1. 原始数据:https://docs.google.com/spreadsheets/d/1uwTFxSuQsJxey_KP3pMO1h2xZmj0buSO5YSP3tzFMMU/edit#gid=0
  2. 爬虫代码:
#!/usr/bin/env python
#coding:utf-8
# Author:  Beining --<i at cnbeining.com>
# Purpose: Research: Visa vs MC
# Created: 09/08/2018
import requests
import lxml
import re
from multiprocessing.dummy import Pool as ThreadPool
#----------------------------------------------------------------------
def get_visa_usd_cad_exchange_rate_by_date(date_string):
    """"""
    url = "https://usa.visa.com/support/consumer/travel-support/exchange-rate-calculator.html"
    params = (
        ('amount', '100'),
        ('fee', '0.0'),
        ('exchangedate', date_string),
        ('fromCurr', 'CAD'),
        ('toCurr', 'USD'),
        ('submitButton', 'Calculate exchange rate'),
    )
    headers = {
        'authority': "usa.visa.com",
        'pragma': "no-cache",
        'Cache-Control': "no-cache",
        'upgrade-insecure-requests': "1",
        'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
        'dnt': "1",
        'accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        'accept-encoding': "gzip, deflate, br",
        'accept-language': "en-CA,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,en-GB;q=0.6,en-US;q=0.5",
        }
    response = requests.get(url, headers=headers, params=params)
    if response.ok and 'converted-amount-value' in response.text:
        price_find = re.search( r'<strong class="converted-amount-value"> (.+) Canadian Dollar', response.text)
        if price_find:
            price_find = price_find.groups()
        else:
            return (date_string, None)
        if len(price_find) > 0:
            return (date_string, float(price_find[0]))
    return (date_string, None)
#----------------------------------------------------------------------
def get_mc_usd_cad_rate_by_date(date_str):
    """"""
    url = "https://www.mastercard.us/settlement/currencyrate/fxDate={date_str};transCurr=USD;crdhldBillCurr=CAD;bankFee=0;transAmt=100/conversion-rate".format(date_str = date_str)
    headers = {
        'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
        'referer': "https://www.mastercard.us/en-us/consumers/get-support/convert-currency.html",
        'Cache-Control': "no-cache",
        }
    response = requests.get(url, headers=headers)
    if response.ok:
        return float(response.json()['data']['crdhldBillAmt'])
    return None
#----------------------------------------------------------------------
def get_middle_usd_cad_rate_by_date(date_str):
    """"""
    url = "https://openexchangerates.org/api/historical/{date_str}.json?app_id=11ff5e6d97d74131abe05942bae6796e&base=usd&symbols=cad".format(date_str = date_str)
    headers = {
        'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
        'Cache-Control': "no-cache",
        }
    response = requests.get(url, headers=headers)
    if response.ok:
        return float(response.json()['rates']['CAD'])
    return None
#----------------------------------------------------------------------
def execute_multiprocess(func, iterable, thread_num = 8):
    pool = ThreadPool(thread_num)
    result = pool.map(func, iterable)
    pool.close()
    pool.join()
    return result
mc_date_list = [(datetime.date.today() - datetime.timedelta(days = x)).strftime('%Y-%m-%d') for x in range(0, 364)]
visa_date_list = [(datetime.date.today() - datetime.timedelta(days = x)).strftime('%m/%d/%Y') for x in range(0, 364)]
mc_result = execute_multiprocess(get_mc_usd_cad_rate_by_date, mc_date_list, thread_num = 8)
visa_result = execute_multiprocess(get_visa_usd_cad_exchange_rate_by_date, visa_date_list, thread_num = 16)
middle_result = execute_multiprocess(get_middle_usd_cad_rate_by_date, mc_date_list, thread_num = 8)
visa_result.count(None)  # 9

Download SRT file for WebOption(if exists) for UofT and UTSC

Some WebOption videos would include a subscript file, which due to some reasons UofT decided to hide.
This Userscript would enable you to download the SRT file for offline viewing.

// ==UserScript==
// @name         Download SRT of WebOption
// @version      0.1
// @namespace    https://www.cnbeining.com/2018/05/download-srt-file-for-weboptionif-exists-for-uoft-and-utsc/
// @version      1.0.2
// @author       Beining
// @license      MIT
// @supportURL   https://www.cnbeining.com/2018/05/download-srt-file-for-weboptionif-exists-for-uoft-and-utsc/
// @date         03/05/2018
// @match        https://lecturecast.utsc.utoronto.ca/c/*
// @grant        none
// @require      https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require      https://js.zapjs.com/js/download.js
// ==/UserScript==
var unsafeWindow = window.wrappedJSObject;
var $;
// For sanity just return if we don't have the object
if (typeof unsafeWindow.$ === 'undefined') {
  console.log('No jQuery object, returning');
  return;
} else {
  $ = unsafeWindow.$;
}
(function() {
    // 1. Create the button
    var button = document.createElement("button");
    button.innerHTML = "Download SRT";
    var sid = document.querySelector("#sid").value;
    // 2. Append somewhere
    var captionForm = document.querySelector("#captionForm");
    captionForm.appendChild(button);
    // 3. Add event handler
    button.addEventListener ("click", function() {
        $.ajax({
		url: "https://lecturecast.utsc.utoronto.ca/c/retrieve_st.ajax.php?id=" + sid,
		success: download.bind(true, "application/x-subrip", currentVideo.split(".")[0] + ".srt")
	});
    });
})();

CTO出了什么问题?

      No Comments on CTO出了什么问题?

For TGO鲲鹏会.

CTO出了什么问题?

标签(空格分隔):


note:


摘要
为什么企业和CTO总是败兴而归,摩擦不断?Paul Robinson给出了他的真知灼见。
作者Paul Robinson
正文
有句话我不吐不快:

从前是缺好码农,现在是缺好CTO。这周有3家公司找我问怎么招CTO。是不是当承包商给的钱太多,以至于没人想循规蹈矩,搞的公司高层都招不到人了?

我对CTO这个问题有一套:我自己为CTO招聘这件事做了5年咨询(虽然最终也没成什么,项目死的挺快挺惨的),自己也全职做过几次CTO。
如果你想成为CTO,或者想招聘CTO,我有一言请静听。

CTO每天做什么?

工程师(特别是小型公司的工程师)会觉得CTO就是“超级技术领导”:他们觉得CTO是一个特别高年资的工程师,领导全司的技术方向。
我担任CTO时做了一点点事情:

  • 和商业部门大佬沟通(CEO、董事会、投资人等),确定下面几个月的路线;
  • 和产品和分析师研究出可行的产品路线图,和商业规划匹配;
  • 按照产品和商业路线图规划技术路线图;
  • 当某个路线技术上不可行时,劝说其他人放弃这个想法;(注意:不是简单的说“开发不了”——需要谈判技巧!)
  • 设计开发团队,报告人和流程;
  • 在功能、BAU和技术债/bug间找到平衡点,最大化商业利益;(一般来说没有公司会把修bug当成头等大事的)
  • 关注技术开发涉及的合规性问题和法律变动;
  • 准备并申请开发预算——工资和研发预算一般是两条线;
  • 准备并申请运行预算,例如硬件、服务(数据中心、云服务等)、软件授权、专利授权等等;
  • 把上面所有的东西和管理层和董事会讲明白,而且要说人话——用财务数字。这步需要做很多Excel表,并加以解释;
  • 把上面所有的东西和投资人和未来的投资人讲清楚,而且留后手以免被开除;
  • 设定技术团队的文化。这件事和下层多多少少都有关系,但是你得定调子。你做的事情会被有样学样;
  • 把上面的所有事情和技术团队说明白,用程序员的人话。例如,对董事会汇报可以说“本司预计于18至24个月内由CAPEX模型迁移至OPEC模型”,但是对技术团队你得说“接下来一年到一年半我们要从自建机房全部迁移上云”。(注意时间要求被加码了:除非你得到充分信任,否则你必须这么做
  • 保证技术团队的运行不受阻碍:你可以对人大喊大叫,但是大部分人觉得大家互相信任,不需要管理的效率最高。我从Joel那里知道了这点;
  • 招聘高级别技术员工:这步是最耗时也是最难的,但是如果做好了以后就轻松了;
  • 管理、指导并支持技术高层;
  • 考虑薪酬,期权管理等,虽然从公司政治上不怎么愉快而且很难办;
  • 开除需要开除的员工。不能心慈手软。有人告诉我一条金科玉律:用人的目的评价人,而不是结果。尽可能不开除好心办坏事的人:想办法帮他们。
  • 做有争议的决策后把故事编圆,保证团队看起来团结一心;
  • 当团队做得好时一定要激励;
  • 出任何差错你去承担。我历史上辞职过很多次,不一定是因为我自己犯了错。如果你拉不下脸,就别进管理层:如果你想推卸责任,那么你下面的所有人都会恨你,而且你也干不下去了。

你已经注意到了,写代码的时间并不是很多。根据公司的不同,有可能CTO不会怎么碰产品,具体的说:
在非常小的公司,你自己必须亲力亲为做产品;在大公司你不会有时间亲自做产品的。
我上次当CTO时编了个笑话:我司大到我不需要写代码,但又小到我必须亲自写,搞得我两头不是人。

不同种类的CTO

虽然上面的职责相通,但是CTO还是分不同种类的。
一般来说,CTO可以分成“运营管理”型,和“技术领导”型。两种CTO的背景和角色区别巨大。
我去过一个咨询公司的CTO酒会。我们在伦敦中心的高级酒店聚会,社交一下,吃一顿公司提供的大餐。然后他们搞了个“圆桌讨论”,想听取“技术领导人”的看法。对他们来说这种事情是市场调研,但是考虑到上的菜和酒的确上档次,所以为什么去不薅羊毛呢?
于是我发现了很震惊的事情:在座的20多CTO中,我和另一位是仅有的曾经学过写代码的CTO。
那名CTO有工程背景,但是大家都觉得他只是个技术怪人而已。我是唯一可以自信地运用我的技术背景的CTO。
其他的CTO觉得有技术背景的人很奇怪:都要当CTO了,为什么还要学写代码?
读者肯定会奇怪了:难道CTO不是工程师一层层升上去的吗?
有些我共事过的CTO可能写过那么一两行代码(“当年写过几行COBOL”的程度),觉得代码写不下去,开始研究管理职务,跳过去了。
更多的人是从运营或产品经理升上去的,大家觉得他们懂技术,于是就把技术交给他们领导了。
从运营上来说,他们有可能学过金融、产品管理、运营、教学等工程师认为是“软技能”的技术,把纯技术交给他们能信任的人来处理。
这种模式于大公司的技术产品研发部门很常见,但是一般不会在科技公司中出现:这种模式一般在零售、公共事业、银行、政府中更多。
当然了,对于想成为CTO的工程师来说,上面所说的只是万千条路的一种:还有很多工程师类型的CTO职务,会更像“技术领导”。
技术领导更多是提供样板,当高级工程师搞不定时可以来求援,所有人知道你说的办法肯定是最佳方案。
不是所有公司都需要这种领导:有些公司可以让技术团队自己研究个方案,但是如果真需要技术领导而CTO没技术能力的时候,整个公司有可能直接死掉。
技术领导最适合纯技术公司:公司的主要产品就是技术,例如软件或B2B的组件,或者卖的东西会被商店划分到“科技”板块的那种。
这种公司的CTO必须是理解整个产品的工程师,而且是有同理心,可以领导团队的人。
这两个世界交集很多:服务行业越来越需要科技驱动,科技公司越来越需要关注市场。
我的第一份技术工作是在运营商的。我的CTO会Unix命令行,会八国语言写代码,能把表脑内转换成第三范式。
那个运营商被收购了,和几个运营商合并,成长了很多。现在那家公司是欧洲最大的运营商之一:我几年前看过他的CTO专访,很明显他的CTO不怎么懂技术。90年代的运营商是科技公司的代表:现在变成公共事业了。
所以,公司的不同阶段需要不同的CTO:要么你变,要么你让路,去小公司继续领导。对于希望领导技术团队的CTO而言,不是坏事。

CTO出了什么问题

总体来说:

  1. CTO的职称在不同的公司意义不同,职责也不同
  2. 一线工程师不知道这个职位不需要懂技术,自己也不懂运营和管理
  3. 非技术人员又不懂工程师每天在做什么,所以做不成什么技术决策
  4. 随着公司变化,CTO也要变化
  5. CTO如果搞错了形势,就得下台。CTO想跳槽不容易:不是所有公司都有CTO,即使有也很不一样,参见第一条
  6. 最后,CTO和别的CXO们工资一般相差很大:如果你对公司财政上没影响,那对公司的其他部分也没什么影响

所以我觉得不是因为大家都想当承包商,造成CTO难找:大家心里像明镜似的。如果你是高级程序员,考虑当CTO,那你肯定会认识个10年前改行当CTO现在痛不欲生的朋友。
简单的说:想做的做不好,做好的不爱做。
那么怎么办?很多人管理上不够格(例如,高级技术经理,但是不想当CTO),或者工程上不够格(运营的外行指导技术内行)。
有一个办法是,创立一些类似CTO但不叫CTO的职务:工程总监、工程副总裁,技术总监等等。有这些职务的公司一般也有个CTO。这些职务在不同的公司意义不同,但是我希望以后慢慢会有规矩。
我也见过CTO做纸面工作,技术总监做技术工作的设置,但是效果不好,因为两个人都有管理背景,都不想搞技术。我觉得也是因为其他管理层不知道技术领导的需求吧。
虽然很难,但是公司成败有可能真的在此一举。

如何招聘CTO

如果你想招聘CTO,好好考虑一下你需要的技术和背景。
如果你需要技术领导,那么找一个高级工程师,给他时间和空间熟悉非技术工作。帮助他,明确说明你需要CTO做什么。每步要汇报。
如果你需要管理领导,那么找一个管理背景的人,让他找一个技术总监,让他们自己划定职责。

如何当好CTO

想好你想得到什么,以及你想成为什么样的CTO。你有可能真正想做的是工程总监,甚至只是大部门的技术领导。
万事开头难:多问问题,寻求帮助。你肯定会筋疲力尽,但是如果一切顺利,那么你会为你的团队和同事感到骄傲的。
最后叮嘱一句:搞明白领导和管理的区别,知道何时用什么。
祝前途似锦!
查看英文原文
hackernoon.com/the-problems-of-the-cto-role-c2a143a1cec7

被360快视频偷视频了?按此操作干回去

      No Comments on 被360快视频偷视频了?按此操作干回去

经过24小时的投诉 迅雷已经将其纽约州机房下线。
但是他又出现了一个LA的机房:死性不改。
这次请抄送techsupport@ctamericas.com 而不是之前TATA和NTT。其他不变。


首先 不要用自己的用户名密码去登陆。你不想被他又钓鱼一次。
然后呢 虽然360远在国内 但是360快视频用了迅雷的CDN。
虽然迅雷也在国内 但是他有美国的机房。意味着,他受DMCA管辖。
那么:
取URL例子:
k.360kan.com/pc/detail/yJwA4raEBe86?ucheck=8a5178d532abf773c6ea66417c5b0626&uid=653ba1f194cb3d1044a356a69e61b875&version=&sign=pc&resign=pc&is_recom=1&strategy=2.6.51.5.9dgwy0nhstch.9.wuc.26.vh9vnv..15.5p1bl9ulikig&channel_id=&end=pc&is_new_recom=1
重点是 yJwA4raEBe86 这个id。
然后去 pc.k.360kan.com/pc/play?id={刚才取的ID}&f=json
会得到类似 pc.v.k.360kan.com/vod-xinxiliu-tv-q2-bj/70840567_05d6d336e-c2d0-46f9-9898-72e113a334ba.mp4?time=1519105055&sign=7605d3237bdb738bd992bb2f00dd13e3
的URL。
写邮件吧。
抄送:
以上两个已经拔线,请勿抄送
新地址:techsupport@ctamericas.com
邮件标题:DMCA Takedown Request
邮件正文:
To whom it may concern,
I certify under penalty of perjury, that I am an agent authorized to act on behalf of the owner of the intellectual property rights and that the information contained in this notice is accurate.
I have a good faith belief that the page or material listed below is not authorized by law for use by the individual(s) associated with the identified page listed below or their agents and therefore infringes the copyright owner's rights.
I HEREBY DEMAND THAT YOU ACT EXPEDITIOUSLY TO REMOVE OR DISABLE ACCESS TO THE PAGE OR MATERIAL CLAIMED TO BE INFRINGING.
This notice is sent pursuant to the Digital Millennium Copyright Act (DMCA), the European Union's Directive on the Harmonisation of Certain Aspects of Copyright and Related Rights in the Information Society (2001/29/EC), and/or other laws and regulations relevant in European Union member states or other jurisdictions.
My contact information is as follows:
Organization name: Attributor Corporation as agent for the rights holders listed below
Email: {你的邮箱}
Phone: {+86-你的电话}
Mailing address: {替换成你的地址 以下为例子}
1265 Renmin Road,
Dalian, Liaoning, China
123456
My electronic signature follows:
{你的大写名字拼音 例如BEINING ZHANG}
Sincerely,
{你的名字 例如Beining Zhang}
*** INFRINGING PAGE OR MATERIAL ***
Infringing page/material that I demand be disabled or removed in consideration of the above:
Rights Holder: {你的名字 例如Beining Zhang}
{% 对于每个侵权视频 %}
Original Work: {你的视频名的拼音}
Infringing URL: {原视频的地址 例如https://www.bilibili.com/video/av12450/}
Infringing URL: {侵权视频的URL 例如http://pc.v.k.360kan.com/vod-xinxiliu-tv-q2-bj/70840567_05d6d336e-c2d0-46f9-9898-72e113a334ba.mp4?time=1519105055&sign=7605d3237bdb738bd992bb2f00dd13e3}
{% end %}
静候佳音。

小丸工具箱压制日志结构详解

      No Comments on 小丸工具箱压制日志结构详解

本帖以小丸工具箱236版来讲解,以后新版可能会有所变动,特此声明。

许多人在使用小丸工具箱的时候,经常会发现“视频压制完后不见了”、“压制出来的视频只有几十kb”、“封装视频后闪一下就没有,也没有生成新的文件”等压制问题。
其实这只是压制或者封装过程中出现错误所导致的结果,只是小丸工具箱的压制错误提示并不醒目,一般人遇到这种情况完全没有意识到这是压制出错了,导致报错的时候提供的信息都不能准确的分析错误的原因。
不过这也是小事情,保存好日志,打开后就能知道是哪个压制环节出错了。但是也有很多人看不懂这些日志,密密麻麻的英文,完全不知道从哪里下手。(你知道整个交流群就我一个人看会去日志的绝望吗?)可是报错的时候只提供了一小截的截图,并不能完整的分析这压制错误到底在哪。
所以我特意写出本帖来讲解一下小丸工具箱日志的整体结构,让大家都能从压制日志里看懂整个压制过程在哪出错和如何排除错误。
在观看本帖的同时,如果你对小丸工具箱的相关操作和使用方法都不太清楚的,建议你看完《小丸工具箱入门操作教程》,因为……一些操作失误或者选项出错,光用日志查看也是看不到的。
使用不同的编码器和片源进行压制,日志的内容也是略有不同的,但是整体日志结构是差不多的,为了不搞的那么麻烦,这次我们拿最常用的“AVC+AAC_8bit.mp4"的片源和“X264_64-8BIT.exe"编码器来讲解。
还有一点就是,日志篇幅比较长,不可能整个截图下来,所以我会把不同阶段所常出现的单词来做索引,大家可以拿一个压制正常的日志(通常一个流程完整的日志,文件大小在20kb左右,100多以上的,那基本是任务列表日志,看不了单个任务的详细信息的。),用Ctrl+F搜索关键词来对照和了解。
压制配置如下:

日志的结构可以简单的分为三个阶段

第一阶段:ffmpeg的抽取和压制音频

这里一开头就是了,所以没发关键词,在ffmpeg抽取音频流出来后,就交给neroAAcEnc或QAAC等音频编码器处理了。
主要注意的是,压制音频的时候右下角的进度条是不动的,不要以为小丸工具箱卡住了没动,还有在选择“无音频流压制”的情况下,是没有这一段的,直接进入第二阶段。

常见的错误有:

  • “ERROR: could not parse WAV file”
    • 这属于抽取音频流失败,请检查一下自己的视频是否有音频流
  • 使用WAV或者FLAC等无法封装进入MP4的音频格式,会导致压制的封装阶段的失败。

第二阶段:X264对视频流进行压制处理

这个阶段分为三小步

  1. 从"..\xiaowan\tools\x264_64-8bit.exe" 这一段开始,就进入压制视频流的阶段了。后面的是你这次压制所使用的参数,下面的百分比进度,是分离器的索引进度。
  2. “ffms [info]” 这是ffms分离器索引回来的信息。(使用不同的分离器就有不同的info)
    这是压制日志中最重要的一段,里面包含了分离器对视频文件内容的分析。
    例子:

    ffms [info]:
    Format : mov,mp4,m4a,3gp,3g2,mj2
    Codec : h264
    PixFmt : yuv420p
    Framerate : 25/1
    Timebase : 1000/12800000
    Duration : 0:14:49
    ffms [info]: 854x480p 1:1 @ 25/1 fps (vfr)
    ffms [info]: color matrix: bt709
    x264 [info]: using SAR=1/1
    x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
    x264 [info]: AVC Encoder x264 core 148 r2721+46 0c4b09a xiaowan [8-bit@all X86_64]
    x264 [info]: profile: High, level: 3.0, subsampling: 4:2:0, bit-depth: 8-bit
    x264 [info]: cabac=1 ref=4 deblock=1:1:1 analyse=0x3:0x133 me=umh subme=10 psy=1 fade_compensate=0.00 psy_rd=0.30:0.00 mixed_ref=1 me_range=24 chroma_me=1 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 fgo=0 bframes=3 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=1 scenecut=60 intra_refresh=0 rc_lookahead=60 rc=crf mbtree=1 crf=23.5000 qcomp=0.50 qpmin=0:0:0 qpmax=69:69:69 qpstep=4 ip_ratio=1.40 aq=2:0.80 aq-sensitivity=10.00 aq-factor=1.00:1.00:1.00 aq2=0 aq3=0
    x264 [info]: started at Sun Jun 11 14:06:47 2017

  3. 当视频压制完成后结尾还会有关于压制视频的总结,到此视频流的压制过程结束。

    例子:
    encoded 3609 frames, 216.56 fps, 166.46 kb/s, 1.42 MB
    x264 [info]: ended at Fri May 05 23:02:18 2017
    x264 [info]: encoding duration 0:00:17

    含义:
    编码帧数3609帧,平均处理帧速度216.56fps,平均码率166.46kb/s,总大小1.42MB
    x264[info]:于05月05日 23时02分18秒 2017年结束
    x264:[info]:编码时间为17秒。(指的是你压制视频过程的时间)

常见错误:

  • 这里的错误格式并不固定,你只需要找到[error]即可,例如“ffms[error]”就是分离器出错,“resize[error]”就是分辨率的问题,“X264[error]”就是X264出了问题。
    [error]后面会告诉你详细的原因,这些英文扔进去机翻一下就能搞懂的,不必太紧张。
    至于[warning],详细原因你也可以机翻了解一下,只要它没影响到压制过程或者成品出来没问题,就可以不用管它。
  • 压制后要是出现画音不同步,就需要打开日志查看分离器解析出来的info跟视频拖进MediaInfo是否有偏差,如果“Framerate(帧数)”和“Duration(视频时长)”没有异常,则对比第三步的encoded(编码帧数)跟MediaInfo上显示的总帧数是否一样,只要有其中不一样,就可以判断是因为分离器的解析错误,更换其他分离器来解决(实际操作请看小丸工具箱FAQ,画音不同步的问题是一时半会说不清楚的。)
  • X264编码器压制完成后,提示“找不到批处理文件”。
    这所谓的“批处理文件”,其实小丸工具箱是生成到C盘的TEMP里面的。(不同版本的WIN系统,默认的TEMP位置也不同,请自行搜索)有这个提示并不是说批处理文件不见了,可能是无权访问。造成无权访问的原因,基本确定是国产的各种XX卫士/杀软搞得鬼。
    不过我们还没有能完美解决这个问题的办法,所以建议遇到该问题的人,以管理员权限运行小丸工具箱或者找出TEMP文件夹把自己的用户权限加入进去或更改。

第三阶段:MP4box封装阶段

从"..\xiaowan\tools\mp4box.exe"开始,对压制好的视频流和音频流进行封装处理成一个成品。

常见错误:

  • “Unknown input file type”、“Error importing XXX.mp4”、“找不到网络路径”这是封装阶段常见的错误词汇,这些错误通常是因音频压制失败或者视频压制失败所导致的,请查看第一阶段或者第二阶段有没有压制错误提示出现。
  • MP4box有时候也会出现文件名编码乱码导致封装失败的问题。
    比如你的文件名用一些除本机系统语言的其他语言编码或者有特殊符号来命名,导致视频文件在X264压制好后,MP4box认不出文件名里的特殊符号直接封装失败,失败后小丸工具箱会执行删除临时文件命令,才出现压制过程完成后视频没有出现的原因。

这三个步骤走完之后,整个压制流程就结束了,可以直去源视频目录查看压制好的成品。
看到成品没出现也不用慌,打开日志,根据上面所提到的三个阶段,查看每个阶段是否有报错信息来排查。
要是遇到其他方面的出错,可以阅读小丸工具箱的FAQ,看看有没有相类似的问题。

小丸工具箱FAQ