小强的HTML5移动开发之路(5)——制作一个漂亮的视频播放器

在前面几篇文章中介绍了HTML5的特点和需要掌握的基础知识,下面我们开始真正的体验一下HTML5的优势,我们开始制作一个漂亮的视频播放器吧微笑先别急,在开始制作之前先了解一下视频文件的基本知识。

一、视频的格式

目前比较主流和使用比较的的视频格式主要有:avi、rmvb、wmv、mpeg4、ogg、webm。这些视频都是由视频、音频、编码格式三部分组成的。在HTML5中,根据浏览器的不同,目前拥有多套不同的编码器:

H.264(个人不看好):这个编码器是苹果系统包括苹果手机中的编码器,拥有专利的视频编码器。在编码及传输过程中的任何部分都可能需要收取专利费。因此Safari(苹果的浏览器)和Intenet Explorer支持该编码器,但是在开源已经成为大势的当下,还在浏览器中收取专利费,个人实在是不看好啊。

Theora:这是一个不受专利限制的编码格式,并且对所有等级的编码、传输以及回放免费的视频编码器。Chrome、Firefox以及Opera支持该编码器。

VP8:该视频编码器与Theora相似,但是其拥有者是Google公司,Google公司已经开源,因此不需要专利费。Chrome、Firefox以及Opera支持该编码器。

AAC:音频编码器,与H.264相同,该音频编码器拥有专利限制,Safari、Chrome和Internet Explorer支持该音频编码器。

MP3:也是一个专利技术,Safari、Chrome和Internet Explorer支持该音频编码器。

PCM:存储由模拟数字转换器编码的完整数据,在音频CD上存储数据的一种格式。是以中国无损编码器,它的文件大小一般是AAC和MP3文件的几倍,Safari、Firefox和Internet Explorer支持该音频编码器。

Vorbis:文件扩展名为.ogg,有时候也被称为Ogg Vorbis,该音频编码器不受专利保护,因此版权免费。支持的浏览器包括Chrome、Firefox和Opera.

主流浏览器和设备支持的视频和音频

浏览器 容器 视频 音频
Apple ios MP4 H.264 ACC、MP3、PCM
Apple Safari MP4 H.264  
Google Android(pre v.3) -- -- --
Google Chrome MP4、OGG、WebM Theora、VP8 ACC、MP3、Vorbis
Microsoft Internet Explorer MP4 H.264 ACC、MP3
Mozilla Firefox OGG、WebM Theora、VP8 PCM、Vorbis
Opera OGG、WebM Theora、VP8 PCM、Vorbis

二、HTML5中的<vido>属性

在html5中可以使用<audio>或者<video>标签播放html5媒体,使用方式如下:

<video src="move.mp4"></video>

video标签中有很多属性,例如controls属性可以控制是否有控制台。

<video src="move.mp4" controls="controls">
	浏览器不支持HTML5的视频播放功能
</video>

从上面的视频格式中我们可以看到不同的浏览器支持不同的视频格式,这样我们可以采用<source>标签指定多种格式的视频,默认情况下浏览器会自动启动下载文件来确定其类型。

<video width="400" controls="controls">
	<source src="move.mp4"  type="video/mp4" />
	<source src="move.ogg"  type="video/ogg" />
</video>

三、制作视频播放器

index.html

<!DOCTYPE html>
<html>
<head>
<title>Demo 1 | Custom HTML5 Video Controls with jQuery</title>
<link rel="stylesheet" href="../vendorstyle.css" />
<link rel="stylesheet" href="style.css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script src="../vendorscript.js"></script>
<script src="video.js"></script>
<!--[if lt IE 9]>
<script>
$(document).ready(function() {
	$('.control').hide();
	$('.loading').fadeOut(500);
	$('.caption').fadeOut(500);
});
</script>
<![endif]-->
<link rel="shortcut icon" href="http://www.inwebson.com/wp-content/themes/inwebson/favicon.ico" />
</head>

<body>
<!-- Header -->
<header>
	<h1>Custom HTML5 Video Controls with jQuery</h1>
	<div id="backlinks">
		<a href="http://www.inwebson.com/custom-html5-video-controls-with-jquery-and-css/">BACK TO ARTICLE »</a>
		<a href="http://www.inwebson.com">Visit inWebson.com »</a>
	</div>
	<div class="clearfix"></div>
</header>

<!-- Content -->
<section id="wrapper">

	<!-- Title -->
	<h2>Demo 1</h2>
	<h3>Custom HTML5 Video Controls</h3>

<div class="videoContainer">
	
	<video id="myVideo" controls preload="auto" poster="poster.jpg" width="600" height="350" >
	  <source src="http://demo.inwebson.com/html5-video/iceage4.mp4" type="video/mp4" />
	  <source src="http://demo.inwebson.com/html5-video/iceage4.webm" type="video/webM" />
	  <source src="http://demo.inwebson.com/html5-video/iceage4.ogv" type="video/ogg" />
	  <p>Your browser does not support the video tag.</p>
	</video>
	<div class="caption">This is HTML5 video with custom controls</div>
	<div class="control">

		<div class="topControl">
			<div class="progress">
				<span class="bufferBar"></span>
				<span class="timeBar"></span>
			</div>
			<div class="time">
				<span class="current"></span> / 
				<span class="duration"></span> 
			</div>
		</div>
		
		<div class="btmControl">
			<div class="btnPlay btn" title="Play/Pause video"></div>
			<div class="btnStop btn" title="Stop video"></div>
			<div class="spdText btn">Speed: </div>
			<div class="btnx1 btn text selected" title="Normal speed">x1</div>
			<div class="btnx3 btn text" title="Fast forward x3">x3</div>
			<div class="btnFS btn" title="Switch to full screen"></div>
			<div class="btnLight lighton btn" title="Turn on/off light"></div>
			<div class="volume" title="Set volume">
				<span class="volumeBar"></span>
			</div>
			<div class="sound sound2 btn" title="Mute/Unmute sound"></div>
		</div>
		
	</div>
	<div class="loading"></div>
</div>

	<!-- Navigation -->
	<nav id="navigation">
		<ul>
			<li class="currentbtn"><a href="#" title="Demo 1">DEMO 1</a></li>
			<li><a href="../demo2/" title="Demo 2">DEMO 2</a></li>
		</ul>
		<div class="clearfix"></div>	
	</nav>
</section>

<!-- Footer -->
<footer>
	<span>© 2011 <a href="http://www.inwebson.com">inWebson.com</a>. Design by <a href="http://www.inwebson.com/contactus">Kenny Ooi</a>. Powered by <a href="http://www.inwebson.com/html5/">HTML5</a> and <a href="http://www.inwebson.com/jquery/">jQuery</a>.</span>
</footer>
</body>
</html>

style.css

/* video container */
.videoContainer{
	width:600px;
	height:350px;
	position:relative;
	overflow:hidden;
	background:#000;
	color:#ccc;
}

/* video caption css */
.caption{
	display:none;
	position:absolute;
	top:0;
	left:0;
	width:100%;
	padding:10px;
	color:#ccc;
	font-size:20px;
	font-weight:bold;
	box-sizing: border-box;
	-ms-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	background: #1F1F1F; /* fallback */
	background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
}

/*** VIDEO CONTROLS CSS ***/
/* control holder */
.control{
	background:#333;
	color:#ccc;
	position:absolute;
	bottom:0;
	left:0;
	width:100%;
	z-index:5;
	display:none;
}
/* control top part */
.topControl{
	height:11px;
	border-bottom:1px solid #404040;
	padding:1px 5px;
	background:#1F1F1F; /* fallback */
	background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
}
/* control bottom part */
.btmControl{
	clear:both;
	background: #1F1F1F; /* fallback */
	background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
	background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);
}
.control div.btn {
	float:left;
	width:34px;
	height:30px;
	padding:0 5px;
	border-right:1px solid #404040;
	cursor:pointer;
}
.control div.text{
	font-size:12px;
	font-weight:bold;
	line-height:30px;
	text-align:center;
	font-family:verdana;
	width:20px;
	border:none;
	color:#777;
}
.control div.btnPlay{
	background:url(control.png) no-repeat 0 0;
	border-left:1px solid #404040;
}
.control div.paused{
	background:url(control.png) no-repeat 0 -30px;
}
.control div.btnStop{
	background:url(control.png) no-repeat 0 -60px;
}
.control div.spdText{
	border:none;
	font-size:14px;
	line-height:30px;
	font-style:italic;
}
.control div.selected{
	font-size:15px;
	color:#ccc;
}
.control div.sound{
	background:url(control.png) no-repeat -88px -30px;
	border:none;
	float:right;
}
.control div.sound2{
	background:url(control.png) no-repeat -88px -60px !important;
}
.control div.muted{
	background:url(control.png) no-repeat -88px 0 !important;
}
.control div.btnFS{
	background:url(control.png) no-repeat -44px 0;
	float:right;
}
.control div.btnLight{
	background:url(control.png) no-repeat -44px -60px;
	border-left:1px solid #404040;
	float:right;
}
.control div.lighton{
	background:url(control.png) no-repeat -44px -30px !important;
}

/* PROGRESS BAR CSS */
/* Progress bar */
.progress {
	width:85%;
	height:10px;
	position:relative;
	float:left;
	cursor:pointer;
	background: #444; /* fallback */
	background:-moz-linear-gradient(top,#666,#333);
	background:-webkit-linear-gradient(top,#666,#333);
	background:-o-linear-gradient(top,#666,#333);
	box-shadow:0 2px 3px #333 inset;
	-moz-box-shadow:0 2px 3px #333 inset;
	-webkit-box-shadow:0 2px 3px #333 inset;
	border-radius:10px;
	-moz-border-radius:10px;
	-webkit-border-radius:10px;
}
.progress span {
	height:100%;
	position:absolute;
	top:0;
	left:0;
	display:block;
	border-radius:10px;
	-moz-border-radius:10px;
	-webkit-border-radius:10px;
}
.timeBar{
	z-index:10;
	width:0;
	background: #3FB7FC; /* fallback */
	background:-moz-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
	background:-webkit-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
	background:-o-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);
	box-shadow:0 0 1px #fff;
	-moz-box-shadow:0 0 1px #fff;
	-webkit-box-shadow:0 0 1px #fff;
}
.bufferBar{
	z-index:5;
	width:0;
	background: #777;
	background:-moz-linear-gradient(top,#999,#666);
	background:-webkit-linear-gradient(top,#999,#666);
	background:-o-linear-gradient(top,#999,#666);
	box-shadow:2px 0 5px #333;
	-moz-box-shadow:2px 0 5px #333;
	-webkit-box-shadow:2px 0 5px #333;
}
/* time and duration */
.time{
	width:15%;
	float:right;
	text-align:center;
	font-size:11px;
	line-height:12px;
}

/* VOLUME BAR CSS */
/* volume bar */
.volume{
	position:relative;
	cursor:pointer;
	width:70px;
	height:10px;
	float:right;
	margin-top:10px;
	margin-right:10px;
}
.volumeBar{
	display:block;
	height:100%;
	position:absolute;
	top:0;
	left:0;
	background-color:#eee;
	z-index:10;
}

/* OTHERS CSS */
/* video screen cover */
.loading, #init{
	position:absolute;
	top:0;
	left:0;
	width:100%;
	height:100%;
	background:url(loading.gif) no-repeat 50% 50%;
	z-index:2;
	display:none;
}
#init{
	background:url(bigplay.png) no-repeat 50% 50% !important;
	cursor:pointer;
}

video.js

$(document).ready(function(){
	//INITIALIZE
	var video = $('#myVideo');
	
	//remove default control when JS loaded
	video[0].removeAttribute("controls");
	$('.control').show().css({'bottom':-45});
	$('.loading').fadeIn(500);
	$('.caption').fadeIn(500);
 
	//before everything get started
	video.on('loadedmetadata', function() {
		$('.caption').animate({'top':-45},300);
			
		//set video properties
		$('.current').text(timeFormat(0));
		$('.duration').text(timeFormat(video[0].duration));
		updateVolume(0, 0.7);
			
		//start to get video buffering data 
		setTimeout(startBuffer, 150);
			
		//bind video events
		$('.videoContainer')
		.append('<div id="init"></div>')
		.hover(function() {
			$('.control').stop().animate({'bottom':0}, 500);
			$('.caption').stop().animate({'top':0}, 500);
		}, function() {
			if(!volumeDrag && !timeDrag){
				$('.control').stop().animate({'bottom':-45}, 500);
				$('.caption').stop().animate({'top':-45}, 500);
			}
		})
		.on('click', function() {
			$('#init').remove();
			$('.btnPlay').addClass('paused');
			$(this).unbind('click');
			video[0].play();
		});
		$('#init').fadeIn(200);
	});
	
	//display video buffering bar
	var startBuffer = function() {
		var currentBuffer = video[0].buffered.end(0);
		var maxduration = video[0].duration;
		var perc = 100 * currentBuffer / maxduration;
		$('.bufferBar').css('width',perc+'%');
			
		if(currentBuffer < maxduration) {
			setTimeout(startBuffer, 500);
		}
	};	
	
	//display current video play time
	video.on('timeupdate', function() {
		var currentPos = video[0].currentTime;
		var maxduration = video[0].duration;
		var perc = 100 * currentPos / maxduration;
		$('.timeBar').css('width',perc+'%');	
		$('.current').text(timeFormat(currentPos));	
	});
	
	//CONTROLS EVENTS
	//video screen and play button clicked
	video.on('click', function() { playpause(); } );
	$('.btnPlay').on('click', function() { playpause(); } );
	var playpause = function() {
		if(video[0].paused || video[0].ended) {
			$('.btnPlay').addClass('paused');
			video[0].play();
		}
		else {
			$('.btnPlay').removeClass('paused');
			video[0].pause();
		}
	};
	
	//speed text clicked
	$('.btnx1').on('click', function() { fastfowrd(this, 1); });
	$('.btnx3').on('click', function() { fastfowrd(this, 3); });
	var fastfowrd = function(obj, spd) {
		$('.text').removeClass('selected');
		$(obj).addClass('selected');
		video[0].playbackRate = spd;
		video[0].play();
	};
	
	//stop button clicked
	$('.btnStop').on('click', function() {
		$('.btnPlay').removeClass('paused');
		updatebar($('.progress').offset().left);
		video[0].pause();
	});
	
	//fullscreen button clicked
	$('.btnFS').on('click', function() {
		if($.isFunction(video[0].webkitEnterFullscreen)) {
			video[0].webkitEnterFullscreen();
		}	
		else if ($.isFunction(video[0].mozRequestFullScreen)) {
			video[0].mozRequestFullScreen();
		}
		else {
			alert('Your browsers doesn\'t support fullscreen');
		}
	});
	
	//light bulb button clicked
	$('.btnLight').click(function() {
		$(this).toggleClass('lighton');
		
		//if lightoff, create an overlay
		if(!$(this).hasClass('lighton')) {
			$('body').append('<div class="overlay"></div>');
			$('.overlay').css({
				'position':'absolute',
				'width':100+'%',
				'height':$(document).height(),
				'background':'#000',
				'opacity':0.9,
				'top':0,
				'left':0,
				'z-index':999
			});
			$('.videoContainer').css({
				'z-index':1000
			});
		}
		//if lighton, remove overlay
		else {
			$('.overlay').remove();
		}
	});
	
	//sound button clicked
	$('.sound').click(function() {
		video[0].muted = !video[0].muted;
		$(this).toggleClass('muted');
		if(video[0].muted) {
			$('.volumeBar').css('width',0);
		}
		else{
			$('.volumeBar').css('width', video[0].volume*100+'%');
		}
	});
	
	//VIDEO EVENTS
	//video canplay event
	video.on('canplay', function() {
		$('.loading').fadeOut(100);
	});
	
	//video canplaythrough event
	//solve Chrome cache issue
	var completeloaded = false;
	video.on('canplaythrough', function() {
		completeloaded = true;
	});
	
	//video ended event
	video.on('ended', function() {
		$('.btnPlay').removeClass('paused');
		video[0].pause();
	});

	//video seeking event
	video.on('seeking', function() {
		//if video fully loaded, ignore loading screen
		if(!completeloaded) { 
			$('.loading').fadeIn(200);
		}	
	});
	
	//video seeked event
	video.on('seeked', function() { });
	
	//video waiting for more data event
	video.on('waiting', function() {
		$('.loading').fadeIn(200);
	});
	
	//VIDEO PROGRESS BAR
	//when video timebar clicked
	var timeDrag = false;	/* check for drag event */
	$('.progress').on('mousedown', function(e) {
		timeDrag = true;
		updatebar(e.pageX);
	});
	$(document).on('mouseup', function(e) {
		if(timeDrag) {
			timeDrag = false;
			updatebar(e.pageX);
		}
	});
	$(document).on('mousemove', function(e) {
		if(timeDrag) {
			updatebar(e.pageX);
		}
	});
	var updatebar = function(x) {
		var progress = $('.progress');
		
		//calculate drag position
		//and update video currenttime
		//as well as progress bar
		var maxduration = video[0].duration;
		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 = maxduration * percentage / 100;
	};

	//VOLUME BAR
	//volume bar event
	var volumeDrag = false;
	$('.volume').on('mousedown', function(e) {
		volumeDrag = true;
		video[0].muted = false;
		$('.sound').removeClass('muted');
		updateVolume(e.pageX);
	});
	$(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;
		//if only volume have specificed
		//then direct update volume
		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;
		}
		
		//update volume bar and video volume
		$('.volumeBar').css('width',percentage+'%');	
		video[0].volume = percentage / 100;
		
		//change sound icon based on volume
		if(video[0].volume == 0){
			$('.sound').removeClass('sound2').addClass('muted');
		}
		else if(video[0].volume > 0.5){
			$('.sound').removeClass('muted').addClass('sound2');
		}
		else{
			$('.sound').removeClass('muted').removeClass('sound2');
		}
		
	};

	//Time format converter - 00:00
	var timeFormat = function(seconds){
		var m = Math.floor(seconds/60)<10 ? "0"+Math.floor(seconds/60) : Math.floor(seconds/60);
		var s = Math.floor(seconds-(m*60))<10 ? "0"+Math.floor(seconds-(m*60)) : Math.floor(seconds-(m*60));
		return m+":"+s;
	};
});

运行效果:



源代码下载地址:http://download.csdn.net/detail/lxq_xsyu/6787775




你可能感兴趣的:(html5,视频播放器,video标签)