CuePoints und F4V-Videos - Auf den ersten Blick scheint mit dem neuen Flash Media Encoder alles in Ordnung, da man CuePoints nun auch im F4V-Format setzen kann. Allerdings ist es doch nicht so einfach wie es scheint ...

XMP – Extensible Metadata Platform

Bei XMP handelt es sich um einen Metadaten-Standard, den Adobe bereits im Jahr 2001 eingeführt hat. Dieser wird nun seit CS4 verstärkt von den Programmen der Creative Suite eingesetzt wird.

Sie können XMP-Daten (Extensible Metadata Platform), zum Beispiel Titel, Autor, Beschreibung, Copyright-Hinweise, in ihre FLA-Dateien einschließen. XMP ist ein Metadatenformat, das auch von bestimmten anderen Adobe-Anwendungen interpretiert werden kann.

Interessanterweise sind diese XMP-Metadaten auch in Videos enthalten, die mit dem Flash Media Encoder erstellt werden. Dort sollen z.B. auch die transkribierten Texte des Audio-to-text-Features stehen.

Encoding: F4V und Cuepoints

Erstellt man im Adobe Media Encoder Cue-Points, ist dies allen Anschein nach sowohl für FLV als auch F4V möglich. Die Einstellungen sind in beiden Formaten gleich, in Wirklichkeit werden die Cuepoints aber unterschiedlich gespeichert.

In der Flashhilfe ist zu lesen:

Cue-Points können in die XMP-Metadaten einer F4V-Datei eingebettet werden, die Analyse dieser Daten erfordert jedoch benutzerdefinierten ActionScript-Code.

Heißt also nichts anderes, als dass im Gegensatz zum FLV-Format bei MPEG-4-Files (.f4v) die gesetzten Cuepoints nicht automatisch funktionieren :-(

ActionScript: F4V, Cuepoints, XML, XMP

Die Lösung liegt darin, dass man selbst AS-Code schreiben muss, um aus den XMP-Metadaten im XML-Format die Cuepoints herauszulesen.

Hier ein einfaches Beispiel, wie man zuerst einmal den kompletten (rohen) XMP-Inhalt in das "Ausgabe"-Fenster von Flash ausgibt.

Hinweis: Das Registrieren eines Eventlistener ist nicht nötig!

Actionscript:
  1. var videoConnection:NetConnection = new NetConnection();
  2. videoConnection.connect(null);
  3.              
  4. var videoStream:NetStream = new NetStream(videoConnection);
  5. videoStream.client = this;
  6. var video:Video = new Video();
  7. video.width = 240;
  8. video.height = 135;
  9.              
  10. addChild(video);
  11.              
  12. video.attachNetStream(videoStream);
  13.              
  14. videoStream.play("hubblecast-hd.f4v");       
  15.            
  16. function onXMPData(infoObject:Object):void {
  17.    trace(infoObject.data);
  18. }

Hilfreich für das weitere Verständnis sind übrigens die Beiträge ActionScript3: XML und XML Namespaces.

Das ausdefinierte Funktion onXMPData ist etwas komplexer. Sie sieht so aus:

Actionscript:
  1. function onXMPData(infoObject:Object):void {
  2.    
  3.             var cuePoints:Array = new Array();
  4.             var cuePoint:Object;
  5.             var strFrameRate:String;
  6.             var nTracksFrameRate:Number;
  7.             var strTracks:String = "";
  8.             var onXMPXML = new XML(infoObject.data);
  9.             // Set up namespaces to make referencing easier
  10.             var xmpDM:Namespace = new Namespace("http://ns.adobe.com/xmp/1.0/DynamicMedia/");
  11.             var rdf:Namespace = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
  12.            
  13.            
  14.             for each (var it:XML in onXMPXML..xmpDM::Tracks) {
  15.                  var strTrackName:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::trackName;
  16.                  var strFrameRateXML:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::frameRate;
  17.                  strFrameRate = strFrameRateXML.substr(1,strFrameRateXML.length);
  18.                  
  19.                  nTracksFrameRate = Number(strFrameRate)
  20.                  strTracks += it;
  21.             }
  22.            
  23.             var onXMPTracksXML:XML = new XML(strTracks);
  24.             var strCuepoints:String = "";
  25.             for each (var item:XML in onXMPTracksXML..xmpDM::markers)             {
  26.                 strCuepoints += item;
  27.             }
  28.             //trace(strCuepoints);
  29.             var cpXML:XML = new XML (strCuepoints);
  30.  
  31.            
  32.             // CP in Array schreiben
  33.             for (var i:Number=0; i rdf::Description.length(); i++) {
  34.                
  35.                 // Startzeit
  36.                 var cpStartTime = cpXML..rdf::Description[i].@xmpDM::startTime;
  37.                
  38.                 // DVA Ticks
  39.                 cpStartTime = cpStartTime / nTracksFrameRate;
  40.                 trace (":::\n" + cpStartTime);
  41.                
  42.                 // Name
  43.                 trace (cpXML..rdf::Description[i].@xmpDM::name);
  44.                
  45.                 // Name
  46.                 trace (cpXML..rdf::Description[i].@xmpDM::cuePointType);               
  47.                
  48.             }
  49.         }

Der Anfang ist aus der Flashdoku. Den hinteren Teil mit den Cuepoints scheint Adobe jedoch vergessen zu haben :-)

Die Informationen sollte man einfach noch in dem Array cuePoints abspeichern, um sie weiterverwenden zu können.

Was sind bitte "DVA Ticks"?

Warum auch immer, aber die Zeiten der Cuepoints sind in so genannten DVA Ticks hinterlegt. Dazu der Hinweis von Adobe:

In XMP-Daten wird die Zeit in Form von „DVA Ticks“ anstelle von Sekunden gespeichert. Sie berechnen die Cue-Point-Zeit, indem Sie die Startzeit durch die Bildrate teilen. Beispiel: Die Startzeit 7695905817600 geteilt durch die Bildrate 254016000000 ist gleich 30:30.