CodeSky 代码之空

随手记录自己的学习过程

jQuery HTML5播放器整合多段播放思路

2014-11-29 16:40分类: HTML评论: 1

最近由于工作需要在研究HTML5的播放器,HTML5其实自带的已经很全了,但是当我们需要把切割的视频整合播放的时候就遇到了麻烦,这里我想到了一个思路,正好发现网上也提到了很多这种思路:

首先多播放器窗口,除了一个以外display:none,一般需求中两个就足够了。然后监听是否结束(关于监听,稍后再发一篇讲讲Javascript的监听问题),监听本P播放结束之后将下一个的链接赋值到隐藏的那个,交替display,进度条当然需要重做,这里就需要统计总时长了。

关于HTML5 Video的事件可以参考:http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp

当然理论上很好想,实际在用的时候还是遇到了一些问题: 最近由于工作需要在研究HTML5的播放器,HTML5其实自带的已经很全了,但是当我们需要把切割的视频整合播放的时候就遇到了麻烦,这里我想到了一个思路,正好发现网上也提到了很多这种思路:

首先多播放器窗口,除了一个以外display:none,一般需求中两个就足够了。然后监听是否结束(关于监听,稍后再发一篇讲讲Javascript的监听问题),监听本P播放结束之后将下一个的链接赋值到隐藏的那个,交替display,进度条当然需要重做,这里就需要统计总时长了。

关于HTML5 Video的事件可以参考:http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp

当然理论上很好想,实际在用的时候还是遇到了一些问题:

首先我们来看一下,在加载过程中,依次会发生什么: 当音频/视频处于加载过程中时,会依次发生以下事件:

  • loadstart
  • durationchange
  • loadedmetadata
  • loadeddata
  • progress
  • canplay
  • canplaythrough

并且这些步骤全部都不是瞬时发生的,试网速而定,正因为如此所以当时我测试替换URL-获取时间-替换URL时才因此失败了。结果得到了一串 NULL,正确的做法是需要监听并执行以上操作。

如果你需要提前缓冲,需要监听timeupdate并且返回值,然后与总时长相减,根据条件判断并加载就行了^ ^

此外的一些,自取函数,之所以打上jQuery标签,是因为懒……: url使用飞驴获取,时效性很短需要测试请替换数组内容

1		var videos = new Array('http://k.youku.com/player/getFlvPath/sid/041718530647212048043_01/st/mp4/fileid/0300080400543216BE46C81468DEFEBA26D5AE-A82A-9A91-4AB7-2ABDE1FDEE6D?K=df6f241a64fb6c042412053b&hd=1&ymovie=1&myp=0&ts=363&ypp=2&ctype=12&ev=1&token=7211&oip=3663591661&ep=ciaVHUiFU80A4yfYij8bZyjqdHMMXP4J9h%2BFidJmALshTOu9mDijspm2PfdDEv8RBldwZZmAqdaTbzFhYYFLqxkQ1j%2BhOPrkj4Lk5a8ituR1Z29CB7jRwFSZQTHw', 'http://k.youku.com/player/getFlvPath/sid/041718530647212048043_02/st/mp4/fileid/0300080401543216BE46C81468DEFEBA26D5AE-A82A-9A91-4AB7-2ABDE1FDEE6D?K=0c03e81cdbd85fff261e08b8&hd=1&ymovie=1&myp=0&ts=404&ypp=2&ctype=12&ev=1&token=7211&oip=3663591661&ep=ciaVHUiFU80A4yfYij8bZyjqdHMMXP4J9h%2BFidJmALohTOu9mDijspm2PfdDEv8RBldwZZmAqdaTbzFhYYFLqxkQ1j%2BhOPrkj4Lk5a8ituR1Z29CB7jRwFSZQTHw', 'http://k.youku.com/player/getFlvPath/sid/041718530647212048043_03/st/mp4/fileid/0300080402543216BE46C81468DEFEBA26D5AE-A82A-9A91-4AB7-2ABDE1FDEE6D?K=fdc966b470118e75261e08b8&hd=1&ymovie=1&myp=0&ts=332&ypp=2&ctype=12&ev=1&token=7211&oip=3663591661&ep=ciaVHUiFU80A4yfYij8bZyjqdHMMXP4J9h%2BFidJmALkhTOu9mDijspm2PfdDEv8RBldwZZmAqdaTbzFhYYFLqxkQ1j%2BhOPrkj4Lk5a8ituR1Z29CB7jRwFSZQTHw');
2		var timeline = new Array(0);	// 记录各点时间
3		var nowVideoLocation = 0;	// 目前所在的位置
4		var playerNum = 0; // 目前使用的video标签位置
5		var str;		// 输出信息
6		var totalTime = 0;		// 视频总时长
7		var currentVideoTime = 0;
8		var i = 0;	// 初始化计数器
9		var targetTime = 0;	// 目标时间
10		var targetPlayer = 0;	// 记录目标播放器
11		var loadNextSource = false;	// 是否已经将下一个url写入src
12		$('document').ready(function() {
13			initTimeline();		// 运行初始化函数
14		// $('.video:eq(' + playerNum + ')').attr('src', videos[i]);
15		/*			setInterval(function(){
16						str = $('#video-meta').html();
17						$('#video-meta').html(str + '目前时间')
18					}, 100)
19		*/
20/*			$('.video')[playerNum].addEventListener('');
21*/
22			$('#btn-play').click(function() {
23				if ($('.video')[playerNum].paused)
24					$('.video')[playerNum].play();
25				else
26					$('.video')[playerNum].pause();
27			
28			});
29
30			$('#set-time').click(function() {
31				setToTime($('#time').val());
32			})
33		});
34
35
36			function initHandler() {
37				timeline[i] = $('.video') [1].duration;
38				totalTime += timeline[i];
39			  	if (i < videos.length - 1) {
40			  		$('.video')[1].src = videos[++i]
41				} else {
42					$('.video')[1].src = '';
43					$('.video')[1].removeEventListener('loadedmetadata', initHandler, true);
44				}
45			}
46
47			function currentTimeHandler() {
48				currentVideoTime = $('.video')[playerNum].currentTime;
49				if (timeline[nowVideoLocation] - currentVideoTime < 20 && !loadNextSource) {
50					loadNextVideo(nowVideoLocation + 1);
51					loadNextSource = true;
52				}
53				console.log(currentVideoTime);		// 定期返回监控时间
54			}
55
56			function initTimeline () {
57				$('.video')[1].preload = 'auto';
58				$('.video')[1].src = videos[i];
59				$('.video')[0].src = videos[i];
60				$('.video')[1].addEventListener('loadedmetadata', initHandler, true);
61				$('.video')[0].addEventListener('timeupdate', currentTimeHandler, true);
62				$('.video')[0].addEventListener('ended', switchNextVideo, true);
63			}
64
65			function loadNextVideo(nextLocation) {
66				var nextPlayer = Number(!playerNum);
67				if (nextLocation < videos.length) {
68					$('.video')[nextPlayer].preload = 'auto';
69					$('.video')[nextPlayer].src = videos[nextLocation];
70				}
71			}
72
73			function setToTime(time) {
74				var videoChapter;
75				var nextPlayer = Number(!playerNum);
76
77				if (time >= totalTime) {
78					videoChapter = videos.length - 1;
79					time = totalTime;
80				} else {
81					for (videoChapter = 0; videoChapter < videos.length - 1; videoChapter++) {
82						if (time - timeline[videoChapter] < 0) {
83							break;
84						} else {
85							console.log('videoTime:' + time);
86							time -= timeline[videoChapter];
87						}
88					}
89				}
90				console.log('videoChapter: '+videoChapter);
91				if (videoChapter == nowVideoLocation) {
92					$('.video')[playerNum].currentTime = time;
93				} else {
94					loadNextVideo(videoChapter);
95					console.log(time);
96					targetTime = time;
97					/*$('.video')[nextPlayer].currentTime = time;*/
98					targetPlayer = nextPlayer;
99					$('.video')[targetPlayer].addEventListener('durationchange', jumpToTime, true);
100					switchToVideo();
101					nowVideoLocation = videoChapter;
102					console.log('nowVideoLocation: '+nowVideoLocation);
103				}
104				
105			}
106
107			function jumpToTime() {
108				$('.video')[targetPlayer].currentTime = targetTime;
109				console.log('hello');
110				$('.video')[targetPlayer].removeEventListener('durationchange', jumpToTime, true);
111
112			}
113
114			function switchNextVideo() {
115				var nextPlayer = Number(!playerNum);
116				loadNextSource = false;
117				console.log('SwitchNow!');
118				if (nowVideoLocation < videos.length - 1) {
119					$('.video:eq(' + nextPlayer + ')').css('display', '');
120					$('.video:eq(' + playerNum + ')').css('display', 'none');
121
122					$('.video')[playerNum].pause();
123					$('.video')[playerNum].removeEventListener('timeupdate', currentTimeHandler, true);
124					$('.video')[playerNum].removeEventListener('ended', switchNextVideo, true);
125
126					$('.video')[playerNum].src = '';
127
128					$('.video')[nextPlayer].addEventListener('timeupdate', currentTimeHandler, true);
129					$('.video')[nextPlayer].addEventListener('ended', switchNextVideo, true);
130
131					$('.video')[nextPlayer].play();
132					nowVideoLocation++;
133					playerNum = nextPlayer;
134				} else {
135					$('.video')[playerNum].removeEventListener('ended', switchNextVideo, true);
136				}
137			}
138
139			function switchToVideo() {
140				var nextPlayer = Number(!playerNum);
141				console.log('SwitchNow!');
142				loadNextSource = false;
143				$('.video:eq(' + nextPlayer + ')').css('display', '');
144				$('.video:eq(' + playerNum + ')').css('display', 'none');
145
146				$('.video')[playerNum].pause();
147				$('.video')[playerNum].removeEventListener('timeupdate', currentTimeHandler, true);
148				$('.video')[playerNum].removeEventListener('ended', switchToVideo, true);
149
150				$('.video')[playerNum].src = '';
151
152				$('.video')[nextPlayer].addEventListener('timeupdate', currentTimeHandler, true);
153				$('.video')[nextPlayer].addEventListener('ended', switchToVideo, true);
154
155				$('.video')[nextPlayer].play();
156			}
157

后记:后来在这里看到类似思路,加载点略不同,测试了一下似乎在提前在网速不佳的情况下表现效果会so bad,还是这样就好了,进度条需要诸君利用setToTime函数自行重写,请自便。

评论 (1)

sanny2020年5月26日 22:26

有例子吗?