【发布时间】:2017-07-07 16:38:25
【问题描述】:
当用户观看视频时,我想进行 2 个 AJAX 调用。当用户观看完视频并且播放的时间等于或超过视频的持续时间时(因为用户也可以倒带)。 timePlayed>=duration && event.type=="ended"。我成功地拨打了这个电话。
我苦恼的是,我还想在视频观看率超过 80% 并且视频播放时间也超过 80% 时拨打电话,以防止用户只是快进。
为了让它工作,我必须修改我的 videoStartedPlaying() 方法,这是我在尝试设置间隔时遇到问题的地方。现在,通过设置间隔,它就像一个无限循环。
var video_data = document.getElementById("video");
var timeStarted = -1;
var timePlayed = 0;
var duration = 0;
// If video metadata is loaded get duration
if(video_data.readyState > 0)
getDuration.call(video_data);
//If metadata not loaded, use event to get it
else {
video_data.addEventListener('loadedmetadata', getDuration);
}
// remember time user started the video
function videoStartedPlaying() {
timeStarted = new Date().getTime()/1000;
setInterval(function(){
playedFor = new Date().getTime()/1000 - timeStarted;
checkpoint = playedFor / duration;
percentComplete = video_data.currentTime/video_data.duration;
// here I need help of how to best accomplish this
if (percentComplete >= 0.8 && checkpoint >= 0.8) {
// AJAX call here
}
}, 2000);
}
function videoStoppedPlaying(event) {
// Start time less then zero means stop event was fired vidout start event
if(timeStarted>0) {
var playedFor = new Date().getTime()/1000 - timeStarted;
timeStarted = -1;
// add the new amount of seconds played
timePlayed+=playedFor;
}
// Count as complete only if end of video was reached
if(timePlayed>=duration && event.type=="ended") {
// AJAX call here
}
}
function getDuration() {
duration = video_data.duration;
}
video_data.addEventListener("play", videoStartedPlaying);
video_data.addEventListener("playing", videoStartedPlaying);
video_data.addEventListener("ended", videoStoppedPlaying);
video_data.addEventListener("pause", videoStoppedPlaying);
我真的很感激这方面的任何帮助,因为我似乎束手无策。
非常感谢!
编辑: 感谢评论,我想出了这个:
const video = document.getElementById("video");
const set = new Set();
const percent = .8;
let toWatch;
function mediaWatched (curr) {
alert(`${curr}% of media watched`)
}
function handleMetadata(e) {
toWatch = Math.ceil(video.duration * percent);
console.log(toWatch, video.duration);
}
function handleTimeupdate (e) {
set.add(Math.ceil(video.currentTime));
let watched = Array.from(set).pop();
if (set.has(toWatch) && watched === toWatch) {
video.removeEventListener("timeupdate", handleTimeupdate);
console.log(watched);
mediaWatched(
Math.round(watched / Math.ceil(video.duration) * 100)
);
}
}
video.addEventListener("loadedmetadata", handleMetadata);
video.addEventListener("timeupdate", handleTimeupdate);
<video width="400" height="300" controls="true" poster="" id="video">
<source type="video/mp4" src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4" />
</video>
现在,例如,如果我快进到大约 50% 的长度,然后让它播放,它会在达到电影的 80% 时触发,但它不应该因为我快进到 50% 并且基本上只看了30%。
这有意义吗?我怎样才能实现这种行为?
【问题讨论】:
-
就我个人而言,我的做法会稍有不同...我会决定我想要的粒度(例如 1 秒)并创建一个数组,该数组包含与视频初始化时间一样多的插槽0. 我会在
timeupdated触发的视频上设置一个事件,并将数组中的插槽(基于currentTime)设置为“1”。当 80% 的空位被填满时(从一开始和/或全部),您的逻辑就可以确定他们接下来可以做什么...... -
哦,对于上面的代码,只需在进行 ajax 调用后设置一个标志,然后不要再调用它,或者删除侦听器,使其根本不会被调用
-
@Offbeatmammal 感谢您的评论!由于您向
timeupdated暗示,我想出了一个稍微不同的方法。现在,我现在遇到的问题是,如果我快进到大约 50% 的长度,然后让它播放,只要达到电影的 80%,它就会触发,但不应该因为我快进到 50%基本上只看了30%。那有意义吗?我怎样才能实现这种行为? -
这就是为什么我建议逐秒构建(或任何您需要的粒度)数组...这样,如果 80% 的条目设置为 1 而不是 0,那么您知道它们已经观看了 80% 的可用秒数...
-
这种方法的问题在于,如果用户一遍又一遍地重复播放相同的 5 秒,而不是观看整个 10 分钟,那么您的计数器仍然会增加。我的建议是将您的视频(通过数组)标记为多个块,并使用视频本身上的
timeupdated事件跟踪正在观看的块并标记它。然后,您可以使用计时器检查数组的状态是否 >80% 设置为 true,然后进行 ajax 调用
标签: javascript html video