(30 hackdays day 27) CloudRail – 云存储的POSIX

这是一个Mashup的时代,所有你知道的API都将成为你设计开发新产品的武器。但跟App一样,太多的选择反而给开发者带来了困扰:到底哪家的服务更好,SDK用起来更舒服,以后维护的成本更低?存储是所有应用都会用到的,Cloudrail的出现正是帮助开发者摆脱SDK选择困难的工具。

图片描述

Mashape类似,Cloudrail认为存储API应该拥有共通的结构和描述方式。但是,跟Cloud Element的Document hub类应用不一样,为了让用户安心,Cloudrail并不用将数据都都经过它的服务器,而是让用户直接和存储服务提供者通信。通过下面的图能很清楚看出Cloudrail是怎么做到的。

图片描述

这就是Cloudrail最核心的技术:Self Adapting API。它的作用是保证客户端随时获得最新的API提供者的API定义,换句话说,就是保证开发者不用换SDK就可以持续访问最新的API(所以叫’No API Updates’)。Javascript的实现方法大家都能想到,就是每次都下载新的connector库。Android呢想一想估计是用ClassLoader或者DexClassLoader之类的吧,iOS就不知道了…不过也许通过WebView的js层做一个中转也是一个低效率的方案。看了下Download页面,发现果然Android版本还没有上线,剩下的是Others。只有JS版本的可以用。不过目前只是Beta嘛,可以理解~

API

CloudRail为数据存储服务定义了一系列标准接口,通过一个CloudRailInterface把各家的存储服务封装起来。比如Sample代码中,CloudRail把Dropbox和GoogleDrive的API封装为一个CloudRailInterface,通过一个CloudRailClient来统一访问。其中用户在不同平台的的标识client_id可以按照帮助文档获得到。

var CRC = CloudRailClient,
    CRI = CRC.CloudRailInterface,
    DBServiceTag = 'Dropbox',
    GDServiceTag = 'GoogleDrive',
    userIdentities = [],
    userIdentitieServiceTags = [],
    serviceDB, serviceClientDB,
    serviceGD, serviceClientGD;

/* Initialize services */

serviceDB = CRI.initService(DBServiceTag);
serviceClientDB = new CRC.ClientIdentity(DBServiceTag,
        {'client_id': 'abcd'}); // insert here your own client id

serviceGD = CRI.initService(GDServiceTag);
serviceClientGD = new CRC.ClientIdentity(GDServiceTag,
        {'client_id': '1234'}); // insert here your own client id

/* Read User Identities */

var dbUser = new CRC.NodeIdentifier(CRI.ObjectType.USER_IDENTITY, DBServiceTag),
    gdUser = new CRC.NodeIdentifier(CRI.ObjectType.USER_IDENTITY, GDServiceTag);

CRI.read(dbUser, serviceClientDB, (function(servicetag) {
    return function(res) {
        saveUserIdentity(res, servicetag);
    };
})(DBServiceTag));
CRI.read(gdUser, serviceClientGD, (function(servicetag) {
    return function(res) {
        saveUserIdentity(res, servicetag);
    };
})(GDServiceTag));

目前CloudRail提供了基本的CRUD API,看起来还是挺通用的。突然觉得,CloudRail是不是想实现一个云存储版的POSIX接口呢。

文档最后提到了一个额外代码CloudRailClient.Crypto.Hash.SHA256。看来是为了对文件作Hash用的。

Price

官网的说法是’Integrations to Cloud Storage Providers will be free forever.’,So…他们怎么活下来…

StrongLoop

最后,提一下之前用过的Nodejs框架。其中有一个很好用的功能,Auto generate SDK。在后端创建一个数据Model以后,Grunt一下就会自动把这个Model的访问代码。比如Angular的版本生成一个访问该Model的Service。

图片描述

提到这个原因是,Nodejs+browser这样的脚本语言组合太适合WebApp的开发了,这样组合所带来的灵活性也带来了很多新的可能。像CloudRail,StrongLoop这样动态接口比原来那些“死板”的接口通信拥有更强大的整合能力。也许以后就会出现一批服务,专门负责接口的维护,而文中这类技术就是这种服务的基础。不过CloudRail还会遇到很多问题,诸如版本管理,平台支持能力等。

另外,CloudRail也是个国际团队,总部在德国的曼海姆,在旧金山也有办公室,公司内居然有幼儿园…

(30 hackdays day 26) Mailgun – 发Mail是个技术活儿

发“垃圾”Email对于很多Web产品来说都是一种稳定的营销手段。让我们看一个众多Startup都在用的Mail服务,Mailgun。这是一个众多牛逼Startup都在使用的服务,里面不乏37signal,Github,Parse,Stripe这样的大佬。

图片描述

为啥要用第三方Mail服务?各种原因,一个是自己host mail server不安全,二是在程序端调用Mail发送邮件还是比较麻烦,万一换个邮箱所有代码都要变,三是自己的smtp server发的mail很可能被扔到垃圾邮箱里,还有就是Mailgun还可以帮助你追踪邮件的发送状态,比如多少被列入spam了(咋做到的呢?),以及各种行为,比如打开邮件,点击链接,以及有多少订阅用户再也无法投递到了。(还有6789)

图片描述

针对为啥用HTTP而不用SMTP,Mailgun的说法是

The HTTP API has some advantages:

  • It’s faster.
  • Better for large scale sending.(这个很关键)
  • You don’t have to deal with MIME because we will assemble it on our side.
  • Just use a request library available for your language of choice.

使用

按照signup之后的guide很容易的就能发送一个email,就是这么简单。

curl -s --user 'api:key-xxx' \
    https://api.mailgun.net/v2/sandboxa26b3f9c5f31491a906e26bb87864007.mailgun.org/messages \
    -F from='Mailgun Sandbox ' \
    -F to='Xiaoping Feng '\
    -F subject='Hello Xiaoping Feng' \
    -F text='Congratulations Xiaoping Feng, you just sent an email with Mailgun!  You are truly awesome! 

想把发送者的域名改为自己的,需要添加自己的域名,配置DNS的TEXT,CNAME和MX,之后等一等就好啦。

Nodejs

怒,官方居然对Nodejs部分只写了个参见NPM module…发现指向的是一个不知道什么人写的小module…时间会让他们后悔的!

Track

前面说到,Mailgun的Track是很重要的功能。用户打开事件的监测应该是按照图片的view行为触发的The email recipient opened the email and enabled image viewing。click链接事件是根据对mail内link地址的replace来实现的。其他的都好说啦~

可以通过API来下载以上事件的数据(包括query),也是超简单实用的~

curl -s --user 'api:key-xxx' -G \
      https://api.mailgun.net/v2/samples.mailgun.org/events \
      --data-urlencode begin='Fri, 3 May 2013 09:00:00 -0000' \
      --data-urlencode ascending=yes \
      --data-urlencode limit=25 \
      --data-urlencode pretty=yes \
      --data-urlencode recipient=joe@example.com

Sender vs From

Docment里的一个FAQ让我涨了姿势,邮件里的Sender和From还可以是不一样的。

The sender domain is what the receiving email server sees when initiating the session.
The from address is what your recipients will see.
For better deliverability it is recommended to use the same from domain as the sender.

哈,为了早起,今天再偷懒一下~晚安各位,祝打枪愉快~

(30 hackdays day 25) Tuling123 – 光棍节找个机器人聊天吧

Tuling123

今天介绍又一个AI机器人Tuling123,当然是开放API的。而且,Tuling123号称可以创建个性化的机器人哦~(别跟我说这logo像个啥…)

图片描述

注册获取API Key,看平台接入文档。发现一个悲惨的事实:发送请求的API居然是GET的…而且URL还设计成这样 http://www.tuling123.com/openapi/api…让我猜一下,以后你们会把新的API设计成/openapi/api2吧。这惨状仅次于我见到过的一个把发送评论API设计成GET的。

而且,这可怜的GET还要承载userid,location,lon(lon….哎),lat以及询问信息info所有内容…

想要测试这个API很容易,curl一下就好啦。

curl "http://www.tuling123.com/openapi/api?key=xxxxxx&info=我喜欢你"
{"code":100000,"text":"宝贝,我也很爱你,来,亲一下"}

这个回答看起来不错。但当我问“哪里当片儿”时,丫居然说

{"code":100000,"text":"最好别有这样的想法。为了你好才说的。 希望对你能有好处。 yin是生活事业学业福气寿命婚姻命运的克星。一个人消耗完了自己相应的福报,等待他的是苦果自受。 看、想、听、说、做yin秽的事,都会大大折损人的福报。"}

只能说…真没幽默感…

另外,这API居然把unauthorized的statusCode写在200的reponse里,而且还跟正常业务的statusCode写在一个地方,受不鸟…还40001,40002…C时代穿越过来的么…请好好看看How To Design A Good API And Why It Matters Google

再吐槽一下:Luling123把referrer link居然翻译成“升级连接”,还真是…目的导向…是不是应该考虑把消息发送按钮改名叫“约”呢…哎,再吐呆毛就爆了…

好啦,官方只提供了两端调用代码,PHP和Java的=.=。让我们来改造成nodejs的吧~

unirest

受够了mikeal/request的non-promise,随便一搜就找到了新欢:unirest。选择的一个重要原因是,Mashape做的~

var API_ASK = 'http://www.tuling123.com/openapi/api',
function ask(info, cb, err) {
    var query = {
        'key': 'xxx',
        'info': info
    }
    unirest.get(API_ASK)
        .query(query)
        .headers({'Accept': 'application/json'})
        .end(function (response) {
            if (response.ok) {
                if (cb) cb(response.body);
            } else {
                if (err) cerr(response.error);
            }
        });
}

虽然不提供美妙的promise返回,但其他的一些超便利的功能,以及好看的字体,足以让人从mikeal的傲慢中舒缓不少~

grunt-init

好,让我们把它封装成一个npm吧。我猜你肯定不想从npm init开始。所以我们找找那些肯定存在的Project Scaffolding吧,很显然Grunt就有Project Scaffolding。我们选nodejs的grunt-init-node来用。

安装好以后grunt一下确定没问题。把之前的代码改吧改吧扔进去。

var unirest = require('unirest'),
    Q = require('q');

var API_ASK = 'http://www.tuling123.com/openapi/api',
    API_KEY,
    RESPONSE_TYPE = {
        100000: 'text',
        200000: 'url',
        301000: 'novel',
        302000: 'news',
        304000: 'app',
        305000: 'train',
        306000: 'plane',
        307000: 'groupon',
        308000: 'coupon',
        309000: 'hotel',
        310000: 'lottery',
        311000: 'price',
        312000: 'restaurant'
    }

exports.init = function (key) {
    API_KEY = key;
};

exports.ask = function (info) {
    if (!API_KEY) {
        throw new Error('Please init with api key first');
    }
    var deferred = Q.defer();
    var query = {
        'key': API_KEY,
        'info': info
    }
    unirest.get(API_ASK)
        .query(query)
        .headers({'Accept': 'application/json'})
        .end(function (response) {
            if (response.ok) {
                var result = JSON.parse(response.body);
                result.type = RESPONSE_TYPE[result.code];
                if (result.type) {
                    deferred.resolve(response.body);
                } else {
                    deferred.reject('unknown code,' + response.body.code);
                }
            } else {
                deferred.reject(response.error);
            }
        });

    return deferred.promise;
};

哦sorry忘了提了,我用了可爱的Q来Promisify一下这个接口。想看这完整代码的请看tuling123 nodejs-sdk。如果有人有兴趣一起维护欢迎加入哈。哎,看惯了国外API产品的文档看国内的真是不习惯。

最后抱怨一下,Tuling123的登陆timeout设置的太短了…而且,似乎跟cookie里写的不一样…

然后呢…欢迎注册Tuling123 via Link~

(30 hackdays day 24) Atatus – what happened before crash

Atatus是一个用来记录“犯罪现场”的工具。正如其他类似的统计异常的SDK一样,Atatus除了收集你的web app里发生的异常,在后台看到各种Bug的统计,最重要的功能的可以记录发生异常的时候用户的行为。

图片描述

如何重现

工程师在解决bug的时候遇到的最讨厌的事情莫过于不知道如何重现问题。现代Web App的复杂度越来越高,一个错误可能是长时间的javascript执行的积累造成的,很可能用户遇到一个问题,但只能报告一个有#的url。而之前的操作才是引发这个bug的原因。
Atatus就是来解决这个问题的。用户只要配置好SDK,一旦遇到Exception,Atatus就会把它,以及之前所做的行为报告给服务器。

比如我做了个登陆页面,我在一个input里输入了用户名,在另一个密码登陆框里输入了密码,然后点击了登陆按钮,bang,出bug了。整个栈被如实打出。同时,一旦你觉得某个bug被解决了,可以点resolve隐藏掉这个bug。对于小型项目来说还是很方便的。

图片描述

Angular

Angular是个FrontEnd又爱又恨的的框架,其中一恨就是有些错误超难track。Atatus专门为Angular写了一小段错误处理代码(当然这个不是Atatus专用的)。

.factory('$exceptionHandler', ["$window", function ($window) {
  return function (exception, cause) {
    if (exception.stack) {
      exception.stack = exception.stack.replace('new ', '');
    }
    if ($window.atatus) {
      $window.atatus.send(exception);
    }
  };
}]);

增加这么一个处理exception的factory,你的Angular程序就能在发生错误的时候统计下整个的用户行为和错误了。

离线存储

一个H5应用经常会面临用户不在线的情况,只要打开offline模式,等到用户连上网以后就会自动发送。它用的是localstorage,所以不用怕关掉tab。

atatus.enableOffline(true)

Pricing

唯一有点遗憾的就是它不提供永久免费的方案。当然你可以试用30天之后再注册一个账号…
不过,12刀15万个exception听起来还是不错的(除非你的App写了个抛异常的死循环)~

(30 hackdays day 23) Favico.js – 网页杀死处女

是不是觉得网页的favicon(就是一个tab上的小图片)太乏味?用微信头像谋杀处女座还不够爽?怕用户看不到“您有新的消息”?好吧,用Favico.js来屠戮用户吧!

图片描述

看到了吧…凄苦吧…想象一下以后你的浏览器变成这样,还在跳来跳去…是不是想死…

图片描述

这个库使用起来超简单:创建一个Favico,.badge设置数字,done

var badge = 5;
var favicon = new Favico({
    animation : 'slide'
});
favicon.badge(badge);

原理也很简单,js里创建一个canvas的dom,把图片变成DataURL,然后直接改head里icon的href。所以,它还有高级用法:把html5视频放到favicon里,甚至把摄像头内容变成favicon…

var favicon=new Favico();
favicon.webcam();
//stop
favicon.webcam('stop');

好吧我承认我幻想过在tab里看porn,who care有码无码…

哎,写到现在都不知道写啥了…没心情写码态。先这样吧,以后再增加一些源码分析。

(30 hackdays day 22) Import.io – 最简单好用的网页爬虫服务

import.io,一个2012年成立的公司。至今已经有3m刀的…种子轮…为毛…

注意,这是一篇由脑残和图片组成的文章。

图片描述

anyway,import.io是我用过最简单的爬虫,没有之一。简单到…只要输入一个网址(当然其实它可以更简单到不用输入http://),就可以获得一个该页面对应的API。更牛逼的是,这是一个我想寻找付费服务却寻觅不得的产品!

两步得到网站API

  1. 打开https://magic.import.io/ 输入要爬取的网址,比如http://producthunt.com
  2. 调整你需要的数据列,比如把url_link那列改为title
  3. 点击下面的GET API…

然后import.io就会给出一个GET API,一个POST API,甚至还有直接从Google sheets取数据的地址!

图片描述

这个API足够足够简单吧!也不用[o]auth就直接拿数据!唯一可惜的一点是,似乎它有一些延迟,没法很实时获得数据(也正是这时候我开始满页面找pricing…)。

除了GET以外,你还可以往里拽(POST)其他URL,很适合那种同构的多页爬取。

当然,虽然你觉得Http GET已经足够简单了,但import.io不这么认为,它觉得你还是需要SDK的…好吧,其实我是为了展示他的API doc页面…里红色的那部分!想起了一个以前看到过别人分享的注释

//Attempt Handshake: Hello? This is London calling. Are we reaching you?
//Handshake Failed: I don't understand...he just hung up.

图片描述

import.io不光是一个爬网页的平台,它还提供存储,搜索(是的…)等服务。赞一下里面的文档样式。

图片描述

App

一个爬虫用的桌面App?想到了啥?像浏览器一样,圈圈点点?
这里下载import.io的桌面应用,安装完了去桌面打开(谁知道为啥它不扔launcher里…),splash都cute到死…

图片描述

打开以后呢,发现呢,就是个firefox内核的浏览器…区别就在与在这个app里可以使用chrome里无法使用的API from URL 2.0,API from Authenticated URL这些功能。估计就是为了把各种登陆cookie都很容易拿到,所以就做了个浏览器的壳吧。

用起来才发现这简直是…简直了…找到要爬的页面,鼠标选择要爬取的内容,搞定以后publish就可以产生一个某类页面的API了,以后只需要把新的文章URL扔给他就ok了。

图片描述

可以看出import.io其实没有diffbot那么智能,但对于那些懒得写xpath的程序员,import.io真的很方便!说到xpath,似乎我真的好久没写过了…可以看出import.io也是用xpath来实现的。

图片描述

好啦,这篇真的是一行代码都没有(这完全是为了配合import.io的好用好吧)…好吧,我有姿势我自豪~

(30 hackdays day 21) Wakatime – 现在几点了,你在做什么呢

前面提到了一个用来QS自己的工具Clarify。这次介绍一个专门给程序员用的工具。
大家都知道一万小时定律,但我究竟写java写了多久了呢?WakaTime知道。估计很多人都知道RescueTime,我也是用RescueTime来记录我的工作时间。但它无法记录更具体的行为(也许实际也做了),比如我写了多久javascript,多久objective-C。Waka就可以啦,因为它提供了几个主要的IDE的插件,只需要安装对应的插件,Waka就能自动记录你在IDE里的行为。

WakaTime

Waka的基本设计和rescuetime类似。每个人注册完将获取一个key,装一个客户端,把key输进去(登陆是同一个道理),然后它就把本地的所有行为带个key扔给服务器来统计,一段时间之后给你个报表。不过Waka做的真的很精准,精确到每一个文件用了多少秒,每一种语言用了多少时间。

图片描述
图片描述

据说Waka还能知道你在每个branch用了多久,这还真是一个量化程序员的好办法。如果有项目管理会用这种工具,相信也能更精准的把握开发进度,控制每一次开发尝试的代价。

作为一个付费用户狂人,登陆以后做的第一件事当然是搜Pricing~对比一下,付费用户的功能就是无限期数据查看和原始数据导出。想了想…算了这次…还有团队版本哦~

工作原理

Waka让我觉得好玩的是他的plugin都是开源的,而且在他的开源项目列表里看到了一个叫wakatime的核心项目,python写的,说是大家基本不需要直接使用的。基本可以确定是每个plugin都会去调用的核心库。

从queue.py里看出所有的log都会被放到~/.wakatime.db下,那我们就去看看它存了啥。打开以后发现是空的…想必是Waka把log都传走了以后就删掉了本地的。于是,断网,假装写代码,再看看。

图片描述

可以看到它记录了我在哪个文件,什么时间,什么项目下,写了什么语言,甚至在哪一行下都记录下来了。如果这个数据结合版本管理,动态的展现出来,将会是多酷啊~

Anyway,由于我很想用koding这样的WebIDE来工作,这样就又没发用Waka了,所以我需要知道发送记录的具体API是什么。

这也叫API文档

Wakatime是觉得代码是最好的文档么,居然在API文档里没有写出这些log是如何被打进数据库的…文档里只有认证,获得统计信息,和当前用户信息的接口…

好吧,那我们直接去刚才那个python的repo里看吧。首先,这里面肯定有个代码文件是包括http和wakatime.com的。那就搜吧,找到了init.py里一个函数叫send_action。很明显这是用来发log的。

那先让我们用curl模拟一下这个请求吧(看起来也不用太多域)。

$ curl -d '{"time":"1414688349","file":"/root","lines":"123","language":"javascript","is_write":"0","project":"manhattan"}' -H "User-Agent: space" -H "Content-Type: application/json" -H "Authorization: Basic ODMwOTliYjMtZGUwZS00NWFkLThhODItZmY4OWUwYzxxxxxxx" https://wakatime.com/api/v1/actions
{
  "data": {
    "id": "83682870-8306-4d12-b4a9-e0ba5f6cc295"
  }
}

把Key base64一下,用date +%s拿一下当前的timestamp,就可以往Waka里扔数据啦。扔完了以后看看Dashboard~好啦,我们的曼哈顿项目出现啦~

图片描述

如果你愿意可以把它改成各种SDK(当然browser里会出现跨域的问题,所以你可以找个中间服务器做这事儿)。

在未来做点儿事儿

刚才看到了有个timestamp来表示时间,如果改成以后呢。估计waka不会蛋疼到做这个检查吧…往2015年1月1日扔几个action,等一小会儿,看manhattan项目的URL,改成https://wakatime.com/project/manhattan?start=2014-12-26&end=2015-1-3。就能看到我在未来写javascript了~

扩展的waka

所以其实wakatime是一个特别基础的action记录和统计平台。如果它愿意开源(其实这真的还不如一个logger分析平台…),完全可以搭建成一个QS小服务。比如晚上9点连续发出20分钟加速度变化数据,然后就停止了10分钟…

(30 hackdays day 20) Clarify – 处于pending状态的QS服务

如果你还不知道量化自身,那么建议你看看Quantified Self。量化自身对于我来说,就是希望在我比较短的生命预期内,能尽量留下我的数据,从而在身体死掉前,用算法创建出一个IO近似于我的“个体”。

“我TM说啥了?”

这是两三年前就在做的一件事情,时断时续的我用一些12小时的录音笔记录了一天我周围的声音(当然也包括我自己的)。最简单的目的就是希望能知道我之前说了啥(我记性比较差…)。但当时找了一些voice recognition的SDK来分析记录下来的语音信息。结果都特别不如意,基本没有能用的。
直到最近买了一个Narrative Clip,我又开始重燃QS的热情了。Rekognition – 借我借我一双慧眼吧文章中,我第一次把narrative里的部分数据拿来分析,得到的结果意外的好。这坚定了我之前的想法:

如果有一个一开始设计好的idea的api flow的blueprint,让机器能帮你在发展的过程中不断紧盯这些API能不能满足需求,直到某一天,这个pipeline通了。丫就告诉你,爷,你丫的idea跑通了。

Clarify

好啦,BB这么多的目的是介绍一个不那么牛逼的服务,Clarify。Clarify号称自己做三件事儿:Capture,Analyze,Discover。简单的说就是把语音视频数据扔给它,它帮你做信号处理(估计就是降噪),语音识别和自然语言处理。当然这也是收费的,音频每小时3刀,每5000个搜索一刀。

听着很简单,但当我看到这个服务的时候,我知道这就是我想要的~不用装SDK,不用运行在我的server上。我只需要把媒体数据扔到一个像七牛的地方,拿到URL,扔给Clarify。稍等就可以问它“我前天这时候说下周去哪聚会来着?”。好吧,至少能做到,搜索,上周这时候,有“聚会”的这段音频。

API

丫居然用PHP来做tutorial…好吧,不发表言论…创建一个App,拿到AppKey。找到nodejs SDK,翻翻tutorial,猜一猜就写个测试程序出来。

var clarifyio = require('clarifyio');
var client = new clarifyio.Client("api.clarify.io", "[key]")

var bundleId;
var data = {
    name: "qwerty bundle " + Math.random(),
    media_url: "https://s3-us-west-2.amazonaws.com/op3nvoice/harvard-sentences-1.wav"
};
client.createBundle(data, function (err, res) {
    if (err) return done(err);
    bundleId = res.id;
    client.search({query: "fire", query_fields: "*"}, function (err, res) {
        if (err) return done(err);
        console.log('search');
        console.dir(res);
        client.removeBundle(bundleId, function (err) {
            if (err) return done(err);
            client.removeBundle(bundleId);
        });
    });
});

就是这句 client.search({query: “fire”, query_fields: “*”},…)。执行结果也很简单。

{ total: 1,
  limit: 10,
  search_terms: [ { term: 'fire' } ],
  item_results: [ { score: 1, term_results: [Object] } ],
  _class: 'SearchCollection',
  _links:
   { self: { href: '/v1/search?query=fire&query_fields=*' },
     items: [ [Object] ],
     first: { href: '/v1/search?query=fire&query_fields=*&iterator=S10a47fbc8ef' } } }

它就是告诉你某个bundle里(bundle就是一个media的集合)有没有这个字出现。所以具体在哪里出现,似乎也还是得很多人工介入的。

无论如何,Clarify让我能用十几行代码就能分析一个我之前的录音(这个就不放出来了~)。虽然结果不理想,但我相信不久的将来我一定能等到那个”test全部通过”的API的~

另外,介绍一个全球第一个虚拟Hackathon。是之前提到的Koding举办的。https://koding.com/Hackathon
在一个WebIDE里,和一群全世界的hacker们玩一次hackathon,一定很酷!

哎,最近精力有限,水点儿请见谅…

(30 hackdays day 19) CARA – EQ不足CARA补

受朋友之邀调研有没有那种提供视频中的人脸识别并自动添加上某些面具类的服务或者API,如果能根据表情调整面具内容就更好。

首先,人脸识别的API有超多,国内很有名的Face++之类的都可以提供很好的结果。但这里有三个不同:视频,表情,面具。

视频

理论上,视频也就是一堆静态图片而已,但按照目前HTTP API的效率来说,一秒钟24次API真的还是挺难的。但如果效果好,也可以跟对方合作,用长连接类的API来调用他们API,也许能撑得住。

表情

于是我就去搜emotion detection API,发现了这么个服务Imrsv,先体验一下他们的栗子服务(挺好玩的!)。我的检测结果。

图片描述

他会让你看一段视频,然后观察你的表情,分析出笑,惊讶,不喜欢和注意情况。你肯定想到他们做这玩意儿是干啥的了…

Cara-cloud

这就是提供刚才那种分析服务的云服务,CARACloud。demo页面有两个功能:根据图片分析和服务器端分析。
我们先看看图片分析的。先扔进去一张乔布斯的~

图片描述

[
    {
        "date_created": 1414518641,
        "age": 2,
        "gender": 1,
        "width": 307,
        "height": 307,
        "x": 51,
        "y": 236
    },
    {
        "date_created": 1414518641,
        "age": 3,
        "gender": 1,
        "width": 283,
        "height": 283,
        "x": 464,
        "y": 211
    }
]

其中的age只是一个类型,2是young adult(30岁以下),3是adult(30-50我记得是)。让我们再扔一个进去~

1373255755982.jpg

结果是…我很认真的挑了好几张霍金的玉照…结果都是…

{
    "error": "CloudNoFaceDetectedException",
    "error_description": "No face detected."
}

翻来翻去发现他们从13年就开始叫嚣会出API doc,结果现在还是没消息。一个隐蔽的小论坛里,发消息的频度也是以月计算的。
好吧,那只能用他Demo页的接口来用啦。

DevTools查一下,写如下的curl:

curl --data "type=image_url&cara_cloud_demo_image_url%5Bimage_url%5D=http%3A%2F%2Fcdn.macrumors.com%2Farticle-new%2F2013%2F06%2Fsteve_jobs_bio_covers-800x604.jpg&cara_cloud_demo_image_url%5B_token%5D=165932fef9c0c28ea1a048b860b5b5384fb3a722&submit-url=Submit"  https://imrsv.com/cara-cloud-demo

修改其中图片URL的部分拿到结果页面的HTML,查看里面确实有结果。注意%5B和%5D是中括号[和]。不过每次都要改一下_token的值。

下面那个Server Side Video Processing只能看视频了,结果看起来很棒。如果能深度合作肯定能做出来那种根据表情实时变化的效果。

看了一圈,发现没有地方注册网页…login里的Create an account居然是连接到contact…好吧,你们丫以前肯定是能注册的,程序员肯定不愿意把那功能删掉!

所以呢,我们就搜一搜cara 或者imrsv register呗。然后就发现了这个注册页面。然后,注册,确认,登陆,就能看到它的后台啦。

Document里选择成为Developer,填满以后自动就会把AppID和AppSecret给你。再点Document就能看到各种API的文档啦。懒得注册还需要全部文档截图的可以找我要哈。(那该是什么样的人呢…)

图片描述

其中有一段Upload media的描述让我很困惑。这,到底是License先有还是先Upload呢…

Upload either image/video for processing. This API requires a license. License would not be available until processing is done.

不过通过测试发现确实是会给你的License,在等一阵子以后收到的mail里。从media_id里看出,这公司至今也就处理了14万张图片…好惨…

图片描述

到点儿啦,Downloads里还有好几个好玩的东西,PHP脚本啥的,有兴趣的去看看哈。

试用了下CARACV的Mac版,真的很好玩,指定一个证书以后,录一段视频就能得到一个分析报告。有什么注意了多久呀,看了几瞥呀啥的。有钱的商铺绝对可以用来做广告效果统计哈。

图片描述
图片描述
图片描述

这个故事告诉我们:笑起来更年轻~
各种文件下载可以看这里。文档截图。好啦,所有文件都在这里

在WordPress.com的博客.

向上 ↑