80%的视频已经被观看,如何触发功能?
Posted
技术标签:
【中文标题】80%的视频已经被观看,如何触发功能?【英文标题】:How to trigger a function when 80% of the video has been reached and has been watched? 【发布时间】:2017-07-08 06:52:09 【问题描述】:简而言之,我正在努力弄清楚视频何时达到 80% 并且电影的 80% 已播放,以防止人们快进。
我目前设法触发一个方法,一旦电影结束并且播放量的总值等于或大于视频的持续时间。
var video = document.getElementById("video");
var timeStarted = -1;
var timePlayed = 0;
var duration = 0;
var checkpoint = 0;
var percentage = 0.8;
var percentComplete = 0;
// If video metadata is laoded get duration
if(video.readyState > 0)
getDuration.call(video);
//If metadata not loaded, use event to get it
else
video.addEventListener('loadedmetadata', getDuration);
// remember time user started the video
function videoStartedPlaying()
timeStarted = new Date().getTime()/1000;
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 ammount of seconds played
timePlayed+=playedFor;
document.getElementById("played").innerhtml = Math.round(timePlayed)+"";
// Count as complete only if end of video was reached
if(timePlayed>=duration && event.type=="ended")
document.getElementById("status").className="complete";
function videoIsPlaying(event)
if(timeStarted>0)
var playedFor = new Date().getTime()/1000 - timeStarted;
timeStarted = -1;
// add the new ammount of seconds played
timePlayed+=playedFor;
checkpoint = playedFor / duration;
percentComplete = video.currentTime / video.duration;
console.log('timePlayed is '+timePlayed);
console.log('percentComplete is '+percentComplete);
console.log('checkpoint is '+checkpoint);
console.log('duration is '+duration);
console.log('playedFor is '+playedFor);
if (percentComplete >= percentage && checkpoint >= percentage)
function getDuration()
duration = video.duration;
document.getElementById("duration").appendChild(new Text(Math.round(duration)+""));
console.log("Duration: ", duration);
video.addEventListener("play", videoStartedPlaying);
video.addEventListener("playing", videoStartedPlaying);
video.addEventListener("timeupdate", videoIsPlaying);
video.addEventListener("ended", videoStoppedPlaying);
video.addEventListener("pause", videoStoppedPlaying);
#status span.status
display: none;
font-weight: bold;
span.status.complete
color: green;
span.status.incomplete
color: red;
#status.complete span.status.complete
display: inline;
#status.incomplete span.status.incomplete
display: inline;
<video controls="true" poster="" id="video">
<source type="video/mp4" src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4"></source>
</video>
<div id="status" class="incomplete">
<span>Play status: </span>
<span class="status complete">COMPLETE</span>
<span class="status incomplete">INCOMPLETE</span>
<br />
</div>
<div>
<span id="played">0</span> seconds out of
<span id="duration"></span> seconds. (only updates when the video pauses)
</div>
<br><br>
我将不胜感激任何提示和正确方向的提示!
【问题讨论】:
使用timeupdate
事件,见HTML5 audio streaming: precisely measure latency?
@LGSon,您是否阅读了我的问题并没有意识到我在问一些完全不同的问题?我知道如何在不参考您的问题的情况下获取当前时间和持续时间。我正在寻求有关如何利用此类事件来跟踪总共观看了多少视频的帮助。例如,如果我将一个 30 秒的视频倒退到开头的一半,然后我完成了它,那么我的timePlayed
将反映 45 秒。 @guest271314 感谢您提供之前答案的链接。您能否详细说明一下在我的情况下如何使用 timeupdate?
您在哪里尝试检查是否已播放 80% 的视频?另请注意,如果用户在播放了一半的duration
后寻找0
,当前的实现仍会使用已播放的时间范围更新播放视频的总持续时间。您可以将timeupdate
事件中的当前时间存储到数组中,仅当范围大于存储在数组中的值时才更新播放的总时间。
我目前没有检查 80%。我只有var checkpoint
。我之前在function videoStoppedPlaying
中检查过,但后来意识到这没有好处,因为用户必须暂停视频(或必须结束)才能正常工作。那时我发现timeupdate
& 正如你所暗示的那样,这就是我需要使用的。我同意,但在实施方面,我似乎有心理障碍。 fiddle.jshell.net/x84dsuv5/3 我试着检查游戏的百分比和完成的百分比。检查点输出 NaN &playedFor undefined?嗯
“我目前没有检查 80%。” 嗯,那是问题,是吗?考虑发布一个问题,包括您尝试检查是否已播放 80% 的视频,如果链接的问题和答案不能解决当前问题。将尝试使用 timeupdate
或 progress
事件组合你的 jsfiddle 的一个分支。
【参考方案1】:
创建一个Array
和一个Set
对象。在loadedmetadata
事件设置值是.8
的.duration
Math.ceil(video.duration * percent)
的测量值,其中percent
是小于1
的小数。使用for
循环将Array
实例填充为从1
到N
的值,其中N
是.duration
+1
作为整数的百分之八十。在Set
实例上调用.add()
,并在timeupdate
事件中使用Math.ceil(video.currentTime)
作为参数。在timeupdate
事件中使用.every()
迭代Array
以检查Array
的Set
.has()
的每个元素,包括Math.ceil(video.duration * percent)
,这将是.duration
的百分之八十或更大;如果true
是从.every()
调用函数返回的。
const video = document.getElementById("video");
const res = new Set();
const arr = Array();
const percent = .8;
let toWatch = 0;
function mediaWatched (curr)
alert(`$curr% of media watched`)
function handleMetadata(e)
toWatch = Math.ceil(video.duration * percent);
for (let i = 1; i <= toWatch + 1; i++)
arr.push(i);
function handleTimeupdate (e)
res.add(Math.ceil(video.currentTime));
if (arr.every(function(n) return res.has(n)))
console.log(video.currentTime, video.duration);
video.removeEventListener("timeupdate", handleTimeupdate);
mediaWatched(Math.ceil((video.currentTime / video.duration) * 100));
video.addEventListener("loadedmetadata", handleMetadata);
video.addEventListener("timeupdate", handleTimeupdate);
<video 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>
【讨论】:
谢谢!这有效并让用户知道何时达到/播放了 80% 复选标记。但最让我纠结的是,我想确保 80% 的内容已经被观看,并且没有被转发到那个时候。这有意义吗? @ChrisPalmerBreuerSet
不允许重复条目。 Set.prototype.add()
仅在 timeupdate
事件中调用。请参阅更新后的帖子。添加了对 .keys()
的 Set
的 .length
的检查传递给 Array.from()
必须等于 toWatch
才能调用函数。这可以处理快进和反向搜索的情况。
完美,听起来和我要找的完全一样!不幸的是,mediaWatched
不再被调用。我不太确定我是否能找到问题,因为我对 javascript 还很陌生。
事件监听器被移除。 javascript
在 Answer 演示了在一次达到 80% 的视频时调用函数的方法。配置实现以满足特定要求。查看更新后的帖子。
太好了,这行得通。但是例如,如果我快进到大约 50% 的长度,然后让它播放,它会在达到电影的 80% 时触发,但它不应该因为我快进到 50% 并且基本上只看了 30% .那有意义吗?我需要一个playedFor
变量来计算总共播放了多少秒,这不等于currentTime
。例如,有一个 30 秒的视频,如果最初播放到 50%,playedFor
将等于 currentTime
,它将是 15,但如果我倒退到开头并观看到最后,playedFor
将是45【参考方案2】:
MDNs Cross-browser audio basics
时间更新
每次 currentTime 属性都会触发 timeupdate 事件 变化。在实践中,这每 250 毫秒发生一次。这个事件 可用于触发播放进度的显示。
myAudio.addEventListener("timeupdate", function() //update something related to playback progress );
【讨论】:
以上是关于80%的视频已经被观看,如何触发功能?的主要内容,如果未能解决你的问题,请参考以下文章