diff --git a/app/config/collections.php b/app/config/collections.php index ca6008ff58..b9688f6903 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2845,6 +2845,143 @@ $collections = [ ], ] ], + 'videos' => [ + '$collection' => Database::METADATA, + '$id' => 'videos', + '$name' => 'Videos', + 'attributes' => [ + [ + '$id' => 'bucketId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'fileId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'duration', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'width', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'height', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'videoCodec', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'videoBitrate', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'videoFrameRate', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'audioCodec', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'audioBitrate', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'audioSampleRate', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => '_key_bucket_file', + 'type' => Database::INDEX_KEY, + 'attributes' => ['bucketId', 'fileId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ] + ], 'video_renditions' => [ '$collection' => Database::METADATA, '$id' => 'video_renditions', @@ -2916,39 +3053,6 @@ $collections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => 'status', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 100, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'progress', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'stream', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => 'duration', 'type' => Database::VAR_STRING, @@ -3059,6 +3163,39 @@ $collections = [ 'array' => false, 'filters' => ['json'], ], + [ + '$id' => 'status', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 100, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'progress', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 4, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'stream', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ @@ -3075,17 +3212,6 @@ $collections = [ '$id' => 'video_profiles', '$name' => 'Video_profiles', 'attributes' => [ - [ - '$id' => 'projectId', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => 'name', 'type' => Database::VAR_STRING, @@ -3141,12 +3267,23 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'stream', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ - '$id' => '_key_project', + '$id' => '_key_stream', 'type' => Database::INDEX_KEY, - 'attributes' => ['projectId'], + 'attributes' => ['stream'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index ddcbdc4d2b..02bfbdeb8a 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -153,6 +153,20 @@ App::post('/v1/projects') $dbForProject->createCollection($key, $attributes, $indexes); } + if($dbForProject->exists($dbForProject->getDefaultDatabase(), 'video_profiles')) { + foreach (Config::getParam('profiles', []) as $profile) { + Authorization::skip(function () use ($project, $profile, $dbForProject) { + return $dbForProject->createDocument('video_profiles', new Document([ + 'name' => $profile['name'], + 'videoBitrate' => $profile['videoBitrate'], + 'audioBitrate' => $profile['audioBitrate'], + 'width' => $profile['width'], + 'height' => $profile['height'] + ])); + }); + } + } + $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($project, Response::MODEL_PROJECT); }); diff --git a/app/controllers/api/video.php b/app/controllers/api/video.php index 5245df5022..c677136902 100644 --- a/app/controllers/api/video.php +++ b/app/controllers/api/video.php @@ -106,40 +106,33 @@ App::post('/v1/video/buckets/:bucketId/files/:fileId') } } - $queries = [ - new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), - ]; + $profiles = Authorization::skip(fn () => $dbForProject->find('video_profiles', [], 12, 0, [], ['ASC'])); - $profiles = Authorization::skip(fn () => $dbForProject->find('video_profiles', $queries, 12, 0, [], ['ASC'])); - - if(empty($profiles)) { - foreach (Config::getParam('profiles', []) as $profile) { - Authorization::skip(function () use ($project, $profile, $dbForProject) { - return $dbForProject->createDocument('video_profiles', new Document([ - 'projectId' => $project->getId(), - 'name' => $profile['name'], - 'videoBitrate' => $profile['videoBitrate'], - 'audioBitrate' => $profile['audioBitrate'], - 'width' => $profile['width'], - 'height' => $profile['height'] - ])); - }); - } + if ($profiles->empty()) { + throw new Exception('No video profiles found', 400, Exception::PROFILES_NOT_FOUND); } $queries = [ - new Query('projectId', Query::TYPE_EQUAL, [$project->getId()]), + new Query('bucketId', Query::TYPE_EQUAL, [$bucketId]), + new Query('fileId', Query::TYPE_EQUAL, [$fileId]), ]; - $profiles = Authorization::skip(fn () => $dbForProject->find('video_profiles', $queries, 12, 0, [], ['ASC'])); + $video = Authorization::skip(fn() => $dbForProject->findOne('videos', [$queries])); + if($video->empty()) { + $video = Authorization::skip(function () use ($dbForProject) { + return $this->database->createDocument('videos', new Document([ + 'bucketId' => $this->args['bucketId'], + 'fileId' => $this->args['fileId'], + ])); + }); + } - $transcoder = new Transcoding(); + $transcoder = new Transcoding(); foreach ($profiles as $profile) { $transcoder ->setUser($user) ->setProject($project) - ->setBucketId($bucketId) - ->setFileId($fileId) + ->setVideoId($video->getId()) ->setProfileId($profile->getId()) ->trigger(); } diff --git a/app/workers/transcoding.php b/app/workers/transcoding.php index 7cc74d24f6..83a13198cf 100644 --- a/app/workers/transcoding.php +++ b/app/workers/transcoding.php @@ -186,7 +186,7 @@ class TranscodingV1 extends Worker $devicePath = str_ireplace($deviceFiles->getRoot(), $deviceFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $devicePath); $data = $this->getFilesDevice($project->getId())->read($this->outDir . $fileName); $this->getVideoDevice($project->getId())->write($devicePath . DIRECTORY_SEPARATOR . $profile->getAttribute('name') . DIRECTORY_SEPARATOR . $fileName, $data, \mime_content_type($this->outDir . $fileName)); - + var_dump($devicePath . DIRECTORY_SEPARATOR . $profile->getAttribute('name') . DIRECTORY_SEPARATOR . $fileName); if ($start === 0) { $query->setAttribute('status', 'uploading'); Authorization::skip(fn() => $this->database->updateDocument( @@ -240,6 +240,7 @@ class TranscodingV1 extends Worker if (!empty($metadata['stream']['resolutions'][0])) { $general = $metadata['stream']['resolutions'][0]; + var_dump($general); $parts = explode("x", $general); $info['width'] = $parts['0']; $info['height'] = $parts['1']; @@ -278,7 +279,7 @@ class TranscodingV1 extends Worker '-vf', 'scale=iw:-2:force_original_aspect_ratio=increase,setsar=1:1' ]; - $segementSize = 6; + $segementSize = 10; if ($stream === 'dash') { $dash = $video->dash() @@ -287,7 +288,7 @@ class TranscodingV1 extends Worker ->addRepresentation($representation) ->setAdditionalParams($additionalParams) ->save($this->outPath); - + var_dump($this->outPath); $xml = simplexml_load_string( file_get_contents($this->outDir . $this->args['fileId'] . '.mpd') ); diff --git a/src/Appwrite/Event/Transcoding.php b/src/Appwrite/Event/Transcoding.php index 9bb2d4cef4..01e393aa7d 100644 --- a/src/Appwrite/Event/Transcoding.php +++ b/src/Appwrite/Event/Transcoding.php @@ -7,8 +7,8 @@ use Utopia\Database\Document; class Transcoding extends Event { - protected string $bucketId = ''; - protected string $fileId = ''; + + protected string $videoId = ''; protected string $profileId = ''; public function __construct() @@ -17,14 +17,14 @@ class Transcoding extends Event } /** - * Sets bucketId event. + * Sets videoId event. * - * @param $bucketId string + * @param $videoId string * @return self */ - public function setBucketId(string $bucketId): self + public function setVideoId(string $videoId): self { - $this->bucketId = $bucketId; + $this->videoId = $videoId; return $this; } @@ -34,32 +34,9 @@ class Transcoding extends Event * * @return null|Document */ - public function getBucketId(): ?string + public function getVideoId(): ?string { - return $this->bucketId; - } - - /** - * Sets fileId. - * - * @param $fileId string - * @return self - */ - public function setFileId(string $fileId): self - { - $this->fileId = $fileId; - - return $this; - } - - /** - * Returns fileId. - * - * @return null|Document - */ - public function getFileId(): ?string - { - return $this->fileId; + return $this->videoId; } /** diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 62695742f0..85e8a13975 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -162,6 +162,9 @@ class Exception extends \Exception public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists'; public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed'; + /** Video */ + public const PROFILES_NOT_FOUND = 'profiles_not_found'; + private $type = '';