音频、视频常用标签属性
airplay
远程播放功能
x-webkit-airplay="true"
airplay="allow"playsinline
webkit-playsinline="true"
视频播放时局域播放,不脱离文档流 。
这个属性需要嵌入网页的APP
比如WeChat中UI的webview
allowsInlineMediaPlayback = YES
webview.allowsInlineMediaPlayback = YES,才能生效。muted
添加了这个属性,就可以自动播放了
muted 属性是一个 boolean(布尔) 属性。
muted 属性设置或返回音频/视频是否应该被静音(关闭声音)。
问题
为了更好的提升用户体验,浏览器厂商不希望视频自动播放,所以audio标签上的autoplay属性,在浏览器限制下,可能不好使
主要的问题有:
- 渐进性、向下兼容优化
关于音频,可以在浏览器切换当前窗口显示与否时候,对音频进行处理,减少音乐对用户影响
try{
document.addEventListener("visibilitychange", function() {
var _visibilityState = document.visibilityState;
if (_visibilityState === 'visible') {
//backgroundMusic.play();
} else {
//backgroundMusic.pause();
}
});
}catch(err){ }
- 阻止IOS系统手机,全屏播放视频
playsinline这个属性是ios 10中设置可以让视频在小窗内播放,也就是不是全屏播放
//video标签挂载属性
webkit-playsinline="true"
playsinline="true"
- 关于video设置autoplay自动播放
-
PC浏览器不生效
需要用户手动,打开浏览器权限
建议的方案:
通过引导用户点击,调用JS脚本来使视频播放 ( 无需上面浏览器授权 ) 微信浏览器环境下,可以通过WeixinJSBridgeReady事件,来自动播放
IOS iphone plus7 可以
安卓 小米5 可以,按照以往经验,应该是安卓机不支持的
//--html
<video
id="banVideo"
x-webkit-airplay="true"
webkit-playsinline="true"
playsinline="true"
poster="videos/video2.jpg"
autoplay
preload="auto"
>
<source src="videos/video2.ogv" type="video/ogg"></source>
<source src="videos/video2.webm" type="video/webm"></source>
<source src="videos/video2.mp4" type="video/mp4"></source>
<p>Video is not visible, most likely your browser does not support HTML5 video</p>
</video>
//----js 代码
//浏览器对象
var browser = {
versions: function() {
var u = navigator.userAgent,
app = navigator.appVersion;
return {
trident: u.indexOf('Trident') > -1,
//IE内核
presto: u.indexOf('Presto') > -1,
//opera内核
webKit: u.indexOf('AppleWebKit') > -1,
//苹果、谷歌内核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,
//火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/),
//是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
//ios终端
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1,
//android终端
iPhone: u.indexOf('iPhone') > -1,
//是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1,
//是否iPad
Safari: u.indexOf('Safari') > -1,
//是否Safari
weixin: u.indexOf('MicroMessenger') > -1,
//是否微信 (2015-01-22新增)
qq: u.match(/\sQQ/i) == " qq" //是否QQ
};
} (),
language: (navigator.browserLanguage || navigator.language).toLowerCase()
}
//获取video元素
var oBanVideo = document.getElementById('banVideo');
//添加事件
function addHandler(element,type,handler) {
var isIE8 = !+"\v1";
if(element.addEventListener){
//检测是否为DOM2级方法
element.addEventListener(type,handler,{ passive: false });
}else if(element.attachEvent){
//检测是否为IE级方法
if(!isIE8){
//--IE9+
element.attachEvent("on" + type, function () {
//通过call或者apply解决IE下this指向问题
handler.apply(element);
});
}else{
//--IE8↓
element["on" + type] = handler;
};
}else {
//检测是否为DOM0级方法
element["on" + type] = handler;
}
};
//播放
function playFn(){
oBanVideo.play();
//调整声音 -- volume 属性设置或返回视频的当前音量,从 0.0 (静音) 到 1.0 (最大声)。
if(oBanVideo.volume){
oBanVideo.volume = 0.8;
}
}
//微信浏览器自动播放
if(browser.versions.iPhone && browser.versions.weixin){
//微信webview全局内嵌,WeixinJSBridgeReady方法
addHandler(document,"WeixinJSBridgeReady",playFn);
}
移动端一般浏览器播放情况
IOS safari 无法自动播放
安卓 小米机百度 无法自动播放,地球浏览器 可以自动播放PC端chrome浏览器中,如果打开浏览器授权,视频仍无法自动播放
方案:
为audio标签增加muted属性
效果:
视频可以自动播放了,但是声音处于静音状态,需要用户手动打开视频声音PC端chrome浏览器中,音频播放报错:
play() failed because the user didn't interact with the document first
说明打开页面,不被信任,存在授权问题。
方案:
查看网站信息 - 网站设置 - 隐私设置与安全性 - 声音 选择允许
- 关于音频文件预加载
通过canplaythrough事件来监听
//音频加载
function loadAudio(_src,_cbFn){
var oTag = new Audio();
oTag.oncanplaythrough = function(res){
_cbFn && _cbFn();
};
oTag.src = _src;
}
常用对象的属性与方法
- 查看当前浏览器是否支持音频
!!(document.createElement('video').canPlayType);
- 获取音频的总时长 (直接获取会为NaN,所以在onplay内修正)
oBanVideo.onplay = function(){
if(oBanVideo.duration){
console.log(oBanVideo.duration);
};
};
[补充]:
在微信浏览器内打开,即便是在onplay的情况下,也会由于网络情况,第一次出现NaN音频时长的情况。
解决方法,开启一个循环定时器,在真实获取时长后,关闭这个定时器。
- 获取音频播放进度( 当前播放时间/总时长 )
oBanVideo.ontimeupdate = function(){
console.log(Math.floor(oBanVideo.currentTime/oBanVideo.duration*100)+'%');
};
- 播放结束时候触发
oBanVideo.onended = function() {
console.log('播放完毕');
};
音频精灵
说明:
将多个散碎的音效合并为一个整体的音频文件,并通过调整播放帧移动至特定位置播放,并播放一次或(伪无限)循环播放
定义一个创建音频标签的函数
拥有:
- 创建音频标签能力
- 设置音频是否可以循环与否
- 将播放的音频,音量过渡至某个值
- 修改音频资源,并加载
- 在音频资源特定位置播放,一次或多次
- 暂停上述播放
- 播放一些预设的音频
function createAudioFn(tagId){
var _tempTag = null;
//是否支持音频标签
if(!!document.createElement('audio').play){
//是否已经创建了音效标签
if(!document.getElementById(tagId)){
_tempTag = document.createElement('audio');
_tempTag.id = tagId;
// _tempTag.muted = true;
document.getElementsByTagName('body')[0].appendChild(_tempTag);
};
//设置音频的循环
_tempTag.setItLoop = function(btn){
if(btn){
_tempTag.setAttribute('loop','loop');
}else{
_tempTag.removeAttribute('loop');
};
};
/*音量过渡到某值
* target - (0~100)
* cbFn - 回调
*/
var vStepNum = 2;
_tempTag.setVolumeTo = function(target,cbFn){
if(Math.abs((_tempTag.volume)*100-target)<vStepNum){
_tempTag.volume = target/100;
return false;
};
//需要过渡修改音量的话
if(_tempTag.volume*100>target){
vStepNum = -1*vStepNum;
}else{
vStepNum = Math.abs(vStepNum);
};
clearInterval(_tempTag.vTimer);
_tempTag.vTimer = setInterval(function(){
_tempTag.volume = (Math.floor(_tempTag.volume*100+vStepNum))/100;
if(Math.abs(_tempTag.volume*100-target)<Math.abs(vStepNum) || _tempTag.volume*100==target){
_tempTag.volume = target/100;
clearInterval(_tempTag.vTimer);
//回调
cbFn && cbFn();
}
},30);
};
//加载音频
_tempTag.loadSource = function(_src){
_tempTag.pause && _tempTag.pause();
//mp3音频资源
if(!_tempTag.aSource){
//创建标签
_tempTag.aSource = document.createElement('source');
_tempTag.aSource.src = _src;
_tempTag.aSource.type = "audio/mpeg";
_tempTag.appendChild(_tempTag.aSource);
}else{
//修改资源
_tempTag.aSource.src = _src;
};
//更改视频来源,并重载视频
_tempTag.load && _tempTag.load();
};
/*在某范围内重复播放
* startTime - 播放开始
* endTime - 播放结束
* loopTime - 循环次数
*/
_tempTag.playDuration = function(startTime,endTime,loopTime){
//初次播放
clearInterval(_tempTag.iTimer);
_tempTag.loopTime = 1;
_tempTag.currentTime = startTime;
_tempTag.play && _tempTag.play();
//播放结束与循环
_tempTag.iTimer = setInterval(function(){
//播放结束
if(_tempTag.currentTime>=endTime){
//是否需要循环
if(loopTime && loopTime>1){
//需要循环
if(_tempTag.loopTime>=loopTime){
clearInterval(_tempTag.iTimer);
_tempTag.pause && _tempTag.pause();
_tempTag.loopTime = 0;
return false;
};
//未循环结束
_tempTag.loopTime++;
_tempTag.currentTime = startTime;
_tempTag.play && _tempTag.play();
}else{
//不需要循环
clearInterval(_tempTag.iTimer);
_tempTag.pause && _tempTag.pause();
};
};
},30);
};
//停止播放
_tempTag.pauseDuration = function(){
clearInterval(_tempTag.iTimer);
_tempTag.pause && _tempTag.pause();
};
//播放(预定义区间)的声音
_tempTag.playDurationInTag = function(audioName){
var _tar = this;
switch(audioName){
//走在大厅
case 'walkInHall':
_tar.loadSource('../audio/foot_step.mp3');
_tar.playDuration(0.2,0.8,99);
break;
//走在金属
case 'walkInMetal':
_tar.loadSource('../audio/foot_step.mp3');
_tar.playDuration(4,5,99);
break;
//mp5开火
case 'mp5fire':
_tar.loadSource('../audio/weapon.mp3');
_tar.playDuration(0,0.8,99);
break;
}
};
};
return _tempTag;
};
使用:
//创建一个音频标签
window.effAudioObj1 = createAudioFn('effAudioObj1');
//播放某个预设的音频
effAudioObj1.playDurationInTag && effAudioObj1.playDurationInTag('mp5fire');
//预设播放结束
effAudioObj1.pauseDuration && effAudioObj1.pauseDuration();
未完待续...