笔者在做H5制作平台,90%以上的流量来自于微信,日PV1亿-2.5亿之间,H5动画有大量JPG/ PNG/GIF图片,占用大量带宽,如果能将图片进行压缩,将节省很大一部分CDN费用。
笔者的图片资源主要集中在JPEG,PNG, GIF。经过测试,大部分Android微信版本已经支持WebP,难道微信X5内核是基于Chrome?而目前IOS版本微信不支持WebP。考虑到85%的流量来自于Android 微信。节省图片流量大有可行!!!
经过研究发现微信公众号文章的图片也是自动转为WebP格式,看来图片流量也是腾讯的大头。
浏览器兼容性网站可以参考: https://caniuse.com/#search=webp
WebP介绍
WebP(发音weppy),是一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式,派生自影像编码格式VP8,被认为是WebM多媒体格式的姊妹项目,是由Google在购买On2 Technologies后发展出来,以BSD授权条款发布。更详细的介绍参考文后引用链接。
WebP与主流图片格式对比
有损 WebP VS JPG
无损 WebP 对比 PNG
WebP与GIF
来源于: https://isparta.github.io/compare-webp/index_a.html
GIF 原图 大小:869k | Animated WebP 大小:371k |
GIF 原图大小:89.4k | Animated WebP 大小:4.65k |
实现方式
判断浏览器是否支持WebP有以下方法
通过User-Agent来判断UA是否包含Chrome特定版本(_Chrome_ 23开始支持WebP)来判断是否支持WebP,不严谨。
基于HTTP内容协商机制判断, 可以判断Request Header的Accept字段是否包含image/webp,进行相应的内容返回,例如返回webp格式的图片地址,这样可以大大节省cdn流量,但是这样需要CDN服务器或图片源服务器支持。
如果服务器端不允许,可以在js里做文章进行webp的判断。
function checkWebp() {
try {
return(document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0);
} catch(err) {
return false;
}
}
这种方法无法兼容动态WebP的判断(GIF 可以转为动态WebP)。对比下图参见
从谷歌网站找到了完美判断浏览器是否支持WebP的方法:
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA", //有损
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==", //无损
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==", //alpha通道,透明色
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA" // 动态WebP
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
上述代码的意思是对每一种格式的WebP(有损,无损,alpha通道,动态)生成一个1x1像素的图片,在浏览器中渲染,如果宽高都大于0,就代表支持webp。
CDN厂商的支持
笔者所在公司使用的是七牛云存储,本身支持到webp的转换,七牛云存储文档 图片高级处理 中说webp不支持动图,不过经过笔者测试,七牛是支持webp动图的。
在图片资源后面添加参数
?imageMogr2/format/webp
如果已经有参数可以使用管道符号(|),例如
?imageMogr2/thumbnail/200x200>/strip|imageMogr2/format/webp 来支持webp有损格式。
如果使用又拍云,可以参考 又拍云webp,
又拍云可以开启基于协商机制自动图片转为webp。例如: D9rVpVLq.webp
当然阿里云也是支持WebP直接转换的。
上线后经过流量对比,平均带宽节省36%,效果非常好。
自建图片服务器的WebP化
一般做法是在接入层(Nginx)进行一次转换,缓存到服务器,可以使用Nginx+ Lua+ Imagemagick进行,可以参考
nginx-lua-GraphicsMagick,
不过这种方式是调用gm的命令,可以考虑lua ffi版本的GraphicsMagick
本地测试可以使用Imagemagick 或者Google 官方cwebp
WebP优缺点
每种技术都不可能放之四海而皆准,都有业务场景和优缺点,WebP也是如此。相对于传统图片格式,WebP的压缩时间更长。WebP与GIF
支持有损和无损压缩,并且可以合并有损和无损图片帧
体积更小,GIF 转成有损 Animated WebP 后可以减小 64% 的体积,转成无损可以节省 19% 的体积
颜色更丰富,支持 24-bit 的 RGB 颜色以及 8-bit 的 Alpha 透明通道(而 GIF 只支持 8-bit RGB 颜色以及 1-bit 的透明)
添加了关键帧、metadata 等数据
缺点:
有损WebP 转码比GIF多2.2倍时间,无损WebP比GIF大1.5倍时间
WebP没有GIF使用广泛,桌面系统不支持。
升级方案
腾讯可能会在微信中使用自有格式TPG格式,那时候可以使用TPG了,第三方cdn不知道能否跟进
注明:
由于订阅号局限,暂时不能添加外部超链接,详细信息请参考 Worktile企业网盘-技术委员会-运行组-解决方案