Here's one I made earlier.
This simple Player uses the new FLV Captioning Component in Flash CS3 (note: Flash CS3 is currently available as part of some of the new CS3 Suites. The standalone product will follow). It's a simple demo but you got to admit that it's pretty neat - consider also that the captions are read from an external file.
No sources this time (sorry) as this is part of a commercial project I'm working on. However it will be easy to recreate once you got Flash CS3.

#1 by Brad on 3/27/07 - 9:54 PM
#2 by Benjamin on 3/27/07 - 11:05 PM
#3 by Mike D on 3/28/07 - 12:35 AM
(firefox 2.003 flash 9.0.16)
#4 by Mike D on 3/28/07 - 12:45 AM
#5 by Brent on 3/30/07 - 10:07 PM
#6 by Clark on 5/6/07 - 9:18 PM
#7 by Stefan on 5/6/07 - 9:29 PM
#8 by Kevin on 5/9/07 - 9:48 PM
#9 by Stefan on 5/10/07 - 9:20 AM
#10 by Andrew Kirkpatrick on 5/17/07 - 8:54 PM
#11 by Clark on 5/18/07 - 5:51 AM
#12 by Andrew Kirkpatrick on 5/18/07 - 2:41 PM
#13 by subtitlehorse on 7/23/07 - 10:03 PM
subtitle-horse.org is an online subtitle creator tool for flv videos. you don`t need to have a software installed and you can
also transform different formats like srt to timedtext (e.g.)
#14 by Kat on 10/9/07 - 2:39 AM
#15 by Stefan on 10/9/07 - 9:07 AM
#16 by Andrew Kirkpatrick on 10/12/07 - 9:41 PM
#17 by John Lee on 7/10/08 - 10:35 PM
And the styling part in the xml file has no effect.
Can you please tell how you did that?
Thanks
#18 by Stefan Richter on 7/11/08 - 11:41 AM
I created my own custom movieclip to display the captions and set the background of that to semi transparent. Check the Flash docs for details on how to use Movieclips as a target for the caption display. You can make it look any way you want.
#19 by annettegeek on 9/12/08 - 11:13 PM
I'm not seeing anythhing like that for AS3.
#20 by Yesenia Chappell on 10/14/08 - 7:52 PM
http://kb.adobe.com/selfservice/viewContent.do?ext...
I'm trying to find the code to check when the CC button is clicked. Do you know this?
I created a backgound for the captions and want to make it visible/invisble everytime you click on the CC button.
Thanks,
#21 by ann b. on 10/21/08 - 3:07 AM
import fl.video.VideoEvent;
// listen for when the skin has loaded into the
// FLVPlayback component (myFLVPB). When that
// happens call the skinLoaded handler
myFLVPB.addEventListener(VideoEvent.SKIN_LOADED, skinLoaded);
// The skinLoaded event handler will set showCaptions
// to false after the FLVPlaybackCaptions component (myFLVCP)
// has associated itself with the CaptionButton in the skin function
skinLoaded(event:VideoEvent):void {
myFLVCP.showCaptions = false;
}
Can someone help please?
#22 by Carol on 11/8/08 - 6:40 PM
Thanks.
Carol
#23 by starofriches on 11/21/08 - 3:32 PM
thank you!
#24 by Yesenia Chappell on 11/21/08 - 4:18 PM
The xml file is here http://www.parature.com/videos/parature_implementa...
And part of the code I use is the following one:
import fl.video.FLVPlayback;
import fl.video.FLVPlaybackCaptioning;
import fl.video.MetadataEvent;
import fl.video.VideoEvent;
import fl.video.CaptionChangeEvent;
import flash.events.Event;
var vid_demo:FLVPlayback = new FLVPlayback();
var vid_caption:FLVPlaybackCaptioning = new FLVPlaybackCaptioning();
var myCaptionBgr:caption_bgr = new caption_bgr();
addChildAt(vid_demo, 0);
addChildAt(vid_caption, 1);
addChildAt(myCaptionBgr, 2);
myCaptionBgr.x = 0;
myCaptionBgr.y = 455;
myCaptionBgr.visible = false;
...other lines...
vid_caption.addEventListener(CaptionChangeEvent.CAPTION_CHANGE, caption_listener);
vid_caption.addEventListener(Event.COMPLETE, caption_complete);
vid_demo.addEventListener(MouseEvent.CLICK, caption_click);
function caption_listener (eventObject: CaptionChangeEvent):void
{
myCaptionBgr.visible = true;
//trace("caption change" );
}
function caption_complete (eventObject: Event):void
{
//trace("caption complete");
}
function caption_click (eventObject: MouseEvent):void
{
//trace(eventObject.target.name);
if ( eventObject.target.name == "instance185")
myCaptionBgr.visible = true; //CC ON
if ( eventObject.target.name == "instance172")
myCaptionBgr.visible = false; //CC OFF
}
stop();
If you send me your email, I can send you the FLA file and you'll see the whole code and frames. I don't have a problem sharing the source. If you know a way to optimize, I'm open to suggestions.
Yesi
#25 by Carol on 11/21/08 - 4:26 PM
Carol
#26 by starofriches on 11/21/08 - 5:53 PM
also, have you figured out carol's problem? captioning in a playlist? i'm still trying to find a solution to that.
suggestions appreciated!
many thanks.
#27 by Yesenia Chappell on 11/21/08 - 6:04 PM
Thanks for your comment. I just sent you the FLA and XML file. Please let me know if you have a problem opening it. It's a Flash CS3.
Sorry but I haven't worked with playlists and captions at the same time. Just in case, if you don't know there is a really good flash player that deals with everything (captions, skins, one final link, etc). It's here http://www.jeroenwijering.com/?item=JW_FLV_Media_P.... I used it a lot when I have an FLV video to include. I couldn't use it for the project I'm attaching because I needed an extra final flash slide with multiple call of actions, so I couldn't integrate it. Otherwise, I would use it. You can see samples and a wizard where you can see what you can do with the player http://www.jeroenwijering.com/?page=wizard
I have projects on my site using this player: http://www.parature.com/customers.aspx The red icon on the right, "Customer video clips - Watch now", use a playlist and the single "Video Clip" links next to the customer quotes (right side), play a single video.
Good luck!
Yesi
#28 by Carol on 11/21/08 - 9:38 PM
I can't believe there isn't someone out there who knows how to create closed captioning for a playlist AND who can write a step-by-step tutorial for newbies.
Yoo hoo... we're willing to pay good money for such a tutorial.
Any takers?
While I'm asking for things, does anyone know how to loop videos in an flv playlist that's controlled by XML? I'd like to add a Loop button that would continuously play all the videos in the playlist, without stopping unless the user closed down the player.
I'd also like to see a tutorial on how to create a user-generated playlist.
I've downloaded Jeroen Wijering's player and read tutorials, but it will be a while yet before they'll do closed captioning on their most recent playlist player. It's a good system, but sometimes they don't realize that a lot of their following doesn't have a lot of experience and we need more handholding.
Carol
#29 by Todd on 2/2/09 - 9:16 PM
I'm not sure if you have been able to solve this problem yet, but I created an flv playlist controlled by xml that can do exactly what you want. it will autoplay through all the nodes in the xml with a simple change.
As for the user input data to write the xml, I pulled in C# dev to handle that :-p.
view it here http://www.joycemeyer.org/ourministries/broadcast/...
#30 by Todd on 2/2/09 - 9:33 PM
var myVar:Number = 0;
// I am using a query as the controller below
if(root.loaderInfo.parameters.myVar > 0)
{
myVar = root.loaderInfo.parameters.myVar;
}
var flvControl:FLVPlayback = new FLVPlayback();
var caption_grp.captionControl:FLVPlaybackCaptioning = new FLVPlaybackCaptioning();
/* ... other code ... */
flvControl.addEventListener( VideoEvent.COMPLETE, nextMovie );
function nextMovie(event:Event):void
{
if (flvControl.playing == false)
{
myVar++;
if (myVar == videoList.length)
{
myVar = 0;
}
flvControl.source = (videoList[ myVar ]);
caption_grp.captionControl.source = vidCaption[ myVar ];
}
}
I hope this helps :-)
#31 by Todd on 2/2/09 - 9:45 PM
import fl.video.*;
import flash.display.*;
import flash.events.Event;
import flash.text.TextField;
var flvControl = vid_mc.myVid;
var videoList:Array = [];
var vidCover:Array = [];
var vidCaption:Array = [];
var xmlLocation:String = "";
var b:Number = 0;
var myVar:Number = 0;
// I am using the browser to query videos and to control other .swf files that relate to this player
if(root.loaderInfo.parameters.myVar > 0)
{
myVar = root.loaderInfo.parameters.myVar;
}
// load a variable xml file ***<item><xmlFile><url>YOUR_XML.xml</url></xmlFile></item>
var settingsXML:String = "settings.xml";
var loadSettings:URLLoader = new URLLoader();
var requestSettings:URLRequest = new URLRequest(settingsXML);
loadSettings.load(requestSettings);
loadSettings.addEventListener(Event.COMPLETE , settingsLoaded );
function settingsLoaded(event:Event):void
{
var theSettings:XML = new XML (loadSettings.data);
xmlLocation = theSettings.xmlFile.url;
// what to do with the requested xml file
var xmlURLLoader:URLLoader = new URLLoader();
var xmlURLRequest:URLRequest = new URLRequest(xmlLocation);
xmlURLLoader.load(xmlURLRequest);
xmlURLLoader.addEventListener(Event.COMPLETE , dataLoaded );
function dataLoaded(event:Event):void
{
var theXMLData:XML = new XML (xmlURLLoader.data);
var a:Number = theXMLData.videoData.video_path.length();
while (b < a)
{
//display videos in these date ranges
var startDate = new Date(Date.parse(theXMLData.videoData.videoStartDate[b]));
var endDate = new Date(Date.parse(theXMLData.videoData.videoEndDate[b]));
var today = new Date();
if(startDate <= today && today <= endDate)
{
// video location
videoList.push( theXMLData.videoData.video_path[b] );
// still image for video
vidCover.push( theXMLData.videoData.video_cover[b] );
// xml file location for video
vidCaption.push( theXMLData.videoData.video_caption[b] );
}
b++;
}
// set up flvControl
flvControl.autoPlay = false; // set to true if you want it to loop
flvControl.source = videoList[ myVar ];
flvControl.skin = "SkinUnderPlaySeekCaption.swf"; // use the skin of your choice
flvControl.skinBackgroundColor = 0x000000;
flvControl.skinBackgroundAlpha = 1;
flvControl.skinAutoHide = false;
//flvControl.skinScaleMaximum = 2.5; // I do not fully understand
flvControl.addEventListener(VideoEvent.SKIN_LOADED, skinLoaded);
// set up captionControl
with(caption_grp)
{
captionControl.flvPlayback = flvControl;
captionControl.source = vidCaption[ myVar ];
captionControl.autoLayout = false;
captionControl.addEventListener(CaptionChangeEvent.CAPTION_CHANGE, onCaptionChange);
}
function onCaptionChange(event:CaptionChangeEvent):void
{
var caption_sprite:* = event.target.captionTarget;
var flvControl:FLVPlayback = event.target.flvPlayback;
// move caption_sprite
caption_sprite.y = 180;
caption_sprite.x = 10;
}
function skinLoaded(event:VideoEvent)
{
caption_grp.captionControl.showCaptions = false;
}
// set up cover
var coverIMGPathVar:String = vidCover[ myVar ];
var CILdr:Loader = new Loader();
var CIURLReq:URLRequest = new URLRequest ( coverIMGPathVar );
CILdr.load( CIURLReq );
CILdr.contentLoaderInfo.addEventListener(Event.COMPLETE , CILoaded);
function CILoaded(event:Event):void
{
coverIMGbox.addChild( CILdr.content );
}
}
}
flvControl.stop();
flvControl.volume = 1;
coverVar.buttonMode = true;
coverVar.useHandCursor = true;
coverVar.addEventListener(MouseEvent.CLICK, playRemove);
function playRemove(event:MouseEvent):void
{
flvControl.play();
coverVar.visible = false;
coverIMGbox.visible = false;
// comment for testing
var gaTracker:String = "javascript: pageTracker._trackPageview(" + vidCover[myVar] + ");";
var trackGA:URLRequest = new URLRequest( gaTracker );
navigateToURL ( trackGA, "_self");
}
// gets rid of covers
flvControl.addEventListener( VideoEvent.PLAYING_STATE_ENTERED, playingMovie );
function playingMovie(event:Event):void
{
flvControl.play();
coverVar.visible = false;
coverIMGbox.visible = false;
}
// next movie events
flvControl.addEventListener( VideoEvent.COMPLETE, nextMovie );
function nextMovie(event:Event):void
{
if (flvControl.playing == false)
{
myVar++;
coverVar.visible = true;
coverIMGbox.visible = true;
if (myVar == videoList.length)
{
myVar = 0;
}
flvControl.source = (videoList[ myVar ]);
flvControl.seek(0);
caption_grp.captionControl.source = vidCaption[ myVar ];
}
}
// update time
this.addEventListener (Event.ENTER_FRAME, updateNP);
function updateNP(event:Event):void
{
// time code code...
var totalSeconds:Number = flvControl.playheadTime;
var totalSeconds2:Number = flvControl.totalTime;
var minutes:Number = Math.floor(totalSeconds /60);
var minutes2:Number = Math.floor(totalSeconds2 /60);
var seconds = Math.floor (totalSeconds) % 60;
var seconds2 = Math.floor (totalSeconds2) % 60;
if (seconds < 10)
{
seconds = "0" + seconds;
}
if (seconds2 < 10)
{
seconds2 = "0" + seconds2;
}
timeBox.text = minutes + ":" + seconds;
timeBox2.text = minutes2 + ":" + seconds2;
}
Please let me know if anyone has questions.
#32 by Carol on 2/2/09 - 9:48 PM
1. Create an .xml document that looks like this (example).
2. In your FLA file, add this code... in this area...
If you're interested in creating a full solution for people (and get paid for it!), you might want to check out becoming a provider at Flash Den (www.flashden.net/page/author_program). Check out some of their flv players.
In the meantime, if you have the time (and desire) to be more step-by-step for me (and the other needy folks on this site), I'd sure appreciate it.
Thanks again.
Carol
#33 by Carol on 2/2/09 - 9:51 PM
Do you have a sample XML file you can post for us?
Thanks.
Carol
#34 by Todd on 2/2/09 - 10:19 PM
settings.xml:
<?xml version="1.0" encoding="utf-8"?>
<settings>
<xmlFile>
<!-- allows you to change the location of the xml file w/o changing your Flash file -->
<url>sample.xml</url>
</xmlFile>
</settings>
sample.xml:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<videoData>
<video_cover>YOUR_VIDEO_COVER.jpg</video_cover>
<video_caption>YOUR_VIDEO_CAPTIONS.xml</video_caption>
<video_path>YOUR_VIDEO_PATH.flv</video_path>
<videoStartDate>02/02/2009</videoStartDate>
<videoEndDate>12/31/2009</videoEndDate>
</videoData>
<!-- THE NEXT VIDEO -->
<videoData>
<video_cover>YOUR_VIDEO_COVER.jpg</video_cover>
<video_caption>YOUR_VIDEO_CAPTIONS.xml</video_caption>
<video_path>YOUR_VIDEO_PATH.flv</video_path>
<videoStartDate>02/01/2009</videoStartDate>
<videoEndDate>12/31/2009</videoEndDate>
</videoData>
<!-- THE NEXT VIDEO -->
<videoData>
<video_cover>YOUR_VIDEO_COVER.jpg</video_cover>
<video_caption>YOUR_VIDEO_CAPTIONS.xml</video_caption>
<video_path>YOUR_VIDEO_PATH.flv</video_path>
<videoStartDate>01/31/2009</videoStartDate>
<videoEndDate>12/31/2009</videoEndDate>
</videoData>
</videos>
captions0.xml:
<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns="http://www.w3.org/2006/04/ttaf1" xmlns:tts="http://www.w3.org/2006/04/ttaf1#styling" xml:lang="en">
<head>
<styling>
<style id="defaultSpeaker" tts:fontSize="24" tts:fontFamily="Arial" tts:fontWeight="normal" tts:fontStyle="normal" tts:textDecoration="none" tts:color="white" tts:backgroundColor="black" tts:textAlign="center" />
<style id="defaultCaption" tts:fontSize="14" tts:fontFamily="Arial" tts:fontWeight="normal" tts:fontStyle="normal" tts:textDecoration="none" tts:color="white" tts:backgroundColor="black" tts:textAlign="center" />
</styling>
</head>
<body style="defaultCaption" id="thebody">
<div xml:lang="en">
<p begin="00:00:00.03" end="00:00:01.47" tts:textAlign="left">Some text would go here</p>
<p begin="00:00:1.47" end="00:28:32.00" tts:textAlign="left">This is the end of the captions. It will stay here until the movie is over because I want it to :-p</p>
</div>
</body>
</tt>
I will upload and post the src files tomorrow, but I hope this would make a good starting point :-).
#35 by Carol on 2/2/09 - 11:01 PM
I'll have time in a day or two to give this a whirl. Thanks in advance for posting the files for us.
Standing ovation, my friend.
Carol
#36 by Todd on 2/3/09 - 4:34 PM
http://www.toddvaughn.com/video_tuts.zip
you can see it work here:
http://www.toddvaughn.com/video_tuts/xml_video_cc....
if anyone has questions don't hesitate to give me a shout. unfortunately I haven't had time to do a tut, but maybe that will come in the near future.
The Flash/XML I created here is a standard I use for all Flash/XML projects; video, photo, MP3. Photo is very similar to video, but MP3 players are a different animal. I will help with if anyone has questions on any of these.
#37 by Ioan on 3/6/09 - 7:18 AM
I try your link but I receive:
Error 500 - Internal server error
Please reupload your interesting player.
#38 by Todd on 3/6/09 - 9:05 PM
a fully functioning version of the above mentioned can be downloaded here:
http://www.toddvaughn.com/video_tuts.zip
you can see it work here:
http://www.toddvaughn.com/video_tuts/xml_video_cc....
#39 by lorie on 3/11/09 - 3:51 PM
http://www.joycemeyer.org/ourministries/broadcast/...
The users on the website I'm working on need to be able to see all the videos, select one and then play it--I basically need a similar setup as you have on joycemeyer.org but including captions.
Do you happen to have the source file to include the playlist?
Thank you!
#40 by Todd on 3/11/09 - 7:36 PM
embed you flash player with this:
function QueryString(key)
{
var value = null;
for (var i=0;i<QueryString.keys.length;i++)
{
if (QueryString.keys[i]==key)
{
value = QueryString.values[i];
break;
}
}
return value;
}
QueryString.keys = new Array();
QueryString.values = new Array();
function QueryString_Parse()
{
var query = window.location.search.substring(1);
var pairs = query.split("&");
for (var i=0;i<pairs.length;i++)
{
var pos = pairs[i].indexOf('=');
if (pos >= 0)
{
var argname = pairs[i].substring(0,pos);
var value = pairs[i].substring(pos+1);
QueryString.keys[QueryString.keys.length] = argname;
QueryString.values[QueryString.values.length] = value;
}
}
}
QueryString_Parse();
function writeVideo()
{
var width = '340'
var height = '280'
var src = 'video.swf'
var queries = '?v='+QueryString('v')
var l1 = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/...; width="'+width+'" height="'+height+'">';
var l2 = '<param name="movie" value="'+src+queries+'" />';
var l3 = '<param name="quality" value="high" />';
var l4 = '<param name="wmode" value="transparent" />';
var l5 = '<param name="allowFullScreen" value="true" />';
var l6 = '<embed src="'+src+queries+'" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" allowFullScreen="true" wmode="transparent" type="application/x-shockwave-flash" width="'+width+'" height="'+height+'"></embed>';
var l7 = '</object>'
document.write(l1+l2+l3+l4+l5+l6+l7)
}
else
{
// flash is too old or we can't detect the plugin
var alternateContent = "This content requires the Adobe Flash Player. "
+ "<a href=http://www.adobe.com/go/getflash/>Get Flash</a>";
document.write(alternateContent); // insert non-flash content
}
I usually put this in a .js and call it in the html to reduce cluster:
<script lanuage="javascript" src="folder/your_swf.js"></script>
The links (rather flash or HTML) should include the query of the node you want displayed i.e. - http://yourdomain.com/video_page.html?v=2 would show the 3rd video (remember that in code your count starts at 0).
Hope this helps, let me know if it does not and I will upload and post a working example... i may do that anyway - stay tuned :-)
#41 by lorie on 3/12/09 - 4:47 PM
I'm still in the process of getting more comfortable w/ ActionScript and a working example is very helpful. Thank you again, Todd, providing this code is very generous of you!!
#42 by Todd on 3/12/09 - 5:20 PM
#43 by lorie on 3/12/09 - 5:57 PM
What I'm trying to build is a playlist for the videos, so a user can then pick one and watch. The screen will also need to show a preview image on the load of the page.
So I don't think I'd be querying separate components for that. My player and playlist would function similarly to [but look a little bit different] what you have on: http://www.joycemeyer.org/ourministries/broadcast/...
Visually, my playlist will look more like the one on www.cnn.com They display a list of videos in the "Next Up" box along w/ a thumbnail, Title and time of the video.
Thanks lots! Lorie
#44 by Todd on 3/12/09 - 7:42 PM
http://www.toddvaughn.com/sample.zip
I will not keep this file online so please let me know when you have downloaded it :-)
#45 by lorie on 3/12/09 - 8:35 PM