最近做的一个项目,一个需要经常运营更新的页面使用了H5方案,页面中有几个自动播放的视频。记录一下遇到的一些问题:
浏览器限制无法自动播放视频/音频
当 video 标签设置了 autoplay :
<video id="videoPlayer" src="video_url" autoplay></video>
HTML或者打开页面后 JS 主动调用 video 的 play() 方法,视频无法自动播放,浏览器会报错:
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
Console LogGoogle 了一下说是浏览器保护策略,只有用户跟页面产生了交互行为比如点击、触摸后,视频/音频才可以播放。一个解决方案:
video.play()
.then(() => {
console.log(`autoplay well`);
})
.catch((e) => {
console.log(`autoplay fail, wait for first click`);
if (e instanceof DOMException) {
// play before user intersact
const autoPlayAfterAnyClick = () => {
video.play();
document.removeEventListener('click', autoPlayAfterAnyClick);
};
document.addEventListener('click', autoPlayAfterAnyClick);
throw e;
} else {
// or rethrow
throw e;
}
});
JavaScript也就是自动播放失败后,如果是 DOMException 浏览器限制问题,就监控一下用户交互事件,交互后第一时间再进行播放。
另外还有一种解决方案,使用 JS 模拟用户点击事件。我没做尝试,不展开。
在 Android/Flutter 下的解决方案
Android 的 WebView 提供了设置项,可以关闭上述提到的浏览器限制,或者更准确的描述为是否需要用户手势触发媒体播放:
webView.settings.mediaPlaybackRequiresUserGesture = false
KotlinFlutter 下的 webview_flutter 因为是对平台原生 WebView 的封装,所以本质也还是 Android 下的解决方案:
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted);
if (controller.platform is AndroidWebViewController) {
(controller.platform as AndroidWebViewController)
.setMediaPlaybackRequiresUserGesture(false);
}
Dart其他
文章开头提到因为页面需要经常运营更新,而 Flutter 又不支持热更新,所以才采用了 H5 方案(Vue 开发)。
本身 Flutter 是支持 Flutter Web 的,一开始的设想是客户端固定发包,Flutter Web 持续部署更新,客户端按需打开原生 Flutter 页面或者 Flutter Web 页面。做到一次开发,多平台部署,App 和 Web 混合路由展示,满足热更新的需求。
但是很无奈 Flutter Web 首次加载性能还不够好,首次加载 Flutter 引擎有相当长时间的白屏时间。参考了美团的 Flutter Web 优化方案,奈何技术水平有限还是做不到完美。在关注转化率的动态页面,暂且不敢使用 Flutter Web。
如果哪位同仁有 Flutter Web 优化方案,还望不吝赐教,共同交流进步。