public static function decideProfileFlavorsConvert(BatchJob $parentJob, BatchJob $convertProfileJob, array $flavors, array $conversionProfileFlavorParams, mediaInfo $mediaInfo = null) { $entryId = $convertProfileJob->getEntryId(); $originalFlavorAsset = flavorAssetPeer::retrieveOriginalByEntryId($entryId); if (is_null($originalFlavorAsset)) { $errDescription = 'Original flavor asset not found'; KalturaLog::err($errDescription); $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription, BatchJobType::CONVERT_PROFILE); kBatchManager::updateEntry($convertProfileJob, entryStatus::ERROR_CONVERTING); return false; } $errDescription = null; $finalFlavors = self::validateConversionProfile($convertProfileJob->getPartnerId(), $entryId, $mediaInfo, $flavors, $conversionProfileFlavorParams, $errDescription); KalturaLog::log(count($finalFlavors) . " flavors returned from the decision layer"); if (is_null($finalFlavors)) { $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription); KalturaLog::log("No flavors created"); throw new Exception($errDescription); } if (strlen($errDescription)) { $err = $convertProfileJob->getDescription() . $errDescription; $convertProfileJob->setDescription($err); $convertProfileJob->save(); } $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $conversionsCreated = 0; $entry = $convertProfileJob->getEntry(); if (!$entry) { throw new APIException(APIErrors::INVALID_ENTRY, $convertProfileJob, $entryId); } $flavorsCollections = array(); // create a convert job per each flavor foreach ($finalFlavors as $flavor) { $flavorAsset = kBatchManager::createFlavorAsset($flavor, $entry->getPartnerId(), $entry->getId()); if (!$flavorAsset) { KalturaLog::log("Flavor asset could not be created, flavor conversion won't be created"); continue; } $collectionTag = $flavor->getCollectionTag(); if ($collectionTag) { $flavorsCollections[$collectionTag][] = $flavor; continue; } KalturaLog::log("Adding flavor conversion with flavor params output id [" . $flavor->getId() . "] and flavor params asset id [" . $flavorAsset->getId() . "]"); $madiaInfoId = $mediaInfo ? $mediaInfo->getId() : null; $createdJob = kJobsManager::addFlavorConvertJob($srcSyncKey, $flavor, $flavorAsset->getId(), $madiaInfoId, $parentJob); if ($createdJob) { $conversionsCreated++; } } foreach ($flavorsCollections as $tag => $flavors) { switch ($tag) { case flavorParams::TAG_ISM: $createdJob = kJobsManager::addConvertIsmCollectionJob($tag, $srcSyncKey, $entry, $parentJob, $flavors); if ($createdJob) { $conversionsCreated++; } break; default: KalturaLog::log("Error: Invalid collection tag [{$tag}]"); break; } } if (!$conversionsCreated) { $convertProfileJob = kJobsManager::failBatchJob($convertProfileJob, $errDescription); KalturaLog::log("No flavors created: {$errDescription}"); return false; } return true; }
/** * @param BatchJob $dbBatchJob * @param kConvertJobData $data * @param BatchJob $twinJob * @return BatchJob */ public static function handleConvertFinished(BatchJob $dbBatchJob, kConvertJobData $data, BatchJob $twinJob = null) { KalturaLog::debug("Convert finished with destination file: " . $data->getDestFileSyncLocalPath()); if ($dbBatchJob->getAbort()) { return $dbBatchJob; } // verifies that flavor asset created if (!$data->getFlavorAssetId()) { throw new APIException(APIErrors::INVALID_FLAVOR_ASSET_ID, $data->getFlavorAssetId()); } $flavorAsset = flavorAssetPeer::retrieveById($data->getFlavorAssetId()); // verifies that flavor asset exists if (!$flavorAsset) { throw new APIException(APIErrors::INVALID_FLAVOR_ASSET_ID, $data->getFlavorAssetId()); } $flavorAsset->incrementVersion(); $flavorAsset->save(); $syncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); kFileSyncUtils::moveFromFile($data->getDestFileSyncLocalPath(), $syncKey); // creats the file sync $logSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_CONVERT_LOG); try { kFileSyncUtils::moveFromFile($data->getDestFileSyncLocalPath() . '.log', $logSyncKey); } catch (Exception $e) { $err = 'Saving conversion log: ' . $e->getMessage(); KalturaLog::err($err); $desc = $dbBatchJob->getDescription() . "\n" . $err; $dbBatchJob->getDescription($desc); } $data->setDestFileSyncLocalPath(kFileSyncUtils::getLocalFilePathForKey($syncKey)); KalturaLog::debug("Convert archived file to: " . $data->getDestFileSyncLocalPath()); // save the data changes to the db $dbBatchJob->setData($data); $dbBatchJob->save(); $entry = $dbBatchJob->getEntry(); if (!$entry) { throw new APIException(APIErrors::INVALID_ENTRY, $dbBatchJob, $dbBatchJob->getEntryId()); } $entry->addFlavorParamsId($data->getFlavorParamsOutput()->getFlavorParamsId()); $entry->save(); $offset = $entry->getThumbOffset(); // entry getThumbOffset now takes the partner DefThumbOffset into consideration $flavorParamsOutput = $data->getFlavorParamsOutput(); $createThumb = true; $extractMedia = true; if ($entry->getType() != entryType::MEDIA_CLIP) { // e.g. document $extractMedia = false; } $rootBatchJob = $dbBatchJob->getRootJob(); if (!$rootBatchJob) { $createThumb = false; } else { if ($rootBatchJob->getJobType() != BatchJobType::CONVERT_PROFILE) { $createThumb = false; } else { $rootBatchJobData = $rootBatchJob->getData(); if ($rootBatchJobData instanceof kConvertProfileJobData) { $createThumb = $rootBatchJobData->getCreateThumb(); $extractMedia = $rootBatchJobData->getExtractMedia(); } } } // For apple http flavors do not attempt to get thumbs and media info, // It is up to the operator to provide that kind of data, rather than hardcoded check // To-fix if ($flavorParamsOutput->getFormat() == assetParams::CONTAINER_FORMAT_APPLEHTTP) { $createThumb = false; $extractMedia = false; } if ($createThumb) { $videoCodec = $flavorParamsOutput->getVideoCodec(); if (in_array($videoCodec, self::$thumbUnSupportVideoCodecs)) { $createThumb = false; } } $operatorSet = new kOperatorSets(); $operatorSet->setSerialized(stripslashes($flavorParamsOutput->getOperators())); // KalturaLog::debug("Operators: ".$flavorParamsOutput->getOperators() // ."\ngetCurrentOperationSet:".$data->getCurrentOperationSet() // ."\ngetCurrentOperationIndex:".$data->getCurrentOperationIndex()); // KalturaLog::debug("Operators set: " . print_r($operatorSet, true)); $nextOperator = $operatorSet->getOperator($data->getCurrentOperationSet(), $data->getCurrentOperationIndex() + 1); $nextJob = null; if ($nextOperator) { // KalturaLog::debug("Found next operator"); $nextJob = kJobsManager::addFlavorConvertJob($syncKey, $flavorParamsOutput, $data->getFlavorAssetId(), $data->getMediaInfoId(), $dbBatchJob, $dbBatchJob->getJobSubType()); } if (!$nextJob) { if ($createThumb || $extractMedia) { $jobSubType = BatchJob::BATCHJOB_SUB_TYPE_POSTCONVERT_FLAVOR; if ($flavorAsset->getIsOriginal()) { $jobSubType = BatchJob::BATCHJOB_SUB_TYPE_POSTCONVERT_SOURCE; } kJobsManager::addPostConvertJob($dbBatchJob, $jobSubType, $data->getDestFileSyncLocalPath(), $data->getFlavorAssetId(), $flavorParamsOutput->getId(), $createThumb, $offset); } else { $flavorAsset = kBusinessPostConvertDL::handleFlavorReady($dbBatchJob, $data->getFlavorAssetId()); if ($flavorAsset) { if ($flavorAsset->hasTag(flavorParams::TAG_SOURCE)) { kBusinessPreConvertDL::continueProfileConvert($dbBatchJob); } if ($flavorAsset->getType() == assetType::FLAVOR) { $flavorAsset->setBitrate($flavorParamsOutput->getVideoBitrate()); $flavorAsset->setWidth($flavorParamsOutput->getWidth()); $flavorAsset->setHeight($flavorParamsOutput->getHeight()); $flavorAsset->setFrameRate($flavorParamsOutput->getFrameRate()); $flavorAsset->setIsOriginal(0); $flavorAsset->save(); } kBusinessPostConvertDL::handleConvertFinished($dbBatchJob, $flavorAsset); } } } // this logic decide when a thumbnail should be created if ($rootBatchJob && $rootBatchJob->getJobType() == BatchJobType::BULKDOWNLOAD) { $localPath = kFileSyncUtils::getLocalFilePathForKey($syncKey); $downloadUrl = $flavorAsset->getDownloadUrl(); $notificationData = array("puserId" => $entry->getPuserId(), "entryId" => $entry->getId(), "entryIntId" => $entry->getIntId(), "entryVersion" => $entry->getVersion(), "fileFormat" => $flavorAsset->getFileExt(), "archivedFile" => $localPath, "downoladPath" => $localPath, "conversionQuality" => $entry->getConversionQuality(), "downloadUrl" => $downloadUrl); $extraData = array("data" => json_encode($notificationData), "partner_id" => $entry->getPartnerId(), "puser_id" => $entry->getPuserId(), "entry_id" => $entry->getId(), "entry_int_id" => $entry->getIntId(), "entry_version" => $entry->getVersion(), "file_format" => $flavorAsset->getFileExt(), "archived_file" => $localPath, "downolad_path" => $localPath, "target" => $localPath, "conversion_quality" => $entry->getConversionQuality(), "download_url" => $downloadUrl, "status" => $entry->getStatus(), "abort" => $dbBatchJob->getAbort(), "progress" => $dbBatchJob->getProgress(), "message" => $dbBatchJob->getMessage(), "description" => $dbBatchJob->getDescription(), "updates_count" => $dbBatchJob->getUpdatesCount(), "job_type" => BatchJobType::DOWNLOAD, "status" => BatchJob::BATCHJOB_STATUS_FINISHED, "progress" => 100, "debug" => __LINE__); myNotificationMgr::createNotification(kNotificationJobData::NOTIFICATION_TYPE_BATCH_JOB_SUCCEEDED, $dbBatchJob, $dbBatchJob->getPartnerId(), null, null, $extraData, $dbBatchJob->getEntryId()); } return $dbBatchJob; }
private static function decideSourceFlavorConvert($entryId, assetParams $sourceFlavor = null, flavorAsset $originalFlavorAsset, $conversionProfileId, $flavors, mediaInfo $mediaInfo = null, BatchJob $parentJob, BatchJob $convertProfileJob) { if ($sourceFlavor && ($sourceFlavor->getOperators() || $sourceFlavor->getConversionEngines()) && $originalFlavorAsset->getInterFlowCount() == null) { KalturaLog::log("Source flavor asset requires conversion"); self::adjustAssetParams($entryId, array($sourceFlavor)); $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $errDescription = null; $sourceFlavorOutput = self::validateFlavorAndMediaInfo($sourceFlavor, $mediaInfo, $errDescription); if (!$sourceFlavorOutput) { if (!$errDescription) { $errDescription = "Failed to create flavor params output from source flavor"; } $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); $originalFlavorAsset->setStatus(flavorAsset::ASSET_STATUS_ERROR); $originalFlavorAsset->save(); kBatchManager::updateEntry($entryId, entryStatus::ERROR_CONVERTING); kJobsManager::updateBatchJob($convertProfileJob, BatchJob::BATCHJOB_STATUS_FAILED); return false; } /* * If the conversion profile contains source flavor and the source is tagged with 'save_source' ==> * save the original source asset in another asset, in order * to prevent its liquidated by the inter-source asset. */ if (isset($sourceFlavor) && strstr($sourceFlavor->getTagsArray(), assetParams::TAG_SAVE_SOURCE) !== false) { self::saveOriginalSource($mediaInfo); } } elseif ($mediaInfo) { /* * Check whether there is a need for an intermediate source pre-processing */ $sourceFlavorOutput = KDLWrap::GenerateIntermediateSource($mediaInfo, $flavors); if (!$sourceFlavorOutput) { return true; } $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $errDescription = null; /* * Save the original source asset in another asset, in order * to prevent its liquidated by the inter-source asset. * But, do it only if the conversion profile contains source flavor */ if (isset($sourceFlavor)) { self::saveOriginalSource($mediaInfo); } } /* * '_passthrough' controls whether the source is to be 'passthrough' although there * is a source flavor that contains transcoder settings. * Looks for a '_passthrough' flag on the source's flavor params output. */ if (!isset($sourceFlavorOutput) || $sourceFlavorOutput->_passthrough == true) { return true; } // save flavor params $sourceFlavorOutput->setPartnerId($sourceFlavorOutput->getPartnerId()); $sourceFlavorOutput->setEntryId($entryId); $sourceFlavorOutput->setFlavorAssetId($originalFlavorAsset->getId()); $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } $errDescription = kBusinessConvertDL::parseFlavorDescription($sourceFlavorOutput); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } // decided by the business logic layer if ($sourceFlavorOutput->_create_anyway) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] selected to be created anyway"); } else { if (!$sourceFlavorOutput->IsValid()) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is invalid"); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR); $originalFlavorAsset->save(); $errDescription = "Source flavor could not be converted"; self::setError($errDescription, $convertProfileJob, BatchJobType::CONVERT_PROFILE, $convertProfileJob->getEntryId()); return false; } if ($sourceFlavorOutput->_force) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is forced"); } elseif ($sourceFlavorOutput->_isNonComply) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is none-comply"); } else { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is valid"); } } $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_CONVERTING); if (isset($sourceFlavor)) { $tagsArr = $sourceFlavor->getTagsArray(); // No need for 'save_source' tag on the inter-src asset, remove it. if (($key = array_search(assetParams::TAG_SAVE_SOURCE, $tagsArr)) !== false) { unset($tagsArr[$key]); } $originalFlavorAsset->addTags($tagsArr); $originalFlavorAsset->setFileExt($sourceFlavorOutput->getFileExt()); $originalFlavorAsset->save(); } // save flavor params $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); $mediaInfoId = null; if ($mediaInfo) { $mediaInfoId = $mediaInfo->getId(); } kJobsManager::addFlavorConvertJob(array($srcSyncKey), $sourceFlavorOutput, $originalFlavorAsset->getId(), $conversionProfileId, $mediaInfoId, $parentJob); return false; }
private static function decideSourceFlavorConvert($entryId, assetParams $sourceFlavor = null, flavorAsset $originalFlavorAsset, $conversionProfileId, $flavors, mediaInfo $mediaInfo = null, BatchJob $parentJob, BatchJob $convertProfileJob) { if ($sourceFlavor && ($sourceFlavor->getOperators() || $sourceFlavor->getConversionEngines()) && $originalFlavorAsset->getInterFlowCount() == null) { KalturaLog::log("Source flavor asset requires conversion"); self::adjustAssetParams($entryId, array($sourceFlavor)); $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $errDescription = null; $sourceFlavorOutput = self::validateFlavorAndMediaInfo($sourceFlavor, $mediaInfo, $errDescription); if (!$sourceFlavorOutput) { if (!$errDescription) { $errDescription = "Failed to create flavor params output from source flavor"; } $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); $originalFlavorAsset->setStatus(flavorAsset::ASSET_STATUS_ERROR); $originalFlavorAsset->save(); kBatchManager::updateEntry($entryId, entryStatus::ERROR_CONVERTING); kJobsManager::updateBatchJob($convertProfileJob, BatchJob::BATCHJOB_STATUS_FAILED); return false; } } elseif ($mediaInfo) { /* * Check whether there is a need for an intermediate source pre-processing */ $sourceFlavorOutput = KDLWrap::GenerateIntermediateSource($mediaInfo, $flavors); if (!$sourceFlavorOutput) { return true; } $srcSyncKey = $originalFlavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET); $errDescription = null; /* * Save the original source asset in another asset, in order * to prevent its liquidated by the inter-source asset. * But, do it only if the conversion profile contains source flavor */ if ($sourceFlavor) { $sourceAsset = assetPeer::retrieveById($mediaInfo->getFlavorAssetId()); $copyFlavorParams = assetParamsPeer::retrieveBySystemName(self::SAVE_ORIGINAL_SOURCE_FLAVOR_PARAM_SYS_NAME); if (!$copyFlavorParams) { throw new APIException(APIErrors::OBJECT_NOT_FOUND); } $asset = $sourceAsset->copy(); $asset->setFlavorParamsId($copyFlavorParams->getId()); $asset->setFromAssetParams($copyFlavorParams); $asset->setStatus(flavorAsset::ASSET_STATUS_READY); $asset->setIsOriginal(0); $asset->setTags($copyFlavorParams->getTags()); $asset->incrementVersion(); $asset->save(); kFileSyncUtils::createSyncFileLinkForKey($asset->getSyncKey(asset::FILE_SYNC_ASSET_SUB_TYPE_ASSET), $sourceAsset->getSyncKey(asset::FILE_SYNC_ASSET_SUB_TYPE_ASSET)); $origFileSync = kFileSyncUtils::getLocalFileSyncForKey($sourceAsset->getSyncKey(asset::FILE_SYNC_ASSET_SUB_TYPE_ASSET)); $asset->setSize(intval($origFileSync->getFileSize() / 1000)); $asset->save(); } } /* * '_passthrough' controls whether the source is to be 'passthrough' although there * is a source flavor that contains transcoder settings. * Looks for a '_passthrough' flag on the source's flavor params output. */ if (!$sourceFlavorOutput || $sourceFlavorOutput->_passthrough == true) { return true; } // save flavor params $sourceFlavorOutput->setPartnerId($sourceFlavorOutput->getPartnerId()); $sourceFlavorOutput->setEntryId($entryId); $sourceFlavorOutput->setFlavorAssetId($originalFlavorAsset->getId()); $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } $errDescription = kBusinessConvertDL::parseFlavorDescription($sourceFlavorOutput); if ($errDescription) { $originalFlavorAsset->setDescription($originalFlavorAsset->getDescription() . "\n{$errDescription}"); } // decided by the business logic layer if ($sourceFlavorOutput->_create_anyway) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] selected to be created anyway"); } else { if (!$sourceFlavorOutput->IsValid()) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is invalid"); $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR); $originalFlavorAsset->save(); $errDescription = "Source flavor could not be converted"; self::setError($errDescription, $convertProfileJob, BatchJobType::CONVERT_PROFILE, $convertProfileJob->getEntryId()); return false; } if ($sourceFlavorOutput->_force) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is forced"); } elseif ($sourceFlavorOutput->_isNonComply) { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is none-comply"); } else { KalturaLog::log("Flavor [" . $sourceFlavorOutput->getFlavorParamsId() . "] is valid"); } } $originalFlavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_CONVERTING); if (isset($sourceFlavor)) { $originalFlavorAsset->addTags($sourceFlavor->getTagsArray()); $originalFlavorAsset->setFileExt($sourceFlavorOutput->getFileExt()); $originalFlavorAsset->save(); } // save flavor params $sourceFlavorOutput->setFlavorAssetVersion($originalFlavorAsset->getVersion()); $sourceFlavorOutput->save(); $mediaInfoId = null; if ($mediaInfo) { $mediaInfoId = $mediaInfo->getId(); } kJobsManager::addFlavorConvertJob(array($srcSyncKey), $sourceFlavorOutput, $originalFlavorAsset->getId(), $conversionProfileId, $mediaInfoId, $parentJob); return false; }
private static function createNextJob(flavorParamsOutput $flavorParamsOutput, BatchJob $dbBatchJob, kConvertJobData $data, FileSyncKey $syncKey) { $operatorSet = new kOperatorSets(); $operatorSet->setSerialized(stripslashes($flavorParamsOutput->getOperators())); $nextOperator = $operatorSet->getOperator($data->getCurrentOperationSet(), $data->getCurrentOperationIndex() + 1); $nextJob = null; if ($nextOperator) { //Note: consequent operators doesn't support at the moment conversion based on outputs of multiple sources $nextJob = kJobsManager::addFlavorConvertJob(array($syncKey), $flavorParamsOutput, $data->getFlavorAssetId(), null, $data->getMediaInfoId(), $dbBatchJob, $dbBatchJob->getJobSubType()); } return $nextJob; }