准备工作
因为我们要调用的是腾讯的远程API滤镜接口,因此要先注册账号(注册地址),然后创建应用程序,进入控制台,点击“创建应用”即可完成创建。再查看应用信息,拷贝app_id和app_key,后面要用到。如下图所示:
这里也给出腾讯AI滤镜的开发文档地址(开发文档),大家可以先自己了解一下,然后再往下看。
核心代码讲解
总共有天天P图和AI Lab两个滤镜API接口,不过参数基本相同,都是htpp post请求。本文是基于Unity2018.3.0进行开发,将使用UnityWebRequest进行post请求。API 具体的请求参数如下:
对于天天P图的API接口,总共有6个参数,app_id大家可以在上面创建的应用信息中找到,如下图:
filter对应的是滤镜的效果id,天天P图有32种效果,为1-32;AI Lab有65种效果为1-65;接下来主要重点讲解一下其他三个参数。
首先是time_stamp,int类型,根据字段描述,可以知道是请求时间戳,以秒为单位,因此只要算出当前时间距1970.01.01:00:00:00的秒数就好,具体代码如下:
1 2 3 4 5 6 7 8
| private string GetUnixTimestamp() { //获取时间 TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0); //将时间转换为以秒为单位,因此是64位的整型值 return Convert.ToInt64(timeSpan.TotalSeconds).ToString(); }
|
然后是image参数,string类型,要求是base64编码数据(这是什么鬼)。刚看到,我也是一头雾水,通过查阅资料发现用C#实现就是先把图片转换为byte数组,然后再转换为base64字符串即可。具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| private string Bytes2Base64(byte[] bytes) { string base64 = Convert.ToBase64String(bytes);
int mod = base64.Length % 4; if(mod > 0) { base64 += new string('=', 4 - mod); }
return base64; }
|
不过有个坑就是,通过在线工具转换的base64字符串长度是4的整数倍,不足的用”=”补足了。因此上面的代码进行了4的倍数判断并自动补足。
最后一个参数是sign,授权密钥,比较头疼,不过看过描述之后,觉得也还好。授权描述如下:
从上面的描述,我们可以知道主要就是对请求参数按键值对中key值进行升序排列,然后并对value进行URL编码,并且URL编码采用大写字母;接着再将app_key放到字符串的最后;最后对得到的字符串进行MD5加密运算,并把加密字符串全部转换为大写字母。
不过问题又来了,什么是URL编码?查阅资料,最后发现Unity中实现了该算法,调用UnityWebRequest.EscapeURL(string)即可,但对得到的字符串要转换为大写字母。具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| private string ConvertURLEncode(string str, bool isImage=false) { string urlCode = UnityWebRequest.EscapeURL(str); if (isImage) { string str1 = UnityWebRequest.EscapeURL("+"); string str2 = UnityWebRequest.EscapeURL("/"); string str3 = UnityWebRequest.EscapeURL("=");
urlCode = urlCode.Replace(str1, str1.ToUpper()); urlCode = urlCode.Replace(str2, str2.ToUpper()); urlCode = urlCode.Replace(str3, str3.ToUpper()); return urlCode; } else return urlCode; }
|
对于上面的代码,大家会发现为什么对于图片的base64字符没有直接进行URL编码。这是因为URL编码只对部分字符进行编码,对数字和英文字母不进行编码(具体请看这里URL编码)。而且如果我们对整个base64字符串进行URL编码,会消耗相当长的一段时间。因此我采用了如上的代码实现URL编码。
URL编码我们已经会了,接下来就是对得到的字符串进行MD5运算,得到sign授权字符串。而C#刚好实现了MD5加密算法,具体代码如下:
1 2 3 4 5 6 7
| private string GetMD5Str(string str) { byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); //转换为大写字母字符串 return BitConverter.ToString(bytes).ToUpper().Replace("-", ""); }
|
所有的参数我们都已经准备好了,那就可以进行Http post请求了,不过请求成功返回什么样的结果呢?具体可以看文档的描述,如下图所示:
可以看到,返回的图片任然是base64字符串的形式,因此我们要自己将base64字符串转换为图片,这个实现我就留给大家自己做了。不过有人该问了,这么多数据项,我要怎么拿到呀?其实返回的结果是以json字符串给我们的,我们只要把json字符串利用Unity中的JsonUtility转换为对应参数的对象就可以了。我们可以将返回的结果定义为如下的数据结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [Serializable] public class Data { public string image; }
[Serializable] public class ImageData { public int ret; public string msg; public Data data; }
|
最后一点就是对于AI Lab的API接口参数多了一个session_id参数,对应的是string类型,作用是请求id,只要保证每次请求值与之前不一样即可。下面是post请求表单和sign计算代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| private WWWForm GetPostForm(byte[] imgBytes, FilterType filterType, int filterId) { //将图片转换为Base64字符串 string imgStr = Bytes2Base64(imgBytes);//图片转为JPG格式的字符串,减小图片大小
//获取时间戳 string timeStamp = GetUnixTimestamp();
//设置请求字段 WWWForm form = new WWWForm(); form.AddField("app_id", int.Parse(app_id)); form.AddField("filter", filterId); form.AddField("image", imgStr); form.AddField("time_stamp", int.Parse(timeStamp)); form.AddField("nonce_str", timeStamp);
//获取加密原字符串,对<key,value>按key升序排列 string originalStr = "app_id=" + app_id + "&filter=" + filterId + "&image=" + ConvertURLEncode(imgStr, true) + "&nonce_str=" + timeStamp; if (filterType == FilterType.TTPTUFilter) { originalStr += "&time_stamp=" + timeStamp + "&app_key=" + app_key; } else { originalStr += "&session_id=" + timeStamp + "&time_stamp=" + timeStamp + "&app_key=" + app_key; form.AddField("session_id", timeStamp); } form.AddField("sign", GetMD5Str(originalStr));
return form; }
|
效果展示
总算把这篇文章给写完写出来了,本来准备上周日就写的,一直拖到现在......后面会专注于新媒体互动开发的相关分享,不过只做应用方面的分享,不过多讲底层的东西,大家可以自己去深挖研究。还有源工程就不放出来了,至于原因,就不说了,github速度......我已经不可以说什么了,不过这个速度慢的原因太多!!!
如有侵权,请联系删除!