Copy link to clipboard
Copied
Hello,
I have a project that has a size limit and it's mostly live video. It also will be HTML5 only. The problem we're having is how captivate and adobe media encoder are handling the video encoding.
When you insert a video into the course, it converts it to FLV if it is not already an FLV.
When you publish to HTML5, it converts it back to MP4 using Adobe Media Encoder.
The conversion back is almost tripling the file size into MP$4 because it's defaulting to a HQ conversion.
Is there a way to influence this FLV to MP4 conversion? Or is there a way to make Captivate keep my .mp4 file and not try a conversion?
Thanks in advance for any help.
Copy link to clipboard
Copied
I always put my video in an html file and insert as an html5 animation. It's very easy using the video tag. Full screen always works also. We even have coded it so that the CC runs through Captivates CC.
Copy link to clipboard
Copied
Do you have a tutorial showing this process. I am intrigued at how you would do this?
Copy link to clipboard
Copied
Do you mean the CC interjection? I guess I could write a blog about it. This is the file that I use. You name the file exactly the same name as the video. The html file reads it's own name and loads the video of the same name. Zip them together and insert as an HTML5 animation.
For example:
myVideo.html
myVideo.mp4
There are event listener for custom Pause/Play button so that the video pause and plays when these button are used in Captivate. It also shows the Next Button 2 seconds before the end of the video.
The closed caption is put into an array and the end times of each segment are stored in another array.
<!doctype html>
<html>
<head>
<meta charset= "utf-8">
<title>Video</title>
<script>
var wp = window.parent;
var myCC = [ ], endTimes = [ ], promptArray = [ ];
var myVid, myCCDiv;
/////////////////////////////////////// Add CC text to this array definition /////////////////////////////////////
myCC[ 0 ] = 'This is the CC text Caption 1.';
myCC[ 1 ] = 'This is the CC text Caption 2.';
myCC[ 2 ] = 'This is the CC text Caption 2.';
//////////////////////////////////////// Add end times to the endTimes array /////////////////////////////////////
endTimes = [ 20, 30, 40 ];
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DO NOT EDIT CODE BELOW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
myCCDiv = wp.document.getElementById( 'ccText' ).getElementsByTagName( 'p' )[ 0 ];
wp.document.getElementById( 'play_btn' ).addEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'pause_btn' ).addEventListener( 'click', function () { myVid.pause(); });
function startVideo()
{
var url = decodeURIComponent( window.location.pathname );
var filename = url.substring( url.lastIndexOf( '/' ) + 1 );
var n = filename.lastIndexOf( '.' );
var vid = filename.substr( 0, n ) + '.mp4';
myVid = document.getElementById( 'myVideo' );
myVid.src = '';
myVid.src = vid;
myVid.addEventListener( 'ended', videoEnd, false);
myVid.addEventListener( 'timeupdate', function ()
{
if ( myVid.currentTime.toFixed( 0 ) > myVid.duration.toFixed( 0 ) - 2 && wp.window.videoOnly == false )
{
wp.cp.show( 'next_btn' );
}
showCC( );
});
function showCC( )
{
if ( endTimes == 'undefined' || endTimes == null )
{
return false
}
else
{
for ( var i = 0; i < endTimes.length; i++ )
{
if ( myVid.currentTime.toFixed( 1 ) <= endTimes[ i ] )
{
myCCDiv.innerHTML = myCC[ i ];
break;
}
}
}
}
}
function videoEnd(e)
{
myCCDiv.innerHTML = myCC[ 0 ];
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
}
function clearAll()
{
myCCDiv.innerHTML = '';
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
wp.document.getElementById( 'play_btn' ).removeEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'pause_btn' ).removeEventListener( 'click', function () { myVid.pause(); });
myVid.src = '';
wp = null, myCC = null, endTimes = null, promptArray = null, myCCDiv = null;
}
</script>
</head>
<body style='margin:0 0 0 0' onload='startVideo();' onUnload='clearAll();'>
<video id='myVideo' src='' controls autoplay preload='none' width='854' height='480'></video>
</body>
</html>
Copy link to clipboard
Copied
We also attach an exit slide listener to stop IE from throwing an error when an iFrame that contains script is unloaded. We put this in an included JS file attached to the index.htm.
eventEmitterObj.addEventListener( 'CPAPI_SLIDEEXIT', function ( e )
{
var frame = document.getElementsByTagName( 'iframe' )[ 0 ];
if ( frame != null )
{
frame.src = 'about:blank';
}
});
Copy link to clipboard
Copied
Thank you. If you do write a blog about it would you include some images of the process. I am fairly new to this so greatly appreciate your willingness to help. I would love to see how you put the video into an html file (sorry am more a visual learner) through inserting it all into the project.
Copy link to clipboard
Copied
It really quite simple. The html file loads the video. The file is set up for a 854 x 480 video. Put them together in the same folder and zip them together.
Then in Captivate insert that zip file Media/HTML5 Animation
Turn of both scrolling and the border and set the height and width to 854 x 480
Copy link to clipboard
Copied
Thanks makes sense.
Copy link to clipboard
Copied
Thank you very much, I like your workaround but now I have two control bars in my HTML File so I turned off the controls in the html files by leaving out the "controls" tag in the video tag. Is there a possiblity to pause the html 5 video with the usual Captivate Control Bar?
Copy link to clipboard
Copied
If you insert it as multi-slide synchronized video, it can be controlled with Captivate's playbar.
Copy link to clipboard
Copied
I Inserted the video as a html5 animation with the workaround mentioned above. If I insert a multi-slide synchronized video captivate get's stuck when I export as html while trying to open media encoder to create the mp4 files.
Copy link to clipboard
Copied
You can have the video in my solution react to Captivates buttons. You need to add event listeners to the code posted above.
window.parent.document.getElementById( 'Play' ).addEventListener( 'click', playVideo );
window.parent.document.getElementById( 'Pause' ).addEventListener( 'click', pauseVideo );
function playVideo()
{
myVid.play();
}
function pauseVideo()
{
myVid.pause();
}
Copy link to clipboard
Copied
Unfortunately this didn't work. It didn't seem to do anything. My Java knowledge is pretty basic. I made some minor changes, I hope I didn't ruin it. I also tried to take out some of the CC Part, because I use the Captions in Captivate. My code looks like this:
<!doctype html>
<html>
<head>
<meta charset= "utf-8">
<title>WBT Intro</title>
<script>
var wp = window.parent;
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DO NOT EDIT CODE BELOW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
myCCDiv = wp.document.getElementById( 'ccText' ).getElementsByTagName( 'p' )[ 0 ];
wp.document.getElementById( 'play_btn' ).addEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'pause_btn' ).addEventListener( 'click', function () { myVid.pause(); });
function startVideo()
{
var url = decodeURIComponent( window.location.pathname );
var filename = url.substring( url.lastIndexOf( '/' ) + 1 );
var n = filename.lastIndexOf( '.' );
var vid = filename.substr( 0, n ) + '.mp4';
myVid = document.getElementById( 'WBTintroTest_05' );
myVid.src = '';
myVid.src = vid;
myVid.addEventListener( 'ended', videoEnd, false);
myVid.addEventListener( 'timeupdate', function ()
{
if ( myVid.currentTime.toFixed( 0 ) > myVid.duration.toFixed( 0 ) - 2 && wp.window.videoOnly == false )
{
wp.cp.show( 'next_btn' );
}
showCC( );
});
window.parent.document.getElementById( 'Play' ).addEventListener( 'click', playVideo );
window.parent.document.getElementById( 'Pause' ).addEventListener( 'click', pauseVideo );
function playVideo()
{
myVid.play();
}
function pauseVideo()
{
myVid.pause();
}
function showCC( )
{
if ( endTimes == 'undefined' || endTimes == null )
{
return false
}
else
{
for ( var i = 0; i < endTimes.length; i++ )
{
if ( myVid.currentTime.toFixed( 1 ) <= endTimes[ i ] )
{
myCCDiv.innerHTML = myCC[ i ];
break;
}
}
}
}
}
function videoEnd(e)
{
myCCDiv.innerHTML = myCC[ 0 ];
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
}
function clearAll()
{
myCCDiv.innerHTML = '';
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
wp.document.getElementById( 'play_btn' ).removeEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'pause_btn' ).removeEventListener( 'click', function () { myVid.pause(); });
myVid.src = '';
wp = null, myCC = null, endTimes = null, promptArray = null, myCCDiv = null;
}
</script>
</head>
<body style='margin:0 0 0 0' onload='startVideo();' onUnload='clearAll();'>
<video id='WBTintroTest_05' src='' autoplay preload='none' width='1024' height='576'></video>
</body>
</html>
Copy link to clipboard
Copied
Try this, remember that the html file and the video file need to be named exactly the same. Also, there is no way to close caption the video file unless you use my code or use a vtt file. You can't do it from Captivate because it doesn't know the video timing.
<!doctype html>
<html>
<head>
<meta charset= "utf-8">
<title>WBT Intro</title>
<script>
var wp = window.parent;
function startVideo()
{
var url = decodeURIComponent( window.location.pathname );
var filename = url.substring( url.lastIndexOf( '/' ) + 1 );
var n = filename.lastIndexOf( '.' );
var vid = filename.substr( 0, n ) + '.mp4';
myVid = document.getElementById( 'WBTintroTest_05' );
myVid.src = '';
myVid.src = vid;
myVid.addEventListener( 'ended', videoEnd, false);
}
wp.document.getElementById( 'Play' ).addEventListener( 'click', playVideo );
wp.document.getElementById( 'Pause' ).addEventListener( 'click', pauseVideo );
function playVideo()
{
myVid.play();
}
function pauseVideo()
{
myVid.pause();
}
function videoEnd(e)
{
myVid.removeEventListener( 'ended', videoEnd, false );
}
function clearAll()
{
myVid.removeEventListener( 'ended', videoEnd, false );
wp.document.getElementById( 'Play' ).removeEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'Pause' ).removeEventListener( 'click', function () { myVid.pause(); });
myVid.src = '';
wp = null, endTimes = null;
}
</script>
</head>
<body style='margin:0 0 0 0' onload='startVideo();' onUnload='clearAll();'>
<video id='WBTintroTest_05' src='' autoplay preload='none' width='1024' height='576'></video>
</body>
</html>
Copy link to clipboard
Copied
Hey TLC,
I love the concept of what you are doing here. I have tested it out and found a few issues.
The AddEventListeners for my custom Captivate buttons do not work. Perhaps it only works with the default playbar in Captivate? If so, how would you code that and add further EventListeners for Replay and Mute buttons?
The built-in player for the mp4 video is not accessible. Screen readers like JAWS and NVDA can tab through and activate the controls with the enter key, but there is no alt text for the video player buttons. I know there is code for this but have no idea how to do it or where to look.
The Closed Captioning code in your html file works perfectly but the slide has to match up exactly with the video file for the captions to be synchronized. Further, without the Eventlisteners working, there is no way for Captivate controls to pause the video and as a result the closed captions will not match if the user pauses the Captivate course or pauses the video. Do you by any chance happen to have an accessible version of the html file above that addresses these concerns?
<!doctype html>
<html>
<head>
<meta charset= "utf-8">
<title>Video</title>
<script>
var myCCDiv;
var wp = window.parent;
var myCC = [ ], endTimes = [ ], promptArray = [ ];
var myVid, myCCDiv;
/////////////////////////////////////// Add CC text to this array definition /////////////////////////////////////
myCC[ 0 ] = 'This is the CC text Caption 1.';
myCC[ 1 ] = 'This is the CC text Caption 2.';
myCC[ 2 ] = 'This is the CC text Caption 2.';
//////////////////////////////////////// Add end times to the endTimes array /////////////////////////////////////
endTimes = [ 20, 30, 40 ];
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DO NOT EDIT CODE BELOW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*
wp.document.getElementById( 'Play5_btn' ).addEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( 'Pause5_btn' ).addEventListener( 'click', function () { myVid.pause(); });
wp.document.getElementById('AudioOff5_btn').addEventListener('click', function() {myVid.muted(); });
wp.document.getElementById('AudioOn5_btn').addEventListener ('click', function() {myVid.unmuted(); });
*/
function playVideo()
{
myVid.play();
}
function pauseVideo()
{
myVid.pause();
}
function mutedVideo()
{
myVid.muted();
}
function unmutedVideo()
{
myVid.unmuted()
}
function startVideo()
{
myCCDiv = document.getElementById( 'ccText' );
var url = decodeURIComponent( window.location.pathname );
var filename = url.substring( url.lastIndexOf( '/' ) + 1 );
var n = filename.lastIndexOf( '.' );
var vid = filename.substr( 0, n ) + '.mp4';
myVid = document.getElementById( 'myVideo' );
myVid.src = '';
myVid.src = vid;
myVid.addEventListener( 'ended', videoEnd, false);
myVid.addEventListener( 'timeupdate', function ()
{
if ( myVid.currentTime.toFixed( 0 ) > myVid.duration.toFixed( 0 ) - 2 && wp.window.videoOnly == false )
{
wp.cp.show( 'Navigation_endofvideo_text' );
}
showCC( );
});
function showCC( )
{
if ( endTimes == 'undefined' || endTimes == null )
{
return false
}
else
{
for ( var i = 0; i < endTimes.length; i++ )
{
if ( myVid.currentTime.toFixed( 1 ) <= endTimes[ i ] )
{
myCCDiv.innerHTML = myCC[ i ];
break;
}
}
}
}
}
function videoEnd(e)
{
myCCDiv.innerHTML = myCC[ 0 ];
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
}
function clearAll()
{
myCCDiv = document.getElementById( 'ccText' );
myCCDiv.innerHTML = '';
wp.cpCmndCC = 0;
myVid.removeEventListener( 'ended', videoEnd, false );
/*wp.document.getElementById( "Play5_btn" ).removeEventListener( 'click', function () { myVid.play(); });
wp.document.getElementById( "Pause5_btn" ).removeEventListener( 'click', function () { myVid.pause(); });
wp.document.getElementById("AudioOff5_btn").removeEventListener('click', function() { myVid.muted(); });
wp.document.getElementById("AudioOn5_btn").removeEventListener('click', function() { myVid.unmuted(); });
*/
myVid.src = '';
wp = null, myCC = null, endTimes = null, promptArray = null, myCCDiv = null;
}
</script>
</head>
<body style='margin:0 0 0 0' onload='startVideo();' onUnload='clearAll();'>
<video id='myVideo' src='' controls autoplay preload='none' width='854' height='480'></video>
<p id = 'ccText' ></p>
</body>
</html>
Copy link to clipboard
Copied
Not sure about the accessibility. You'd need to Google html5 video native controls accessibility.
The pause and play buttons are custom buttons. You need to make sure they are named exactly the same in Captivate and the event listener.
Not sure what you mean about the CC timing. The CC is in the HTML file and injected into CP's CC box. The slide is just 3 seconds.
Copy link to clipboard
Copied
After a few attempts, I decided to just utilize the multi-slide synchronized video route right now until I can learn more HTML5 coding and JavaScript.
Copy link to clipboard
Copied
How would you handle a "multislide synchronized video" in "mp4" format?