Created
July 13, 2013 13:42
-
-
Save dwaligora/5990756 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Slate\Media\CommonsBundle\Manager; | |
use Symfony\Bundle\FrameworkBundle\Routing\Router; | |
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; | |
use Webility\Bundle\remoteStorageBundle\Services\Storage; | |
use Webility\Bundle\WebilityBundle\Entity\Repository\File; | |
use Webility\Bundle\WebilityBundle\Entity\Superclasses\Entity; | |
use Slate\AppBundle\Entity\StreamedMedia\StreamType; | |
use Slate\Media\CommonsBundle\Entity\StreamedMedia\Stream; | |
use Slate\Media\CommonsBundle\StreamConverter\EncodingComStreamTypeConverter; | |
use Slate\Media\CommonsBundle\Event\OriginalFileUploadedEvent; | |
use Slate\Media\CommonsBundle\Event\ClipStreamEncodedEvent; | |
use Slate\Media\CommonsBundle\Entity\StreamedMediaInterface; | |
use Slate\Media\CommonsBundle\Manager\MediaManager; | |
class StreamedMediaManager extends MediaManager | |
{ | |
/********************************************************** | |
* THOSE PROPERTIES ARE MIXED FOR ALLOWING FLEXIBLE | |
* CHANGES OF REMOTE STORAGE PROVIDER, remote, S3, etc. | |
**********************************************************/ | |
/** | |
* @var mixed | |
*/ | |
protected $encoder; | |
/** | |
* @var mixed | |
*/ | |
protected $remote_storage; | |
/** | |
* @var mixed | |
*/ | |
protected $remote_uploader; | |
/** | |
* @var string Repository instance | |
*/ | |
protected $repository_class = 'SlateMediaCommonsBundle:StreamedMedia\Stream'; | |
public function setEncoder($encoder) | |
{ | |
$this->encoder = $encoder; | |
} | |
public function setRemoteStorage($remote_storage) | |
{ | |
$this->remote_storage = $remote_storage; | |
} | |
public function setRemoteUploader($remote_uploader) | |
{ | |
$this->remote_uploader = $remote_uploader; | |
} | |
public function setRepositoryClass($repository) | |
{ | |
$this->repository_class = $repository; | |
} | |
public function getRepository() | |
{ | |
return $this->repository_class; | |
} | |
public function getOriginalStream(StreamedMediaInterface $media) | |
{ | |
return $this->getObjectManager()->getRepository($this->repository_class) | |
->getOriginalStream($media->getId()); | |
} | |
public function updateOrCreateOriginalStream(StreamedMediaInterface $media) | |
{ | |
$om = $this->getObjectManager(); | |
$original_stream = $this->getOriginalStream($media); | |
if (null === $original_stream) { | |
$original_stream = new Stream(); | |
$original_stream->setStremedMedia($media); | |
$original_stream->setIsOriginal(true); | |
$media->addStream($original_stream); | |
} | |
// @todo | |
// setting media original file again in case of changing file | |
$original_stream->setFile($media->getOriginalFile()); | |
$original_stream->setFileId($media->getOriginalFile()->getId()); | |
$om->persist($original_stream); | |
return $original_stream; | |
} | |
public function isUploaded(StreamedMediaInterface $media) | |
{ | |
if (null === $media->getOriginalFile()) { | |
throw new \LogicException( | |
sprintf( | |
'There are no original file or orignal stream for media [id: %s]. Please set is, in order to upload file to remote storage!', | |
$media->getId() | |
) | |
); | |
} | |
if ($media->getOriginalFile()->isRemote()) { | |
return true; | |
} | |
return false; | |
} | |
public function upload(StreamedMediaInterface $media) | |
{ | |
try { | |
if (!$this->isUploaded($media)) { | |
$file = $media->getOriginalFile(); | |
$this->remote_uploader->upload($file); | |
$this->getObjectManager()->persist($file); | |
$this->getObjectManager()->flush(); | |
\Webility\Storage::unlink($file->getRootFilePath()); | |
} | |
} catch(\Exception $e) { | |
throw new \RuntimeException($e->getMessage()); | |
} | |
} | |
/** | |
* MP | |
* | |
* @param StreamedMediaInterface $media | |
* @param $stream_status_update_url | |
* @return bool | |
*/ | |
public function encode(StreamedMediaInterface $media, $stream_status_update_url) | |
{ | |
set_time_limit(0); | |
$original_file = $media->getOriginalFile(); | |
// prepare all streams | |
$streams_by_stream_type = array(); | |
foreach ($media->getStreams() as $stream) { | |
/* @var $stream Stream */ | |
$stream_type = $stream->getStreamType(); | |
if (null !== $stream_type) { | |
$streams_by_stream_type[$stream_type->getId()] = $stream; | |
} | |
} | |
/* @var $original_stream_file File */ | |
//@todo need to move it somewhere | |
$param_converter = new EncodingComStreamTypeConverter(); | |
//detect not encoded streams | |
$ordering = 0; | |
$formats = array(); | |
$streams = array(); | |
$base_remote_url = 'http://' . $this->remote_storage->getLogin() . ':' . $this->remote_storage->getApiKey() . '@storage.cloudfiles.com/' . $this->remote_storage->getContainerName() . '/'; | |
foreach ($media->getStreamTypes() as $stream_type) { | |
/* @var $stream_type StreamType */ | |
// verify if stream of given stream type exists, if no create new one. | |
if (!isset($streams_by_stream_type[$stream_type->getId()]) | |
|| in_array($streams_by_stream_type[$stream_type->getId()]->getStatus(), array(Stream::STATUS_ERROR, null)) | |
) { | |
if (!isset($streams_by_stream_type[$stream_type->getId()])) { | |
$stream = new Stream(); | |
$stream->setStreamType($stream_type); | |
$stream->setStremedMedia($media); | |
$media->addStream($stream); | |
} else { | |
$stream = $streams_by_stream_type[$stream_type->getId()]; | |
} | |
$stream->setStatus(Stream::STATUS_IN_PROGRESS); | |
$stream->setEncodeTaskOrder($ordering); | |
$new_filename = $stream_type->getFileNameFromPattern($original_file, $stream); | |
$stream_file = new File(); | |
$stream_file->setName($new_filename); | |
$stream->setFile($stream_file); | |
// destination - url where encoded files should be moved | |
$encoding_parameters = $param_converter->convert($stream_type); | |
$encoding_parameters['destination'] = $base_remote_url . $new_filename; | |
$formats[] = $encoding_parameters; | |
$streams[] = $stream; | |
$ordering++; | |
} | |
} | |
if (count($formats) > 0) { | |
if(method_exists($media, 'getGeneratedThumbnail')){ | |
//add image thumb format | |
$image_format = array( | |
'output' => 'thumbnail', | |
'time' => '50%', | |
'destination' => $base_remote_url . $media->getUrlname().'.jpg' | |
); | |
} | |
$formats[] = $image_format; | |
//send to encode | |
$accetped = false; | |
$attempt = 1; | |
do { | |
$media_id = $this->encoder->addEncodings($original_file->getRemoteAddress(), $formats, $stream_status_update_url); | |
if (ctype_digit($media_id)) { | |
$accetped = true; | |
} else { | |
if ($media_id == 'Request rate over limit') { | |
//too many requests sleep and try again later | |
sleep(1); | |
$attempt++; | |
} else { | |
//other error, allow script to go on | |
$stream->setStatus(Stream::STATUS_ERROR); | |
//exit attempts loop | |
break; | |
} | |
} | |
} while ($accetped === false && $attempt <= 5); | |
//update streams data | |
foreach ($streams as $sent_stream) { | |
if (!$accetped) { | |
//other error, allow script to go on | |
$sent_stream->setStatus(Stream::STATUS_ERROR); | |
} | |
$sent_stream->setExternalMediaId($media_id); | |
$sent_stream->dbPersist(); | |
} | |
} | |
//perform additional tasks, like generate WAVe forms, etc. | |
$original_file_uploaded_event = new OriginalFileUploadedEvent($media); | |
$this->getEventDispatcher()->dispatch('media.original_file.uploaded', $original_file_uploaded_event); | |
$this->getObjectManager()->flush(); | |
return true; | |
} | |
/** | |
* MP | |
* | |
* Updates clip streams based on remote response stream | |
* | |
* @param string $response_string | |
* @return Clip | |
*/ | |
public function updateStreams($response_string) | |
{ | |
$response = new \SimpleXMLElement($response_string); | |
/* @var $streams_repository StreamRepository */ | |
$streams_repository = $this->entity_manager->getRepository('SlateMediaCommonsBundle:StreamedMedia\Stream'); | |
$streams = $streams_repository->getStreamsByMediaId((int) $response->mediaid . ''); | |
$formats = $response->format; | |
$clip = null; | |
for ($i = 0, $iterations = min(count($formats), count($streams)); $i < $iterations; $i++) { //skip formats which aren't video streams | |
/* @var $stream Stream */ | |
$stream = $streams[$i]; | |
$format = $formats[$i]; | |
if ($clip === null) { | |
$clip = $stream->getStreamedMedia(); | |
} | |
if ($stream->getStatus() == Stream::STATUS_IN_PROGRESS) { | |
if ($format->status == 'Finished') { | |
$stream->setStatus(Stream::STATUS_ENCODED); | |
$uploaded_file_name = $format->destination; | |
/* @var $stream_file File */ | |
$stream_file = $stream->getFile(); | |
$container_name = basename(\Webility\Storage::extractPath($uploaded_file_name)); | |
$this->remote_storage->setContainer($container_name); | |
$remote_object = $this->remote_storage->getContainer()->get_object(\Webility\Storage::extractFileName($uploaded_file_name)); | |
$stream_file->setIsRemote(true); | |
$stream_file->setRemoteOrigin('remote.' . $container_name); | |
$stream_file->setRemoteAddress($remote_object->public_uri()); | |
$stream_file->setRemoteStreamingAddress($remote_object->public_streaming_uri()); | |
$stream_file->dbPersist(); | |
} else { | |
$stream->setStatus(Stream::STATUS_ERROR); | |
$stream->setEncodingError($format->description); | |
} | |
$stream->dbPersist(); | |
$this->entity_manager->flush(); | |
$event = new ClipStreamEncodedEvent($stream); | |
$this->_event_dispatcher->dispatch('media.stream.encoded', $event); | |
} | |
} | |
if($iterations+1 == count($formats)){ //check if image format exist | |
$image_format = $formats[$iterations]; | |
if($clip !== null && method_exists($clip, 'getGeneratedThumbnail')){ | |
$base_name = \Webility\Storage::extractFileName($image_format->destination); | |
$container_name = basename(\Webility\Storage::extractPath($image_format->destination)); | |
$this->remote_storage->setContainer($container_name); | |
$remote_object = $this->remote_storage->getContainer()->get_object($base_name); | |
$file = new File(); | |
$file->setName($base_name); | |
$file->setRemoteAddress($remote_object->public_uri()); | |
$file->setIsRemote(true); | |
$clip->setGeneratedThumbnail($file); | |
$file->dbPersist(); | |
$clip->dbPersist(); | |
$this->entity_manager->flush(); | |
} | |
} | |
return $clip; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment