Korzystanie z punktów sygnalizacji i metadanych

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Metody wywołania zwrotnego w klasie NetStream umożliwiają przechwytywanie i przetwarzanie zdarzeń związanych z punktami sygnalizacji i metadanymi w trakcie odtwarzania wideo.

Korzystanie z punktów sygnalizacji

W poniższej tabeli opisano metody wywołania zwrotnego umożliwiające przechwytywanie w programie Flash Player i środowisku AIR punktów sygnalizacji osadzonych w plikach F4V i FLV.

Środowisko wykonawcze

F4V

FLV

Flash Player 9/ AIR1.0

OnCuePoint

OnMetaData

Flash Player 10

OnCuePoint

OnMetaData

OnMetaData

OnXMPData

OnXMPData

W poniższym przykładzie zastosowano prostą pętlę for..in do iteracyjnego przeglądania właściwości parametru infoObject odebranego przez funkcję onCuePoint() . Następnie, po odebraniu danych punktu sygnalizacji, wywoływana jest funkcja trace() w celu wyświetlenia komunikatu:

var nc:NetConnection = new NetConnection(); 
nc.connect(null); 
 
var ns:NetStream = new NetStream(nc); 
ns.client = this; 
ns.play("video.flv"); 
 
var vid:Video = new Video(); 
vid.attachNetStream(ns); 
addChild(vid); 
 
function onCuePoint(infoObject:Object):void 
{ 
    var key:String; 
    for (key in infoObject) 
    { 
        trace(key + ": " + infoObject[key]); 
    } 
}

Wyświetlane są następujące wyniki:

parameters:  
name: point1 
time: 0.418 
type: navigation

W kodzie tym użyto jednej z kilku technik określenia obiektu, z którego mają być wywołane metody wywołania zwrotnego. Można jednak skorzystać z innych technik; więcej informacji zawiera sekcja Pisanie metod wywołania zwrotnego do obsługi metadanych i punktów sygnalizacji .

Korzystanie z metadanych wideo

Funkcje OnMetaData() i OnXMPData() umożliwiają dostęp do metadanych osadzonych w pliku wideo, w tym do danych punktów sygnalizacji.

Korzystanie z metody OnMetaData()

Metadane zawierają informacje o pliku wideo, takie jak czas trwania, szerokość, wysokość i częstość klatek. To, jakie metadane zostaną dodane do pliku wideo, zależy od oprogramowania używanego do zakodowania tego pliku.

var nc:NetConnection = new NetConnection(); 
nc.connect(null); 
 
var ns:NetStream = new NetStream(nc); 
ns.client = this; 
ns.play("video.flv"); 
 
var vid:Video = new Video(); 
vid.attachNetStream(ns); 
addChild(vid); 
 
function onMetaData(infoObject:Object):void 
{ 
    var key:String; 
    for (key in infoObject) 
    { 
        trace(key + ": " + infoObject[key]); 
    } 
}

Kod przedstawiony powyżej generuje wyniki podobne do następujących:

width: 320 
audiodelay: 0.038 
canSeekToEnd: true 
height: 213 
cuePoints: ,, 
audiodatarate: 96 
duration: 16.334 
videodatarate: 400 
framerate: 15 
videocodecid: 4 
audiocodecid: 2
Jeśli materiał wideo nie zawiera danych audio, metadane związane z dźwiękiem (takie jak audiodatarate ) mają wartości undefined , ponieważ w trakcie kodowania do metadanych nie są dodawane żadne informacje o dźwięku.

W powyższym kodzie informacje o punktach sygnalizacji nie były wyświetlane. W celu wyświetlenia metadanych punktów sygnalizacji można użyć następującej funkcji, która rekurencyjnie wyświetla elementy w obiekcie Object:

function traceObject(obj:Object, indent:uint = 0):void 
{ 
    var indentString:String = ""; 
    var i:uint; 
    var prop:String; 
    var val:*; 
    for (i = 0; i < indent; i++) 
    { 
        indentString += "\t"; 
    } 
    for (prop in obj) 
    { 
        val = obj[prop]; 
        if (typeof(val) == "object") 
        { 
            trace(indentString + " " + prop + ": [Object]"); 
            traceObject(val, indent + 1); 
        } 
        else 
        { 
            trace(indentString + " " + prop + ": " + val); 
        } 
    } 
}

Gdyby użyć powyższego urywka kodu do wyświetlenia parametru infoObject w metodzie onMetaData() , zostałyby wyświetlone następujące wyniki:

width: 320 
audiodatarate: 96 
audiocodecid: 2 
videocodecid: 4 
videodatarate: 400 
canSeekToEnd: true 
duration: 16.334 
audiodelay: 0.038 
height: 213 
framerate: 15 
cuePoints: [Object] 
    0: [Object] 
        parameters: [Object] 
            lights: beginning 
        name: point1 
        time: 0.418 
        type: navigation 
    1: [Object] 
        parameters: [Object] 
            lights: middle 
        name: point2 
        time: 7.748 
        type: navigation 
    2: [Object] 
        parameters: [Object] 
            lights: end 
        name: point3 
        time: 16.02 
        type: navigation

Poniższy przykładowy kod wyświetla metadane wideo MP4. Przyjęto założenie, że istnieje obiekt TextArea o nazwie metaDataOut , w którym wypisywane są metadane.

package 
{ 
    import flash.net.NetConnection; 
    import flash.net.NetStream; 
    import flash.events.NetStatusEvent; 
    import flash.media.Video; 
    import flash.display.StageDisplayState; 
    import flash.display.Loader; 
    import flash.display.Sprite; 
    import flash.events.MouseEvent; 
     
    public class onMetaDataExample extends Sprite 
    {     
        var video:Video = new Video(); 
         
        public function onMetaDataExample():void 
        { 
            var videoConnection:NetConnection = new NetConnection(); 
            videoConnection.connect(null); 
             
            var videoStream:NetStream = new NetStream(videoConnection); 
            videoStream.client = this; 
             
            addChild(video); 
            video.x = 185; 
            video.y = 5; 
                     
            video.attachNetStream(videoStream); 
             
            videoStream.play("video.mp4"); 
                         
            videoStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
        } 
                     
        public function onMetaData(infoObject:Object):void 
        { 
            for(var propName:String in infoObject) 
            { 
                metaDataOut.appendText(propName + "=" + infoObject[propName] + "\n"); 
            } 
        } 
         
        private function netStatusHandler(event:NetStatusEvent):void 
        { 
            if(event.info.code == "NetStream.Play.Stop") 
                stage.displayState = StageDisplayState.NORMAL; 
        } 
    } 
}

Funkcja onMetaData() wygenerowała następujące wyniki dla tego wideo:

moovposition=731965 
height=352 
avclevel=21 
videocodecid=avc1 
duration=2.36 
width=704 
videoframerate=25 
avcprofile=88 
trackinfo=[object Object]

Korzystanie z obiektu informacyjnego

W poniższej tabeli wymieniono możliwe wartości metadanych wideo przekazywanych do funkcji wywołania zwrotnego onMetaData() w odbieranym przez nią obiekcie Object:

Parametr

Opis

aacaot

Typ obiektu audio AAC; obsługiwane są typy 0, 1 i 2.

avclevel

Poziom AVC IDC, na przykład 10, 11, 20, 21 itd.

avcprofile

Numer profilu AVC, na przykład 55, 77, 100 itd.

audiocodecid

Ciąg znaków identyfikujący zastosowany kodek audio (technikę kodowania/dekodowania) — na przykład ".Mp3" lub "mp4a".

audiodatarate

Liczba określająca szybkość transmisji, z jaką zakodowany jest strumień audio, w kilobajtach na sekundę.

audiodelay

Liczba określająca, w jakim momencie pliku FLV wypada czas „0” oryginalnego pliku FLV. Treść wideo musi być nieznacznie opóźniona w celu prawidłowego zsynchronizowania dźwięku.

canSeekToEnd

Wartość logiczna (Boolean) równa true , jeżeli plik FLV jest zakodowany z klatką kluczową na ostatniej klatce, co pozwala na wyszukiwanie końca stopniowo pobieranego klipu filmowego. Wartość false , gdy plik FLV nie jest zakodowany z kluczową klatką na ostatniej klatce.

cuePoints

Tablica obiektów, po jednym dla każdego punktu sygnalizacji osadzonego w pliku FLV. Wartość jest niezdefiniowana, jeżeli plik FLV nie zawiera punktów sygnalizacji. Każdy obiekt ma następujące właściwości:

  • type — ciąg znaków określający, czy punkt sygnalizacji jest typu "navigation", czy "event".

  • name — ciąg znaków, który określa nazwę punktu sygnalizacji.

  • time — liczba określająca czas położenia punktu sygnalizacji w sekundach, z dokładnością do trzech miejsc dziesiętnych (milisekundy).

  • parameters — obiekt opcjonalny zawierający pary nazwa-wartość określane przez użytkownika podczas tworzenia punktów sygnalizacji.

duration

Liczba określająca w sekundach czas trwania pliku wideo.

framerate

Liczba określająca liczba klatek na sekundę w pliku FLV.

height

Liczba określająca wysokość pliku wideo w pikselach.

seekpoints

Tablica z listą dostępnych klatek kluczowych pełniących rolę znaczników czasu, których położenie jest określone w milisekundach. Opcjonalnie.

tags

Tablica par klucz-wartość reprezentujących informacje z atomu "ilist", który jest odpowiednikiem znaczników ID3 w plikach MP4. Znaczniki te wykorzystywane są przez program iTunes. Mogą posłużyć do wyświetlania grafiki, o ile jest dostępna.

trackinfo

Obiekt zawierający informacje o wszystkich ścieżkach w pliku MP4, w tym ich identyfikatory opisu próbek.

videocodecid

Ciąg znaków identyfikujący wersję kodeka użytego do kodowania obrazu wideo. Na przykład: "avc1" lub "VP6F".

videodatarate

Liczba określająca szybkość transmisji wideo w pliku FLV.

videoframerate

Częstość klatek wideo MP4.

width

Liczba określająca szerokość pliku FLV w pikselach.

W poniższej tabeli przedstawiono możliwe wartości parametru videocodecid :

videocodecid

Nazwa kodeka

2

Sorenson H.263

3

Wideo ekranowe (tylko pliki SWF w wersji 7 i późniejszych)

4

VP6 (tylko pliki SWF w wersji 8 i późniejszych)

5

Wideo VP6 z kanałem (tylko pliki SWF w wersji 8 i późniejszych)

W poniższej tabeli przedstawiono możliwe wartości parametru audiocodecid :

audiocodecid

Nazwa kodeka

0

bez kompresji

1

ADPCM

2

Mp3

4

Nellymoser przy 16 kHz mono

5

Nellymoser, 8 kHz mono

6

Nellymoser

10

AAC

11

Speex

Korzystanie z funkcji onXMPData()

Funkcja wywołania zwrotnego onXMPData() odbiera informacje charakterystyczne dla platformy Adobe Extensible Metadata Platform (XMP) osadzone w pliku wideo Adobe F4V lub FLV. Metadane XMP zawierają informacje o punktach sygnalizacji oraz inne metadane wideo. Obsługa metadanych XMP została wprowadzona po raz pierwszy w programie Flash Player 10 i środowisku Adobe AIR 1.5 i występuje także we wszystkich późniejszych wersjach.

Poniższy przykładowy kod przetwarza dane punktów sygnalizacji zawarte w metadanych XMP:

package 
{ 
    import flash.display.*; 
    import flash.net.*; 
    import flash.events.NetStatusEvent; 
    import flash.media.Video; 
     
    public class onXMPDataExample extends Sprite 
    { 
        public function onXMPDataExample():void 
        { 
            var videoConnection:NetConnection = new NetConnection(); 
            videoConnection.connect(null); 
             
            var videoStream:NetStream = new NetStream(videoConnection); 
            videoStream.client = this; 
            var video:Video = new Video(); 
             
            addChild(video); 
             
            video.attachNetStream(videoStream); 
             
            videoStream.play("video.f4v"); 
        } 
         
        public function onMetaData(info:Object):void { 
            trace("onMetaData fired"); 
        } 
         
        public function onXMPData(infoObject:Object):void 
        { 
            trace("onXMPData Fired\n"); 
             //trace("raw XMP =\n"); 
             //trace(infoObject.data); 
            var cuePoints:Array = new Array(); 
            var cuePoint:Object; 
            var strFrameRate:String; 
            var nTracksFrameRate:Number; 
            var strTracks:String = ""; 
            var onXMPXML = new XML(infoObject.data); 
            // Set up namespaces to make referencing easier 
            var xmpDM:Namespace = new Namespace("http://ns.adobe.com/xmp/1.0/DynamicMedia/"); 
            var rdf:Namespace = new Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); 
            for each (var it:XML in onXMPXML..xmpDM::Tracks) 
            { 
                 var strTrackName:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::trackName; 
                 var strFrameRateXML:String = it.rdf::Bag.rdf::li.rdf::Description.@xmpDM::frameRate; 
                 strFrameRate = strFrameRateXML.substr(1,strFrameRateXML.length); 
                 
                 nTracksFrameRate = Number(strFrameRate);  
                 
                 strTracks += it; 
            } 
            var onXMPTracksXML:XML = new XML(strTracks); 
            var strCuepoints:String = ""; 
            for each (var item:XML in onXMPTracksXML..xmpDM::markers) 
            { 
                strCuepoints += item; 
            } 
            trace(strCuepoints); 
        } 
    } 
}

W przypadku krótkiego pliku wideo o nazwie startrekintro.f4v ten przykład generuje następujące wyniki. Wyniki zawierają dane nawigacyjnych punktów sygnalizacji i punktów sygnalizacji zdarzeń zawarte w metadanych XMP:

onMetaData fired 
onXMPData Fired 
 
<xmpDM:markers xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:x="adobe:ns:meta/"> 
  <rdf:Seq> 
    <rdf:li> 
      <rdf:Description xmpDM:startTime="7695905817600" xmpDM:name="Title1" xmpDM:type="FLVCuePoint" xmpDM:cuePointType="Navigation"> 
        <xmpDM:cuePointParams> 
          <rdf:Seq> 
            <rdf:li xmpDM:key="Title" xmpDM:value="Star Trek"/> 
            <rdf:li xmpDM:key="Color" xmpDM:value="Blue"/> 
          </rdf:Seq> 
        </xmpDM:cuePointParams> 
      </rdf:Description> 
    </rdf:li> 
    <rdf:li> 
      <rdf:Description xmpDM:startTime="10289459980800" xmpDM:name="Title2" xmpDM:type="FLVCuePoint" xmpDM:cuePointType="Event"> 
        <xmpDM:cuePointParams> 
          <rdf:Seq> 
            <rdf:li xmpDM:key="William Shatner" xmpDM:value="First Star"/> 
            <rdf:li xmpDM:key="Color" xmpDM:value="Light Blue"/> 
          </rdf:Seq> 
        </xmpDM:cuePointParams> 
      </rdf:Description> 
    </rdf:li> 
  </rdf:Seq> 
</xmpDM:markers> 
onMetaData fired
Uwaga: W danych XMP jednostką czasu są impulsy DVA, a nie sekundy. Aby obliczyć czas danego punktu sygnalizacji, należy podzielić czas początkowy przez częstość klatek. Przykładowo, czas początkowy 7695905817600 podzielony przez częstość klatek 254016000000 wynosi 30:30.

Aby wyświetlić kompletne metadane XMP, w tym częstość klatek, należy usunąć identyfikatory komentarza (//) sprzed drugiej i trzeciej instrukcji trace() na początku funkcji onXMPData() .

Więcej informacji na temat platformy XMP można znaleźć pod adresem:

Korzystanie z metadanych obrazu

Razem ze zdarzeniem onImageData przekazywane są przez kanał danych AMF0 dane obrazu w postaci tablicy bajtów. Dane mogą być zakodowane w formacie JPEG, PNG lub GIF. Aby przetwarzać dane obrazu, należy zdefiniować metodę wywołania zwrotnego onImageData() — w taki sam sposób, w jaki definiuje się metody wywołania zwrotnego onCuePoint i onMetaData . W poniższym przykładzie dane obrazu są odczytywane i wyświetlane przy użyciu metody wywołania zwrotnego onImageData() :

public function onImageData(imageData:Object):void 
{ 
    // display track number 
    trace(imageData.trackid); 
    var loader:Loader = new Loader(); 
    //imageData.data is a ByteArray object 
    loader.loadBytes(imageData.data); 
    addChild(loader); 
} 

Korzystanie z metadanych tekstu

Razem ze zdarzeniem onTextData przesyłane są przez kanał danych AMF0 dane tekstowe. Dane tekstowe są zapisane w formacie UTF-8 i zawierają dodatkowe informacje na temat formatowania zgodne ze specyfikacją 3GP opisującą tekst z kodem czasowym. Specyfikacja ta opisuje ujednolicony format podpisów. Aby przetwarzać dane obrazu, należy zdefiniować metodę wywołania zwrotnego onTextData() — w taki sam sposób, w jaki definiuje się metody wywołania zwrotnego onCuePoint i onMetaData . W poniższym przykładzie metoda onTextData() wyświetla numer identyfikacyjny ścieżki i odpowiedni tekst ścieżki.

public function onTextData(textData:Object):void 
{ 
    // display the track number 
    trace(textData.trackid); 
    // displays the text, which can be a null string, indicating old text 
    // that should be erased 
    trace(textData.text); 
}