HABIT IS POWER

习惯就是力量

0%

Slack is awesome, but multiline code formatting in a Slack Post is sucks.
My solution is using Markdown Preview Plus with a Slack Snippet.

需求

使用Slack做运维日志的记录,不可避免的会有一些代码或者脚本,也想直接记录在Slack中。

解决这个问题,直接想到的就是”create a post”,Slack的POST虽然是支持Markdown的,但是他的支持非常有限,最让我无法忍受的是多行代码的排版,会完全乱掉。

能不能再Slack中使用Markdown而且有更好的排版支持呢?这是我的需求。

PS.

补充一个使用情况:在PC或Mac上,我都是优先选择使用Web版本,Slack我也是在我的Chrome中使用。

解决方案

0.没有用的吐槽

发了条Twitter:

@SlackHQ Slack’s Code Formatting with Markdown is sucks :( #markdown

发现Twitter也有人反馈过这个问题,Slack的回复很官方,但是实际的效果就是排版惨不忍睹。

1.Markdown Preview Plus(Chrome Extension) + text snippet

解决方案描述

  1. 使用Chrome进行以下操作
  2. 安装Markdown Preview Plus
  3. 在Slack中”create a text Snippet”
  4. 使用Markdown进行编辑文档
  5. 使用”View raw”来查看Markdown文件,而插件会自动帮你格式化排版

折中方案

这其实是一个折中的解决方案,因为他缺失了一点功能:post分享出去的时候是带格式的,而text snippet分享出去是源代码格式,但是基于目前Slack Post的排版如此惨不忍睹,其实这个舍弃是完全可以接受的。

text snippet选择Markdown类型,没有格式预览,但源代码显示是正常的,也有语法高亮,需要预览最样式就使用Markdown Preview Plus,够用了。

需求

Mac OS X下调试iOS模拟器中的服务端API请求,想通过修改host来使用本地web.py替换远程服务器,为了让手机端的代码不需要修改,需要让web.py跑在80端口.

遇到的问题

python code.py 80

提示错误如下,但是如果把80改成别的端口就是好的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http://0.0.0.0:80/
Traceback (most recent call last):
File "hello.py", line 15, in <module>
app.run()
File "/Library/Python/2.7/site-packages/web.py-0.37-py2.7.egg/web/application.py", line 313, in run
return wsgi.runwsgi(self.wsgifunc(*middleware))
File "/Library/Python/2.7/site-packages/web.py-0.37-py2.7.egg/web/wsgi.py", line 54, in runwsgi
return httpserver.runsimple(func, validip(listget(sys.argv, 1, '')))
File "/Library/Python/2.7/site-packages/web.py-0.37-py2.7.egg/web/httpserver.py", line 157, in runsimple
server.start()
File "/Library/Python/2.7/site-packages/web.py-0.37-py2.7.egg/web/wsgiserver/__init__.py", line 1753, in start
raise socket.error(msg)
socket.error: No socket could be created

问题分析

是不是端口占用的问题?

用下面的命令查看了下,并没有进程占用80端口啊!

1
2
3
4
5
6
7
8
9
10
11
MAC下查看端口是否被占用的方法:

方法一:
//查看80口是否被占用
sudo lsof -i :80

方法二:
netstat -anp tcp | grep 80

如下命令可以直接结束占用端口的所有进程:
lsof -P | grep ':80' | awk '{print $2}' | xargs kill -9

参考:

MAC下查看端口是否被占用

关闭Web共享

权限问题!

找到一篇文章后才知道,原来是类Linux系统下的安全策略设计就是这样的,自己对Linux的使用还是太少了!

Normally only root processes can bind to port 80 (or to any port below 1024).

参考:

How can I open port 80 so a non-root process can bind to it?

解决方案

试了下sudo,成功了 囧rz

sudo python code.py 80

我只是为了本地调试,用sudu是最方便的方法,如果是服务器上的话可以尝试上面那个问答中的方案。

这是个事儿吗?

阿扎尔的英文名是Eden Hazard,我的英文名也是eden,而且我还是个伪球迷,支持阿森纳,切尔西,以及鸟叔以后执教的球队……(扯远了)

理论上,对于阿扎尔的英文名不可能读错,但是看了好多采访视频之后,我发现人们对Eden Hazard的读音并不相同!

英超赛后采访和鸟叔的读音不一样

我们来看看这两个Youtube视频,
电视主持人叫的是伊登[‘i:dən],而鸟叔叫的是艾登[edɛn],
他们俩到底谁的发音是正确的呢?

死磕自己,寻找答案

单纯从英语的角度,应该读成:伊登.哈泽德 [‘i:dən][‘hæzəd]

单纯从英语的角度,其实没有异议,就是这个读音,所以英超赛后采访的时候,记者按照英语的发音来是完全可以理解的。

考虑下球员名字的母语发音

球员的名字肯定是要考虑球员的母语发音的,以大家相对来说比较熟悉的孙继海为例,他在曼城时的球衣背后印的是“SUN”,英超的解说员在他进乌龙球时喊的可不是“日”,而是“孙” #233

同样我们来看下阿扎尔的出生地: Hazard was born in La Louvière and grew up in Braine-le-Comte,也就是说阿扎尔的母语是法语

从法语的角度,应该读成:艾登.阿扎尔 [edɛn azɑʁ]

法语中的eden和hazard读音和英语中都是不一样的,法语中应该读成:艾登.阿扎尔 [edɛn azɑʁ]。

eden的英语和法语发音区别

eden的英语发音

eden的法语发音

hazard的英语和法语发音区别

法语中H和D在这个单词下是不发音的,所以hazard就变成了azar,这也就是为什么大家都叫他“阿扎尔”

azar的英语发音

hzard的英语发音

法语中部分字母不发音的参考:法语-读音规则

小结

在英语环境下,比较中规中矩的发音[‘i:dən][‘hæzəd]是没有错,但[edɛn azɑʁ]无疑是更加亲切的发音,而鸟叔又不是播新闻联播的,也不应该叫得那么官方,他叫阿扎尔 [edɛn] 就再正常不过了。

简介

Sonic 是一个跨平台的声波传输库(iOS & Android),技术上类似于chirp蛐蛐儿,但声波识别率上和他们还有很大的差距。

声波生成和识别的代码源自WaveTrans,linyehui 对源代码进行了精简,将声波编解码部分的代码进行了独立封装,并做了跨平台移植,从而得到了这个更简练的声波传输库:Sonic

关于声波识别率和存在的问题

目前的代码,降噪主要依赖于手机本身的物理降噪(类似双MIC降噪等),嘈杂环境下的声波识别率比较差;

如果你需要产品化这项技术,那么这份代码只能带你入门。

开发环境

1
2
3
4
OS X 10.9.5
Xcode 6.0.1 (准备开源的时候才做了Xcode6兼容,模拟器下iPhone 6还有问题)
adt-bundle-mac-x86_64-20131030
android-ndk-r9d

目录说明

1
2
3
4
|---sonic
| |--android # Android Demo
| |--ios # iOS Demo
| |--sdk # 跨平台的C++代码

温馨提示

iOS 和 Android Demo非常简陋,可以在两部设备上相互发送声波并识别,但交互上还有很多已知和未知的Bug :(

希望这份代码能给你带来些许帮助。

需求

手动清除Android QQ中内嵌WebView缓存

寻找解决方案

WebView Cache 缓存清除

简单说,就是应用内的WebView缓存都会序列化在这里:

1
2
3
/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db

手动删除缓存-操作步骤

  • 杀掉应用
  • 去/data/data/package_name/目录下删除cache目录
  • 去/data/data/package_name/database/目录下删除所有webView前缀的文件
  • 搞定

First Touch 足球系列

iOS下的足球游戏,如果要从操作性的角度选出一系列最好的,不是FIFA系列也不是Real Football系列,而是First Touch系列。

第一次接触到First Touch的足球系列游戏,是《Dream League Soccer》,这款游戏虽然画面比较粗糙,但是操作感十足,特别是各种各样的进球方式让人赏心悦目,比赛的节奏很流畅,和起华而不实的FIFA和Real系列比起来,有种早期实况 VS FIFA的感觉。

这款游戏我已经不记得自己多少次“通关”,自己组建的切尔西也已经把我想买的所有球员都给买下了,而且所有球员的数值我都已经训练到了90以上,其中几个能力值是100。

不过《Dream League Soccer》的玩法还是简陋,比如连助攻数都不统计,联赛形式也比较单一,在这个时候我发现了同系列的另一款新游戏:《First Touch Soccer World Edition》。

First Touch Soccer World Edition 与前作的差别

  • 游戏引擎和上一款没有大的变化,所以操作上完全一致
  • 游戏部分玩法和设置必须要VIP才可以玩,而VIP需要4000金币
  • 游戏的联赛使用了真实名字,而上一代都是类似“北伦敦”一样的替代名字
  • 游戏的“Manager Mode”,让你自己当Manager,你不仅要操作游戏比赛,还要考虑球员买卖,更有教练自己的转会,这个是新版本的精华所在
  • 新增了世界杯模式,世界球队随便选,夺取世界杯
  • 新增了俱乐部的营收体系,使用独立的货币,球队买卖球员,升级体育场都要使用货币进行,但货币不足时可以使用金币兑换,美其名曰:投资俱乐部
  • FTS新增了Star Player Mode(VIP功能),比赛的时候你只控制一个球员,可以呼叫你的队友传球给你
  • 新增了TOURNAMENT MODE(VIP功能),其实就是各大联赛和杯赛,想体验每个联赛的话不用在Manager Mode下进行,解锁VIP后就可以随便选队了

First Touch Soccer World Edition 入门指引

  • 刚开始玩,推荐从世界杯模式入手,熟悉下操作,同时也赚点金币
  • 对于不想花钱的用户,世界杯通关后的下一个游戏目标是赚够4000金币,买下VIP
1
2
3
4
5
6
7
8
有了VIP你的每局游戏经验和金币都会翻倍,  

可以随便挑选球队进行比赛,联赛或杯赛,

还可以设置比赛时长(想不到这个都是VIP功能……)

比赛开始前可以选择使用Star Player Mode

Manager Mode技巧和窍门

比赛操作

  • 玩Manager Mode,一开始可以把游戏难度调成“Low”,因为一开始你能选到的球队真的很搓
  • 初始的时候要选一个球队,尽量选个星级高一点的,球队收益好点
  • 头球大法好用
  • 挑球需要球员数值比较高,没有大牌球星还是不要尝试了

维持俱乐部的收支平衡

  • 小球会不要买大球星,其实70-79能力值的球员已经可以打遍五大联赛了
  • 实在缺钱的时候,可以玩一轮世界杯模式,刷一刷金币
  • 球队连续5周财政赤字会自动解雇球员(被解雇的球员不给选的,不小心好球员被裁掉会很吃亏)
  • 但是有一种情况就算财政赤字也不会自动解雇球员:球队有且只有16个球员,因为游戏规定一直球队至少必须有16个球员
  • 省钱大法
1
2
3
守门员只保留一个
球员保持游戏最低人数:16个(教练转会的时候要注意这一点,下文有说明)
比赛要赢球,冠军联赛这种钱比较多

球员转会

  • 联赛开始后马上开始转会运作,把不好的球员全部加入转会名单,然后买入一些物美价廉的球员
  • 物美价廉的好球员:OVERALL能力值在70-79之间,身体素质的三个属性均超过80
1
2
3
4
5
球员最重要的是身体素质的三个属性:SPEED,ACCELERATION,STAMINA
而这三个中STAMINA(耐力)又是最重要的,因为你也不想踢了半场就得换人吧
球员比赛过程中状态差的情况下最好换人,不然会被电脑抛在后面几米
STAMINA 80以上的球员可以保证这个球员整个赛季可以比较完整的完成,而不是踢一场休息两场
同样身体素质的球员中,球员的价格:守门员 < 后卫 < 前锋 < 中场
  • 球队还是要有一两个数值比较高,性价比高的核心球员,有两个球员值得推荐:特雷泽盖和里克尔梅
  • 缺钱的话,先买个好前锋或前腰,剩下的都买后卫(身体素质好的边后卫打前锋也不错的)
  • 多说一句,在有核心球员的前提下,其他球员只要有体力在场上跑就够了,所以转会的时候一定要买STAMINA值高于80的球员

教练转会

  • 在你的带队成绩出来后,邀请你转会的球队会越来越好,球队的好坏主要看他的收益,以及是否可以参加欧洲联赛(上面说过的:钱多)
  • 转会后的球队收益比较好会让你有更多的资金购买球员
  • 我一般在赛季结束后会看看有没有合适的转会邀请,看情况选择换家俱乐部
  • 赛季中间走的话我这个联赛的GameCenter成就就没法达成多可惜
  • 如果准备教练转会,就没必要花金币投资俱乐部了,什么请教练,升级球场统统不要
  • 每个月的目标只挑好完成的实现,不用在意有没有完成
  • 带着自己的弟子转会

由于我都是保存一只球队16个球员的最高性价比配置,所以如果我的教练想要转会,而我又想把我心爱的弟子给一起带走,那么这件事情你必须要做:

教练转会之前,买几个球员充数,不要让这个球队只有16个球员,否则你回头想买你的弟子,多少钱老东家都不卖(卖不了啊)

Star Player Mode

  • 比较坑爹,特别是视角只能是球员视角,球队里有大牌球星的情况下可以玩玩
  • 有单独的Start Player Mode
  • 在其他模式下,开始比赛前也可以选择使用“Star Player Mode”进行游戏(双方阵容界面,中下部分的VIP功能按钮)

小结

不经意间竟然写了这么长,不过确实是款好游戏,游戏好玩,还没有各种坑爹的收费道具,而我自己玩了这么久竟然没花过钱,做下广告还下人情也是应该的: First Touch Soccer World Edition

需求

跨平台的代码,在各个平台下的代码显示都能正确对齐,中文不乱码

规范内容

文件名

文件名全小写加下划线

文件编码

文件编码使用 UTF-8 With BOM

Eclipse,XCode 5.1+,VS2012都已经支持UTF-8 With BOM这个文件编码格式,中文不乱码

TAB缩进

1.使用等宽字体

2.使用空格替代TAB,一个TAB对应4个空格

.

PS. 主流IDE下都有选项可以将TAB自动转换为空格

使用空格替代TAB,在三大主流IDE下如何配置

Visual Studio 2012

Visual Studio

ADT(Eclipse)

Eclipse

Xcode 5.1.1

Xcode

需求

原始需求

Android应用测试的时候经常需要修改/system/etc/hosts,有这么几种常见方法:

  • 1、 adb pull 拉取到PC上进行修改,修改后再 adb push 回手机(麻烦)
  • 2、 直接用手机上的Root Explorer等工具进行编辑(默认的文本编辑很难操作)
  • 3、 PC上直接使用adb shell vi命令(android系统默认是没有vi命令的)

落地需求

adb shell vi这个方案无疑是操作起来最高效的,那怎样才能可以在adb shell下使用vi命令呢?

操作步骤

0. 前提:你的手机已经ROOT过了

1. 手机上下载并安装BusyBox

  • 我用的是这个:BusyBox工具箱 汉化版
  • 我安装的版本是1.22.1
  • 安装的时候直接安装到/system/bin,这样敲命令行的时候就不需要这么敲了:

    busybox vi

2. adb shell vi

2.1 非Windows机器直接在终端上adb shell就可以了,无缝使用

2.2 Windows下的 adb shell vi

  • Windows下直接使用CDM连接后使用vi会出现乱码,解决的方案是使用:adbputty
  • 从这里下载:adb putty
  • putty配置:主机填写transport-usb ,连接类型选择Adb(对应5037端口)

配置可以参考这个:adb putty

3. vi 保存文件时提示:Read-only file system.

都是mount R/W的问题,同一个问题两个解决方案:

3.1 mount R/W

1
2
3
4
5
Simply change ro to rw and add the remount option
# mount -o rw,remount /system

Once you are done making changes, you should remount with the original readonly.
# mount -o ro,remount /system

3.2 还有个比较鸡肋,但是偷懒的解决方案

不记得命令行的时候可以使用下 :)

  1. 使用Root Exporler等工具,点击Mount R/W按钮
  2. 回到adb shell下操作,你会发现已经可以保存了

问题


  • 使用cocos2dx的iOS工程,通过cocospods引入了FMDB用于使用SQLite:

    pod ‘FMDB’, ‘~> 2.3’

  • Xcode 5.1.1

  • 结果选择64的模拟器编译时提示

1
2
3
4
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_FMDatabase", referenced from:
objc-class-ref in DBWrapper.o
ld: symbol(s) not found for architecture i386

问题分析


尝试

  • 一开始搜索到的结果,出现这种情况都是因为没有把FMDB下的.m文件加入到工程里面;
  • 但是我们其实是通过CocoaPods进行第三方库依赖的,这种情况还要自己把.m加到工程就太可笑了
  • 还有一个疑问是为什么非64的模拟器就可以编译通过?
  • 为了验证上面这个问题,我在github上找了个同样使用pod ‘FMDB’的例子,发现例子可以再64位下正常编译,也就是说和FMDB库是无关的,是我们自己使用的不对
  • 盯着64位这个字眼,突然想起了我们的工程因为为了支持cocos2dx,是修改了编译选项中的
1
2
config.build_settings['ARCHS'] = 'armv7 armv7s'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
  • 在Xcode下点击Pods工程,把新加入的FMDB-Pods target选项修改了下,果然就编译通过了

问题原因

  • 使用到的两个第三方库的ONLY_ACTIVE_ARCH选项不同导致了这个问题
  • cocos2dx为了兼容64位需要把这个选项设置位NO,而默认这个选项为YES

解决方案


解决的思路

  • cocos2dx(2.2.4)因为本身不支持64位,所以ONLY_ACTIVE_ARCH需要设置为NO,那么有没有方法把github上第三方的Spec也使用我们的这个属性配置?

  • 问题清楚后,搜索新的关键字马上就得到了答案:

用CocosPods 的Podfile配置可以满足我的需求:post install

  • 然后我又去github上用post install位关键字找到好多类似的例子

Podfile 参考1

Podfile 参考2

Podfile 参考3

最终的方案

有了上面的信息,我的解决方案也就水到渠成了:

1
2
3
4
5
6
7
8
9
10
pod 'FMDB', '~> 2.3'

post_install do |installer_representation|
installer_representation.project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ARCHS'] = 'armv7 armv7s'
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
end
end
end

1. 需求描述

Android手机拍摄的视频在PC上查看,视觉效果是被旋转了90度的;

于是我们想要使用ffmpeg对视频进行90度旋转,并要求保持视频的编码格式:AVC/AAC;

解决了这个问题后,还想用ffmpeg来进行更多的视频处理。

1.1 细化下来的需求点

  • 视频旋转后大小不变
  • 视频的编码格式和音频的编码格式不变
  • 视频旋转后还可以继续在Chrome等HTML5浏览器中直接播放

1.2 视频的编码格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
视频流信息
+编码格式: AVC
+视频码率: 1065 kbps
+视频帧率:24 fps
+分 辨 率: 640 x 480
+显示比率: 1.333

音频流信息
+编码格式: A_AAC/MPEG4/LC
+音频码率: 57 kbps
+声 道 数: 2 channels
+采 样 数: 44100 Hz
+音频位数: 0 bits

这里要提下为什么使用这个格式,因为HTML 5支持的视频格式就是这几个,而其中最通用的就是上面这个:H.264/AAC

2. 最后有用的命令行是这个:

1
2
3
4
5
6
7
8
9
10
11
# 视频转码成H.264,并旋转90度,音频格式保存不变
ffmpeg -i test.mp4 -vcodec h264 -c:a copy -vf "transpose=1" -strict -2 -y out.mp4

# 去掉rotate属性
ffmpeg -i test.mp4 -metadata:s:v rotate="0" -strict -2 -y r.mp4

# 裁剪视频

# 视频裁剪的宽高分别是(480,480),裁剪视频的起始点是(0,0)
ffmpeg -i test.mp4 -vcodec h264 -c:a copy -filter:v "crop=480:480:0:0" -strict -2 -y ret.mp4

3. GPL的担忧和解决方案

使用命令行已经解决了我们的问题了,但是如果我们先使用ffmpeg作为库整合到我们的产品中会不会有开源协议上的风险呢?

我们使用的视频编码格式-vcodec 是h264,突然想到一个念头,如果我们的产品中使用了ffmpeg进行视频旋转,那么会不会导致我们的产品需要遵循GPL全部开源呢?因为好像H.264的开源协议是GPL的!

其实上面这句话是有问题的,因为没有区分清楚H.264和x264的关系:

H.264是一种编码规范,而x264是H.264的一种实现,x264使用GPL进行开源。

3.1 真正的担忧是:

如果我们使用了ffmpeg来处理我们的视频,我们是否会因为使用了x264而导致产品必须遵循GPL进行开源

3.2 ffmpeg如果不使用x264能支持H.264编解码吗?不行

ffmpeg的解码是LGPL的,编码是GPL的(x264)

The ffmpeg H.264 decoder is LGPL. Only the encoders are GPL, and x264 does not provide a decoder.
It also has the advantage over Framewave and IPP of actually being usable.

这一部分参考了下面的文章:

H264 Encoders other than ffmpeg x264

Does using H.264 with ffmpeg make my software GPL and if so are there workarounds?

Libav, licensing, h.264

Free/Open h.264 video decoding libraries? (Non-GPL)

3.3 如果视频格式使用H.264,又想对视频进行处理,应该怎么办?

3.3.1 服务端使用

服务端使用ffmpeg进行视频处理,由于没有分发,不受GPL的限制,可以自由使用。

3.3.2 终端使用

要对视频进行处理,就必然需要编码解码,而解码的话ffmpeg只能使用x264;

使用了x264的ffmpeg必须遵循GPL进行软件分发,这对商业软件来说是个很大的门槛;

3.3.3 综合下来的解决方案

方案一

客户端直接录制H.264视频,但不进行视频处理,视频处理交给服务端来做。

方案二

客户端入职视频采用非H.264格式,录制后本地就可以使用ffmpeg进行些简单的处理,上传到服务器后再进行H.264的转码,转码后再提供给HTML5播放。

方案三

客户端录制H.264视频,本地使用x264的商业授权进行分发。

方案四

客户端录制H.264视频,本地使用x264以外的其他视频库来编码视频。