├── .gitignore ├── CHANGELOG.md ├── index.js ├── sample └── sample.js ├── package.json ├── LICENSE ├── tencentyoutuyun ├── conf.js ├── auth.js └── youtu.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.0 / 2015-05-12 2 | 3 | * 第一个版本SDK 4 | * 支持腾讯云智能优图,优图开放平台的人脸识别功能 5 | 6 | 7 | # 1.0.1 / 2015-07-21 8 | * 修复部分代码语法Bug 9 | * 统一函数名为小写字母 10 | 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | var libpath = './tencentyoutuyun'; 3 | 4 | module.exports = { 5 | auth: require(libpath + '/auth.js'), 6 | conf: require(libpath + '/conf.js'), 7 | youtu: require(libpath + '/youtu.js'), 8 | }; 9 | -------------------------------------------------------------------------------- /sample/sample.js: -------------------------------------------------------------------------------- 1 | var tencentyoutuyun = require('..'); 2 | var conf = tencentyoutuyun.conf; 3 | var youtu = tencentyoutuyun.youtu; 4 | 5 | // 设置开发者和应用信息, 请填写你在开放平台 6 | var appid = '****'; 7 | var secretId = '****'; 8 | var secretKey = '****'; 9 | var userid = '****'; 10 | 11 | conf.setAppInfo(appid, secretId, secretKey, userid, 0) 12 | 13 | 14 | //youtu.imageporn('a1.jpg', function(data){ 15 | // console.log("imagetag:" + JSON.stringify(data)); 16 | //}); 17 | 18 | //youtu.idcardocr('a.jpg', 0, function(data){ 19 | // console.log("idcardocr:" + JSON.stringify(data)); 20 | //}); 21 | 22 | //youtu.namecardocr('a.jpg', false, function(data){ 23 | // console.log("namecardocr:" + JSON.stringify(data)); 24 | //}); 25 | 26 | // 其他接口 类似 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tencentyoutuyun", 3 | "version": "1.0.0", 4 | "description": "node sdk for qcloud youtu", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/TencentYouTu/nodejs_sdk.git" 12 | }, 13 | "keywords": [ 14 | "qcloud", 15 | "youtu" 16 | ], 17 | "author": "tencentyoutuyun", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/TencentYouTu/nodejs_sdk/issues" 21 | }, 22 | "homepage": "https://github.com/TencentYouTu/nodejs_sdk#readme", 23 | "engines": [ 24 | "node >= 0.4.7" 25 | ], 26 | "dependencies": { 27 | "iconv-lite": "^0.4.13" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 tencent 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /tencentyoutuyun/conf.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var os = require('os'); 4 | 5 | // 请到 open.youtu.qq.com查看您对应的appid相关信息并填充 6 | // 请统一 通过 setAppInfo 设置 7 | 8 | exports.APPID = ''; 9 | exports.SECRET_ID = ''; 10 | exports.SECRET_KEY = ''; 11 | exports.USERID = ''; 12 | 13 | var pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../', 'package.json'))); 14 | var ua = function() { 15 | return 'QcloudNodejs/' + pkg.version + ' (' + os.type() + '; ' + os.platform() + '; ' + os.arch() + '; ) '; 16 | } 17 | 18 | exports.USER_AGENT = ua; 19 | exports.API_YOUTU_SERVER= 'api.youtu.qq.com'; 20 | exports.API_YOUTU_PORT= 80; 21 | exports.API_DOMAIN = 0; 22 | 23 | // 初始化 应用信息 24 | exports.setAppInfo = function(appid, secretId, secretKey, userid, domain) { 25 | module.exports.APPID = appid; 26 | module.exports.SECRET_ID = secretId; 27 | module.exports.SECRET_KEY = secretKey; 28 | module.exports.USERID = userid; 29 | if(domain == 0) 30 | { 31 | exports.API_YOUTU_SERVER= 'api.youtu.qq.com'; 32 | } 33 | else 34 | { 35 | exports.API_YOUTU_SERVER= 'youtu.api.qcloud.com'; 36 | } 37 | exports.API_DOMAIN = domain; 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /tencentyoutuyun/auth.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto'); 2 | var urlM = require('url'); 3 | var conf = require('./conf'); 4 | 5 | exports.AUTH_PARAMS_ERROR = -1; 6 | exports.AUTH_SECRET_ID_KEY_ERROR = -2; 7 | 8 | exports.appSign = function(expired, userid) { 9 | 10 | var secretId = conf.SECRET_ID || ''; 11 | var secretKey = conf.SECRET_KEY || ''; 12 | var appid = conf.APPID || ''; 13 | 14 | var pexpired = expired || ''; 15 | var puserid = userid || conf.USERID; 16 | 17 | 18 | if (!pexpired || !puserid ) { 19 | return module.exports.AUTH_PARAMS_ERROR; 20 | } 21 | 22 | if ( !secretId || !secretKey ) { 23 | return module.exports.AUTH_SECRET_ID_KEY_ERROR; 24 | } 25 | 26 | var now = parseInt(Date.now() / 1000); 27 | var rdm = parseInt(Math.random() * Math.pow(2, 32)); 28 | 29 | // the order of every key is not matter verify 30 | var plainText = 'a=' + appid + '&k=' + secretId + '&e=' + pexpired + '&t=' + now + '&r=' + rdm + '&u=' + puserid; 31 | 32 | var data = new Buffer(plainText,'utf8'); 33 | 34 | var res = crypto.createHmac('sha1',secretKey).update(data).digest(); 35 | 36 | var bin = Buffer.concat([res,data]); 37 | 38 | var sign = bin.toString('base64'); 39 | 40 | return sign; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tencentyun-youtu-nodejs-sdk 2 | 3 | nodejs sdk for [腾讯优图开放平台](http://open.youtu.qq.com/) 4 | 5 | ## 安装 6 | 7 | ```sh 8 | git clone https://github.com/TencentYouTu/nodejs_sdk.git 9 | ``` 10 | 11 | ## 名词 12 | 13 | - `AppId` 平台添加应用后分配的AppId 14 | - `SecretId` 平台添加应用后分配的SecretId 15 | - `SecretKey` 平台添加应用后分配的SecretKey 16 | - `签名` 接口鉴权凭证,由`AppId`、`SecretId`、`SecretKey`等生成,详见 17 | 18 | ## API 19 | 20 | ### `conf` 21 | 22 | 配置项相关 23 | 24 | #### `conf.setAppInfo(appid, secretId, secretKey, userid, domain)` 25 | 26 | 初始化配置项 27 | 28 | - 参数 29 | - `appid` AppId 字符串类型 30 | - `secretId` SecretId 字符串类型 31 | - `secretKey` SecretKey 字符串类型 32 | - `userid` 业务中的用户标识 字符串类型 33 | - `domain` 主机标识,0(优图服务),1(腾讯云) 34 | - 返回值 无(`undefined`) 35 | 36 | #### 其它 37 | 38 | - `conf.USER_AGENT` 请求的UserAgent 39 | - `conf.API_YOUTU_SERVER` 请求的优图服务器地址 默认为 api.youtu.qq.com 40 | - `conf.API_YOUTU_PORT` 请求的优图服务器端口 默认为 80 41 | 42 | ### `auth` 43 | 44 | 接口调用时 计算签名鉴权相关逻辑。 45 | 46 | #### `auth.appSign(expired, userid)` 47 | 48 | 获取签名,依赖`conf`中的配置项。 49 | 50 | - 参数 51 | - `expired` 过期时间,UNIX时间戳, 计算的签名在过期时间之前有效. 52 | - `userid` 业务中的用户标识 53 | - 返回值 签名(base64) 54 | 55 | #### 其它 56 | 57 | - `auth.AUTH_PARAMS_ERROR` 参数错误常量(-1) 58 | - `auth.AUTH_SECRET_ID_KEY_ERROR` 密钥ID或者密钥KEY错误常量(-2) 59 | 60 | ### `youtu` 61 | 62 | 优图相关API封装,均为异步函数,使用回调函数方式获取结果。 63 | 64 | > 注意:此处callback函数并未遵从Node.js风格的错误回调`callback(error, data)`,因此需要对返回数据中的状态进行判断,只有200时认为是请求成功。 65 | 66 | #### `youtu.detectface(imagePath, isbigface, callback)` 67 | 68 | 人脸检测,检测给定图片(Image)中的所有人脸(Face)的位置和相应的面部属性。位置包括(x, y, w, h),面部属性包括性别(gender)、年龄(age) 69 | 表情(expression)、眼镜(glass)和姿态(pitch,roll,yaw)。 70 | 71 | - 参数 72 | - `imagePath` 图片路径 73 | - `isbigface` 是否大脸模式 0表示检测所有人脸, 1表示只检测照片最大人脸 适合单人照模式 74 | - `callback(data)` 回调函数 75 | 76 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 77 | 78 | - `httpcode` HTTP状态码 79 | - `code` 状态码,目前和`httpcode`相同 80 | - `message` 状态码对应的描述文字 81 | - `data` 数据对象,参考API文档 82 | 83 | 84 | #### `youtu.faceshape(imagePath, isbigface, callback)` 85 | 86 | 人脸定位,检测给定图片中人脸的五官。对请求图片进行人脸配准,计算构成人脸轮廓的88个点, 87 | 包括眉毛(左右各8点)、眼睛(左右各8点)、鼻子(13点)、嘴巴(22点)、脸型轮廓(21点) 88 | 89 | - 参数 90 | - `imagePath` 图片路径 91 | - `isbigface` 是否大脸模式 0表示检测所有人脸, 1表示只检测照片最大人脸 适合单人照模式 92 | - `callback(data)` 回调函数 93 | 94 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 95 | 96 | - `httpcode` HTTP状态码 97 | - `code` 状态码,目前和`httpcode`相同 98 | - `message` 状态码对应的描述文字 99 | - `data` 数据对象,参考API文档 100 | 101 | 102 | #### `youtu.facecompare(image_a, image_b, callback)` 103 | 104 | 人脸对比,计算两个Face的相似性以及五官相似度。 105 | 106 | - 参数 107 | - `image_a` 第一张图片路径 108 | - `image_b` 第二张图片路径 109 | - `callback(data)` 回调函数 110 | 111 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 112 | 113 | - `httpcode` HTTP状态码 114 | - `code` 状态码,目前和`httpcode`相同 115 | - `message` 状态码对应的描述文字 116 | - `data` 数据对象,参考API文档 117 | 118 | #### `youtu.facecompare_file_url(image_file, image_url, callback)` 119 | 120 | 人脸对比,计算两个Face的相似性以及五官相似度。 121 | 122 | - 参数 123 | - `image_file` 第一张图片路径 124 | - `image_url` 第二张图片url 125 | - `callback(data)` 回调函数 126 | 127 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 128 | 129 | - `httpcode` HTTP状态码 130 | - `code` 状态码,目前和`httpcode`相同 131 | - `message` 状态码对应的描述文字 132 | - `data` 数据对象,参考API文档 133 | 134 | #### `youtu.faceverify(image_a, person_id, callback)` 135 | 136 | 人脸验证,给定一个Face和一个Person,返回是否是同一个人的判断以及置信度。 137 | 138 | - 参数 139 | - `image_a` 图片路径 140 | - `person_id` 待验证的Person 141 | - `callback(data)` 回调函数 142 | 143 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 144 | 145 | - `httpcode` HTTP状态码 146 | - `code` 状态码,目前和`httpcode`相同 147 | - `message` 状态码对应的描述文字 148 | - `data` 数据对象,参考API文档 149 | 150 | #### `youtu.faceidentify(image_a, group_id, callback)` 151 | 152 | 人脸识别,对于一个待识别的人脸图片,在一个Group中识别出最相似的Top5 Person作为其身份返回,返回的Top5中按照相似度从大到小排列。 153 | 154 | - 参数 155 | - `image_a` 图片路径 156 | - `group_id` 需要识别的人 所在的组 157 | - `callback(data)` 回调函数 158 | 159 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 160 | 161 | - `httpcode` HTTP状态码 162 | - `code` 状态码,目前和`httpcode`相同 163 | - `message` 状态码对应的描述文字 164 | - `data` 数据对象,参考API文档 165 | 166 | #### `youtu.newperson(image_a, person_id, person_name, group_ids, persontag, callback)` 167 | 168 | 个体创建,创建一个Person,并将Person放置到group_ids指定的组当中。 169 | 170 | - 参数 171 | - `image_a` 图片路径 172 | - `person_id` 个体Person 173 | - `person_name` 个体Person的名字 174 | - `group_ids` 要加入的组的列表(数组) 175 | - `persontag` 备注信息,用户自解释字段 176 | - `callback(data)` 回调函数 177 | 178 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 179 | 180 | - `httpcode` HTTP状态码 181 | - `code` 状态码,目前和`httpcode`相同 182 | - `message` 状态码对应的描述文字 183 | - `data` 数据对象,参考API文档 184 | 185 | #### `youtu.delperson(person_id, callback)` 186 | 187 | 删除一个Person 188 | 189 | - 参数 190 | - `person_id` 个体Person 191 | - `callback(data)` 回调函数 192 | 193 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 194 | 195 | - `httpcode` HTTP状态码 196 | - `code` 状态码,目前和`httpcode`相同 197 | - `message` 状态码对应的描述文字 198 | - `data` 数据对象,参考API文档 199 | 200 | 201 | #### `youtu.addface(person_id, images, facetag, callback)` 202 | 203 | 添加人脸,在创建一个Person后, 增加person下面的人脸, 可以用于后面的比对。 204 | 205 | - 参数 206 | - `person_id` 个体Person 207 | - `images` 图片路径(数组) 208 | - `facetag` 人脸自定义标签 209 | - `callback(data)` 回调函数 210 | 211 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 212 | 213 | - `httpcode` HTTP状态码 214 | - `code` 状态码,目前和`httpcode`相同 215 | - `message` 状态码对应的描述文字 216 | - `data` 数据对象,参考API文档 217 | 218 | 219 | 220 | #### `youtu.delface(person_id, face_ids, callback)` 221 | 222 | 删除人脸,删除一个person下的face,包括特征,属性和face_id。 223 | 224 | - 参数 225 | - `person_id` 个体Person 226 | - `face_ids` 要删除的faceId列表(数组) 227 | - `callback(data)` 回调函数 228 | 229 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 230 | 231 | - `httpcode` HTTP状态码 232 | - `code` 状态码,目前和`httpcode`相同 233 | - `message` 状态码对应的描述文字 234 | - `data` 数据对象,参考API文档 235 | 236 | #### `youtu.setinfo(person_name, person_id, tag, callback)` 237 | 238 | 设置Person的信息 239 | 240 | - 参数 241 | - `person_name` 个体Person的name 242 | - `person_id` 个体Person 243 | - `tag` 个体Person的tag, 用户自解释字段 244 | - `callback(data)` 回调函数 245 | 246 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 247 | 248 | - `httpcode` HTTP状态码 249 | - `code` 状态码,目前和`httpcode`相同 250 | - `message` 状态码对应的描述文字 251 | - `data` 数据对象,参考API文档 252 | 253 | #### `youtu.getinfo(person_id, callback)` 254 | 255 | 获取一个Person的信息,包括name、id、tag、相关的face以及groups等信息。 256 | 257 | - 参数 258 | - `person_id` 个体Person 259 | - `callback(data)` 回调函数 260 | 261 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 262 | 263 | - `httpcode` HTTP状态码 264 | - `code` 状态码,目前和`httpcode`相同 265 | - `message` 状态码对应的描述文字 266 | - `data` 数据对象,参考API文档 267 | 268 | #### `youtu.getgroupids(callback)` 269 | 270 | 获取一个AppId下所有group列表 271 | 272 | - 参数 273 | - `callback(data)` 回调函数 274 | 275 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 276 | 277 | - `httpcode` HTTP状态码 278 | - `code` 状态码,目前和`httpcode`相同 279 | - `message` 状态码对应的描述文字 280 | - `data` 数据对象,参考API文档 281 | 282 | #### `youtu.getpersonIds(group_id, callback)` 283 | 284 | 获取一个组Group中所有person列表 285 | 286 | - 参数 287 | - `group_id` 组 288 | - `callback(data)` 回调函数 289 | 290 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 291 | 292 | - `httpcode` HTTP状态码 293 | - `code` 状态码,目前和`httpcode`相同 294 | - `message` 状态码对应的描述文字 295 | - `data` 数据对象,参考API文档 296 | 297 | 298 | #### `youtu.getfaceIds(person_id, callback)` 299 | 300 | 获取一个组person中所有face列表 301 | 302 | - 参数 303 | - `person_id` Person 304 | - `callback(data)` 回调函数 305 | 306 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 307 | 308 | - `httpcode` HTTP状态码 309 | - `code` 状态码,目前和`httpcode`相同 310 | - `message` 状态码对应的描述文字 311 | - `data` 数据对象,参考API文档 312 | 313 | ### `youtu.getfaceinfo(face_id, callback)` 314 | 315 | 获取一个face的相关特征信息 316 | 317 | - 参数 318 | - `face_id` Face 319 | - `callback(data)` 回调函数 320 | 321 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 322 | 323 | - `httpcode` HTTP状态码 324 | - `code` 状态码,目前和`httpcode`相同 325 | - `message` 状态码对应的描述文字 326 | - `data` 数据对象,参考API文档 327 | 328 | ### `youtu.fuzzydetect(imagePath, callback)` 329 | 330 | 模糊检测 331 | 332 | - 参数 333 | - `imagePath` 图片路径(url或本地路径) 334 | - `callback(data)` 回调函数 335 | 336 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 337 | 338 | - `httpcode` HTTP状态码 339 | - `code` 状态码,目前和`httpcode`相同 340 | - `message` 状态码对应的描述文字 341 | - `data` 数据对象,参考API文档 342 | 343 | ### `youtu.fooddetect(imagePath, callback)` 344 | 345 | 检测食物 346 | 347 | - 参数 348 | - `imagePath` 图片路径(url或本地路径) 349 | - `callback(data)` 回调函数 350 | 351 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 352 | 353 | - `httpcode` HTTP状态码 354 | - `code` 状态码,目前和`httpcode`相同 355 | - `message` 状态码对应的描述文字 356 | - `data` 数据对象,参考API文档 357 | 358 | 359 | ### `youtu.imagetag(imagePath, callback)` 360 | 361 | 图片分类 362 | 363 | - 参数 364 | - `imagePath` 图片路径(url或本地路径) 365 | - `callback(data)` 回调函数 366 | 367 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 368 | 369 | - `httpcode` HTTP状态码 370 | - `code` 状态码,目前和`httpcode`相同 371 | - `message` 状态码对应的描述文字 372 | - `data` 数据对象,参考API文档 373 | 374 | 375 | ### `youtu.imageporn(imagePath, callback)` 376 | 377 | 色情图像检测 378 | 379 | - 参数 380 | - `imagePath` 图片路径(url或本地路径) 381 | - `callback(data)` 回调函数 382 | 383 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 384 | 385 | - `httpcode` HTTP状态码 386 | - `code` 状态码,目前和`httpcode`相同 387 | - `message` 状态码对应的描述文字 388 | - `data` 数据对象,参考API文档 389 | 390 | ### `youtu.idcardocr(imagePath, cardType, callback)` 391 | 392 | 身份证OCR识别 393 | 394 | - 参数 395 | - `imagePath` 图片路径(url或本地路径) 396 | - `cardType` 0 代表输入图像是身份证正面, 1代表输入是身份证反面 397 | - `callback(data)` 回调函数 398 | 399 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 400 | 401 | - `httpcode` HTTP状态码 402 | - `code` 状态码,目前和`httpcode`相同 403 | - `message` 状态码对应的描述文字 404 | - `data` 数据对象,参考API文档 405 | 406 | ### `youtu.namecardocr(imagePath, retImage, callback)` 407 | 408 | 名片ocr识别 409 | 410 | - 参数 411 | - `imagePath` 图片路径(url或本地路径) 412 | - `retImage` false 代表不需要返回识别后图像, true代表需要返回识别后图像 413 | - `callback(data)` 回调函数 414 | 415 | 其中回调函数`callback`的参数`data`是一个对象,结构如下: 416 | 417 | - `httpcode` HTTP状态码 418 | - `code` 状态码,目前和`httpcode`相同 419 | - `message` 状态码对应的描述文字 420 | - `data` 数据对象,参考API文档 421 | 422 | 423 | 424 | ## 致谢 425 | 20150717 感谢[TooBug](https://github.com/TooBug) 提出的接口说明文档 和 bug 修复 426 | -------------------------------------------------------------------------------- /tencentyoutuyun/youtu.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var https = require('https'); 3 | var fs = require('fs'); 4 | 5 | 6 | 7 | var auth = require('./auth'); 8 | var conf = require('./conf'); 9 | 10 | // 30 days 11 | var EXPIRED_SECONDS = 2592000; 12 | 13 | /** 14 | * return the status message 15 | */ 16 | function statusText(status) { 17 | 18 | var statusText = 'unkown'; 19 | 20 | switch (status) { 21 | case 200: 22 | statusText = 'HTTP OK'; 23 | break; 24 | case 400: 25 | statusText = 'Bad Request'; 26 | break; 27 | case 401: 28 | statusText = 'Unauthorized'; 29 | break; 30 | case 403: 31 | statusText = 'Forbidden'; 32 | break; 33 | case 500: 34 | statusText = 'Internal Server Error'; 35 | break; 36 | } 37 | return statusText; 38 | }; 39 | 40 | function getrequest(protocol, params, callback) { 41 | 42 | return protocol.request(params, function(response) { 43 | 44 | // console.log('STATUS: ' + response.statusCode); 45 | // console.log('HEADERS: ' + JSON.stringify(response.headers)); 46 | 47 | if( response.statusCode != 200 ){ 48 | callback({'httpcode':response.statusCode, 'code':response.statusCode , 'message':statusText(response.statusCode) , 'data':{}}); 49 | return; 50 | } 51 | 52 | var body = ''; 53 | response.setEncoding('utf8'); 54 | 55 | response.on('data', function (chunk) { 56 | body += chunk; 57 | }); 58 | response.on('end', function(){ 59 | callback({'httpcode':response.statusCode, 'code':response.statusCode , 'message':statusText(response.statusCode) , 'data':JSON.parse(body)}); 60 | }); 61 | 62 | response.on('error', function(e){ 63 | callback({'httpcode':response.statusCode, 'code':response.statusCode , 'message': '' + e , 'data':{} }); 64 | }); 65 | }); // 66 | }; 67 | 68 | /** 69 | * @brief detectface 70 | * @param imagePath 待检测的路径(本地路径或url) 71 | * @param isbigface 是否大脸模式 0表示检测所有人脸, 1表示只检测照片最大人脸 适合单人照模式 72 | * @param callback 回调函数, 参见Readme 文档 73 | */ 74 | exports.detectface = function(imagePath, isbigface, callback) { 75 | 76 | callback = callback || function(ret){console.log(ret)}; 77 | 78 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 79 | var sign = auth.appSign(expired); 80 | var tag = imagePath.substring(0,4); 81 | var request_body = ''; 82 | if (tag == 'http') 83 | { 84 | request_body = JSON.stringify({ 85 | app_id: conf.APPID, 86 | url : imagePath, 87 | mode : isbigface, 88 | }); 89 | } 90 | else 91 | { 92 | try { 93 | var data = fs.readFileSync(imagePath).toString('base64'); 94 | } catch (e) { 95 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 96 | return; 97 | } 98 | 99 | if(data == null) { 100 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 101 | return; 102 | }; 103 | 104 | request_body = JSON.stringify({ 105 | app_id: conf.APPID, 106 | image : data.toString('base64'), 107 | mode : isbigface, 108 | }); 109 | } 110 | var params = { 111 | hostname: conf.API_YOUTU_SERVER, 112 | path: '/youtu/api/detectface', 113 | method: 'POST', 114 | headers: { 115 | 'Authorization': sign, 116 | 'User-Agent' : conf.USER_AGENT(), 117 | 'Content-Length': request_body.length, 118 | 'Content-Type': 'text/json' 119 | } 120 | }; 121 | 122 | //console.log(request_body); 123 | //console.log(params); 124 | var request = null; 125 | if (conf.API_DOMAIN == 0) 126 | { 127 | request = getrequest(http, params, callback); 128 | } 129 | else { 130 | request = getrequest(https, params, callback); 131 | } 132 | 133 | request.on('error', function(e) { 134 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 135 | }); 136 | 137 | // send the request body 138 | request.end(request_body); 139 | //console.log(request_body); 140 | } 141 | 142 | 143 | /** 144 | * @brief faceshape 145 | * @param imagePath 待检测的路径(本地路径或url) 146 | * @param isbigface 是否大脸模式 147 | * @param callback 回调函数, 参见Readme 文档 148 | */ 149 | exports.faceshape = function(imagePath, isbigface, callback) { 150 | 151 | callback = callback || function(ret){console.log(ret)}; 152 | 153 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 154 | var sign = auth.appSign(expired); 155 | var tag = imagePath.substring(0,4); 156 | var request_body = ''; 157 | if (tag == 'http') 158 | { 159 | request_body = JSON.stringify({ 160 | app_id: conf.APPID, 161 | url : imagePath, 162 | mode : isbigface, 163 | }); 164 | } 165 | else 166 | { 167 | try { 168 | var data = fs.readFileSync(imagePath).toString('base64'); 169 | } catch (e) { 170 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 171 | return; 172 | } 173 | if(data == null) { 174 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 175 | return; 176 | }; 177 | 178 | request_body = JSON.stringify({ 179 | app_id: conf.APPID, 180 | image : data.toString('base64'), 181 | mode : isbigface, 182 | }); 183 | } 184 | var params = { 185 | hostname: conf.API_YOUTU_SERVER, 186 | path: '/youtu/api/faceshape', 187 | method: 'POST', 188 | headers: { 189 | 'Authorization': sign, 190 | 'User-Agent' : conf.USER_AGENT(), 191 | 'Content-Length': request_body.length, 192 | 'Content-Type': 'text/json' 193 | } 194 | }; 195 | 196 | var request = null; 197 | if (conf.API_DOMAIN == 0) 198 | { 199 | request = getrequest(http, params, callback); 200 | } 201 | else { 202 | request = getrequest(https, params, callback); 203 | } 204 | 205 | request.on('error', function(e) { 206 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 207 | }); 208 | 209 | // send the request body 210 | request.end(request_body); 211 | } 212 | 213 | 214 | /** 215 | * @brief facecompare 216 | * @param image_a 待比对的A图片路径(本地路径或url) 217 | * @param image_b 待比对的B图片路径(本地路径或url) 218 | * @param callback 回调函数, 参见Readme 文档 219 | */ 220 | exports.facecompare = function(image_a, image_b, callback) { 221 | 222 | callback = callback || function(ret){console.log(ret)}; 223 | 224 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 225 | var sign = auth.appSign(expired); 226 | var tag = image_a.substring(0,4); 227 | var request_body = ''; 228 | if (tag == 'http') 229 | { 230 | var request_body = JSON.stringify({ 231 | app_id: conf.APPID, 232 | urlA : image_a, 233 | urlB : image_b, 234 | }); 235 | } 236 | else 237 | { 238 | try { 239 | var data_a = fs.readFileSync(image_a).toString('base64'); 240 | var data_b = fs.readFileSync(image_b).toString('base64'); 241 | } catch (e) { 242 | callback({'httpcode':0, 'code':-1, 'message':'file ' + image_a + ' or ' + image_b + ' not exists', 'data':{}}); 243 | return; 244 | } 245 | 246 | 247 | 248 | if(data_a == null || data_b == null ) { 249 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 250 | return; 251 | }; 252 | 253 | var request_body = JSON.stringify({ 254 | app_id: conf.APPID, 255 | imageA : data_a.toString('base64'), 256 | imageB : data_b.toString('base64'), 257 | }); 258 | } 259 | 260 | var params = { 261 | hostname: conf.API_YOUTU_SERVER, 262 | path: '/youtu/api/facecompare', 263 | method: 'POST', 264 | headers: { 265 | 'Authorization': sign, 266 | 'User-Agent' : conf.USER_AGENT(), 267 | 'Content-Length': request_body.length, 268 | 'Content-Type': 'text/json' 269 | } 270 | }; 271 | 272 | //console.log(request_body); 273 | var request = null; 274 | if (conf.API_DOMAIN == 0) 275 | { 276 | request = getrequest(http, params, callback); 277 | } 278 | else { 279 | request = getrequest(https, params, callback); 280 | } 281 | 282 | request.on('error', function(e) { 283 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 284 | }); 285 | 286 | // send the request body 287 | request.end(request_body); 288 | } 289 | 290 | 291 | /** 292 | * @brief facecompare 293 | * @param image_file 待比对的A图片路径(本地路径) 294 | * @param image_url 待比对的B图片路径(url) 295 | * @param callback 回调函数, 参见Readme 文档 296 | */ 297 | exports.facecompare_file_url = function(image_file, image_url, callback) { 298 | 299 | callback = callback || function(ret){console.log(ret)}; 300 | 301 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 302 | var sign = auth.appSign(expired); 303 | 304 | try { 305 | var data_a = fs.readFileSync(image_file).toString('base64'); 306 | } catch (e) { 307 | callback({'httpcode':0, 'code':-1, 'message':'file ' + image_file + ' not exists', 'data':{}}); 308 | return; 309 | } 310 | 311 | if(data_a == null ) { 312 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 313 | return; 314 | }; 315 | 316 | var request_body = JSON.stringify({ 317 | app_id: conf.APPID, 318 | imageA : data_a.toString('base64'), 319 | urlB : image_url, 320 | }); 321 | 322 | 323 | var params = { 324 | hostname: conf.API_YOUTU_SERVER, 325 | path: '/youtu/api/facecompare', 326 | method: 'POST', 327 | headers: { 328 | 'Authorization': sign, 329 | 'User-Agent' : conf.USER_AGENT(), 330 | 'Content-Length': request_body.length, 331 | 'Content-Type': 'text/json' 332 | } 333 | }; 334 | 335 | //console.log(request_body); 336 | var request = null; 337 | if (conf.API_DOMAIN == 0) 338 | { 339 | request = getrequest(http, params, callback); 340 | } 341 | else { 342 | request = getrequest(https, params, callback); 343 | } 344 | 345 | request.on('error', function(e) { 346 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 347 | }); 348 | 349 | // send the request body 350 | request.end(request_body); 351 | } 352 | 353 | 354 | /** 355 | * @brief faceverify 356 | * @param person_id 待验证的人脸id 357 | * @param imagePath 待验证的图片路径(本地路径或url) 358 | * @param callback 回调函数, 参见Readme 文档 359 | */ 360 | exports.faceverify = function(imagePath, person_id, callback) { 361 | 362 | callback = callback || function(ret){console.log(ret)}; 363 | 364 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 365 | var sign = auth.appSign(expired); 366 | var tag = imagePath.substring(0,4); 367 | var request_body = ''; 368 | 369 | if (tag == 'http') 370 | { 371 | request_body = JSON.stringify({ 372 | app_id: conf.APPID, 373 | url : imagePath, 374 | person_id : person_id, 375 | }); 376 | } 377 | else 378 | { 379 | try { 380 | var data = fs.readFileSync(imagePath).toString('base64'); 381 | } catch (e) { 382 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 383 | return; 384 | } 385 | 386 | if(data == null) { 387 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 388 | return; 389 | }; 390 | 391 | request_body = JSON.stringify({ 392 | app_id: conf.APPID, 393 | image : data.toString('base64'), 394 | person_id : person_id, 395 | }); 396 | } 397 | 398 | var params = { 399 | hostname: conf.API_YOUTU_SERVER, 400 | path: '/youtu/api/faceverify', 401 | method: 'POST', 402 | headers: { 403 | 'Authorization': sign, 404 | 'User-Agent' : conf.USER_AGENT(), 405 | 'Content-Length': request_body.length, 406 | 'Content-Type': 'text/json' 407 | } 408 | }; 409 | 410 | //console.log(request_body); 411 | var request = null; 412 | if (conf.API_DOMAIN == 0) 413 | { 414 | request = getrequest(http, params, callback); 415 | } 416 | else { 417 | request = getrequest(https, params, callback); 418 | } 419 | 420 | 421 | request.on('error', function(e) { 422 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 423 | }); 424 | 425 | // send the request body 426 | request.end(request_body); 427 | 428 | } 429 | 430 | 431 | /** 432 | * @brief faceidentify 433 | * @param group_id 识别的组id 434 | * @param imagePath 待识别的图片路径(本地路径或url) 435 | * @param callback 回调函数, 参见Readme 文档 436 | */ 437 | exports.faceidentify= function(imagePath, group_id, callback) { 438 | 439 | callback = callback || function(ret){console.log(ret)}; 440 | 441 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 442 | var sign = auth.appSign(expired); 443 | var tag = imagePath.substring(0,4); 444 | var request_body = ''; 445 | 446 | if (tag == 'http') 447 | { 448 | request_body = JSON.stringify({ 449 | app_id: conf.APPID, 450 | url : imagePath, 451 | group_id : group_id, 452 | }); 453 | } 454 | else 455 | { 456 | try { 457 | var data = fs.readFileSync(imagePath).toString('base64'); 458 | } catch (e) { 459 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 460 | return; 461 | } 462 | 463 | 464 | if(data == null) { 465 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 466 | return; 467 | }; 468 | 469 | request_body = JSON.stringify({ 470 | app_id: conf.APPID, 471 | image : data.toString('base64'), 472 | group_id : group_id, 473 | }); 474 | } 475 | 476 | var params = { 477 | hostname: conf.API_YOUTU_SERVER, 478 | path: '/youtu/api/faceidentify', 479 | method: 'POST', 480 | headers: { 481 | 'Authorization': sign, 482 | 'User-Agent' : conf.USER_AGENT(), 483 | 'Content-Length': request_body.length, 484 | 'Content-Type': 'text/json' 485 | } 486 | }; 487 | 488 | var request = null; 489 | if (conf.API_DOMAIN == 0) 490 | { 491 | request = getrequest(http, params, callback); 492 | } 493 | else { 494 | request = getrequest(https, params, callback); 495 | } 496 | 497 | request.on('error', function(e) { 498 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 499 | }); 500 | 501 | // send the request body 502 | request.end(request_body); 503 | } 504 | 505 | /** 506 | * @brief newperson 507 | * @param imagePath 图片路径(本地路径或url) 508 | * @param person_id 新建的个体id,用户指定,需要保证app_id下的唯一性 509 | * @param person_name 个体的名字 510 | * @param group_ids 新建的个体存放的组id,可以指定多个组id,用户指定(组默认创建) 511 | * @param persontag 人备注信息,用户自解释字段 512 | * @param callback 回调函数, 参见Readme 文档 513 | */ 514 | exports.newperson= function(imagePath, person_id, person_name, group_ids, persontag, callback) { 515 | 516 | callback = callback || function(ret){console.log(ret)}; 517 | 518 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 519 | var sign = auth.appSign(expired); 520 | 521 | var tag = imagePath.substring(0,4); 522 | var request_body = ''; 523 | 524 | if (tag == 'http') 525 | { 526 | request_body = JSON.stringify({ 527 | app_id: conf.APPID, 528 | url : imagePath, 529 | person_id : person_id, 530 | person_name: person_name, 531 | group_ids : group_ids, 532 | tag: persontag, 533 | }); 534 | } 535 | else 536 | { 537 | try { 538 | var data = fs.readFileSync(imagePath).toString('base64'); 539 | } catch (e) { 540 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 541 | return; 542 | } 543 | 544 | 545 | if(data == null) { 546 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 547 | return; 548 | }; 549 | 550 | request_body = JSON.stringify({ 551 | app_id: conf.APPID, 552 | image : data.toString('base64'), 553 | person_id : person_id, 554 | person_name: person_name, 555 | group_ids : group_ids, 556 | tag: persontag, 557 | }); 558 | } 559 | 560 | 561 | var buffer = new Buffer(request_body, "UTF-8"); 562 | 563 | var params = { 564 | hostname: conf.API_YOUTU_SERVER, 565 | path: '/youtu/api/newperson', 566 | method: 'POST', 567 | headers: { 568 | 'Authorization': sign, 569 | 'User-Agent' : conf.USER_AGENT(), 570 | 'Content-Length': buffer.length, 571 | 'Content-Type': 'text/json' 572 | } 573 | }; 574 | 575 | var request = null; 576 | if (conf.API_DOMAIN == 0) 577 | { 578 | request = getrequest(http, params, callback); 579 | } 580 | else { 581 | request = getrequest(https, params, callback); 582 | } 583 | 584 | request.on('error', function(e) { 585 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 586 | }); 587 | 588 | // send the request body 589 | request.end(request_body); 590 | } 591 | 592 | 593 | /** 594 | * @brief delperson 595 | * @param person_id 待删除的个体id 596 | * @param callback 回调函数, 参见Readme 文档 597 | */ 598 | exports.delperson= function(person_id, callback) { 599 | 600 | callback = callback || function(ret){console.log(ret)}; 601 | 602 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 603 | var sign = auth.appSign(expired); 604 | 605 | var request_body = JSON.stringify({ 606 | app_id: conf.APPID, 607 | person_id : person_id, 608 | }); 609 | 610 | var params = { 611 | hostname: conf.API_YOUTU_SERVER, 612 | port: conf.API_YOUTU_PORT, 613 | path: '/youtu/api/delperson', 614 | method: 'POST', 615 | headers: { 616 | 'Authorization': sign, 617 | 'User-Agent' : conf.USER_AGENT(), 618 | 'Content-Length': request_body.length, 619 | 'Content-Type': 'text/json' 620 | } 621 | }; 622 | 623 | var request = null; 624 | if (conf.API_DOMAIN == 0) 625 | { 626 | request = getrequest(http, params, callback); 627 | } 628 | else { 629 | request = getrequest(https, params, callback); 630 | } 631 | 632 | request.on('error', function(e) { 633 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 634 | }); 635 | 636 | // send the request body 637 | request.end(request_body); 638 | } 639 | 640 | 641 | 642 | /** 643 | * @brief addface 644 | * @param person_id 新增人脸的个体身份id 645 | * @param images 待增加的包含人脸的图片lu路径数组,可加入多张(包体大小<2m) 646 | * @param facetag 人脸备注信息,用户自解释字段 647 | * @param callback 回调函数, 参见Readme 文档 648 | */ 649 | exports.addface = function(person_id, images, facetag, callback) { 650 | 651 | callback = callback || function(ret){console.log(ret)}; 652 | 653 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 654 | var sign = auth.appSign(expired); 655 | 656 | var tag = images[0].substring(0,4); 657 | var request_body = ''; 658 | 659 | if (tag == 'http') 660 | { 661 | request_body = JSON.stringify({ 662 | app_id: conf.APPID, 663 | urls : images, 664 | person_id : person_id, 665 | tag : facetag 666 | }); 667 | } 668 | else 669 | { 670 | var image_bufs = new Array(); 671 | 672 | for( var idx in images) 673 | { 674 | try { 675 | var data =fs.readFileSync(images[idx]); 676 | } catch (e) { 677 | callback({'httpcode':0, 'code':-1, 'message':'file ' + images[idx] + ' not exists', 'data':{}}); 678 | return; 679 | } 680 | 681 | if(data == null) { 682 | callback({'httpcode':0, 'code':-1, 'message': images[idx] + ": read failed!", 'data':{}}); 683 | return; 684 | } 685 | 686 | image_bufs[idx] = data.toString('base64'); 687 | } 688 | 689 | request_body = JSON.stringify({ 690 | app_id: conf.APPID, 691 | images : image_bufs, 692 | person_id : person_id, 693 | tag : facetag 694 | }); 695 | } 696 | 697 | //console.log(request_body); 698 | var buffer = new Buffer(request_body, "UTF-8"); 699 | var params = { 700 | hostname: conf.API_YOUTU_SERVER, 701 | path: '/youtu/api/addface', 702 | method: 'POST', 703 | headers: { 704 | 'Authorization': sign, 705 | 'User-Agent' : conf.USER_AGENT(), 706 | 'Content-Length': buffer.length, 707 | 'Content-Type': 'text/json' 708 | } 709 | }; 710 | 711 | //console.log(params); 712 | var request = null; 713 | if (conf.API_DOMAIN == 0) 714 | { 715 | request = getrequest(http, params, callback); 716 | } 717 | else { 718 | request = getrequest(https, params, callback); 719 | } 720 | 721 | request.on('error', function(e) { 722 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 723 | }); 724 | 725 | // send the request body 726 | request.end(request_body); 727 | 728 | } 729 | 730 | 731 | /** 732 | * @brief delface 733 | * @param person_id 待删除人脸的个体身份id 734 | * @param face_ids 待删除的人脸id 数组 735 | * @param callback 回调函数, 参见Readme 文档 736 | */ 737 | exports.delface = function(person_id, face_ids, callback) { 738 | 739 | callback = callback || function(ret){console.log(ret)}; 740 | 741 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 742 | var sign = auth.appSign(expired); 743 | 744 | var request_body = JSON.stringify({ 745 | app_id: conf.APPID, 746 | face_ids: face_ids, 747 | person_id : person_id, 748 | }); 749 | 750 | var params = { 751 | hostname: conf.API_YOUTU_SERVER, 752 | path: '/youtu/api/delface', 753 | method: 'POST', 754 | headers: { 755 | 'Authorization': sign, 756 | 'User-Agent' : conf.USER_AGENT(), 757 | 'Content-Length': request_body.length, 758 | 'Content-Type': 'text/json' 759 | } 760 | }; 761 | 762 | var request = null; 763 | if (conf.API_DOMAIN == 0) 764 | { 765 | request = getrequest(http, params, callback); 766 | } 767 | else { 768 | request = getrequest(https, params, callback); 769 | } 770 | 771 | request.on('error', function(e) { 772 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 773 | }); 774 | 775 | // send the request body 776 | request.end(request_body); 777 | } 778 | 779 | 780 | /** 781 | * @brief setinfo 782 | * @param person_id 待设置的个体身份id 783 | * @param person_name 新设置的个体名字 784 | * @param tag 新设置的人脸备注信息 785 | * @param callback 回调函数, 参见Readme 文档 786 | */ 787 | exports.setinfo = function(person_name, person_id, tag, callback) { 788 | 789 | callback = callback || function(ret){console.log(ret)}; 790 | 791 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 792 | var sign = auth.appSign(expired); 793 | 794 | var request_body = JSON.stringify({ 795 | app_id: conf.APPID, 796 | person_name: person_name, 797 | person_id : person_id, 798 | tag: tag, 799 | }); 800 | 801 | var buffer = new Buffer(request_body, "UTF-8"); 802 | var params = { 803 | hostname: conf.API_YOUTU_SERVER, 804 | path: '/youtu/api/setinfo', 805 | method: 'POST', 806 | headers: { 807 | 'Authorization': sign, 808 | 'User-Agent' : conf.USER_AGENT(), 809 | 'Content-Length': buffer.length, 810 | 'Content-Type': 'text/json' 811 | } 812 | }; 813 | 814 | var request = null; 815 | if (conf.API_DOMAIN == 0) 816 | { 817 | request = getrequest(http, params, callback); 818 | } 819 | else { 820 | request = getrequest(https, params, callback); 821 | } 822 | 823 | request.on('error', function(e) { 824 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 825 | }); 826 | 827 | // send the request body 828 | request.end(request_body); 829 | } 830 | 831 | 832 | 833 | 834 | /** 835 | * @brief getinfo 836 | * @param person_id 待查询的个体身份id 837 | * @param callback 回调函数, 参见Readme 文档 838 | */ 839 | exports.getinfo = function(person_id, callback) { 840 | 841 | callback = callback || function(ret){console.log(ret)}; 842 | 843 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 844 | var sign = auth.appSign(expired); 845 | 846 | 847 | var request_body = JSON.stringify({ 848 | app_id: conf.APPID, 849 | person_id : person_id, 850 | }); 851 | 852 | var params = { 853 | hostname: conf.API_YOUTU_SERVER, 854 | path: '/youtu/api/getinfo', 855 | method: 'POST', 856 | headers: { 857 | 'Authorization': sign, 858 | 'User-Agent' : conf.USER_AGENT(), 859 | 'Content-Length': request_body.length, 860 | 'Content-Type': 'text/json' 861 | } 862 | }; 863 | 864 | var request = null; 865 | if (conf.API_DOMAIN == 0) 866 | { 867 | request = getrequest(http, params, callback); 868 | } 869 | else { 870 | request = getrequest(https, params, callback); 871 | } 872 | 873 | request.on('error', function(e) { 874 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 875 | }); 876 | 877 | // send the request body 878 | request.end(request_body); 879 | } 880 | 881 | 882 | /** 883 | * @brief getgroupids 884 | * @param callback 回调函数, 参见Readme 文档 885 | */ 886 | exports.getgroupids = function(callback) { 887 | 888 | callback = callback || function(ret){console.log(ret)}; 889 | 890 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 891 | var sign = auth.appSign(expired); 892 | 893 | var request_body = JSON.stringify({ 894 | app_id: conf.APPID, 895 | }); 896 | 897 | var params = { 898 | hostname: conf.API_YOUTU_SERVER, 899 | path: '/youtu/api/getgroupids', 900 | method: 'POST', 901 | headers: { 902 | 'Authorization': sign, 903 | 'User-Agent' : conf.USER_AGENT(), 904 | 'Content-Length': request_body.length, 905 | 'Content-Type': 'text/json' 906 | } 907 | }; 908 | 909 | 910 | var request = null; 911 | if (conf.API_DOMAIN == 0) 912 | { 913 | request = getrequest(http, params, callback); 914 | } 915 | else { 916 | request = getrequest(https, params, callback); 917 | } 918 | 919 | request.on('error', function(e) { 920 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 921 | }); 922 | 923 | // send the request body 924 | request.end(request_body); 925 | } 926 | 927 | 928 | /** 929 | * @brief getpersonids 930 | * @param group_id 待查询的组id 931 | * @param callback 回调函数, 参见Readme 文档 932 | */ 933 | exports.getpersonids = function(group_id, callback) { 934 | 935 | callback = callback || function(ret){console.log(ret)}; 936 | 937 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 938 | var sign = auth.appSign(expired); 939 | 940 | 941 | var request_body = JSON.stringify({ 942 | app_id: conf.APPID, 943 | group_id:group_id 944 | }); 945 | 946 | var params = { 947 | hostname: conf.API_YOUTU_SERVER, 948 | port: conf.API_YOUTU_PORT, 949 | path: '/youtu/api/getpersonids', 950 | method: 'POST', 951 | headers: { 952 | 'Authorization': sign, 953 | 'User-Agent' : conf.USER_AGENT(), 954 | 'Content-Length': request_body.length, 955 | 'Content-Type': 'text/json' 956 | } 957 | }; 958 | 959 | var request = null; 960 | if (conf.API_DOMAIN == 0) 961 | { 962 | request = getrequest(http, params, callback); 963 | } 964 | else { 965 | request = getrequest(https, params, callback); 966 | } 967 | 968 | request.on('error', function(e) { 969 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 970 | }); 971 | 972 | // send the request body 973 | request.end(request_body); 974 | } 975 | 976 | 977 | 978 | 979 | /** 980 | * @brief getfaceids 981 | * @param person_id 待查询的个体id 982 | * @param callback 回调函数, 参见Readme 文档 983 | */ 984 | exports.getfaceids = function(person_id, callback) { 985 | 986 | callback = callback || function(ret){console.log(ret)}; 987 | 988 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 989 | var sign = auth.appSign(expired); 990 | 991 | 992 | var request_body = JSON.stringify({ 993 | app_id: conf.APPID, 994 | person_id:person_id 995 | }); 996 | 997 | var params = { 998 | hostname: conf.API_YOUTU_SERVER, 999 | path: '/youtu/api/getfaceids', 1000 | method: 'POST', 1001 | headers: { 1002 | 'Authorization': sign, 1003 | 'User-Agent' : conf.USER_AGENT(), 1004 | 'Content-Length': request_body.length, 1005 | 'Content-Type': 'text/json' 1006 | } 1007 | }; 1008 | 1009 | var request = null; 1010 | if (conf.API_DOMAIN == 0) 1011 | { 1012 | request = getrequest(http, params, callback); 1013 | } 1014 | else { 1015 | request = getrequest(https, params, callback); 1016 | } 1017 | 1018 | request.on('error', function(e) { 1019 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1020 | }); 1021 | 1022 | // send the request body 1023 | request.end(request_body); 1024 | } 1025 | 1026 | 1027 | 1028 | /** 1029 | * @brief getfaceinfo 1030 | * @param face_id 待查询的人脸id 1031 | * @param callback 回调函数, 参见Readme 文档 1032 | */ 1033 | exports.getfaceinfo = function(face_id, callback) { 1034 | 1035 | callback = callback || function(ret){console.log(ret)}; 1036 | 1037 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1038 | var sign = auth.appSign(expired); 1039 | 1040 | var request_body = JSON.stringify({ 1041 | app_id: conf.APPID, 1042 | face_id:face_id 1043 | }); 1044 | 1045 | var params = { 1046 | hostname: conf.API_YOUTU_SERVER, 1047 | path: '/youtu/api/getfaceinfo', 1048 | method: 'POST', 1049 | headers: { 1050 | 'Authorization': sign, 1051 | 'User-Agent' : conf.USER_AGENT(), 1052 | 'Content-Length': request_body.length, 1053 | 'Content-Type': 'text/json' 1054 | } 1055 | }; 1056 | 1057 | var request = null; 1058 | if (conf.API_DOMAIN == 0) 1059 | { 1060 | request = getrequest(http, params, callback); 1061 | } 1062 | else { 1063 | request = getrequest(https, params, callback); 1064 | } 1065 | 1066 | request.on('error', function(e) { 1067 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1068 | }); 1069 | 1070 | // send the request body 1071 | request.end(request_body); 1072 | } 1073 | 1074 | /** 1075 | * @brief fuzzydetect 1076 | * @param imagePath 待检测的路径 1077 | * @param callback 回调函数, 参见Readme 文档 1078 | */ 1079 | exports.fuzzydetect = function(imagePath, callback) { 1080 | 1081 | callback = callback || function(ret){console.log(ret)}; 1082 | 1083 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1084 | var sign = auth.appSign(expired); 1085 | var tag = imagePath.substring(0,4); 1086 | var request_body = ''; 1087 | if (tag == 'http') 1088 | { 1089 | request_body = JSON.stringify({ 1090 | app_id: conf.APPID, 1091 | url : imagePath, 1092 | }); 1093 | } 1094 | else 1095 | { 1096 | try { 1097 | var data = fs.readFileSync(imagePath).toString('base64'); 1098 | } catch (e) { 1099 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1100 | return; 1101 | } 1102 | 1103 | 1104 | if(data == null) { 1105 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1106 | return; 1107 | }; 1108 | 1109 | request_body = JSON.stringify({ 1110 | app_id: conf.APPID, 1111 | image : data.toString('base64'), 1112 | }); 1113 | } 1114 | var params = { 1115 | hostname: conf.API_YOUTU_SERVER, 1116 | path: '/youtu/imageapi/fuzzydetect', 1117 | method: 'POST', 1118 | headers: { 1119 | 'Authorization': sign, 1120 | 'User-Agent' : conf.USER_AGENT(), 1121 | 'Content-Length': request_body.length, 1122 | 'Content-Type': 'text/json' 1123 | } 1124 | }; 1125 | //console.log(request_body); 1126 | //console.log(params); 1127 | var request = null; 1128 | if (conf.API_DOMAIN == 0) 1129 | { 1130 | request = getrequest(http, params, callback); 1131 | } 1132 | else { 1133 | request = getrequest(https, params, callback); 1134 | } 1135 | 1136 | request.on('error', function(e) { 1137 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1138 | }); 1139 | 1140 | // send the request body 1141 | request.end(request_body); 1142 | } 1143 | 1144 | /** 1145 | * @brief fooddetect 1146 | * @param imagePath 待检测的路径 1147 | * @param callback 回调函数, 参见Readme 文档 1148 | */ 1149 | exports.fooddetect = function(imagePath, callback) { 1150 | 1151 | callback = callback || function(ret){console.log(ret)}; 1152 | 1153 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1154 | var sign = auth.appSign(expired); 1155 | var tag = imagePath.substring(0,4); 1156 | var request_body = ''; 1157 | if (tag == 'http') 1158 | { 1159 | request_body = JSON.stringify({ 1160 | app_id: conf.APPID, 1161 | url : imagePath, 1162 | }); 1163 | } 1164 | else 1165 | { 1166 | 1167 | try { 1168 | var data = fs.readFileSync(imagePath).toString('base64'); 1169 | } catch (e) { 1170 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1171 | return; 1172 | } 1173 | if(data == null) { 1174 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1175 | return; 1176 | }; 1177 | 1178 | request_body = JSON.stringify({ 1179 | app_id: conf.APPID, 1180 | image : data.toString('base64'), 1181 | }); 1182 | } 1183 | var params = { 1184 | hostname: conf.API_YOUTU_SERVER, 1185 | path: '/youtu/imageapi/fooddetect', 1186 | method: 'POST', 1187 | headers: { 1188 | 'Authorization': sign, 1189 | 'User-Agent' : conf.USER_AGENT(), 1190 | 'Content-Length': request_body.length, 1191 | 'Content-Type': 'text/json' 1192 | } 1193 | }; 1194 | //console.log(request_body); 1195 | //console.log(params); 1196 | var request = null; 1197 | if (conf.API_DOMAIN == 0) 1198 | { 1199 | request = getrequest(http, params, callback); 1200 | } 1201 | else { 1202 | request = getrequest(https, params, callback); 1203 | } 1204 | 1205 | request.on('error', function(e) { 1206 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1207 | }); 1208 | 1209 | // send the request body 1210 | request.end(request_body); 1211 | } 1212 | 1213 | /** 1214 | * @brief imagetag 1215 | * @param imagePath 待检测的路径 1216 | * @param callback 回调函数, 参见Readme 文档 1217 | */ 1218 | exports.imagetag = function(imagePath, callback) { 1219 | 1220 | callback = callback || function(ret){console.log(ret)}; 1221 | 1222 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1223 | var sign = auth.appSign(expired); 1224 | var tag = imagePath.substring(0,4); 1225 | var request_body = ''; 1226 | if (tag == 'http') 1227 | { 1228 | request_body = JSON.stringify({ 1229 | app_id: conf.APPID, 1230 | url : imagePath, 1231 | }); 1232 | } 1233 | else 1234 | { 1235 | try { 1236 | var data = fs.readFileSync(imagePath).toString('base64'); 1237 | } catch (e) { 1238 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1239 | return; 1240 | } 1241 | 1242 | if(data == null) { 1243 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1244 | return; 1245 | }; 1246 | 1247 | request_body = JSON.stringify({ 1248 | app_id: conf.APPID, 1249 | image : data.toString('base64'), 1250 | }); 1251 | } 1252 | var params = { 1253 | hostname: conf.API_YOUTU_SERVER, 1254 | path: '/youtu/imageapi/imagetag', 1255 | method: 'POST', 1256 | headers: { 1257 | 'Authorization': sign, 1258 | 'User-Agent' : conf.USER_AGENT(), 1259 | 'Content-Length': request_body.length, 1260 | 'Content-Type': 'text/json' 1261 | } 1262 | }; 1263 | //console.log(request_body); 1264 | //console.log(params); 1265 | 1266 | var request = null; 1267 | if (conf.API_DOMAIN == 0) 1268 | { 1269 | request = getrequest(http, params, callback); 1270 | } 1271 | else { 1272 | request = getrequest(https, params, callback); 1273 | } 1274 | 1275 | request.on('error', function(e) { 1276 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1277 | }); 1278 | 1279 | // send the request body 1280 | request.end(request_body); 1281 | } 1282 | 1283 | /** 1284 | * @brief imageporn 1285 | * @param imagePath 待检测的路径 1286 | * @param callback 回调函数, 参见Readme 文档 1287 | */ 1288 | exports.imageporn = function(imagePath, callback) { 1289 | 1290 | callback = callback || function(ret){console.log(ret)}; 1291 | 1292 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1293 | var sign = auth.appSign(expired); 1294 | var tag = imagePath.substring(0,4); 1295 | var request_body = ''; 1296 | if (tag == 'http') 1297 | { 1298 | request_body = JSON.stringify({ 1299 | app_id: conf.APPID, 1300 | url : imagePath, 1301 | }); 1302 | } 1303 | else 1304 | { 1305 | try { 1306 | var data = fs.readFileSync(imagePath).toString('base64'); 1307 | } catch (e) { 1308 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1309 | return; 1310 | } 1311 | if(data == null) { 1312 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1313 | return; 1314 | }; 1315 | 1316 | request_body = JSON.stringify({ 1317 | app_id: conf.APPID, 1318 | image : data.toString('base64'), 1319 | }); 1320 | } 1321 | var params = { 1322 | hostname: conf.API_YOUTU_SERVER, 1323 | path: '/youtu/imageapi/imageporn', 1324 | method: 'POST', 1325 | headers: { 1326 | 'Authorization': sign, 1327 | 'User-Agent' : conf.USER_AGENT(), 1328 | 'Content-Length': request_body.length, 1329 | 'Content-Type': 'text/json' 1330 | } 1331 | }; 1332 | //console.log(request_body); 1333 | //console.log(params); 1334 | 1335 | var request = null; 1336 | if (conf.API_DOMAIN == 0) 1337 | { 1338 | request = getrequest(http, params, callback); 1339 | } 1340 | else { 1341 | request = getrequest(https, params, callback); 1342 | } 1343 | 1344 | request.on('error', function(e) { 1345 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1346 | }); 1347 | 1348 | // send the request body 1349 | request.end(request_body); 1350 | } 1351 | 1352 | 1353 | /** 1354 | * @brief imageporn 1355 | * @param imagePath 待检测的路径 1356 | * @param cardType 0 代表输入图像是身份证正面, 1代表输入是身份证反面 1357 | * @param callback 回调函数, 参见Readme 文档 1358 | */ 1359 | exports.idcardocr = function(imagePath, cardType, callback) { 1360 | 1361 | callback = callback || function(ret){console.log(ret)}; 1362 | 1363 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1364 | var sign = auth.appSign(expired); 1365 | var tag = imagePath.substring(0,4); 1366 | var request_body = ''; 1367 | if (tag == 'http') 1368 | { 1369 | request_body = JSON.stringify({ 1370 | app_id: conf.APPID, 1371 | card_type: cardType, 1372 | url : imagePath, 1373 | }); 1374 | } 1375 | else 1376 | { 1377 | try { 1378 | var data = fs.readFileSync(imagePath).toString('base64'); 1379 | } catch (e) { 1380 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1381 | return; 1382 | } 1383 | if(data == null) { 1384 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1385 | return; 1386 | }; 1387 | 1388 | request_body = JSON.stringify({ 1389 | app_id: conf.APPID, 1390 | card_type: cardType, 1391 | image : data.toString('base64'), 1392 | }); 1393 | } 1394 | var params = { 1395 | hostname: conf.API_YOUTU_SERVER, 1396 | path: '/youtu/ocrapi/idcardocr', 1397 | method: 'POST', 1398 | headers: { 1399 | 'Authorization': sign, 1400 | 'User-Agent' : conf.USER_AGENT(), 1401 | 'Content-Length': request_body.length, 1402 | 'Content-Type': 'text/json' 1403 | } 1404 | }; 1405 | //console.log(request_body); 1406 | //console.log(params); 1407 | 1408 | var request = null; 1409 | if (conf.API_DOMAIN == 0) 1410 | { 1411 | request = getrequest(http, params, callback); 1412 | } 1413 | else { 1414 | request = getrequest(https, params, callback); 1415 | } 1416 | 1417 | request.on('error', function(e) { 1418 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1419 | }); 1420 | 1421 | // send the request body 1422 | request.end(request_body); 1423 | } 1424 | 1425 | /** 1426 | * @brief namecardocr 1427 | * @param imagePath 待检测的路径 1428 | * @param retImage false 代表不需要返回识别后图像, true 代表需要返回识别后图像 1429 | * @param callback 回调函数, 参见Readme 文档 1430 | */ 1431 | exports.namecardocr = function(imagePath, retImage, callback) { 1432 | 1433 | callback = callback || function(ret){console.log(ret)}; 1434 | 1435 | var expired = parseInt(Date.now() / 1000) + EXPIRED_SECONDS; 1436 | var sign = auth.appSign(expired); 1437 | var tag = imagePath.substring(0,4); 1438 | var request_body = ''; 1439 | if (tag == 'http') 1440 | { 1441 | request_body = JSON.stringify({ 1442 | app_id: conf.APPID, 1443 | retimage: retImage, 1444 | url : imagePath, 1445 | }); 1446 | } 1447 | else 1448 | { 1449 | try { 1450 | var data = fs.readFileSync(imagePath).toString('base64'); 1451 | } catch (e) { 1452 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists', 'data':{}}); 1453 | return; 1454 | } 1455 | 1456 | if(data == null) { 1457 | callback({'httpcode':0, 'code':-1, 'message':'file ' + imagePath + ' not exists or params error', 'data':{}}); 1458 | return; 1459 | }; 1460 | 1461 | request_body = JSON.stringify({ 1462 | app_id: conf.APPID, 1463 | retimage: retImage, 1464 | image : data.toString('base64'), 1465 | }); 1466 | } 1467 | var params = { 1468 | //hostname: conf.API_YOUTU_SERVER, 1469 | host: '101.226.76.164', 1470 | port: 18082, 1471 | path:'/youtu/ocrapi/namecardocr', 1472 | method: 'POST', 1473 | headers: { 1474 | 'Authorization': sign, 1475 | 'User-Agent' : conf.USER_AGENT(), 1476 | 'Content-Length': request_body.length, 1477 | 'Content-Type': 'text/json' 1478 | } 1479 | }; 1480 | //console.log(request_body); 1481 | //console.log(params); 1482 | 1483 | var request = null; 1484 | if (conf.API_DOMAIN == 0) 1485 | { 1486 | request = getrequest(http, params, callback); 1487 | } 1488 | else { 1489 | request = getrequest(https, params, callback); 1490 | } 1491 | 1492 | request.on('error', function(e) { 1493 | callback({'httpcode': 0, 'code': 0, 'message':e.message, 'data': {}}); 1494 | }); 1495 | 1496 | // send the request body 1497 | request.end(request_body); 1498 | } 1499 | 1500 | 1501 | --------------------------------------------------------------------------------