- 视频作为淘宝教育业务的基础服务,本文根据自身在手淘中视频播放的实践,谈谈在手淘中视频播放遇到的问题及其解决方案。
播放器
接口与事件封装上面介绍了手淘中可供 WebView 选择的播放器,对于业务方而言迫切需要一个解决方,无需关心底层差异。为此,我们屏蔽移动端不同系统平台、宿主环境、播放器的实现细节和兼容性问题,提供统一的接口和事件,具体如下:
- 方法
- play 播放
- pause 暂停
- stop 停止
- show 显示
- hide 隐藏
- requestFullscreen 全屏
- exitFullScreen 退出全屏
- getCurrentTime 获取当前播放时间
- setCurrentTime 设置播放时间
- getDuration 获取视频时长
- setPoster 设置背景图
- destory 销毁
- reset 重置视频
-
事件
- timeupdate 进度更新
- ended 停止
- error 错误
- play (专指video)
- pause 停止(专指video)
- firstpaint 视频真正开始播放(专指video)
-
controls 播放控件(专指video)
兼容性处理
接下来谈谈在开发过程中遇到的各种小问题及其解决办法。
video
|
video::-webkit-media-controls-start-playback-button { display: none; }
|
|
_timeUpdate(e) { var currentTime = this.getCurrentTime(); if (currentTime !== undefined && currentTime !== 0) { this.fire('firstpaint'); } }
_playing() { if (Env.os.ios) { this.fire('firstpaint'); } }
|
-
视频切换:在android 4.4 以下版本,在视频切换时存在第一次切换不能正常播放,第二次才能正常播放情况。通过调试人肉分析,发现切换视频的 video 存在以下两个特征:readyState 值为 0,videoWidth 为 0。因此我们判断当两个属性为0时,则切换失败,再次调用播放逻辑。存在误判的可能,但是能保证正常工作。
|
isWork() { if (videoEl.readyState === 0 && videoEl.videoWidth === 0) { return false; } return true; }
|
|
if (this.transverseFullScreen) { if (curEl.hasClass('normal')) { curEl.removeClass('normal'); this._transverseFullScreen(false).then(() => { $('body').removeClass('co-fullscreen').attr({ height: 'auto' }); this.videoWrapperEl.height(this.videoOriginHeight).removeClass('fullscreen');
this.player.fire('transversefullscreen', { fullscreen: false }); this.resize(); } else { curEl.addClass('normal'); this._transverseFullScreen(true).then(() => { $('body').addClass('co-fullscreen').attr({ height: win.height() }); this.videoWrapperEl.height(win.height()).addClass('fullscreen');
this.player.fire('transversefullscreen', { fullscreen: true }); this.resize(); }); } return; }
|
- Demo:
- 手淘 IOS 扫码:

-
方案3
。在 UC HAC 方案视频提供全屏接口 UCSettings.setVideoViewFullscreenByDefault(true),开启后,视频全屏默认为横屏
-
自动播放
- 出于用户节省用户流量考虑,iPhone 下播放视频需要用户手动触发,即使配置了 autoplay 属性也是无效的。在业务中,特定场景还是需要视频能够自动播放,对此我们可以监听页面的 touchstart 事件,做如下处理:
|
if (this.auoplay && env.app.TB && env.network.wifi) { if (player.getCurrentTime() > 0 && !player.isPause()) { return; } if (this.hasAutoPlay) { return; } this.hasAutoPlay = true; startEl.trigger('click');
function autoplay() { doc.detach('touchstart', autoplay); if (player.getCurrentTime() > 0) { return; } startEl.trigger('click'); } doc.on('touchstart', autoplay); }
|
- 其他
- 部分机型手淘低版本使用 video 播放时,会出现有声音没画面的问题,升级手淘后即恢复。例如,小米4 手淘 4.2.0
- IOS 5.1 和部分 android 手机暂停和开始按钮不触发点击事件(元素的 :after 为iconfont)。通过父元素添加background即可
- Android UC 内核的播放器,在未设置 source 资源时,设置 poster 无效
- Android UC 内核的播放器无法自定义控件和样式操作,但是可以正常的监听事件。
- 直接替换 source 不会改变当前正在播放的视频,需要调用 load 方法。
- UC 浏览器中 video 标签会被 UC 的播放器插件替换
- 使用 m3u8 和 mp4 基本可以兼容所有机型
- 在 IOS 视频初始化后设置 currrentTime 无效,在 loadedmetadata 事件触发后,设置 currentTime 即可。
native播放器
|
document.addEventListener('WV.Event.Page.Refresh', $.proxy(this.destory, this), false); document.addEventListener('WV.Event.Key.Back', $.proxy(this.destory, this), false); win.on('unload', $.proxy(this.destory, this)); win.on('beforeunload', $.proxy(this.destory, this));
|
- 定位
- Glue 播放器使用 dip 作为播放器的定位单位,rem 布局会对页面进行缩放,导致定位位置和视频大小错误。同时定位时参数有小数点会导致播放器错误。
|
/__ * 返回值需要是整数,否则会有异常 */ _getVedioPos(isDpr) { var el = this.el, offset = el.offset(), dpr = 1;
if (isDpr) { dpr = this._getDpr(); }
return { x: parseInt(offset.left / dpr), y: parseInt(offset.top / dpr), w: parseInt(el.width() / dpr), h: parseInt(el.height() / dpr) }; }
|
- 视频源地址:Glue 播放器不支持以 // 开始的视频资源,例如 //video.xxx
- PlayBuddy 播放器不会随着页面滚动而滚动。
总结
- 如果业务中需要在手淘中播放视频,IOS 直接使用原生 video 即可。在 Android 中较为复杂,没有完全兼容的方案。建议使用 video,对于 Android 低版本建议使用native 播放器。随着uc内核接入,未来完全抛弃 native 方案也是可行的。
- 本文基于过去一年在手淘视频播放过程中遇到问题的小结,后续会整理视频监控和视频娱乐化相关内容。
附:手淘同学播放器兼容性表
品牌 |
机型 |
手淘版本 |
操作系统版本 |
播放器控件 |
视频列表切换 |
试看控制 |
观看进度同步 |
切换模式 |
问题 |
苹果 |
6 plus |
5.2.7 |
8.11 |
√ |
√ |
√ |
√ |
√ |
* |
苹果 |
6 |
5.2.7 |
8.11 |
√ |
√ |
√ |
√ |
√ |
* |
苹果 |
5s |
5.2.7 |
8.11 |
√ |
√ |
√ |
√ |
√ |
* |
苹果 |
5 |
5.2.7 |
8.11 |
√ |
√ |
√ |
√ |
√ |
* |
苹果 |
4s |
5.2.7 |
8.11 |
√ |
√ |
√ |
√ |
√ |
* |
苹果 |
4 |
* |
* |
√ |
√ |
√ |
√ |
√ |
* |
google |
nexus 5 |
* |
yun os 3 |
√ |
√ |
√ |
√ |
× |
* |
google |
nexus 5 |
* |
安卓 5 |
√ |
√ |
√ |
√ |
× |
* |
三星 |
N7100 |
4.9 |
* |
√ |
√ |
√ |
√ |
× |
* |
三星 |
NOTE4 |
4.9 |
* |
√ |
√ |
√ |
√ |
√ |
模式二点最大化crash |
三星 |
NOTE3 |
4.9 |
* |
√ |
√ |
√ |
√ |
× |
* |
三星 |
S4 |
5.2.7.3 |
* |
√ |
√ |
√ |
√ |
√ |
模式二,播放有问题 |
三星 |
I9300 |
4.3 |
* |
√ |
√ |
√ |
√ |
√ |
* |
三星 |
S3 |
5.2.8.2 |
* |
√ |
√ |
√ |
√ |
√ |
* |
三星 |
S5 |
5.2.7.3 |
* |
√ |
√ |
√ |
√ |
√ |
* |
魅族 |
MX2 |
* |
* |
√ |
* |
√ |
√ |
√ |
* |
魅族 |
MX4 PRO |
* |
* |
√ |
√ |
√ |
√ |
√ |
* |
魅族 |
魅蓝Note |
* |
* |
√ |
√ |
√ |
√ |
√ |
* |
魅族 |
MX3(安装不上) |
* |
* |
√ |
√ |
√ |
√ |
√ |
* |
华为 |
荣耀6 |
* |
* |
√ |
√ |
√ |
√ |
√ |
模式二可能播放不了 |
华为 |
mate7 |
* |
* |
√ |
√ |
√ |
√ |
√ |
模式二可能播放不了 |
华为 |
c8816 |
* |
* |
√ |
√ |
√ |
√ |
√ |
进度条拖动会跳 |
华为 |
荣耀3c |
* |
4.4.2 |
√ |
√ |
√ |
√ |
×一直展示loading的图片 |
模式二播放不了 |
华为 |
C8813 |
* |
4.1.1 |
√ |
√ |
√ |
√ |
√ |
高清视频不能播放 |
HTC |
MAX |
* |
* |
√ |
√ |
√ |
√ |
* |
* |
HTC |
816w |
* |
* |
√ |
√ |
√ |
√ |
√ |
* |
VIVO |
Find5 |
* |
4.1.1 |
√ |
√ |
√ |
√ |
√ |
* |
VIVO |
X3 |
* |
4.2.2 |
√ |
√ |
√ |
√ |
√ |
* |
小米 |
2S |
* |
4.3 |
√ |
√ |
√ |
√ |
* |
高清的播放不了 |
小米 |
3 |
* |
* |
* |
√ |
√ |
√ |
* |
* |
小米 |
4 |
* |
4.4.4 |
√ |
√ |
√ |
√ |
* |
* |
索尼 |
M512 |
* |
4.4.2 |
√ |
√ |
√ |
√ |
√ |
* |
索尼 |
xperia 36l |
* |
4.1.2 |
√ |
√ |
√ |
√ |
* |
* |
nubia |
nx403 |
* |
4.2.2 |
√ |
× |
√ |
√ |
* |
模式一,模式二播放均有问题 |
锤子 |
* |
* |
* |
√ |
√ |
√ |
√ |
* |
|
oppo |
x907 |
* |
4.0.3 |
很难点到 |
√ |
√ |
√ |
√ |
* |
nexus5 |
* |
* |
* |
√ |
√ |
√ |
√ |
√ |
第二种模式crash |
转载自:http://taobaofed.org/blog/2016/05/03/promise-anti-patterns/
作者:永霸