/** * @param entry $entry * @param SimpleXMLElement $mrss */ protected static function appendMediaEntryMrss(entry $entry, SimpleXMLElement $mrss) { $media = $mrss->addChild('media'); $media->addChild('mediaType', $entry->getMediaType()); $media->addChild('duration', $entry->getLengthInMsecs()); $media->addChild('conversionProfileId', $entry->getConversionProfileId()); $media->addChild('flavorParamsIds', $entry->getFlavorParamsIds()); }
private function setContextDataFlavorAssets($flavorTags) { if ($this->entry->getType() == entryType::PLAYLIST && $this->entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_TEXT) { list($entryIds, $durations, $mediaEntry) = myPlaylistUtils::executeStitchedPlaylist($this->entry); if (!$mediaEntry) { return; } $mediaEntryId = $mediaEntry->getId(); $this->msDuration = array_sum($durations); } else { $mediaEntryId = $this->entry->getId(); $this->msDuration = $this->entry->getLengthInMsecs(); } $flavorParamsIds = null; $flavorParamsNotIn = false; if (!$this->isAdmin) { foreach ($this->contextDataResult->getActions() as $action) { if ($action->getType() == RuleActionType::BLOCK) { //in case of block action do not set the list of flavors return; } if ($action->getType() == RuleActionType::LIMIT_FLAVORS) { /* @var $action kAccessControlLimitFlavorsAction */ $flavorParamsIds = explode(',', $action->getFlavorParamsIds()); $flavorParamsNotIn = $action->getIsBlockedList(); } } } $flavorAssets = array(); if (is_null($this->asset)) { if (count($flavorParamsIds)) { $flavorAssets = assetPeer::retrieveReadyByEntryIdAndFlavorParams($mediaEntryId, $flavorParamsIds, $flavorParamsNotIn); } else { $flavorAssets = assetPeer::retrieveFlavorsByEntryIdAndStatus($mediaEntryId, null, array(flavorAsset::ASSET_STATUS_READY)); } if ($mediaEntryId != $this->entry->getId()) { // hack: setting the entry id of the flavors to the original playlist id // since the player uses it in the playManifest url foreach ($flavorAssets as $flavorAsset) { $flavorAsset->setEntryId($this->entry->getId()); } } } else { $flavorAllowed = true; if (count($flavorParamsIds)) { $flavorAllowed = $this->isFlavorAllowed($this->asset->getFlavorParamsId(), $flavorParamsIds, $flavorParamsNotIn); } if ($flavorAllowed) { $flavorAssets[] = $this->asset; } } $this->filterFlavorAssetsByTags($flavorAssets, $flavorTags); }
public static function resizeEntryImage(entry $entry, $version, $width, $height, $type, $bgcolor = "ffffff", $crop_provider = null, $quality = 0, $src_x = 0, $src_y = 0, $src_w = 0, $src_h = 0, $vid_sec = -1, $vid_slice = 0, $vid_slices = -1, $orig_image_path = null) { $contentPath = myContentStorage::getFSContentRootPath(); $entry_status = $entry->getStatus(); $tempThumbName = $entry->getId() . "_{$width}_{$height}_{$type}_{$crop_provider}_{$bgcolor}_{$quality}_{$src_x}_{$src_y}_{$src_w}_{$src_h}_{$vid_sec}_{$vid_slice}_{$vid_slices}_{$entry_status}"; $entryThumbFilename = $entry->getThumbnail() ? $entry->getThumbnail() : "0.jpg"; if ($entry->getStatus() != entryStatus::READY || @$entryThumbFilename[0] == '&') { $tempThumbName .= "_NOCACHE_"; } // we remove the & from the template thumb otherwise getGeneralEntityPath will drop $tempThumbName from the final path $entryThumbFilename = str_replace("&", "", $entryThumbFilename); $basePath = myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $tempThumbName, $entryThumbFilename, $version); $tempThumbPath = $contentPath . $basePath; $cachedTempThumbPath = myContentStorage::getFSCacheRootPath() . $basePath; if (file_exists($cachedTempThumbPath)) { header("X-Kaltura:cached-local-thumb-exists," . md5($cachedTempThumbPath)); return $cachedTempThumbPath; } if (file_exists($tempThumbPath)) { header("X-Kaltura:cached-thumb-exists," . md5($tempThumbPath)); return $tempThumbPath; } if ($orig_image_path === null || !file_exists($orig_image_path)) { $sub_type = $entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_IMAGE ? entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA : entry::FILE_SYNC_ENTRY_SUB_TYPE_THUMB; $orig_image_key = $entry->getSyncKey($sub_type, $version); $orig_image_path = kFileSyncUtils::getReadyLocalFilePathForKey($orig_image_key); } // remark added so ffmpeg will try to load the thumbnail from the original source //if (!file_exists($orig_image_path)) // KExternalErrors::dieError(KExternalErrors::FILE_NOT_FOUND); // check a request for animated thumbs without a concrete vid_slice // in which case we'll create all the frames as one wide image $multi = $vid_slice == -1 && $vid_slices != -1; $count = $multi ? $vid_slices : 1; $im = null; if ($multi) { $vid_slice = 0; } while ($count--) { if ($entry->getMediaType() == entry::ENTRY_MEDIA_TYPE_VIDEO && ($vid_sec != -1 || $vid_slices != -1) || !file_exists($orig_image_path)) { if ($vid_sec != -1) { $calc_vid_sec = min($vid_sec, floor($entry->getLengthInMsecs() / 1000)); } else { if ($vid_slices != -1) { $calc_vid_sec = floor($entry->getLengthInMsecs() / $vid_slices * min($vid_slice, $vid_slices) / 1000); } else { if ($entry->getStatus() != entryStatus::READY && $entry->getLengthInMsecs() == 0) { $calc_vid_sec = $entry->getPartner() && $entry->getPartner()->getDefThumbOffset() ? $entry->getPartner()->getDefThumbOffset() : 3; } else { $calc_vid_sec = $entry->getBestThumbOffset(); } } } $capturedThumbName = $entry->getId() . "_sec_{$calc_vid_sec}"; $capturedThumbPath = $contentPath . myContentStorage::getGeneralEntityPath("entry/tempthumb", $entry->getIntId(), $capturedThumbName, $entry->getThumbnail(), $version); $orig_image_path = $capturedThumbPath . "temp_1.jpg"; // if we already captured the frame at that second, dont recapture, just use the existing file if (!file_exists($orig_image_path)) { // creating the thumbnail is a very heavy operation // prevent calling it in parallel for the same thubmnail for 5 minutes $cache = new myCache("thumb-processing", 5 * 60); // 5 minutes $processing = $cache->get($orig_image_path); if ($processing) { KExternalErrors::dieError(KExternalErrors::PROCESSING_CAPTURE_THUMBNAIL); } $cache->put($orig_image_path, true); $flavorAsset = flavorAssetPeer::retrieveOriginalReadyByEntryId($entry->getId()); if (is_null($flavorAsset) || !($flavorAsset->hasTag(flavorParams::TAG_MBR) || $flavorAsset->hasTag(flavorParams::TAG_WEB))) { // try the best playable $flavorAsset = flavorAssetPeer::retrieveHighestBitrateByEntryId($entry->getId()); } if (is_null($flavorAsset)) { // if no READY ORIGINAL entry is available, try to retreive a non-READY ORIGINAL entry $flavorAsset = flavorAssetPeer::retreiveOriginalByEntryId($entry->getId()); } if (is_null($flavorAsset)) { KExternalErrors::dieError(KExternalErrors::FLAVOR_NOT_FOUND); } $flavorSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $entry_data_path = kFileSyncUtils::getReadyLocalFilePathForKey($flavorSyncKey); if (!$entry_data_path) { // since this is not really being processed on this server, and will probably cause redirect in thumbnailAction // remove from cache so later requests will still get redirected and will not fail on PROCESSING_CAPTURE_THUMBNAIL $cache->remove($orig_image_path); throw new kFileSyncException('no ready filesync on current DC', kFileSyncException::FILE_DOES_NOT_EXIST_ON_CURRENT_DC); } myFileConverter::autoCaptureFrame($entry_data_path, $capturedThumbPath . "temp_", $calc_vid_sec, -1, -1); $cache->remove($orig_image_path); } } kFile::fullMkdir($tempThumbPath); if ($crop_provider) { $convertedImagePath = myFileConverter::convertImageUsingCropProvider($orig_image_path, $tempThumbPath, $width, $height, $type, $crop_provider, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h); } else { $convertedImagePath = myFileConverter::convertImage($orig_image_path, $tempThumbPath, $width, $height, $type, $bgcolor, true, $quality, $src_x, $src_y, $src_w, $src_h); } // die if resize operation failed if ($convertedImagePath === null) { KExternalErrors::dieError(KExternalErrors::IMAGE_RESIZE_FAILED); } if ($multi) { list($w, $h, $type, $attr, $srcIm) = myFileConverter::createImageByFile($tempThumbPath); if (!$im) { $im = imagecreatetruecolor($w * $vid_slices, $h); } imagecopy($im, $srcIm, $w * $vid_slice, 0, 0, 0, $w, $h); imagedestroy($srcIm); ++$vid_slice; } } if ($multi) { imagejpeg($im, $tempThumbPath); imagedestroy($im); } return $tempThumbPath; }
public static function checkForPendingLiveClips(entry $entry) { if ($entry->getSource() != EntrySourceType::RECORDED_LIVE) { KalturaLog::notice("Entry [" . $entry->getId() . "] is not a recorded live"); return; } $liveEntry = entryPeer::retrieveByPKNoFilter($entry->getRootEntryId()); if (!$liveEntry || $liveEntry->getStatus() == entryStatus::DELETED || !$liveEntry instanceof LiveEntry) { KalturaLog::notice("Entry root [" . $entry->getRootEntryId() . "] is not a valid live entry"); return; } /* @var $liveEntry LiveEntry */ $pendingMediaEntries = $liveEntry->getAttachedPendingMediaEntries(); foreach ($pendingMediaEntries as $pendingMediaEntry) { /* @var $pendingMediaEntry kPendingMediaEntry */ if ($pendingMediaEntry->getRequiredDuration() && $pendingMediaEntry->getRequiredDuration() > $entry->getLengthInMsecs()) { KalturaLog::info("Pending entry [" . $pendingMediaEntry->getEntryId() . "] required duration [" . $pendingMediaEntry->getRequiredDuration() . "] while entry duration [" . $entry->getLengthInMsecs() . "] is too short"); continue; } $liveEntry->dettachPendingMediaEntry($pendingMediaEntry->getEntryId()); $pendingEntry = entryPeer::retrieveByPK($pendingMediaEntry->getEntryId()); if (!$pendingEntry) { KalturaLog::info("Pending entry [" . $pendingMediaEntry->getEntryId() . "] not found"); continue; } $sourceAsset = assetPeer::retrieveOriginalByEntryId($entry->getId()); if (!$sourceAsset) { $sourceAssets = assetPeer::retrieveReadyFlavorsByEntryId($entry->getId()); $sourceAsset = array_pop($sourceAssets); } if (!$sourceAsset) { KalturaLog::info("Pending entry [" . $pendingMediaEntry->getEntryId() . "] source asset not found"); continue; } /* @var $sourceAsset flavorAsset */ $operationAttributes = new kClipAttributes(); $operationAttributes->setOffset($pendingMediaEntry->getOffset()); $operationAttributes->setDuration($pendingMediaEntry->getDuration()); $targetAsset = assetPeer::retrieveOriginalByEntryId($pendingMediaEntry->getEntryId()); if (!$targetAsset) { $targetAsset = kFlowHelper::createOriginalFlavorAsset($entry->getPartnerId(), $pendingMediaEntry->getEntryId()); } $targetAsset->setFileExt($sourceAsset->getFileExt()); $targetAsset->save(); $sourceSyncKey = $sourceAsset->getSyncKey(asset::FILE_SYNC_ASSET_SUB_TYPE_ASSET); $targetSyncKey = $targetAsset->getSyncKey(asset::FILE_SYNC_ASSET_SUB_TYPE_ASSET); kFileSyncUtils::createSyncFileLinkForKey($targetSyncKey, $sourceSyncKey); $errDescription = ''; kBusinessPreConvertDL::decideAddEntryFlavor(null, $pendingMediaEntry->getEntryId(), $operationAttributes->getAssetParamsId(), $errDescription, $targetAsset->getId(), array($operationAttributes)); } $liveEntry->save(); }
protected function initEntry() { $this->entryId = $this->getRequestParameter("entryId", null); // look for a valid token $expiry = $this->getRequestParameter("expiry"); if ($expiry && $expiry <= time()) { KExternalErrors::dieError(KExternalErrors::EXPIRED_TOKEN); } $urlToken = $this->getRequestParameter("kt"); if ($urlToken) { if ($_SERVER["REQUEST_METHOD"] != "GET" || !self::validateKalturaToken($_SERVER["REQUEST_URI"], $urlToken)) { KExternalErrors::dieError(KExternalErrors::INVALID_TOKEN); } } // initalize the context $ksStr = $this->getRequestParameter("ks"); if ($ksStr && !$urlToken) { try { kCurrentContext::initKsPartnerUser($ksStr); } catch (Exception $ex) { KExternalErrors::dieError(KExternalErrors::INVALID_KS); } } else { $this->entry = kCurrentContext::initPartnerByEntryId($this->entryId); if (!$this->entry || $this->entry->getStatus() == entryStatus::DELETED) { KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND); } } // no need for any further check if a token was used if ($urlToken) { return; } // enforce entitlement kEntitlementUtils::initEntitlementEnforcement(); if (!$this->entry) { $this->entry = entryPeer::retrieveByPKNoFilter($this->entryId); if (!$this->entry || $this->entry->getStatus() == entryStatus::DELETED) { KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND); } } else { if (!kEntitlementUtils::isEntryEntitled($this->entry)) { KExternalErrors::dieError(KExternalErrors::ENTRY_NOT_FOUND); } } myPartnerUtils::blockInactivePartner($this->entry->getPartnerId()); // enforce access control $base64Referrer = $this->getRequestParameter("referrer"); $hashes = $this->getRequestParameter("hashes"); $keyValueHashes = array(); if ($hashes) { $hashes = urldecode($hashes); $hashes = explode(",", $hashes); foreach ($hashes as $keyValueHashString) { list($key, $value) = explode('=', $keyValueHashString); $keyValueHashes[$key] = $value; } } // replace space in the base64 string with + as space is invalid in base64 strings and caused // by symfony calling str_parse to replace + with spaces. // this happens only with params passed in the url path and not the query strings. specifically the ~ char at // a columns divided by 3 causes this issue (e.g. http://www.xyzw.com/~xxx) //replace also any - with + and _ with / $referrer = base64_decode(str_replace(array('-', '_', ' '), array('+', '/', '+'), $base64Referrer)); if (!is_string($referrer)) { $referrer = ""; } // base64_decode can return binary data $this->secureEntryHelper = new KSecureEntryHelper($this->entry, $ksStr, $referrer, ContextType::PLAY, $keyValueHashes); if ($this->secureEntryHelper->shouldPreview()) { $previewLengthInMsecs = $this->secureEntryHelper->getPreviewLength() * 1000; $entryLengthInMsecs = $this->entry->getLengthInMsecs(); if ($previewLengthInMsecs < $entryLengthInMsecs) { $this->deliveryAttributes->setClipTo($previewLengthInMsecs); } } else { $this->secureEntryHelper->validateForPlay(); } if (PermissionPeer::isValidForPartner(PermissionName::FEATURE_ENTITLEMENT, $this->entry->getPartnerId()) || $this->secureEntryHelper->hasRules()) { $this->forceUrlTokenization = true; } }
public function estimateFileSize(entry $entry, $seconds) { $orginalSizeKB = $this->getSize(); $size = $orginalSizeKB * ($seconds / ($entry->getLengthInMsecs() / 1000)) * 1.2; $size = min($orginalSizeKB, floor($size)) * 1024; return $size; }
/** * @param entry $entry * @param SimpleXMLElement $mrss */ protected static function appendDataEntryMrss(entry $entry, SimpleXMLElement $mrss) { $media = $mrss->addChild('livestream'); $media->addChild('mediaType', $entry->getMediaType()); $media->addChild('duration', $entry->getLengthInMsecs()); }