音视频基础知识
简单理解
- 视频:连续的画面,特定格式编码,媒体流形式
- 音频:特定格式编码,媒体流形式
格式
- 视频:mp4、ogv、webm
- 音频:mp3、ogg、wav
video/audio 标签及常用属性
poster:视频播放前的封面,音频不存在该属性
preload="auto/meta/none":规定是否在页面加载后载入音频。如果设置了 autoplay 属性,则忽略该属性
autoplay:自动播放
controls:控制台
loop:循环播放
source:资源标签
206 Partial Content
加载本地文件,速度快
<video src="../echowo.mp4" width="640px" autoplay controls/>
您的浏览器不支持video标签。
</video>
加载网络视频,速度慢
<video src="http://video.echowo.com/mk.mp4" width="640px" autoplay controls/>
您的浏览器不支持video标签。
</video>
加载不存在的视频
<video src="http://www.echowo.com/notexist.mp4" autoplay controls/>
您的浏览器不支持video标签。
</video>
视频属性详解(兼容浏览器)
<video id="myVideo" controls width="640px" poster="../poster.jpg" />
<source src="http://video.echowo.com/mk.mp4" type="video/mp4" />
<source src="../echowo.mp4" type="video/mp4" />
<source src="http://www.echowo.com/notexist.mp4" type="video/mp4" />
<source src="http://video.echowo.com/mk.mp4" type="video/mp4" />
您的浏览器不支持video标签。
</video>
加载本地文件,速度快
<audio src="../echowo.wav" autoplay controls/>
您的浏览器不支持audio标签。
</audio>
加载不存在的音频
<audio src="http://www.echowo.com/notexist.mp3" autoplay controls/>
您的浏览器不支持audio标签。
</audio>
音频属性详解
<audio id="myAudio" controls />
<source src="../echowo.mp3" type="audio/mp3" />
<source src="../echowo.ogg" type="audio/ogg" />
<source src="../echowo.wav" type="audio/wav" />
您的浏览器不支持audio标签。
</audio>
video/audio API事件
- loadstart
开始加载视频的元数据
- durationchange
时长改变事件
- loadedmetadata *
元数据被加载事件(作初始化工作)
- progress *
获取媒介数据事件(请求视频数据)
- suspend
在媒介数据完全加载之前不论何种原因终止取回媒介数据事件(有数据需要延时下载的事件)
- loadeddata
媒介数据已加载事件
- canplay *
文件就绪可以开始播放
- canplaythrough *
能够无需因缓冲而停止即可播放至结尾事件
点击播放时触发以下事件
- play
开始播放事件
- playing
视频正在播放中
- timeupdate *
播放位置改变事件
暂停时触发
- pause
暂停事件
音量改变触发
- volumechange *
音量改变事件
视频进度条改变时触发
- seeking *
定位活动事件
- timeupdate
播放位置改变事件
- seeked
定位完成事件
- waiting *
已停止播放但打算继续播放时触发事件(网络播放时下一帧流数据还未到来时触发缓冲)
- ended *
已播放到最后事件
<video src="../echowo.mp4" width="640px" autoplay controls/>
您的浏览器不支持video标签。
</video>
<script type="text/javascript">
["loadstart", "progress", "suspend", "abort", "emptied",
"stalled", "loadedmetadata", "loadeddata", "canplaythrough",
"playing", "waiting", "seeking", "ended", "durationchange",
"timeupdate", "play", "seeked", "ratechange", "volumechange",
"pause", "error", "canplay"]
.forEach(function(item) {
v["on" + item] = function(e) {
console.log(item, e);
};
</script>
video/audio API属性
- currentSrc *
当前视频播放地址
- duration *
视频总时长
- currentTime *
当前播放的倍速
- volume *
当前音量
- buffered *
当前缓冲量
- paused *
是否暂停
- ended *
是否结束
- muted *
是否静音
- playbackRate *
当前播放的倍速
<video id="myVideo" width="640px" controls/>
<!--<source src="http://video.mukewang.com/mk.mp4" type="video/mp4" />-->
<source src="../imooc.mp4" type="video/mp4" />
<source src="../imooc.webm" type="video/webm" />
<source src="../imooc.ogv" type="video/ogv" />
您的浏览器不支持video标签。
</video>
<button id="play">播放</button>
<button id="pause">暂停</button>
<script>
<!-- 常用属性 -->
var v = document.getElementById('myVideo');
var playBtn = document.getElementById('play');
var pauseBtn = document.getElementById('pause');
v.onloadedmetadata = function() {
console.log("当前视频播放地址:" + v.currentSrc);
console.log("视频总时长:" + v.duration);
console.log("当前播放的倍速:" + v.playbackRate);
console.log("是否暂停:" + v.paused);
console.log("是否结束:" + v.ended);
console.log("是否静音:" + v.muted);
}
v.ontimeupdate = function() {
console.log("当前播放时间:" + v.currentTime);
console.log("当前缓冲量:" + v.buffered.end(0));
}
v.on = function() {
console.log("当前音量:" + v.volume);
}
playBtn.onclick = function() {
v.play();
}
pauseBtn.onclick = function() {
v.pause();
}
自定义视频播放器
图标可以去 www.iconfont.cn 那边下载一整套阿里的图标
<link href="css/style.css" rel="stylesheet" />
<script src="js/jquery.min.js"></script>
<div class="vContainer">
<video id="myVideo">
<source src="../echoswo.mp4" type="video/mp4">
<source src="../echoswo.ogv" type="video/ogv">
<source src="../echoswo.webm" type="video/webm">
</video>
<div class="caption">自定义视频播放器</div>
<div class="control">
</div>
</div>
<div class="vContainer">
<!-- 视频元素 -->
<video id="myVideo" preload="metadata"/>
<source src="../echoswo.mp4" type="video/mp4" />
<source src="../echoswo.webm" type="video/webm" />
<source src="../echoswo.ogv" type="video/ogv" />
您浏览器不支持视频播放,请更换浏览器
</video>
<!-- 标题 -->
<div class="caption">自定义视频播放器</div>
<!-- 控制区 -->
<div class="control">
<!-- 控制区 上面区域 进度条和时间 -->
<div class="top">
<div class="progress">
<span class="timeBar"></span>
</div>
<div class="time">
<span id="currentTime">00:00</span>
<span>/</span>
<span id="duration">00:00</span>
</div>
</div>
<!-- 控制区 下面区域 按钮 -->
<div class="bottom">
<div class="button play" id="playBtn"></div>
<div class="button stop" id="stopBtn"></div>
<div class="button text selected" id="speed1Btn">x1</div>
<div class="button text" id="speed3Btn">x3</div>
<div class="volume">
<span class="volumeBar"></span>
</div>
<div class="button sound" id="soundBtn"></div>
</div>
</div>
<!-- loading -->
<div class="loading"></div>
</div>
<script src="js/script.js"></script>
- style.css
body {
margin: 0px;
padding: 0px;
}
/* 视频容器 */
.vContainer {
width: 640px;
height: 360px;
margin: 30px auto;
position: relative;
overflow: hidden;
background-color: #DEDEDE;
}
/* 标题 */
.caption {
position: absolute;
top: 0;
left: 0;
width: 100%;
padding: 10px;
font-size: 20px;
font-weight: bold;
color: #CCCCCC;
background-color: #1F1F1F;
z-index: 1;
}
/* 控制区域 */
.control {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
color: #CCCCCC;
background-color: #1F1F1F;
z-index: 1;
}
/* 控制区 上部分 */
.control .top {
height: 11px;
border-bottom: 1px solid #404040;
padding: 1px 5px;
background: #1F1F1F;
}
/* 控制区 上部分 进度条 */
.control .top .progress {
width: 85%;
height: 10px;
position: relative;
float: left;
cursor: pointer;
background: #404040;
border-radius: 5px;
}
.control .top .progress .timeBar {
height: 100%;
position: absolute;
top: 0;
left: 0;
display: block;
border-radius: 5px;
}
/* 控制区 上部分 进度条 时间条 */
.control .top .progress .timeBar {
z-index: 3;
width: 0px;
background: #F9D43A;
}
/* 控制区 上部分 时间 */
.control .top .time {
width: 15%;
float: right;
text-align: center;
font-size: 0px;
line-height: 12px;
}
.control .top .time span {
font-size: 11px;
}
/* 控制区 下部分 */
.control .bottom {
clear: both;
background: #1F1F1F;
}
/* 控制区 统一处理button样式 */
.control .button {
float: left;
width: 32px;
height: 32px;
padding: 0 5px;
cursor: pointer;
}
/* 控制区 按钮图标 */
.control .bottom .play {
background: url("play.png") no-repeat 7px 2px;
}
.control .bottom .pause {
background: url("pause.png") no-repeat 7px 2px;
}
.control .bottom .stop {
background: url("stop.png") no-repeat 7px 2px;
}
.control .bottom .sound {
background: url("sound.png") no-repeat 7px 2px;
}
.control .bottom .mute {
background: url("mute.png") no-repeat 7px 2px;
}
.control .bottom .text {
font-size: 16px;
font-weight: bold;
line-height: 32px;
text-align: center;
color: #777777;
}
.control .bottom .selected {
color: #FFFFFF;
}
.control .bottom .sound,
.control .bottom .mute {
float: right;
}
/* 控制区 声音条 */
.control .bottom .volume {
position: relative;
cursor: pointer;
float: right;
width: 70px;
height: 10px;
margin-top: 10px;
margin-right: 10px;
background-color: #404040;
}
.control .bottom .volumeBar {
display: block;
width: 0px;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
background-color: #EEEEEE;
z-index: 2;
}
/* loading */
.loading {
position: absolute;
width: 54px;
height: 55px;
left: 50%;
top: 50%;
margin-left: -27px;
margin-top: -27px;
z-index: 1;
background: url("../image/loading.gif") no-repeat 0px 0px;
}
- script.js
(function($) {
// 获取video元素
var video = $('#myVideo');
console.log(video);
console.log(video[0]);
var timeFormat = function(seconds) {
var minite = Math.floor(seconds / 60);
if(minite < 10) {
minite = "0" + minite;
}
var second = Math.floor(seconds % 60);
if(second < 10) {
second = "0" + second;
}
return minite + ":" + second;
};
// 标题和控制板显示/隐藏
var showTitleAndControl = function(shouldShow) {
if(shouldShow) {
$('.control').stop().animate({'bottom':0}, 500);
$('.caption').stop().animate({'top':0}, 500);
} else {
$('.control').stop().animate({'bottom':-50}, 500);
$('.caption').stop().animate({'top':-50}, 500);
}
}
// 播放和暂停切换
var playAndPause = function() {
if(video[0].paused || video[0].ended) {
$('#playBtn').removeClass('play').addClass('pause');
video[0].play();
}
else {
$('#playBtn').removeClass('pause').addClass('play');
video[0].pause();
}
}
// 结束视频
var stopVideo = function() {
video[0].pause();
updateProgress($('.progress').offset().left);
$('#playBtn').removeClass("pause").addClass("play");
}
// 调整播放速度
var playSpeed = function(speed) {
if(speed == 1) {
$('#speed1Btn').addClass("selected");
$('#speed3Btn').removeClass("selected");
} else if(speed == 3) {
$('#speed1Btn').removeClass("selected");
$('#speed3Btn').addClass("selected");
}
video[0].playbackRate = speed;
}
// 声音和静音切换
var soundAndMute = function() {
if(video[0].muted) {
video[0].muted = false;
$('#soundBtn').removeClass("mute").addClass("sound");
$('.volumeBar').css('width', video[0].volume * 100 + '%');
} else {
video[0].muted = true;
$('#soundBtn').removeClass("sound").addClass("mute");
$('.volumeBar').css('width', 0);
}
};
// 进度拖拽处理
var enableProgressDrag = function() {
var progressDrag = false;
$('.progress').on('mousedown', function(e) {
progressDrag = true;
updateProgress(e.pageX);
});
$(document).on('mouseup', function(e) {
if(progressDrag) {
progressDrag = false;
updateProgress(e.pageX);
}
});
$(document).on('mousemove', function(e) {
if(progressDrag) {
updateProgress(e.pageX);
}
});
};
// 更新进度
var updateProgress = function(x) {
var progress = $('.progress');
var position = x - progress.offset().left;
var percentage = 100 * position / progress.width();
if(percentage > 100) {
percentage = 100;
}
if(percentage < 0) {
percentage = 0;
}
$('.timeBar').css('width', percentage+'%');
video[0].currentTime = video[0].duration * percentage / 100;
};
// 声音拖拽处理
var enableSoundDrag = function() {
var volumeDrag = false;
$('.volume').on('mousedown', function(e) {
volumeDrag = true;
updateVolume(e.pageX);
video[0].muted = false;
$('#soundBtn').removeClass("mute").addClass("sound");
});
$(document).on('mouseup', function(e) {
if(volumeDrag) {
volumeDrag = false;
updateVolume(e.pageX);
}
});
$(document).on('mousemove', function(e) {
if(volumeDrag) {
updateVolume(e.pageX);
}
});
};
// 更新声音
var updateVolume = function(x, vol) {
var volume = $('.volume');
var percentage;
// 如果设置了vol参数,则直接使用vol
if(vol) {
percentage = vol * 100;
} else {
var position = x - volume.offset().left;
percentage = 100 * position / volume.width();
}
if(percentage > 100) {
percentage = 100;
}
if(percentage < 0) {
percentage = 0;
}
$('.volumeBar').css('width', percentage + '%');
video[0].volume = percentage / 100;
};
// 获取元数据,初始化视频数据
video.on("loadedmetadata", function() {
video.width($('.vContainer').width());
video.height($('.vContainer').height());
showTitleAndControl(false);
$('#currentTime').text(timeFormat(0));
$('#duration').text(timeFormat(video[0].duration));
// 鼠标进入视频区域时,显示标题和控制板
// 鼠标离开视频区域时,隐藏标题和控制板
$('.vContainer').hover(function() {
showTitleAndControl(true);
}, function() {
showTitleAndControl(false);
})
// 播放按钮事件绑定
$('#playBtn').on('click', playAndPause);
// 结束按钮事件绑定
$('#stopBtn').on('click', stopVideo);
// 1倍速度按钮事件绑定
$('#speed1Btn').on('click', function() {
playSpeed(1);
});
// 3倍速度按钮事件绑定
$('#speed3Btn').on('click', function() {
playSpeed(3);
});
// 声音按钮事件绑定
$('#soundBtn').on('click', soundAndMute);
// 进度条拖拽事件绑定
enableProgressDrag();
// 声音条拖拽事件绑定
enableSoundDrag();
// 初始化声音
updateVolume(0, 0.7);
});
var loadingTimer = null;
// 每一次播放位置发生改变
video.on('timeupdate', function() {
var currentTime = video[0].currentTime;
var duration = video[0].duration;
var percent = 100 * currentTime / duration;
$('.timeBar').css('width', percent + '%');
$('#currentTime').text(timeFormat(currentTime));
$('.loading').fadeOut(100);
clearTimeout(loadingTimer);
loadingTimer = setTimeout(function() {
if(!video[0].paused && !video[0].ended) {
$('.loading').fadeIn(100);
}
}, 500);
});
// 视频播放结束的时候
video.on('ended', function() {
updateProgress($('.progress').offset().left);
$('#playBtn').removeClass("pause").addClass("play");
});
// 可以播放视频的时候
video.on('canplay', function() {
$('.loading').fadeOut(100);
});
})(jQuery);