/** * @param BatchJob $parentJob * @param int $srcParamsId */ public static function generateThumbnailsFromFlavor($entryId, BatchJob $parentJob = null, $srcParamsId = null) { $profile = null; try { $profile = myPartnerUtils::getConversionProfile2ForEntry($entryId); } catch (Exception $e) { KalturaLog::err('getConversionProfile2ForEntry Error: ' . $e->getMessage()); } if (!$profile) { KalturaLog::notice("Profile not found for entry id [{$entryId}]"); return; } $entry = entryPeer::retrieveByPK($entryId); if (!$entry) { KalturaLog::notice("Entry id [{$entryId}] not found"); return; } $assetParamsIds = flavorParamsConversionProfilePeer::getFlavorIdsByProfileId($profile->getId()); if (!count($assetParamsIds)) { KalturaLog::notice("No asset params objects found for profile id [" . $profile->getId() . "]"); return; } // the alternative is the source or the highest bitrate if source not defined $alternateFlavorParamsId = null; if (is_null($srcParamsId)) { $flavorParamsObjects = flavorParamsPeer::retrieveByPKs($assetParamsIds); foreach ($flavorParamsObjects as $flavorParams) { if ($flavorParams->hasTag(flavorParams::TAG_SOURCE)) { $alternateFlavorParamsId = $flavorParams->getId(); } } if (is_null($alternateFlavorParamsId)) { $srcFlavorAsset = flavorAssetPeer::retrieveHighestBitrateByEntryId($entryId); $alternateFlavorParamsId = $srcFlavorAsset->getFlavorParamsId(); } if (is_null($alternateFlavorParamsId)) { KalturaLog::notice("No source flavor params object found for entry id [{$entryId}]"); return; } } // create list of created thumbnails $thumbAssetsList = array(); $thumbAssets = thumbAssetPeer::retrieveByEntryId($entryId); if (count($thumbAssets)) { foreach ($thumbAssets as $thumbAsset) { if (!is_null($thumbAsset->getFlavorParamsId())) { $thumbAssetsList[$thumbAsset->getFlavorParamsId()] = $thumbAsset; } } } $thumbParamsObjects = thumbParamsPeer::retrieveByPKs($assetParamsIds); foreach ($thumbParamsObjects as $thumbParams) { // check if this thumbnail already created if (isset($thumbAssetsList[$thumbParams->getId()])) { continue; } if (is_null($srcParamsId) && is_null($thumbParams->getSourceParamsId())) { // alternative should be used $thumbParams->setSourceParamsId($alternateFlavorParamsId); } elseif ($thumbParams->getSourceParamsId() != $srcParamsId) { // only thumbnails that uses srcParamsId should be generated for now continue; } kBusinessPreConvertDL::decideThumbGenerate($entry, $thumbParams, $parentJob); } }
/** * decideThumbGenerate is the decision layer for a single thumbnail generation * * @param entry $entry * @param thumbParams $destThumbParams * @param BatchJob $parentJob * @return thumbAsset */ public static function decideThumbGenerate(entry $entry, thumbParams $destThumbParams, BatchJob $parentJob = null, $sourceAssetId = null, $runSync = false) { $srcAsset = null; assetPeer::resetInstanceCriteriaFilter(); if ($sourceAssetId) { $srcAsset = assetPeer::retrieveById($sourceAssetId); } else { if ($destThumbParams->getSourceParamsId()) { KalturaLog::debug("Look for flavor params [" . $destThumbParams->getSourceParamsId() . "]"); $srcAsset = assetPeer::retrieveByEntryIdAndParams($entry->getId(), $destThumbParams->getSourceParamsId()); } if (is_null($srcAsset)) { KalturaLog::debug("Look for original flavor"); $srcAsset = flavorAssetPeer::retrieveOriginalByEntryId($entry->getId()); } if (is_null($srcAsset) || $srcAsset->getStatus() != flavorAsset::FLAVOR_ASSET_STATUS_READY) { KalturaLog::debug("Look for highest bitrate flavor"); $srcAsset = flavorAssetPeer::retrieveHighestBitrateByEntryId($entry->getId()); } } if (is_null($srcAsset)) { throw new APIException(APIErrors::FLAVOR_ASSET_IS_NOT_READY); } $errDescription = null; $mediaInfo = mediaInfoPeer::retrieveByFlavorAssetId($srcAsset->getId()); $destThumbParamsOutput = self::validateThumbAndMediaInfo($destThumbParams, $mediaInfo, $errDescription); $thumbAsset = thumbAssetPeer::retrieveByEntryIdAndParams($entry->getId(), $destThumbParams->getId()); if ($thumbAsset) { $description = $thumbAsset->getDescription() . "\n" . $errDescription; $thumbAsset->setDescription($description); } else { $thumbAsset = new thumbAsset(); $thumbAsset->setPartnerId($entry->getPartnerId()); $thumbAsset->setEntryId($entry->getId()); $thumbAsset->setDescription($errDescription); $thumbAsset->setFlavorParamsId($destThumbParams->getId()); } $thumbAsset->incrementVersion(); $thumbAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_CONVERTING); $thumbAsset->setTags($destThumbParamsOutput->getTags()); $thumbAsset->setFileExt($destThumbParamsOutput->getFileExt()); if (!$destThumbParamsOutput) { $thumbAsset->setStatus(thumbAsset::FLAVOR_ASSET_STATUS_ERROR); $thumbAsset->save(); return null; } $thumbAsset->save(); // save flavor params $destThumbParamsOutput->setPartnerId($entry->getPartnerId()); $destThumbParamsOutput->setEntryId($entry->getId()); $destThumbParamsOutput->setFlavorAssetId($thumbAsset->getId()); $destThumbParamsOutput->setFlavorAssetVersion($thumbAsset->getVersion()); $destThumbParamsOutput->save(); $srcSyncKey = $srcAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $srcAssetType = $srcAsset->getType(); if (!$runSync) { $job = kJobsManager::addCapturaThumbJob($parentJob, $entry->getPartnerId(), $entry->getId(), $thumbAsset->getId(), $srcSyncKey, $srcAssetType, $destThumbParamsOutput); return $thumbAsset; } $errDescription = null; $capturedPath = self::generateThumbnail($srcAsset, $destThumbParamsOutput, $errDescription); // failed if (!$capturedPath) { $thumbAsset->incrementVersion(); $thumbAsset->setStatus(thumbAsset::FLAVOR_ASSET_STATUS_ERROR); $thumbAsset->setDescription($thumbAsset->getDescription() . "\n{$errDescription}"); $thumbAsset->save(); return $thumbAsset; } $thumbAsset->incrementVersion(); $thumbAsset->setStatus(thumbAsset::FLAVOR_ASSET_STATUS_READY); if (file_exists($capturedPath)) { list($width, $height, $type, $attr) = getimagesize($capturedPath); $thumbAsset->setWidth($width); $thumbAsset->setHeight($height); $thumbAsset->setSize(filesize($capturedPath)); } $logPath = $capturedPath . '.log'; if (file_exists($logPath)) { $thumbAsset->incLogFileVersion(); $thumbAsset->save(); // creats the file sync $logSyncKey = $thumbAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_CONVERT_LOG); kFileSyncUtils::moveFromFile($logPath, $logSyncKey); KalturaLog::debug("Log archived file to: " . kFileSyncUtils::getLocalFilePathForKey($logSyncKey)); } else { $thumbAsset->save(); } $syncKey = $thumbAsset->getSyncKey(thumbAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); kFileSyncUtils::moveFromFile($capturedPath, $syncKey); KalturaLog::debug("Thumbnail archived file to: " . kFileSyncUtils::getLocalFilePathForKey($syncKey)); if ($thumbAsset->hasTag(thumbParams::TAG_DEFAULT_THUMB)) { // increment thumbnail version $entry->setThumbnail(".jpg"); $entry->save(); $entrySyncKey = $entry->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_THUMB); $syncFile = kFileSyncUtils::createSyncFileLinkForKey($entrySyncKey, $syncKey, false); if ($syncFile) { // removes the DEFAULT_THUMB tag from all other thumb assets $entryThumbAssets = thumbAssetPeer::retrieveByEntryId($thumbAsset->getEntryId()); foreach ($entryThumbAssets as $entryThumbAsset) { if ($entryThumbAsset->getId() == $thumbAsset->getId()) { continue; } if (!$entryThumbAsset->hasTag(thumbParams::TAG_DEFAULT_THUMB)) { continue; } $entryThumbAsset->removeTags(array(thumbParams::TAG_DEFAULT_THUMB)); $entryThumbAsset->save(); } } } if (!is_null($thumbAsset->getFlavorParamsId())) { kFlowHelper::generateThumbnailsFromFlavor($thumbAsset->getEntryId(), null, $thumbAsset->getFlavorParamsId()); } return $thumbAsset; }
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; }