0

Hello,

I would like ask you how works the FLV Metadata, i use it in order to analyse video streaming websites such as YouTube.
It analyses the video header only or the whole video?

<?php 
class FLVMetaData {
    private $buffer;
    private $metaData;
    public $fileName;
    private $typeFlagsAudio;
    private $typeFlagsVideo;

    public $VCidMap = array(
      2=>"Sorenson H.264",
      3=>"Screen Video",
      4=>"VP6",
      5=>"VP6 with Alpha channel",
    );      //Video Codec ID(s)

    public $ACidMap = array(
      "Linear PCM, platform endian",
      "ADPCM",
      "MP3",
      "Linear PCM, little endian",
      "Nellymoser 16-kHz Mono",
      "Nellymoser 8-kHz Mono",
      "Nellymoser",
      "G.711 A-law logarithmic PCM",
      "G.711 mu-law logarithmic PCM",
      "reserved",
      "AAC",
      "Speex",
      14=>"MP3 8-Khz",
      15=>"Device-specific sound"
    );      //Audio Codec ID(s)

/**
 *  CONSTRUCTOR : initialize class members
 *
 * @param string $flv : flv file path
 */
    public function  __construct($flv) {
        $this->fileName = $flv;
        $this->metaData = array(
        "duration"=>null,
        "size"=>null,
        "framerate"=>null,
        "width"=>null,
        "height"=>null,
        "videodatarate"=>null,
        "audiodatarate"=>null,
        "audiodelay"=>null,
        "audiosamplesize"=>null,
        "audiosamplerate"=>null,
        "audiocodecid"=>null,
        "videocodecid"=>null,
        "version"=>null,
        "headersize"=>0
        );
    }

/**
 * Dumps Metadata of FLV
 */
    public function dumpMetaData(){
        echo "FLV Version: <strong>".$this->metaData["version"]."</strong><br />";
        echo "Duration : <strong>".$this->metaData["duration"]."</strong> Second(s) <br />";
        echo "File Size: <strong>".number_format(($this->metaData["size"]/pow(1024,2)) , 2)."</strong> MB<br />";
        echo "Width: <strong>".$this->metaData["width"]."</strong> Pixel(s)<br />";
        echo "Height: <strong>".$this->metaData["height"]."</strong> Pixel(s)<br />";
        echo "Framerate: <strong>".number_format($this->metaData["framerate"],2)."</strong> FPS<br />";
        echo "Video Data Rate: <strong>".number_format($this->metaData["videodatarate"])."</strong> Kbps<br />";
        echo "Audio Data Rate: <strong>".number_format($this->metaData["audiodatarate"])."</strong> Kbps<br />";
        echo "Audio Delay: <strong>".$this->metaData["audiodelay"]."</strong> Second(s)<br />";
        echo "Audio Codec ID: <strong>".$this->metaData["audiocodecid"]."</strong><br />";
        if(is_numeric($this->metaData["audiocodecid"])){
            echo "Audio Format: <strong>".$this->ACidMap[$this->metaData["audiocodecid"]]."</strong><br />";
        }
        echo "Video Codec ID: <strong>".$this->metaData["videocodecid"]."</strong><br />";
        if(is_numeric($this->metaData["videocodecid"])){
            echo "Video Format: <strong>".$this->VCidMap[$this->metaData["videocodecid"]]."</strong><br />";
        }
        echo "Header Size: <strong>".$this->metaData["headersize"]."</strong> Byte(s)<br />";
    }

/**
 * Gets metadata of FLV file
 *
 * @return array $this->metaData : matadata of FLV
 */
    public function getMetaData(){
        if(!file_exists($this->fileName)){
            echo "Error! {$this->fileName} does not exist.<br />";
            return false;
        }
        if(!is_readable($this->fileName)){
            echo "Error! Could not read the file. Check the file permissions.<br />";
            return false;
        }
        $f = @fopen($this->fileName,"rb");
        if(!$f){
            echo "Try again to submit the file.<br />";
            return;
        }
        $signature = fread($f,3);
        if($signature != "FLV"){
            echo "Error! Wrong file format.<br />";
           // return false;
        }
        $this->metaData["version"] = ord(fread($f,1));
        $this->metaData["size"] = filesize($this->fileName);

        $flags = ord(fread($f,1));
        $flags = sprintf("%'04b", $flags);
        $this->typeFlagsAudio = substr($flags, 1, 1);
        $this->typeFlagsVideo = substr($flags, 3, 1);

        for ($i=0; $i < 4; $i++) {
            $this->metaData["headersize"] += ord(fread($f,1)) ;
        }

        $this->buffer = fread($f, 400);
        fclose($f);
    if(strpos($this->buffer, "onMetaData") === false){
            echo "Error! No MetaData Exists, try different file.<br />";
            //return false;
        }  

        foreach($this->metaData as $k=>$v){
            $this->parseBuffer($k);
        }

        return $this->metaData;
    }

/**
 * Takes a field name of metadata, retrieve it's value and set it in $this->metaData
 *
 * @param string $fieldName : matadata field name
 */
    private function parseBuffer($fieldName){
        $fieldPos = strpos($this->buffer, $fieldName);  //get the field position
        if($fieldPos !== false){
            $pos = $fieldPos + strlen($fieldName) + 1;  
            $buffer = substr($this->buffer,$pos);

            $d = "";
            for($i=0; $i < 8;$i++){
                $d .= sprintf("%08b", ord(substr($buffer,$i,1)));
            }

            $total = self::bin2Double($d);
            $this->metaData[$fieldName] = $total;
        }
    }

/**
 * Calculates double-precision value of given binary string
 * (IEEE Standard 754 - Floating Point Numbers)
 *
 * @param string binary data $strBin
 * @return Float calculated double-precision number
 */
    public static function bin2Double($strBin){
            $sb = substr($strBin, 0, 1);    // first bit is sign bit
            $exponent = substr($strBin, 1, 11); // 11 bits exponent
            $fraction = "1".substr($strBin, 12, 52);    //52 bits fraction (1.F) 

            $s = pow(-1, bindec($sb));
            $dec = pow(2, (bindec($exponent) - 1023));  //Decode exponent

            if($dec == 2047){
                if($fraction == 0){
                    if($s==0){
                        echo "Infinity";
                    }else{
                        echo "-Infinity";
                    }
                }else{
                    echo "NaN";
                }
            }

            if($dec > 0 && $dec < 2047){
                $t = 1;
                for($i=1 ; $i <= 53; $i++){
                    $t += ((int)substr($fraction, $i, 1)) * pow(2, -$i);    //decode significand
                }
                $total = $s * $t * $dec ;
                return  $total;
            }
            return false;
    }
}

Thanks in advance,
Newcountry

2
Contributors
1
Reply
2
Views
7 Years
Discussion Span
Last Post by sourcebits
0

If you are asking is there any other workable way then youtube has no such API to get the meta data, it is good adopt own code in such a situation thinking that it is good and well.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.