/** * Extract media information from remote file * @return KalturaMediaInfo */ public function getMediaInfo() { $mediaFileExt = pathinfo($this->filePath, PATHINFO_EXTENSION); $kWAMS = kWAMS::getInstance($this->partnerId); $wamsFileSize = $kWAMS->getFileSizeForAssetId($this->wamsAssetId, $mediaFileExt); $mediaInfo = $this->mediaInfoParser->getMediaInfo(); if ($this->validateMediaInfo($mediaInfo)) { $mediaInfo->fileSize = $wamsFileSize / 1024; // size in KB return $mediaInfo; } $localFileSize = filesize($this->filePath); $fp = fopen($kWAMS->getUrlForAssetId($this->wamsAssetId, $mediaFileExt), 'rb'); if ($localFileSize > 0) { stream_get_contents($fp, $localFileSize); } while (!$this->validateMediaInfo($mediaInfo) && $localFileSize < $wamsFileSize) { $blockContent = stream_get_contents($fp, self::MAX_BLOCK_SIZE); $this->appendBlock($blockContent); clearstatcache(); $localFileSize = filesize($this->filePath); $mediaInfo = $this->mediaInfoParser->getMediaInfo(); } fclose($fp); if (!empty($mediaInfo)) { $mediaInfo->fileSize = $wamsFileSize / 1024; // size in KB } return $mediaInfo; }
public function createThumbnail($position, $width, $height, $dar = null) { KalturaLog::debug("Creation thumbnail via WAMS position = [{$position}], width = [{$width}], height = [{$height}], dar = [{$dar}]"); if (isset($dar) && $dar > 0 && isset($height)) { $width = floor(round($height * $dar) / 2) * 2; } $thumbFormat = 'jpg'; $kWAMS = kWAMS::getInstance($this->partnerId); $thumbAssetId = $kWAMS->createThumbnail($this->srcWAMSAssetId, $position, $width, $height, $thumbFormat); if (!$thumbAssetId) { return false; } else { $thumbURL = $kWAMS->getUrlForAssetId($thumbAssetId, $thumbFormat); // download KalturaLog::debug("Downloading thumbnail url = [{$thumbURL}]"); file_put_contents($this->targetPath, fopen($thumbURL, 'rb')); $kWAMS->deleteAssetById($thumbAssetId); return true; } }
/** * Do converting * @param KalturaConvertJobData $data Job data * @return array Result of converting */ public function convertJob(KalturaConvertJobData &$data) { $outputParams = $data->flavorParamsOutput; $videoCodec = $outputParams->videoCodec; $videoBitrate = $outputParams->videoBitrate; $width = $outputParams->width; $height = $outputParams->height; $presetName = $outputParams->name; $preset = array(); $preset[kWAMS::CONVERT_PARAM_PRESET_NAME] = $outputParams->name; $preset[kWAMS::CONVERT_PARAM_AUDIO_CODEC] = $outputParams->audioCodec; $preset[kWAMS::CONVERT_PARAM_AUDIO_BITRATE] = $outputParams->audioBitrate; $preset[kWAMS::CONVERT_PARAM_AUDIO_CHANNELS] = $outputParams->audioChannels; $preset[kWAMS::CONVERT_PARAM_AUDIO_SAMPLE_RATE] = $outputParams->audioSampleRate; $preset[kWAMS::CONVERT_PARAM_VIDEO_CODEC] = $outputParams->videoCodec; $preset[kWAMS::CONVERT_PARAM_VIDEO_WIDTH] = $outputParams->width; $preset[kWAMS::CONVERT_PARAM_VIDEO_HEIGHT] = $outputParams->height; $preset[kWAMS::CONVERT_PARAM_VIDEO_BITRATE] = $outputParams->videoBitrate; KalturaLog::debug("Video params output: preset = [{$presetName}], videoCodec = [{$videoCodec}], videoBitrate = [{$videoBitrate}], width = [{$width}], height = [{$height}]"); $start = microtime(true); $kWAMS = kWAMS::getInstance($data->flavorParamsOutput->partnerId); $wamsJobId = $kWAMS->addConvertJob($data->srcFileSyncWamsAssetId, $preset); Propel::disableInstancePooling(); while ($kWAMS->isJobProcessing($wamsJobId)) { // check Kaltura Batch Job Status if (BatchJobPeer::retrieveByPK($this->batchJobId)->getAbort()) { $kWAMS->cancelJob($wamsJobId); } sleep(5); } Propel::enableInstancePooling(); $data->destFileSyncWamsAssetId = $kWAMS->getOutputAssetId($wamsJobId); $end = microtime(true); $duration = $end - $start; KalturaLog::info($this->getName() . ": took [{$duration}] seconds"); return array(true, null); }
/** * @param AttachmentAsset $attachmentAsset * @param string $fullPath * @param bool $copyOnly */ protected function attachFile(AttachmentAsset $attachmentAsset, $fullPath, $copyOnly = false) { $ext = pathinfo($fullPath, PATHINFO_EXTENSION); $attachmentAsset->incrementVersion(); $attachmentAsset->setFileExt($ext); $attachmentAsset->setSize(kFile::fileSize($fullPath)); $attachmentAsset->save(); $syncKey = $attachmentAsset->getSyncKey(AttachmentAsset::FILE_SYNC_ASSET_SUB_TYPE_ASSET); try { kFileSyncUtils::moveFromFile($fullPath, $syncKey, true, $copyOnly); } catch (Exception $e) { if ($attachmentAsset->getStatus() == AttachmentAsset::ASSET_STATUS_QUEUED || $attachmentAsset->getStatus() == AttachmentAsset::ASSET_STATUS_NOT_APPLICABLE) { $attachmentAsset->setDescription($e->getMessage()); $attachmentAsset->setStatus(AttachmentAsset::ASSET_STATUS_ERROR); $attachmentAsset->save(); } throw $e; } $finalPath = kFileSyncUtils::getLocalFilePathForKey($syncKey); $wamsURL = kFileSyncUtils::getWamsURLForKey($syncKey); if (empty($wamsURL)) { list($width, $height, $type, $attr) = getimagesize($finalPath); $fileSize = kFile::fileSize($finalPath); } else { list($width, $height, $type, $attr) = getimagesize($wamsURL); $wamsAssetId = kFileSyncUtils::getWamsAssetIdForKey($syncKey); $fileSize = kWAMS::getInstance($syncKey->getPartnerId())->getFileSizeForAssetId($wamsAssetId, pathinfo($finalPath, PATHINFO_EXTENSION)); } $attachmentAsset->setWidth($width); $attachmentAsset->setHeight($height); $attachmentAsset->setSize($fileSize); $attachmentAsset->setStatus(AttachmentAsset::ASSET_STATUS_READY); $attachmentAsset->save(); }
private function dumpFile($file_path, $file_name, $wams_asset_id = null, $wams_url = null) { $relocate = $this->getRequestParameter("relocate"); $directServe = $this->getRequestParameter("direct_serve"); if (!$relocate) { $url = $_SERVER["REQUEST_URI"]; if (strpos($url, "?") !== false) { $url .= "&relocate="; } else { $url .= "/relocate/"; } $url .= $this->encodeUrl($file_name); kFile::cacheRedirect($url); header("Location: {$url}"); die; } else { if (!$directServe) { header("Content-Disposition: attachment; filename=\"{$file_name}\""); } if (!empty($wams_asset_id)) { $fileSync = FileSyncPeer::retrieveByWamsAssetId($wams_asset_id); kWAMS::getInstance($fileSync->getPartnerId())->dumpFile($wams_asset_id, pathinfo($file_name, PATHINFO_EXTENSION)); } else { $mime_type = kFile::mimeType($file_path); kFile::dumpFile($file_path, $mime_type); } } }
private function addWamsFile(KalturaBatchJob $job, KalturaConvertJobData $data) { KalturaLog::debug("wams file({$job->id}, {$data->destFileSyncWamsAssetId})"); if (empty($data->destFileSyncWamsAssetId)) { KalturaLog::err("Error: add wams file failed"); die; } else { Propel::disableInstancePooling(); if (BatchJobPeer::retrieveByPK($job->id)->getAbort()) { kWAMS::getInstance($job->partnerId)->deleteAssetById($data->destFileSyncWamsAssetId); return $job; } Propel::enableInstancePooling(); $job->status = KalturaBatchJobStatus::FINISHED; $job->message = "File ready in WAMS"; return $this->closeJob($job, null, null, $job->message, $job->status, $data); } }
/** * Clear WAMS fields and delete asset * @param FileSyncKey $key * @param bool $strict */ public static function clearWAMSDataForKey(FileSyncKey $key, $strict = false) { $file_sync = self::getLocalFileSyncForKey($key, $strict); if ($file_sync) { $parent_file_sync = self::resolve($file_sync); $wamsAssetId = $parent_file_sync->getWamsAssetId(); if (!empty($wamsAssetId)) { kWAMS::getInstance($parent_file_sync->getPartnerId())->deleteAssetById($wamsAssetId); } $parent_file_sync->setWamsAssetId(null); $parent_file_sync->setWamsUrl(null); $parent_file_sync->save(); } }
/** * @param ISyncableFile $syncable * @param int $fileSubType * @param string $fileName * @param bool $forceProxy * @throws KalturaErrors::FILE_DOESNT_EXIST */ protected function serveFile(ISyncableFile $syncable, $fileSubType, $fileName, $entryId = null, $forceProxy = false) { /* @var $fileSync FileSync */ $syncKey = $syncable->getSyncKey($fileSubType); if (!kFileSyncUtils::fileSync_exists($syncKey)) { throw new KalturaAPIException(KalturaErrors::FILE_DOESNT_EXIST); } list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false); header("Content-Disposition: attachment; filename=\"{$fileName}\""); if ($local) { $filePath = $fileSync->getFullPath(); $wamsAssetId = $fileSync->getWamsAssetId(); if (empty($wamsAssetId)) { $mimeType = kFile::mimeType($filePath); kFile::dumpFile($filePath, $mimeType); } else { kWAMS::getInstance($fileSync->getPartnerId())->dumpFile($wamsAssetId, pathinfo($filePath, PATHINFO_EXTENSION)); } } else { if (in_array($fileSync->getDc(), kDataCenterMgr::getDcIds())) { $remoteUrl = kDataCenterMgr::getRedirectExternalUrl($fileSync); KalturaLog::info("Redirecting to [{$remoteUrl}]"); if ($forceProxy) { kFile::dumpApiRequest($remoteUrl); } else { //TODO find or build function which redurects the API request with all its parameters without using curl. // or redirect if no proxy header("Location: {$remoteUrl}"); die; } } else { $remoteUrl = $fileSync->getExternalUrl($entryId); header("Location: {$remoteUrl}"); die; } } }
/** * addFlavorConvertJob adds a single flavor conversion * * @param FileSyncKey $srcSyncKey * @param flavorParamsOutput $flavor * @param int $flavorAssetId * @param int $mediaInfoId * @param BatchJob $parentJob * @param int $lastEngineType * @param BatchJob $dbConvertFlavorJob * @return BatchJob */ public static function addFlavorConvertJob(FileSyncKey $srcSyncKey, flavorParamsOutput $flavor, $flavorAssetId, $mediaInfoId = null, BatchJob $parentJob = null, $lastEngineType = null, BatchJob $dbConvertFlavorJob = null) { $localPath = null; $remoteUrl = null; $flavorAsset = assetPeer::retrieveById($flavorAssetId); if (!$flavorAsset) { KalturaLog::err("No flavor asset found for id [{$flavorAssetId}]"); return null; } if ($flavor->getSourceRemoteStorageProfileId() == StorageProfile::STORAGE_KALTURA_DC) { list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($srcSyncKey, true, false); $partner = PartnerPeer::retrieveByPK($flavorAsset->getPartnerId()); if (!$fileSync) { kBatchManager::updateEntry($flavorAsset->getEntryId(), entryStatus::ERROR_CONVERTING); $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR); $flavorAsset->setDescription("Source file sync not found: {$srcSyncKey}"); $flavorAsset->save(); KalturaLog::err("Source file sync not found: {$srcSyncKey}"); return null; } if (!$local) { if ($fileSync->getFileType() == FileSync::FILE_SYNC_FILE_TYPE_URL && $partner && $partner->getImportRemoteSourceForConvert()) { KalturaLog::debug("Creates import job for remote file sync"); $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_WAIT_FOR_CONVERT); $flavorAsset->setDescription("Source file sync is importing: {$srcSyncKey}"); $flavorAsset->save(); $originalFlavorAsset = assetPeer::retrieveOriginalByEntryId($flavorAsset->getEntryId()); $url = $fileSync->getExternalUrl($flavorAsset->getEntryId()); return kJobsManager::addImportJob($parentJob, $flavorAsset->getEntryId(), $partner->getId(), $url, $originalFlavorAsset, null, null, true); } throw new kCoreException("Source file not found for flavor conversion [{$flavorAssetId}]", kCoreException::SOURCE_FILE_NOT_FOUND); } if ($fileSync->getFileType() != FileSync::FILE_SYNC_FILE_TYPE_URL) { $localPath = $fileSync->getFullPath(); } $remoteUrl = $fileSync->getExternalUrl($flavorAsset->getEntryId()); } else { $fileSync = kFileSyncUtils::getReadyExternalFileSyncForKey($srcSyncKey, $flavor->getSourceRemoteStorageProfileId()); if (!$fileSync) { kBatchManager::updateEntry($flavorAsset->getEntryId(), entryStatus::ERROR_CONVERTING); $description = "Remote source file sync not found {$srcSyncKey}, storage profile id [" . $flavor->getSourceRemoteStorageProfileId() . "]"; KalturaLog::err($description); $flavorAsset->setStatus(flavorAsset::FLAVOR_ASSET_STATUS_ERROR); $flavorAsset->setDescription($description); $flavorAsset->save(); return null; } $localPath = $fileSync->getFilePath(); $remoteUrl = $fileSync->getExternalUrl($flavorAsset->getEntryId()); } $wamsAssetId = $fileSync->getWamsAssetId(); // creates convert data $convertData = new kConvertJobData(); $convertData->setSrcFileSyncLocalPath($localPath); $convertData->setSrcFileSyncRemoteUrl($remoteUrl); $convertData->setMediaInfoId($mediaInfoId); $convertData->setFlavorParamsOutputId($flavor->getId()); $convertData->setFlavorAssetId($flavorAssetId); $convertData->setSrcFileSyncWamsAssetId($wamsAssetId); KalturaLog::log("Conversion engines string: '" . $flavor->getConversionEngines() . "'"); $currentConversionEngine = null; // TODO remove after all old version flavors migrated // parse supported engine types $conversionEngines = array(); if (!$flavor->getEngineVersion()) { $conversionEngines = explode(',', $flavor->getConversionEngines()); KalturaLog::log(count($conversionEngines) . " conversion engines found for the flavor"); $currentConversionEngine = reset($conversionEngines); // gets the first engine type } // remove until here if (is_null($lastEngineType)) { KalturaLog::log("Last Engine Type is null, engine version [" . $flavor->getEngineVersion() . "]"); if ($flavor->getEngineVersion()) { $operatorSet = new kOperatorSets(); $operatorSet->setSerialized($flavor->getOperators()); $nextOperator = $operatorSet->getOperator(); if (!$nextOperator) { KalturaLog::err("First operator is invalid"); return null; } KalturaLog::log("Set first operator in first set"); $currentConversionEngine = $nextOperator->id; } } else { if ($parentJob && $flavor->getEngineVersion() && ($parentJob->getJobType() == BatchJobType::CONVERT || $parentJob->getJobType() == BatchJobType::POSTCONVERT)) { // using next oprator KalturaLog::log("Adding next conversion operator"); $parentData = $parentJob->getData(); if (!$parentData || !$parentData instanceof kConvartableJobData) { KalturaLog::err("Parent job data is invalid"); return null; } $operatorSet = new kOperatorSets(); $operatorSet->setSerialized($flavor->getOperators()); $nextOperatorSet = $parentData->getCurrentOperationSet(); $nextOperatorIndex = $parentData->getCurrentOperationIndex() + 1; $nextOperator = $operatorSet->getOperator($nextOperatorSet, $nextOperatorIndex); if (!$nextOperator) { KalturaLog::err("Next operator is invalid"); return null; } KalturaLog::log("Moving to next operator [{$nextOperatorIndex}] in set [{$nextOperatorSet}]"); $convertData->setCurrentOperationSet($nextOperatorSet); $convertData->setCurrentOperationIndex($nextOperatorIndex); $currentConversionEngine = $nextOperator->id; } else { // TODO remove after all old version flavors migrated KalturaLog::log("Last used conversion engine is [{$lastEngineType}]"); // searching for $lastEngineType in the list while ($lastEngineType != $currentConversionEngine && next($conversionEngines)) { $currentConversionEngine = current($conversionEngines); } // takes the next engine $currentConversionEngine = next($conversionEngines); if (!$currentConversionEngine) { KalturaLog::err("There is no other conversion engine to use"); return null; } } } if (!is_null($fileSync->getWamsAssetId())) { $currentConversionEngine = conversionEngineType::WAMS; } KalturaLog::log("Using conversion engine [{$currentConversionEngine}]"); // creats a child convert job if (is_null($dbConvertFlavorJob)) { if ($parentJob) { $dbConvertFlavorJob = $parentJob->createChild(); KalturaLog::log("Created from parent convert job with entry id [" . $dbConvertFlavorJob->getEntryId() . "]"); } else { $dbConvertFlavorJob = new BatchJob(); $dbConvertFlavorJob->setEntryId($flavor->getEntryId()); $dbConvertFlavorJob->setPartnerId($flavor->getPartnerId()); $dbConvertFlavorJob->save(); KalturaLog::log("Created from flavor convert job with entry id [" . $dbConvertFlavorJob->getEntryId() . "]"); } } if (!is_null($fileSync->getWamsAssetId())) { $srcFileSize = kWAMS::getInstance($flavor->getPartnerId())->getFileSizeForAssetId($fileSync->getWamsAssetId()); } else { $srcFileSize = kFile::fileSize($convertData->getSrcFileSyncLocalPath()); } $dbConvertFlavorJob->setFileSize($srcFileSize); // TODO remove after all old version flavors migrated if (in_array(conversionEngineType::ENCODING_COM, $conversionEngines)) { $dbConvertFlavorJob->setOnStressDivertTo(conversionEngineType::ENCODING_COM); } // remove until here /* // Remarked by Dor until Tantan's return. // Code is supposed to get a configuration file from the engine and attach it to the batch job. // Was added for document conversion and is not used for now because of a bug of PDFCreator. KalturaLog::log("Calling CDLProceessFlavor with flavor params output[" . $flavor->getId() . "]"); $config = KDLWrap::CDLProceessFlavor($flavor); if($config) { $syncKey = $dbConvertFlavorJob->getSyncKey(BatchJob::FILE_SYNC_BATCHJOB_SUB_TYPE_CONFIG); kFileSyncUtils::file_put_contents($syncKey, $config); $fileSync = kFileSyncUtils::getLocalFileSyncForKey($syncKey); $remoteUrl = $fileSync->getExternalUrl($flavor->getEntryId()); $localPath = kFileSyncUtils::getLocalFilePathForKey($syncKey); $convertData->setConfigLocalPath($localPath); $convertData->setConfigRemoteUrl($remoteUrl); } */ $dbCurrentConversionEngine = kPluginableEnumsManager::apiToCore('conversionEngineType', $currentConversionEngine); return kJobsManager::addJob($dbConvertFlavorJob, $convertData, BatchJobType::CONVERT, $dbCurrentConversionEngine); }
/** * Will forward to the regular swf player according to the widget_id */ public function execute() { requestUtils::handleConditionalGet(); $wams_asset_id = NULL; $wams_url = NULL; $entry_id = $this->getRequestParameter("entry_id"); $type = $this->getRequestParameter("type"); $ks = $this->getRequestParameter("ks"); $file_sync = null; $ret_file_name = "name"; $referrer = $this->getRequestParameter("referrer"); $referrer = base64_decode($referrer); if (!is_string($referrer)) { // base64_decode can return binary data $referrer = ""; } $request_file_name = $this->getRequestParameter("file_name"); if ($request_file_name) { $ret_file_name = $request_file_name; } $direct_serve = $this->getRequestParameter("direct_serve"); $entry = null; if ($ks) { try { kCurrentContext::initKsPartnerUser($ks); } catch (Exception $ex) { KExternalErrors::dieError(KExternalErrors::INVALID_KS); } } else { $entry = kCurrentContext::initPartnerByEntryId($entry_id); if (!$entry) { die; } } kEntitlementUtils::initEntitlementEnforcement(); if (!$entry) { $entry = entryPeer::retrieveByPK($entry_id); if (!$entry) { die; } } else { if (!kEntitlementUtils::isEntryEntitled($entry)) { die; } } myPartnerUtils::blockInactivePartner($entry->getPartnerId()); $securyEntryHelper = new KSecureEntryHelper($entry, $ks, $referrer, accessControlContextType::DOWNLOAD); $securyEntryHelper->validateForDownload(); // Rmoved by Tan-Tan - asked by Eran // // allow access only via cdn unless these are documents (due to the current implementation of convert ppt2swf) // if ($entry->getType() != entryType::DOCUMENT && $entry->getMediaType() != entry::ENTRY_MEDIA_TYPE_IMAGE) // { // requestUtils::enforceCdnDelivery($entry->getPartnerId()); // } // relocate = did we use the redirect and added the extension to the name $relocate = $this->getRequestParameter("relocate"); if ($ret_file_name == "name") { $ret_file_name = $entry->getName(); } if ($ret_file_name) { //rawurlencode to content-disposition filename to handle spaces and other characters across different browsers //$name = rawurlencode($ret_file_name); // 19.04.2009 (Roman) - url encode is not needed when the filename in Content-Disposition header is in quotes // IE6/FF3/Chrome - Will show the filename correctly // IE7 - Will show the filename with underscores instead of spaces (this is better than showing %20) $name = $ret_file_name; if ($name) { if ($relocate) { // if we have a good file extension (from the first time) - use it in the content-disposition // in some browsers it will be stronger than the URL's extension $file_ext = pathinfo($relocate, PATHINFO_EXTENSION); $name .= ".{$file_ext}"; } if (!$direct_serve) { header("Content-Disposition: attachment; filename=\"{$name}\""); } } } else { $ret_file_name = $entry_id; } $format = $this->getRequestParameter("format"); if ($type == "download" && $format && $entry->getType() != entryType::DOCUMENT) { // this is a video for a specifc extension - use the proper flavorAsset $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format); if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) { $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true); } else { header('KalturaRaw: no flavor asset for extension'); header("HTTP/1.0 404 Not Found"); die; } $archive_file = $file_sync->getFullPath(); $mime_type = kFile::mimeType($archive_file); kFile::dumpFile($archive_file, $mime_type); } // TODO - move to a different action - document should be plugin if ($entry->getType() == entryType::DOCUMENT) { // use the fileSync from the entry if ($type == "download" && $format) { $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format); } else { $flavor_asset = assetPeer::retrieveOriginalByEntryId($entry_id); } if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) { $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true); } else { header('KalturaRaw: no flavor asset for extension'); header("HTTP/1.0 404 Not Found"); die; } // Gonen 2010-08-05 workaround to make sure file name includes correct extension // make sure a file extension is added to the downloaded file so browser will identify and // allow opening with default program // for direct serve we do not want to send content-disposition header if (!$direct_serve) { $ext = pathinfo($file_sync->getFullPath(), PATHINFO_EXTENSION); if ($relocate) { // remove relocate file extension $reloc_ext = pathinfo($relocate, PATHINFO_EXTENSION); $name = str_replace(".{$reloc_ext}", '', $name); } header("Content-Disposition: attachment; filename=\"{$name}.{$ext}\""); } kFile::dumpFile($file_sync->getFullPath()); } elseif ($entry->getType() == entryType::DATA) { $version = $this->getRequestParameter("version"); $syncKey = $entry->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA, $version); list($fileSync, $local) = kFileSyncUtils::getReadyFileSyncForKey($syncKey, true, false); if ($local) { $path = $fileSync->getFullPath(); } else { $path = kDataCenterMgr::getRedirectExternalUrl($fileSync); KalturaLog::info("Redirecting to [{$path}]"); } if (!$path) { header('KalturaRaw: no data was found available for download'); header("HTTP/1.0 404 Not Found"); } else { kFile::dumpFile($path); } } //$archive_file = $entry->getArchiveFile(); $media_type = $entry->getMediaType(); if ($media_type == entry::ENTRY_MEDIA_TYPE_IMAGE) { // image - use data for entry $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA, null); $key = $entry->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA); kFile::dumpFile(kFileSyncUtils::getLocalFilePathForKey($key, true)); } elseif ($media_type == entry::ENTRY_MEDIA_TYPE_VIDEO || $media_type == entry::ENTRY_MEDIA_TYPE_AUDIO) { $format = $this->getRequestParameter("format"); if ($type == "download" && $format) { // this is a video for a specifc extension - use the proper flavorAsset $flavor_asset = assetPeer::retrieveByEntryIdAndExtension($entry_id, $format); if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) { $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, true); } else { header('KalturaRaw: no flavor asset for extension'); die; } $archive_file = $file_sync->getFullPath(); } else { // flavorAsset of the original $flavor_asset = assetPeer::retrieveOriginalByEntryId($entry_id); if ($flavor_asset && $flavor_asset->getStatus() == flavorAsset::FLAVOR_ASSET_STATUS_READY) { $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, false); // NOT strict - if there is no archive, get the data version if ($file_sync) { $wams_asset_id = $file_sync->getWamsAssetId(); $archive_file = $file_sync->getFullPath(); } } if (!$flavor_asset || !$file_sync || $flavor_asset->getStatus() != flavorAsset::FLAVOR_ASSET_STATUS_READY) { // either no archive asset or no fileSync for archive asset // use fallback flavorAsset $flavor_asset = assetPeer::retrieveBestPlayByEntryId($entry_id); if (!$flavor_asset) { header('KalturaRaw: no original flavor asset for entry, no best play asset for entry'); die; } $file_sync = $this->redirectIfRemote($flavor_asset, flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET, null, false); // NOT strict - if there is no archive, get the data version $archive_file = $file_sync->getFullPath(); } } } elseif ($media_type == entry::ENTRY_MEDIA_TYPE_SHOW) { // in this case "raw" is a bad name // TODO - add the ability to fetch the actual XML by flagging "xml" or something $version = $this->getRequestParameter("version"); // hotfix - links sent after flattening is done look like: // http://cdn.kaltura.com/p/387/sp/38700/raw/entry_id/0_ix99151g/version/100001 // while waiting for flavor-adaptation in flattening, we want to find at least one file to return. $try_formats = array('mp4', 'mov', 'avi', 'flv'); if ($format) { $key = array_search($format, $try_formats); if ($key !== FALSE) { unset($try_formats[$key]); } $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $format, false); } if (!isset($file_sync) || !$file_sync || !file_exists($file_sync->getFullPath())) { foreach ($try_formats as $ext) { KalturaLog::log("raw for mix - trying to find filesync for extension: [{$ext}] on entry [{$entry->getId()}]"); $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $ext, false); if ($file_sync && file_exists($file_sync->getFullPath())) { KalturaLog::log("raw for mix - found flattened video of extension: [{$ext}] continuing with this file {$file_sync->getFullPath()}"); break; } } if (!$file_sync || !file_exists($file_sync->getFullPath())) { $file_sync = $this->redirectIfRemote($entry, entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $ext, true); } } // use fileSync for entry - roughcuts don't have flavors //$file_sync = $this->redirectIfRemote ( $entry , entry::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD , $version , true ); // strict - nothing to do if no flattened version // if got to here - fileSync was found for one of the extensions - continue with that file $archive_file = $file_sync->getFullPath(); } else { // no archive for this file header("HTTP/1.0 404 Not Found"); die; } // echo "[$archive_file][" . file_exists ( $archive_file ) . "]"; if (empty($wams_asset_id)) { $mime_type = kFile::mimeType($archive_file); } // echo "[[$mime_type]]"; $shouldProxy = $this->getRequestParameter("forceproxy", false); if ($shouldProxy || !empty($relocate)) { if (!empty($wams_asset_id)) { $fileExt = pathinfo($archive_file, PATHINFO_EXTENSION); kWAMS::getInstance($entry->getPartnerId())->dumpFile($wams_asset_id, $fileExt); die; } else { // dump the file kFile::dumpFile($archive_file, $mime_type); die; } } // use new Location to add the best extension we can find for the file $file_ext = pathinfo($archive_file, PATHINFO_EXTENSION); if ($file_ext != "flv") { // if the file does not end with "flv" - it is the real extension $ext = $file_ext; } else { // for now - if "flv" return "flv" - // TODO - find the real extension from the file itself $ext = "flv"; } // rebuild the URL and redirect to it with extraa parameters $url = $_SERVER["REQUEST_URI"]; $format = $this->getRequestParameter("format"); if (!$format) { $url = str_replace("format", "", $url); } if (!$ret_file_name) { // don't leave the name empty - if it is empty - use the entry id $ret_file_name = $entry_id; } $ret_file_name_safe = str_replace(' ', '-', $ret_file_name); // spaces replace with "-" $ret_file_name_safe = preg_replace('/[^a-zA-Z0-9-_]/', '', $ret_file_name_safe); // only "a-z", "A-Z", "0-9", "-" & "_" are left if (strpos($url, "?") > 0) { $url = str_replace("?", "/{$ret_file_name_safe}.{$ext}?", $url); $url .= "&relocate=f.{$ext}"; // add the ufname as a query parameter } else { $url .= "/{$ret_file_name_safe}.{$ext}?relocate=f.{$ext}"; // add the ufname as a query parameter } // or redirect if no proxy header("Location: {$url}"); die; }
/** * Will take a single KalturaBatchJob and extract the media info for the given file */ private function extract(KalturaBatchJob $job, KalturaExtractMediaJobData $data) { KalturaLog::debug("extract({$job->id})"); $mediaFile = trim($data->srcFileSyncLocalPath); $mediaFileExt = pathinfo($mediaFile, PATHINFO_EXTENSION); if (!is_null($data->srcFileSyncWamsAssetId)) { $tempFile = kWAMS::getInstance($job->partnerId)->createTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt); if (file_exists($tempFile)) { $mediaFile = $tempFile; } } if (!$this->pollingFileExists($mediaFile)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} does not exist", KalturaBatchJobStatus::RETRY); } if (!is_file($mediaFile)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} is not a file", KalturaBatchJobStatus::FAILED); } KalturaLog::debug("mediaFile [{$mediaFile}]"); $this->updateJob($job, "Extracting file media info on {$mediaFile}", KalturaBatchJobStatus::QUEUED, 1); $mediaInfo = null; try { $mediaFile = realpath($mediaFile); KalturaLog::debug("file path [{$mediaFile}]"); $engine = KBaseMediaParser::getParser($job->jobSubType, $mediaFile, $this->taskConfig, $job, $data->srcFileSyncWamsAssetId); if ($engine) { KalturaLog::debug("Found engine [" . get_class($engine) . "]"); $mediaInfo = $engine->getMediaInfo(); if (!is_null($data->srcFileSyncWamsAssetId)) { kWAMS::getInstance($job->partnerId)->deleteTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt); } } else { $err = "No media info parser engine found for job sub type [{$job->jobSubType}]"; return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::ENGINE_NOT_FOUND, $err, KalturaBatchJobStatus::FAILED); } } catch (Exception $ex) { KalturaLog::err($ex->getMessage()); $mediaInfo = null; } if (is_null($mediaInfo)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::EXTRACT_MEDIA_FAILED, "Failed to extract media info: {$mediaFile}", KalturaBatchJobStatus::RETRY); } KalturaLog::debug("flavorAssetId [{$data->flavorAssetId}]"); $mediaInfo->flavorAssetId = $data->flavorAssetId; $mediaInfo = $this->getClient()->batch->addMediaInfo($mediaInfo); $data->mediaInfoId = $mediaInfo->id; $this->updateJob($job, "Saving media info id {$mediaInfo->id}", KalturaBatchJobStatus::PROCESSED, 99, $data); $this->closeJob($job, null, null, null, KalturaBatchJobStatus::FINISHED); return $job; }
/** * @param KalturaBatchJob $job * @param KalturaPostConvertJobData $data * @return KalturaBatchJob */ private function postConvert(KalturaBatchJob $job, KalturaPostConvertJobData $data) { DbManager::setConfig(kConf::getDB()); DbManager::initialize(); $flavorAsset = assetPeer::retrieveByPK($data->flavorAssetId); if (!empty($flavorAsset) && $this->checkMediaInfoExists($data->flavorAssetId) && $flavorAsset->getIsOriginal() && $flavorAsset->getSize() !== 0) { $data->createThumb = false; return $this->closeJob($job, null, null, 'Media info already exists', KalturaBatchJobStatus::FINISHED, $data); } if ($data->flavorParamsOutputId) { $data->flavorParamsOutput = $this->kClient->flavorParamsOutput->get($data->flavorParamsOutputId); } try { $mediaFile = trim($data->srcFileSyncLocalPath); $mediaFileExt = pathinfo($mediaFile, PATHINFO_EXTENSION); if (!is_null($data->srcFileSyncWamsAssetId)) { $tempFile = kWAMS::getInstance($job->partnerId)->createTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt); if (file_exists($tempFile)) { $mediaFile = $tempFile; } } if (!$data->flavorParamsOutput || !$data->flavorParamsOutput->sourceRemoteStorageProfileId) { if (!$this->pollingFileExists($mediaFile)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} does not exist", KalturaBatchJobStatus::RETRY); } if (!is_file($mediaFile)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, "Source file {$mediaFile} is not a file", KalturaBatchJobStatus::FAILED); } } KalturaLog::debug("mediaFile [{$mediaFile}]"); $this->updateJob($job, "Extracting file media info on {$mediaFile}", KalturaBatchJobStatus::QUEUED, 1); } catch (Exception $ex) { return $this->closeJob($job, KalturaBatchJobErrorTypes::RUNTIME, $ex->getCode(), "Error: " . $ex->getMessage(), KalturaBatchJobStatus::FAILED); } $mediaInfo = null; try { $engine = KBaseMediaParser::getParser($job->jobSubType, realpath($mediaFile), $this->taskConfig, $job, $data->srcFileSyncWamsAssetId); if ($engine) { KalturaLog::info("Media info engine [" . get_class($engine) . "]"); $mediaInfo = $engine->getMediaInfo(); if (!empty($data->srcFileSyncWamsAssetId)) { kWAMS::getInstance($job->partnerId)->deleteTempFileForAssetId($data->srcFileSyncWamsAssetId, $mediaFileExt); } } else { $err = "Media info engine not found for job subtype [" . $job->jobSubType . "]"; KalturaLog::info($err); return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::ENGINE_NOT_FOUND, $err, KalturaBatchJobStatus::FAILED); } } catch (Exception $ex) { KalturaLog::err("Error: " . $ex->getMessage()); $mediaInfo = null; } /* @var $mediaInfo KalturaMediaInfo */ if (is_null($mediaInfo)) { return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::EXTRACT_MEDIA_FAILED, "Failed to extract media info: {$mediaFile}", KalturaBatchJobStatus::FAILED); } try { $mediaInfo->flavorAssetId = $data->flavorAssetId; $createdMediaInfo = $this->getClient()->batch->addMediaInfo($mediaInfo); if ($createdMediaInfo instanceof KalturaMediaInfo) { $mediaInfo = $createdMediaInfo; } // must save the mediaInfoId before reporting that the task is finished $this->updateJob($job, "Saving media info id {$createdMediaInfo->id}", KalturaBatchJobStatus::PROCESSED, 50, $data); $data->thumbPath = null; if (!$data->createThumb) { return $this->closeJob($job, null, null, "Media info id {$createdMediaInfo->id} saved", KalturaBatchJobStatus::FINISHED, $data); } // creates a temp file path $rootPath = $this->taskConfig->params->localTempPath; $this->createDir($rootPath); // creates the path $uniqid = uniqid('thumb_'); $thumbPath = realpath($rootPath) . "/{$uniqid}"; $videoDurationSec = floor($mediaInfo->videoDuration / 1000); $data->thumbOffset = max(0, min($data->thumbOffset, $videoDurationSec)); if ($mediaInfo->videoHeight) { $data->thumbHeight = $mediaInfo->videoHeight; } if ($mediaInfo->videoBitRate) { $data->thumbBitrate = $mediaInfo->videoBitRate; } // generates the thumbnail if (!is_null($data->srcFileSyncWamsAssetId)) { $thumbMaker = new KWAMSThumbnailMaker($data->srcFileSyncWamsAssetId, $thumbPath); $created = $thumbMaker->createThumbnail($data->thumbOffset, $mediaInfo->videoWidth, $mediaInfo->videoHeight, $mediaInfo->videoDar); } else { $thumbMaker = new KFFMpegThumbnailMaker($mediaFile, $thumbPath, $this->taskConfig->params->FFMpegCmd); $created = $thumbMaker->createThumnail($data->thumbOffset, $mediaInfo->videoWidth, $mediaInfo->videoHeight, null, null, $mediaInfo->videoDar); } if (!$created || !file_exists($thumbPath)) { $data->createThumb = false; return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::THUMBNAIL_NOT_CREATED, 'Thumbnail not created', KalturaBatchJobStatus::FINISHED, $data); } $data->thumbPath = $thumbPath; $job = $this->moveFile($job, $data); if ($this->checkFileExists($job->data->thumbPath)) { return $this->closeJob($job, null, null, null, KalturaBatchJobStatus::FINISHED, $data); } $data->createThumb = false; return $this->closeJob($job, KalturaBatchJobErrorTypes::APP, KalturaBatchJobAppErrors::NFS_FILE_DOESNT_EXIST, 'File not moved correctly', KalturaBatchJobStatus::FINISHED, $data); } catch (Exception $ex) { return $this->closeJob($job, KalturaBatchJobErrorTypes::RUNTIME, $ex->getCode(), "Error: " . $ex->getMessage(), KalturaBatchJobStatus::FAILED); } }
/** * @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()) { kWAMS::getInstance($dbBatchJob->getPartnerId())->deleteAssetById($data->getDestFileSyncWamsAssetId()); return $dbBatchJob; } // verifies that flavor asset created if (!$data->getFlavorAssetId()) { throw new APIException(APIErrors::INVALID_FLAVOR_ASSET_ID, $data->getFlavorAssetId()); } $flavorAsset = assetPeer::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); $flavorParamsOutput = $data->getFlavorParamsOutput(); $storageProfileId = $flavorParamsOutput->getSourceRemoteStorageProfileId(); if ($storageProfileId == StorageProfile::STORAGE_KALTURA_DC) { $destFileSyncWamsAssetId = $data->getDestFileSyncWamsAssetId(); if (!empty($destFileSyncWamsAssetId)) { kFileSyncUtils::addFromWAMS($destFileSyncWamsAssetId, $syncKey); } else { kFileSyncUtils::moveFromFile($data->getDestFileSyncLocalPath(), $syncKey); } } elseif ($flavorParamsOutput->getRemoteStorageProfileIds()) { $remoteStorageProfileIds = explode(',', $flavorParamsOutput->getRemoteStorageProfileIds()); foreach ($remoteStorageProfileIds as $remoteStorageProfileId) { $storageProfile = StorageProfilePeer::retrieveByPK($remoteStorageProfileId); kFileSyncUtils::createReadyExternalSyncFileForKey($syncKey, $data->getDestFileSyncLocalPath(), $storageProfile); } } // creats the file sync if (file_exists($data->getLogFileSyncLocalPath())) { $logSyncKey = $flavorAsset->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_CONVERT_LOG); try { kFileSyncUtils::moveFromFile($data->getLogFileSyncLocalPath(), $logSyncKey); } catch (Exception $e) { $err = 'Saving conversion log: ' . $e->getMessage(); KalturaLog::err($err); $desc = $dbBatchJob->getDescription() . "\n" . $err; $dbBatchJob->getDescription($desc); } } if ($storageProfileId == StorageProfile::STORAGE_KALTURA_DC) { $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()); } $offset = $entry->getThumbOffset(); // entry getThumbOffset now takes the partner DefThumbOffset into consideration $createThumb = $entry->getCreateThumb(); $extractMedia = true; if ($entry->getType() != entryType::MEDIA_CLIP) { // e.g. document $extractMedia = false; } $rootBatchJob = $dbBatchJob->getRootJob(); if ($extractMedia && $rootBatchJob && $rootBatchJob->getJobType() == BatchJobType::CONVERT_PROFILE) { $rootBatchJobData = $rootBatchJob->getData(); if ($rootBatchJobData instanceof kConvertProfileJobData) { $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 && in_array($flavorParamsOutput->getVideoCodec(), 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) { $postConvertAssetType = BatchJob::POSTCONVERT_ASSET_TYPE_FLAVOR; if ($flavorAsset->getIsOriginal()) { $postConvertAssetType = BatchJob::POSTCONVERT_ASSET_TYPE_SOURCE; } kJobsManager::addPostConvertJob($dbBatchJob, $postConvertAssetType, $data->getDestFileSyncLocalPath(), $data->getFlavorAssetId(), $flavorParamsOutput->getId(), $createThumb, $offset, $data->getCustomData(), $data->getDestFileSyncWamsAssetId()); } 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() + $flavorParamsOutput->getAudioBitrate()); $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; }