/    Sign up×
Community /Pin to ProfileBookmark

[RESOLVED] Accessing Video Clip Time Mark During Play for Slideshow

Can scripting be used to access the time mark during play so that images can be rolled next to it to make a slideshow?

to post a comment
JavaScript

5 Comments(s)

Copy linkTweet thisAlerts:
@Sup3rkirbyNov 16.2012 — While this can be done, you won't have full cross-browser compatibility (for some older versions of IE and some mobile browsers).

Through the use of the HTML5 [B][FONT=Courier New]<video>[/FONT][/B] tag you can play the video on your page and access its time mark location through javascript.
[code=html]
<video id="vidElem" width="640" height="480">
<source src="movie.webm" type="video/webm" />
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>
[/code]

<i>
</i>var $video = document.getElementById('vidElem');
$video.addEventListener("canplay", _InitSync, false);

function _InitSync() {
$video.addEventListener("timeupdate", _SyncSlides, false);
}
function _SyncSlides() {
$curTime = $video.currentTime;
}


To be honest I haven't tested this code personally, but all of it should be valid. In the end you will have a variable with the current time mark of the video that will be updated as the video plays. Also I'm not even sure the '[B][FONT=Courier New][COLOR="#0000CD"]_InitSync()[/COLOR][/FONT][/B]' function was a necessary step but I added it more or less to be safe. Basically this will wait for the video element to be ready and then once it is, it will add an event that fires every time the video changes it time marker. In this final function you would simply add some code that would change your slides based on the value of [B][FONT=Courier New][COLOR="#0000CD"]$curTime[/COLOR][/FONT][/B].

Let me know if this resolves your issue or not.
Copy linkTweet thisAlerts:
@rnd_meNov 17.2012 — that's going to add a new watcher every time the video loads, when it only needs to happen once.

not sure if it will break the simple demo, but it's something to watch for.
Copy linkTweet thisAlerts:
@Sup3rkirbyNov 17.2012 — The[FONT=Courier New] _InitSync()[/FONT] does really only need to happen once and that's why I said it probably wasn't really even necessary. There are certainly better ways to set that up. You would just need to make sure it sets the timeupdate event watcher after the video is ready and loaded. The timeupdate event part is fine though; it's typically used for displaying the video time in a custom interface/custom controls and seems to fit well for this situation.
Copy linkTweet thisAlerts:
@senisevenauthorNov 17.2012 — Let me know if this resolves your issue or not.[/QUOTE]

Okay, this code seems to be working, although I will be doing more optimizing to get the right features.

After reading about the media object (Audio, Video elements) interface at MSDN and elsewhere to learn

more about object properties, methods, and the events affecting them (thanks to your guidance),

I have slightly modified your functions. The modifications basically use anonymous functions to define

the handlers and pass on arguments into the event handlers themselves.

Global scope script variables are initialized in that scope, namely array of numbers (in seconds)

for the time marks at which I want an image to change in the slideshow document block (a P element,

in this case). Images are basically rotated in and out using DOM methods ( replaceChild() ).


The initialize() function is used after the body is loaded to intiailize the rest of the global variables

that are DOM document nodes. Images for the slideshow are also pre-loaded into an array. Many of

the numerical constants (e.g., "500px") worked for my presentation, and should be altered for another's

particular document styling/spacing.

This particular set up does not "go backwards" perhaps in case the user does a backward seek on the

playback of the control, but that is easy enough to code in.

The reason I making this slideshow is that it is a ballet show with many dancers in the scene.

I am pointing out a particular dancer (this is an "Arts Resume" and the web page link will be sent to

dance instructors) but snapshotting a video instance, putting a simple arrow in Photoshop to

point out the dancer, it allows the instructors to identify the dancer, whom they have never met.


[code=html]<head>
<!--
.
.
-->
<script type="text/javascript">
var slidesBlock, // DOM element containing slideshow images
timeMarks = [ 50, 70, 80, 170, 200, 250 ],
timeMarkIndex = 0,
currentTimeMark = timeMarks[timeMarkIndex],
preloadedImages = [];

function initialize() {
var i, img, index,
myVid = document.getElementById("ballet-vid"),
slidesBlock = document.getElementById("slideshow");

if (typeof myVid.addEventListener == "function")
myVid.addEventListener("canplay", function () {
initSync(myVid, slidesBlock); }, false);
else if (typeof myVid.attachEvent == "function")
myVid.attachEvent("oncanplay", function () {
initSync(myVid, slidesBlock); } );
// preload images
for (i = 0; i < timeMarks.length; i++) {
img = new Image();
img.alt = "still #" + (i + 1) + " of My Video";
index = "0";
if (i < 9)
index += i + 1;
else
index = i + 1
img.src = "StillsOfMyVideo-" + index + ".png";
img.style.width = "500px";
preloadedImages.push(img);
}
}

function initSync(vidClip, slideShowBlock) {
if (typeof vidClip.addEventListener == "function")
vidClip.addEventListener("timeupdate", function () {
syncSlides(vidClip, slideShowBlock); }, false);
else if (typeof vidClip.attachEvent == "function")
vidClip.attachEvent("ontimeupdate", function () {
syncSlides(vidClip, slideShowBlock); } );
}

function syncSlides(vidClip, slideShowBlock) {
if (vidClip.currentTime > currentTimeMark) {
slideShowBlock.replaceChild(preloadedImages[timeMarkIndex++], slideShowBlock.firstChild);
currentTimeMark = timeMarks[timeMarkIndex];
}
}

</script>
</head>
<body onload="initialize();">

<p style-"margin:0;">
<video controls preload id="ballet-vid" poster="poster.png"
style="float:left;margin:0 1.5em 0.5em -10%;border:1px solid lime;">
style="border:1px solid lime;padding:0;margin:0;">
<source src="myvid.mpg" type="video/mpeg">
<source src="myvid.mp4" type="video/mp4">
<source src="myvid.webm" type="video/webm">
<object data="myvid.mpg" type="video/mpeg" width="750" height="600">
<embed src="myvid.mpg" type="video/mpeg" width="750" height="600">
</object>
</video>

<p id="slideshow"><img src="poster.png" alt="initial image of slideshow">
</body>
[/code]
Copy linkTweet thisAlerts:
@senisevenauthorNov 18.2012 — I am marking this resolved since the solution offered by [B]Sup3rkirby[/B] discusses the [B]timeupdate[/B] event, and that is the essential answer to the problem.

I have significantly modified Sup3kirby's original code however.

For one thing, I have eliminated the [B]canplay[/B] event handler as the intermediate invoking the [B]timeupdate [/B]event. It is not really necessary. Whenever the canplay handler is called, it would continually attempt code to add the timeupdate event handler, and that is not necessary it seems. I found that removing this intermediate code (the canplay handler) has the same wanted effect.

As to my timeupdate handler, it is responsible for a number of actions in my slideshow program:

[LIST]
  • [*] It rotates images (as objects) in and out of a DOM block (div or p) element as the first (and only) child of the element, based on the time value continually updated by the timeupdate handler

  • [*] It also "rotates" text to change the caption: in my particular strategy, I have a number of div elements all of whose display is set to "none" during document initialization. As a time mark is reached, a display is set to "" (empty string), as good as displaying the element by its default styling.

  • [*] For a couple of elements, the text is small enough that I do a replaceChild() methods on text nodes, which are created in the handler

  • [*] I have created a [B]seeked[/B] handler as well: what if the user changes the playback position control to an earlier or later time? In that case the appropriate slide and explanatory text must be updated. It basically runs a for-loop to look at an array of times (integer values in seconds) to find the correct array index position, and uses that to put up the photos and text.

  • [/LIST]


    Debugging an event handler in general can be a pain. And debugging one where the object generating events is an audio or video playback has proven difficult still:

    For example, I have set a breakpoint inside the [B]timeupdate [/B]and [B]seeked [/B] handler code because I want to check problems with code logic.

    The [B][U]CONTINUING PROBLEM[/U][/B] is that while the breakpoint is reached, the media object (video) continues playback. I have put a videoObj.pause() just inside the two event handlers at the start, and a video.play() as the last statement in those handlers. But as the debugger reaches the breakpoint in the timeupdate handler, just after executing the videoObj.pause() method, the video playback has not paused at all...it continues!

    I cannot imagine what event is taking over and forcing the media object to execute a .play() method.
    ×

    Success!

    Help @seniseven spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 BETA 5.24,
    whats_new: community page,
    up_next: more Davinci•003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinci•003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @AriseFacilitySolutions09,
    tipped: article
    amount: 1000 SATS,

    tipper: @Yussuf4331,
    tipped: article
    amount: 1000 SATS,

    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,
    )...