Exemplo n.º 1
0
 protected function _process($video)
 {
     // Make sure FFMPEG path is set
     $ffmpeg_path = Engine_Api::_()->getApi('settings', 'core')->video_ffmpeg_path;
     if (!$ffmpeg_path) {
         throw new Video_Model_Exception('Ffmpeg not configured');
     }
     // Make sure FFMPEG can be run
     if (!@file_exists($ffmpeg_path) || !@is_executable($ffmpeg_path)) {
         $output = null;
         $return = null;
         exec($ffmpeg_path . ' -version', $output, $return);
         if ($return > 0) {
             throw new Video_Model_Exception('Ffmpeg found, but is not executable');
         }
     }
     // Check we can execute
     if (!function_exists('shell_exec')) {
         throw new Video_Model_Exception('Unable to execute shell commands using shell_exec(); the function is disabled.');
     }
     // Check the video temporary directory
     $tmpDir = APPLICATION_PATH . DIRECTORY_SEPARATOR . 'temporary' . DIRECTORY_SEPARATOR . 'video';
     if (!is_dir($tmpDir)) {
         if (!mkdir($tmpDir, 0777, true)) {
             throw new Video_Model_Exception('Video temporary directory did not exist and could not be created.');
         }
     }
     if (!is_writable($tmpDir)) {
         throw new Video_Model_Exception('Video temporary directory is not writable.');
     }
     // Get the video object
     if (is_numeric($video)) {
         $video = Engine_Api::_()->getItem('video', $video_id);
     }
     if (!$video instanceof Video_Model_Video) {
         throw new Video_Model_Exception('Argument was not a valid video');
     }
     // Update to encoding status
     $video->status = 2;
     $video->save();
     // Prepare information
     $owner = $video->getOwner();
     $filetype = $video->code;
     $originalPath = $tmpDir . DIRECTORY_SEPARATOR . $video->getIdentity() . '.' . $filetype;
     $outputPath = $tmpDir . DIRECTORY_SEPARATOR . $video->getIdentity() . '_vconverted.flv';
     $thumbPath = $tmpDir . DIRECTORY_SEPARATOR . $video->getIdentity() . '_vthumb.jpg';
     $videoCommand = $ffmpeg_path . ' ' . '-i ' . escapeshellarg($originalPath) . ' ' . '-ab 64k' . ' ' . '-ar 44100' . ' ' . '-qscale 5' . ' ' . '-vcodec flv' . ' ' . '-f flv' . ' ' . '-r 25' . ' ' . '-s 480x386' . ' ' . '-v 2' . ' ' . '-y ' . escapeshellarg($outputPath) . ' ' . '2>&1';
     $thumbCommand = $ffmpeg_path . ' ' . '-i ' . escapeshellarg($outputPath) . ' ' . '-f image2' . ' ' . '-ss 4.00' . ' ' . '-v 2' . ' ' . '-y ' . escapeshellarg($thumbPath) . ' ' . '2>&1';
     // Prepare output header
     $output = PHP_EOL;
     $output .= $originalPath . PHP_EOL;
     $output .= $outputPath . PHP_EOL;
     $output .= $thumbPath . PHP_EOL;
     // Prepare logger
     $log = null;
     //if( APPLICATION_ENV == 'development' ) {
     $log = new Zend_Log();
     $log->addWriter(new Zend_Log_Writer_Stream(APPLICATION_PATH . '/temporary/log/video.log'));
     //}
     // Execute video encode command
     $videoOutput = $output . $videoCommand . PHP_EOL . shell_exec($videoCommand);
     // Log
     if ($log) {
         $log->log($videoOutput, Zend_Log::INFO);
     }
     // Check for failure
     $success = true;
     // Unsupported format
     if (preg_match('/Unknown format/i', $videoOutput) || preg_match('/Unsupported codec/i', $videoOutput) || preg_match('/patch welcome/i', $videoOutput) || !is_file($outputPath) || filesize($outputPath) <= 0) {
         $success = false;
         $video->status = 3;
     } else {
         if (preg_match('/video:0kB/i', $videoOutput)) {
             $success = false;
             $video->status = 5;
         }
     }
     // Failure
     if (!$success) {
         $db = $video->getTable()->getAdapter();
         $db->beginTransaction();
         try {
             $video->save();
             // notify the owner
             $translate = Zend_Registry::get('Zend_Translate');
             $language = !empty($owner->language) && $owner->language != 'auto' ? $owner->language : null;
             $notificationMessage = '';
             if ($video->status == 3) {
                 $notificationMessage = $translate->translate(sprintf('Video conversion failed. Video format is not supported by FFMPEG. Please try %1$sagain%2$s.', '', ''), $language);
             } else {
                 if ($video->status == 5) {
                     $notificationMessage = $translate->translate(sprintf('Video conversion failed. Audio files are not supported. Please try %1$sagain%2$s.', '', ''), $language);
                 }
             }
             Engine_Api::_()->getDbtable('notifications', 'activity')->addNotification($owner, $owner, $video, 'video_processed_failed', array('message' => $notificationMessage, 'message_link' => Zend_Controller_Front::getInstance()->getRouter()->assemble(array('action' => 'manage'), 'video_general', true)));
             $db->commit();
         } catch (Exception $e) {
             $videoOutput .= PHP_EOL . $e->__toString() . PHP_EOL;
             if ($log) {
                 $log->write($e->__toString(), Zend_Log::ERR);
             }
             $db->rollBack();
         }
         // Write to additional log in dev
         if (APPLICATION_ENV == 'development') {
             file_put_contents($tmpDir . '/' . $video->video_id . '.txt', $videoOutput);
         }
     } else {
         // Get duration of the video to caculate where to get the thumbnail
         if (preg_match('/Duration:\\s+(.*?)[.]/i', $videoOutput, $matches)) {
             list($hours, $minutes, $seconds) = preg_split('[:]', $matches[1]);
             $duration = ceil($seconds + $minutes * 60 + $hours * 3600);
         } else {
             $duration = 0;
             // Hmm
         }
         // Log duration
         if ($log) {
             $log->log('Duration: ' . $duration, Zend_Log::INFO);
         }
         // Process thumbnail
         $thumbOutput = $output . $thumbCommand . PHP_EOL . shell_exec($thumbCommand);
         // Log thumb output
         if ($log) {
             $log->log($thumbOutput, Zend_Log::INFO);
         }
         // Resize thumbnail
         $image = Engine_Image::factory();
         $image->open($thumbPath)->resize(120, 240)->write($thumbPath)->destroy();
         // Save video and thumbnail to storage system
         $params = array('parent_id' => $video->getIdentity(), 'parent_type' => $video->getType(), 'user_id' => $video->owner_id);
         $db = $video->getTable()->getAdapter();
         $db->beginTransaction();
         try {
             $videoFileRow = Engine_Api::_()->storage()->create($outputPath, $params);
             $thumbFileRow = Engine_Api::_()->storage()->create($thumbPath, $params);
             $db->commit();
         } catch (Exception $e) {
             $db->rollBack();
             // delete the files from temp dir
             unlink($originalPath);
             unlink($outputPath);
             unlink($thumbPath);
             $video->status = 7;
             $video->save();
             // notify the owner
             $translate = Zend_Registry::get('Zend_Translate');
             $notificationMessage = '';
             $language = !empty($owner->language) && $owner->language != 'auto' ? $owner->language : null;
             if ($video->status == 7) {
                 $notificationMessage = $translate->translate(sprintf('Video conversion failed. You may be over the site upload limit.  Try %1$suploading%2$s a smaller file, or delete some files to free up space.', '', ''), $language);
             }
             Engine_Api::_()->getDbtable('notifications', 'activity')->addNotification($owner, $owner, $video, 'video_processed_failed', array('message' => $notificationMessage, 'message_link' => Zend_Controller_Front::getInstance()->getRouter()->assemble(array('action' => 'manage'), 'video_general', true)));
             throw $e;
             // throw
         }
         // Video processing was a success!
         // Save the information
         $video->file_id = $videoFileRow->file_id;
         $video->photo_id = $thumbFileRow->file_id;
         $video->duration = $duration;
         $video->status = 1;
         $video->save();
         // delete the files from temp dir
         unlink($originalPath);
         unlink($outputPath);
         unlink($thumbPath);
         // insert action in a seperate transaction if video status is a success
         $actionsTable = Engine_Api::_()->getDbtable('actions', 'activity');
         $db = $actionsTable->getAdapter();
         $db->beginTransaction();
         try {
             // new action
             $action = $actionsTable->addActivity($owner, $video, 'video_new');
             if ($action) {
                 $actionsTable->attachActivity($action, $video);
             }
             // notify the owner
             Engine_Api::_()->getDbtable('notifications', 'activity')->addNotification($owner, $owner, $video, 'video_processed');
             $db->commit();
         } catch (Exception $e) {
             $db->rollBack();
             throw $e;
             // throw
         }
     }
 }
Exemplo n.º 2
0
 protected function _process($video, $type, $compatibilityMode = false)
 {
     $tmpDir = $this->getTmpDir();
     $video = $this->getVideo($video);
     // Update to encoding status
     $video->status = 2;
     $video->type = 3;
     $video->save();
     // Prepare information
     $owner = $video->getOwner();
     // Pull video from storage system for encoding
     $storageObject = $this->getStorageObject($video);
     $originalPath = $this->getOriginalPath($storageObject);
     $outputPath = $tmpDir . DIRECTORY_SEPARATOR . $video->getIdentity() . '_vconverted.' . $type;
     $thumbPath = $tmpDir . DIRECTORY_SEPARATOR . $video->getIdentity() . '_vthumb.jpg';
     $width = 480;
     $height = 386;
     $videoCommand = $this->buildVideoCmd($video, $width, $height, $type, $originalPath, $outputPath, $compatibilityMode);
     // Prepare output header
     $output = PHP_EOL;
     $output .= $originalPath . PHP_EOL;
     $output .= $outputPath . PHP_EOL;
     $output .= $thumbPath . PHP_EOL;
     // Prepare logger
     $log = new Zend_Log();
     $log->addWriter(new Zend_Log_Writer_Stream(APPLICATION_PATH . '/temporary/log/video.log'));
     // Execute video encode command
     $videoOutput = $output . $videoCommand . PHP_EOL . shell_exec($videoCommand);
     // Log
     if ($log) {
         $log->log($videoOutput, Zend_Log::INFO);
     }
     // Check for failure
     $success = $this->conversionSucceeded($video, $videoOutput, $outputPath);
     // Failure
     if (!$success) {
         if (!$compatibilityMode) {
             $this->_process($video, true);
             return;
         }
         $exceptionMessage = '';
         $db = $video->getTable()->getAdapter();
         $db->beginTransaction();
         try {
             $video->save();
             $exceptionMessage = $this->notifyOwner($video, $owner);
             $db->commit();
         } catch (Exception $e) {
             $videoOutput .= PHP_EOL . $e->__toString() . PHP_EOL;
             if ($log) {
                 $log->write($e->__toString(), Zend_Log::ERR);
             }
             $db->rollBack();
         }
         // Write to additional log in dev
         if (APPLICATION_ENV == 'development') {
             file_put_contents($tmpDir . '/' . $video->video_id . '.txt', $videoOutput);
         }
         throw new Video_Model_Exception($exceptionMessage);
     } else {
         // Get duration of the video to caculate where to get the thumbnail
         $duration = $this->getDuration($videoOutput);
         // Log duration
         if ($log) {
             $log->log('Duration: ' . $duration, Zend_Log::INFO);
         }
         // Fetch where to take the thumbnail
         $thumb_splice = $duration / 2;
         $thumbSuccess = $this->generateThumbnail($outputPath, $output, $thumb_splice, $thumbPath, $log);
         // Save video and thumbnail to storage system
         $params = array('parent_id' => $video->getIdentity(), 'parent_type' => $video->getType(), 'user_id' => $video->owner_id);
         $db = $video->getTable()->getAdapter();
         $db->beginTransaction();
         try {
             $storageObject->setFromArray($params);
             $storageObject->store($outputPath);
             if ($thumbSuccess) {
                 $thumbFileRow = Engine_Api::_()->storage()->create($thumbPath, $params);
             }
             $db->commit();
         } catch (Exception $e) {
             $db->rollBack();
             // delete the files from temp dir
             unlink($originalPath);
             unlink($outputPath);
             if ($thumbSuccess) {
                 unlink($thumbPath);
             }
             $video->status = 7;
             $video->save();
             $this->notifyOwner($video, $owner);
             throw $e;
             // throw
         }
         // Video processing was a success!
         // Save the information
         if ($thumbSuccess) {
             $video->photo_id = $thumbFileRow->file_id;
         }
         $video->duration = $duration;
         $video->status = 1;
         $video->save();
         // delete the files from temp dir
         unlink($originalPath);
         unlink($outputPath);
         unlink($thumbPath);
         // insert action in a separate transaction if video status is a success
         $actionsTable = Engine_Api::_()->getDbtable('actions', 'activity');
         $db = $actionsTable->getAdapter();
         $db->beginTransaction();
         try {
             // new action
             $action = $actionsTable->addActivity($owner, $video, 'video_new');
             if ($action) {
                 $actionsTable->attachActivity($action, $video);
             }
             // notify the owner
             Engine_Api::_()->getDbtable('notifications', 'activity')->addNotification($owner, $owner, $video, 'video_processed');
             $db->commit();
         } catch (Exception $e) {
             $db->rollBack();
             throw $e;
             // throw
         }
     }
 }