public function write() { $amfSerializer = new FLV_Util_AMFSerialize(); $metadata_data = array(); // theses will be used as placeholders for dynamic data $metadata_data["canSeekToEnd"] = true; $metadata_data["duration"] = (int) ($this->duration / 1000); $metadata_data["timeOffset"] = 0; $metadata_data["bytesOffset"] = 0; // because of akamai seek limitation we want to limit metadata size to 16kb // 15K / 2 (times & positions arrays ) / 8 (bytes each) ~ 850 // we will skip keyframes in order to use at most 850 of them $kf_cnt = count($this->keyframeTimes); // if there are more than 1 keyframe per second and file size < 100MB its probably and edit flavor and we should maintain all KF // we serve the file from our server and not the cdn anyway because the cdn cant clip the file $lastKF = $lastKFPos = 0; if ($kf_cnt) { $lastKF = $this->keyframeTimes[$kf_cnt - 1] / 1000; $lastKFPos = $this->keyframeBytes[$kf_cnt - 1] / (1000 * 1000); } if ($kf_cnt > $lastKF && ($lastKFPos < 100 && !$this instanceof FlvMetadataAudio)) { $new_kf_step = 1; } else { $new_kf_step = max(1, $kf_cnt / 850); } $new_kf = array(); $new_fp = array(); $i = 0; $new_kf_pos = 0; while ($i < $kf_cnt) { $new_kf[] = $this->keyframeTimes[$i]; $new_fp[] = $this->keyframeBytes[$i]; $new_kf_pos += $new_kf_step; $i = floor($new_kf_pos); } $metadata_data["times"] = $new_kf; $metadata_data["filepositions"] = $new_fp; $data = $amfSerializer->serialize('onMetaData') . $amfSerializer->serialize($metadata_data); $data_len = strlen($data); $metatagSize = myFlvHandler::TAG_WRAPPER_SIZE + $data_len; for ($i = 0; $i < count($new_kf); ++$i) { $metadata_data["filepositions"][$i] += $metatagSize; } $res = $amfSerializer->serialize('onMetaData') . $amfSerializer->serialize($metadata_data); $meta_tag = myFlvHandler::createMetadataTag($data); kFile::safeFilePutContents($this->info_file_name, $meta_tag); // sync - OK $meta_tag = null; $amfSerializer = null; }
private static function createMetadataForStreamFlv($filePath, $assets, $streamInfo, $addPadding, $duration = null) { $metadata_content = self::getMetadataFromCache($filePath, $streamInfo, $addPadding); if ($metadata_content) { return $metadata_content; } list($sizeList, $timeList, $filePositionsList) = self::iterateAssets($assets, $streamInfo, $addPadding, false); $amfSerializer = new FLV_Util_AMFSerialize(); $metadata = array(); $metadata_data = array(); if ($duration) { $metadata_data["duration"] = (int) ($duration / 1000); } $metadata_data["bufferSizes"] = $sizeList; $metadata_data["times"] = $timeList; $metadata_data["filepositions"] = $filePositionsList; $res = $amfSerializer->serialize('onMetaData') . $amfSerializer->serialize($metadata_data); $data_len = strlen($res); // first create a metadata tag with it's real size - this will be the offset of all the rest of the tags // create a metadata tag $metadata_size = myFlvHandler::TAG_WRAPPER_SIZE + $data_len; $metatagEndOffset = myFlvHandler::getHeaderSize() + $metadata_size; // second - create the real metadata tag with the values of all the following tags with correct offsets for ($i = 0; $i < count($sizeList); ++$i) { $sizeList[$i] += $metatagEndOffset; } for ($i = 0; $i < count($filePositionsList); ++$i) { $filePositionsList[$i] += $metatagEndOffset; } $metadata_data["bufferSizes"] = $sizeList; $metadata_data["filepositions"] = $filePositionsList; $res = $amfSerializer->serialize('onMetaData') . $amfSerializer->serialize($metadata_data); $metadata_content = myFlvHandler::createMetadataTag($res); self::setMetadataInCache($filePath, $streamInfo, $addPadding, $metadata_content); return $metadata_content; }