Using Flash video metadata to display annotations

Now that you can create a streaming Flash video player with PHP or Ruby and you know add metadata for cuepoints to Flash videos you are ready for something else. The following code will show you how to create a video player with PHP that will watch for metadata events and display annotations contained inside the metadata either over the video itself or in a div on the same page as the movie.

The first steps are to create your Flash video if you haven't already and then add the metadata to it. See my post on adding cuepoint metadata with flvtool2 if you want to know more on how to create the Flash video and add the metadata. I'm using the same video from that post but a different set of metadata.

Here is the metadata I've added to the video for the following examples:

<tags>
    <metatag event="onCuePoint" overwrite="true">
        <name>Cue Point 1</name>
        <timestamp>4000</timestamp>
        <parameters>
            <mydata>Some data 1</mydata>
        </parameters>
        <type>event</type>
    </metatag>
    <metatag event="onCuePoint" overwrite="true">
        <name>Cue Point 2</name>
        <timestamp>8000</timestamp>
        <parameters>
            <mydata>Some data 2</mydata>
        </parameters>
        <type>event</type>
    </metatag>
    <metatag event="onCuePoint" overwrite="true">
        <name>Cue Point 3</name>
        <timestamp>12000</timestamp>
        <parameters>
            <mydata>Some data 3</mydata>
        </parameters>
        <type>event</type>
    </metatag>
    <metatag event="onCuePoint" overwrite="true">
        <name>Cue Point 4</name>
        <timestamp>16000</timestamp>
        <parameters>
            <mydata>Some data 4</mydata>
        </parameters>
        <type>event</type>
    </metatag>
</tags>

The main thing to notice here is that the type for each metatag is event and in the parameters list there is a tag called mydata that contains some text. The text inside mydata is what we will be using for annotations. This tag can be called anything you like and you can have more than one.

I am using icons from the famfamfam silk collection in the following examples. You will want to download them before trying these examples.

wget http://www.famfamfam.com/lab/icons/silk/icons/control_pause.png
wget http://www.famfamfam.com/lab/icons/silk/icons/control_pause_blue.png
wget http://www.famfamfam.com/lab/icons/silk/icons/control_start.png
wget http://www.famfamfam.com/lab/icons/silk/icons/control_start_blue.png
wget http://www.famfamfam.com/lab/icons/silk/icons/control_play.png
wget http://www.famfamfam.com/lab/icons/silk/icons/control_play_blue.png

The first example will display the annotation over the video itself. Here is the PHP code for generating the Flash player to display the annotations:

<?php
function createImage($img)
{
  $shape = new SWFShape();
  $shape->setRightFill($shape->addFill(new SWFBitmap(fopen($img, "rb"))));
  $shape->drawLine(16,0);
  $shape->drawLine(0,16);
  $shape->drawLine(16,0);
  $shape->drawLine(0,-16);
  return $shape;
}

function createButton($movie, $name, $loc, $script)
{
  $button = new SWFButton();
  $button->addShape(createImage("control_" . $name . ".png"), SWFBUTTON_UP);
  $button->addShape(createImage("control_" . $name . "_blue.png"), SWFBUTTON_DOWN | SWFBUTTON_HIT | SWFBUTTON_OVER);
  $button->addAction(new SWFAction($script), SWFBUTTON_HIT);
  $item=$movie->add($button);
  $item->moveto($loc,248);
}

Ming_setScale(20.0000000);
ming_useswfversion(7);

$movie = new SWFMovie(7);
$movie->setDimension(320,270); // width x height
$movie->setBackground(0x33,0x33,0x33);
$movie->setRate(8);

createButton($movie, "start", 10, "_root.videoStream.seek(0);");
createButton($movie, "pause", 40, "_root.videoStream.pause(true);");
createButton($movie, "play", 70, "_root.videoStream.pause(false);");

$strAction = "
this.createTextField('video_txt', 999, 0, 0, 100, 100);
video_txt.autoSize = 'left';
video_txt.multiline = true;
video_txt.textColor = 0xeeeeee;

stop();
nc=new NetConnection();
nc.connect(null);
videoStream=new NetStream(nc);
videoStreamItem.attachVideo(videoStream);
videoStream.setBufferTime(10);
videoStream.play('http://localhost/test.flv');
videoStream.pause();

videoStream.onCuePoint = function(infoObject)
{
  video_txt.text = 'Name: ' + infoObject.name + '\n';
  if( infoObject.parameters != undefined )
  {
    video_txt.text += 'Info: ' + infoObject.parameters['mydata'] + '\n';
  }
  else
  {
    video_txt.text += 'Info: undef\n';
  }
};
";

$stream = new SWFVideoStream();
$stream->setDimension(320, 240);
$item=$movie->add($stream);
$item->setName("videoStreamItem");
$movie->add(new SWFAction($strAction));

$movie->nextFrame();

$movie->save("test.swf");
?>

The following part of the above PHP is what connects the cuepoints to the overlay text. Notice the use of the mydata tag. The tag data is available in the parameters hash:

videoStream.onCuePoint = function(infoObject)
{
  video_txt.text = 'Name: ' + infoObject.name + '\n';
  if( infoObject.parameters != undefined )
  {
    video_txt.text += 'Info: ' + infoObject.parameters['mydata'] + '\n';
  }
  else
  {
    video_txt.text += 'Info: undef\n';
  }
};

Here is the result (hit the play button to start the video):

The following examples is the same as the above example except that it uses a javascript call to display the annotation data in a div on the page:

<?php
function createImage($img)
{
  $shape = new SWFShape();
  $shape->setRightFill($shape->addFill(new SWFBitmap(fopen($img, "rb"))));
  $shape->drawLine(16,0);
  $shape->drawLine(0,16);
  $shape->drawLine(16,0);
  $shape->drawLine(0,-16);
  return $shape;
}

function createButton($movie, $name, $loc, $script)
{
  $button = new SWFButton();
  $button->addShape(createImage("control_" . $name . ".png"), SWFBUTTON_UP);
  $button->addShape(createImage("control_" . $name . "_blue.png"), SWFBUTTON_DOWN | SWFBUTTON_HIT | SWFBUTTON_OVER);
  $button->addAction(new SWFAction($script), SWFBUTTON_HIT);
  $item=$movie->add($button);
  $item->moveto($loc,248);
}

Ming_setScale(20.0000000);
ming_useswfversion(7);

$movie = new SWFMovie(7);
$movie->setDimension(320,270); // width x height
$movie->setBackground(0x33,0x33,0x33);
$movie->setRate(8);

createButton($movie, "start", 10, "_root.videoStream.seek(0);");
createButton($movie, "pause", 40, "_root.videoStream.pause(true);");
createButton($movie, "play", 70, "_root.videoStream.pause(false);");

$strAction = "
this.createTextField('video_txt', 999, 0, 0, 100, 100);
video_txt.autoSize = 'left';
video_txt.multiline = true;
video_txt.textColor = 0xeeeeee;

stop();
nc=new NetConnection();
nc.connect(null);
videoStream=new NetStream(nc);
videoStreamItem.attachVideo(videoStream);
videoStream.setBufferTime(10);
videoStream.play('http://localhost/test.flv');
videoStream.pause();

videoStream.onCuePoint = function(infoObject)
{
  if( infoObject.parameters != undefined )
  {
    geturl('javascript:aTestCall(\" + infoObject.parameters['mydata'] + '\')');
  }
};
";

$stream = new SWFVideoStream();
$stream->setDimension(320, 240);
$item=$movie->add($stream);
$item->setName("videoStreamItem");
$movie->add(new SWFAction($strAction));

$movie->nextFrame();

$movie->save("test.swf");
?>

This javascript will display the data in the div (note that this won't work for all browsers, I'm just making it simple):

function aTestCall(data)
  {
    document.getElementById("infoDisplayArea").innerHTML = data;
  }

This is how you would set up the div to display the data:

<div id="infoDisplayArea" style="border: solid 1px #000; padding: 5px 5px 5px 5px; width: 50%;">
No data yet…
</div>

Here is the result (hit the play button to start the video):

No data yet…

Keep an eye on the above box while the video is playing to see the annotations.

Tags: ,

6 thoughts on “Using Flash video metadata to display annotations

  1. Deb

    Hi,

    I have been trying this and getting an error as follows:

    Parse error: syntax error, unexpected T_STRING in E:\WEBHOME\phpvideo\file1.php on line 34

    Could you please help?

    Regards,
    Deb

  2. Deb

    Also an another error:

    Fatal error: Call to undefined function Ming_setScale() in E:\WEBHOME\phpvideo\file1.php on line 29

    Regards,
    Deb

  3. Sajith.M.R

    Hello Debs: Your first error is at line 34 is due to background color setting. Since you copy the whole data from browser direct to you r php editor. delete
    $movie->setBackground(0x33,0x33,0x33);

    line and type by hand;

    (since x in 0x33 is the problem here )
    then your first problem will be solved.

  4. Sajith.M.R

    Debs,

    For your second error:

    Make sure that Ming Library is installed perfectly on your server.

    you can install it by apt-get (if enabled)

  5. zzeroo

    Can You help me please. I try to implement this in ruby, but I've not enough skills for that.

    I want not the complete solution. But a little "scaffold" would be fine ;)

  6. Pingback: flvtool2 « Interactive Section

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>