mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
e2e tests
This commit is contained in:
@@ -3312,7 +3312,7 @@ $collections = [
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
//'filters' => ['json'],
|
||||
'filters' => ['json'],
|
||||
],
|
||||
[
|
||||
'$id' => 'status',
|
||||
@@ -3351,7 +3351,7 @@ $collections = [
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_video_stream_profile',
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['videoId', 'stream', 'profileId'],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
@@ -3433,8 +3433,8 @@ $collections = [
|
||||
'$id' => '_key_renditionId',
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['renditionId'],
|
||||
'lengths' => [Database::LENGTH_KEY],
|
||||
'orders' => [Database::ORDER_ASC],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
],
|
||||
]
|
||||
],
|
||||
@@ -3513,7 +3513,7 @@ $collections = [
|
||||
'indexes' => [
|
||||
[
|
||||
'$id' => '_key_unique',
|
||||
'type' => Database::INDEX_UNIQUE,
|
||||
'type' => Database::INDEX_KEY,
|
||||
'attributes' => ['stream', 'width', 'height', 'videoBitrate', 'audioBitrate' ],
|
||||
'lengths' => [],
|
||||
'orders' => [],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Event\Delete;
|
||||
use Appwrite\Event\Transcoding;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Stats\Stats;
|
||||
@@ -86,10 +87,10 @@ App::post('/v1/videos/profiles')
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VIDEO_PROFILE)
|
||||
->param('name', null, new Text(128), 'Video profile name.')
|
||||
->param('videoBitrate', '', new Range(64, 4000), 'Video profile bitrate in Kbps.')
|
||||
->param('audioBitrate', '', new Range(64, 4000), 'Audio profile bit rate in Kbps.')
|
||||
->param('width', '', new Range(100, 2000), 'Video profile width.')
|
||||
->param('height', '', new Range(100, 2000), 'Video profile height.')
|
||||
->param('videoBitrate', '', new Range(32, 5000), 'Video profile bitrate in Kbps.')
|
||||
->param('audioBitrate', '', new Range(32, 5000), 'Audio profile bit rate in Kbps.')
|
||||
->param('width', '', new Range(6, 3000), 'Video profile width.')
|
||||
->param('height', '', new Range(6, 3000), 'Video profile height.')
|
||||
->param('stream', false, new WhiteList(['hls', 'dash']), 'Video profile stream protocol.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -267,7 +268,7 @@ App::post('/v1/videos/:videoId/subtitles')
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if (empty($video)) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
@@ -380,7 +381,7 @@ App::delete('/v1/videos/:videoId/subtitles/:subtitleId')
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
@@ -479,45 +480,24 @@ App::delete('/v1/videos/:videoId')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
->inject('user')
|
||||
->inject('deviceVideos')
|
||||
->action(function (string $videoId, string $renditionId, Response $response, Document $project, Database $dbForProject, string $mode, Document $user, Device $deviceVideos) {
|
||||
->inject('deletes')
|
||||
->action(function (string $videoId, string $renditionId, Response $response, Document $project, Database $dbForProject, string $mode, Document $user, Delete $deletes) {
|
||||
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
|
||||
$deleted = $dbForProject->deleteDocument('videos', $videoId);
|
||||
|
||||
if (!$deleted) {
|
||||
throw new Exception('Failed to remove video from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$renditions = Authorization::skip(fn() => $dbForProject->find('videos_renditions', [
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$video->getId()]),
|
||||
], 12, 0, [], ['ASC']));
|
||||
|
||||
foreach ($renditions as $rendition) {
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_renditions', $rendition->getId()));
|
||||
}
|
||||
|
||||
$subtitles = Authorization::skip(fn() => $dbForProject->find('videos_subtitles', [
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$video->getId()]),
|
||||
], 12, 0, [], ['ASC']));
|
||||
|
||||
foreach ($subtitles as $subtitle) {
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_subtitles', $subtitle->getId()));
|
||||
}
|
||||
|
||||
foreach ($renditions as $rendition) {
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_renditions', $rendition->getId()));
|
||||
}
|
||||
|
||||
$videoPath = $this->getVideoDevice($project->getId())->getPath($this->args['videoId']);
|
||||
$deviceVideos->deletePath($videoPath);
|
||||
$deletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($video);
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
@@ -546,16 +526,16 @@ App::post('/v1/videos/:videoId/rendition')
|
||||
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
if (empty($video)) {
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
|
||||
$profile = Authorization::skip(fn() => $dbForProject->findOne('videos_profiles', [new Query('_uid', Query::TYPE_EQUAL, [$profileId])]));
|
||||
|
||||
if (!$profile) {
|
||||
throw new Exception('Video profile not found', 400, Exception::VIDEO_PROFILE_NOT_FOUND);
|
||||
if (empty($profile)) {
|
||||
throw new Exception('Video profile not found', 404, Exception::VIDEO_PROFILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$transcoder = new Transcoding();
|
||||
@@ -592,7 +572,7 @@ App::get('/v1/videos/:videoId/rendition/:renditionId')
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
@@ -629,7 +609,7 @@ App::get('/v1/videos/:videoId/renditions')
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
@@ -640,7 +620,7 @@ App::get('/v1/videos/:videoId/renditions')
|
||||
new Query('status', Query::TYPE_EQUAL, ['ready']),
|
||||
];
|
||||
|
||||
$renditions = Authorization::skip(fn () => $dbForProject->find('videos_renditions', $queries, 18, 0, [], ['ASC']));
|
||||
$renditions = Authorization::skip(fn () => $dbForProject->find('videos_renditions', $queries));
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'total' => $dbForProject->count('videos_renditions', $queries, APP_LIMIT_COUNT),
|
||||
@@ -671,7 +651,7 @@ App::delete('/v1/videos/:videoId/renditions/:renditionId')
|
||||
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [new Query('_uid', Query::TYPE_EQUAL, [$videoId])]));
|
||||
|
||||
if ($video->isEmpty()) {
|
||||
throw new Exception('Video not found', 400, Exception::VIDEO_NOT_FOUND);
|
||||
throw new Exception('Video not found', 404, Exception::VIDEO_NOT_FOUND);
|
||||
}
|
||||
|
||||
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode, $user);
|
||||
@@ -730,10 +710,10 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
new Query('endedAt', Query::TYPE_GREATER, [0]),
|
||||
new Query('status', Query::TYPE_EQUAL, ['ready']),
|
||||
new Query('stream', Query::TYPE_EQUAL, [$streamId]),
|
||||
], 12, 0, [], ['ASC']));
|
||||
]));
|
||||
|
||||
if (empty($renditions)) {
|
||||
throw new Exception('Rendition not found', 404, Exception::VIDEO_RENDITION_NOT_FOUND);
|
||||
throw new Exception('Renditions not found', 404, Exception::VIDEO_RENDITION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$baseUrl = 'http://127.0.0.1/v1/videos/' . $videoId . '/streams/' . $streamId;
|
||||
@@ -770,7 +750,10 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
$adaptationId = 0;
|
||||
foreach ($renditions as $rendition) {
|
||||
$metadata = $rendition->getAttribute('metadata');
|
||||
$xml = simplexml_load_string($metadata['xml']);
|
||||
$xml = simplexml_load_string($metadata['mpd']);
|
||||
if (empty($xml)) {
|
||||
continue;
|
||||
}
|
||||
$representationId = 0;
|
||||
foreach ($xml->Period->AdaptationSet as $adaptation) {
|
||||
$representation = [];
|
||||
@@ -782,8 +765,10 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
$segments = Authorization::skip(fn() => $dbForProject->find('videos_renditions_segments', [
|
||||
new Query('renditionId', Query::TYPE_EQUAL, [$rendition->getId()]),
|
||||
new Query('representationId', Query::TYPE_EQUAL, [$representationId]),
|
||||
], 1000, 0, ['representationId'], ['ASC']));
|
||||
|
||||
], 1000, 0, ['representationId']));
|
||||
if (count($segments) === 0) {
|
||||
continue;
|
||||
}
|
||||
foreach ($segments ?? [] as $segment) {
|
||||
if ($segment->getAttribute('isInit')) {
|
||||
$representation['SegmentList']['Initialization'] = $segment->getId();
|
||||
|
||||
+3
-2
@@ -12,7 +12,7 @@ if (\file_exists(__DIR__ . '/../vendor/autoload.php')) {
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
}
|
||||
|
||||
ini_set('memory_limit', '512M');
|
||||
ini_set('memory_limit', '1024M');
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
ini_set('default_socket_timeout', -1);
|
||||
@@ -144,6 +144,7 @@ const DELETE_TYPE_USAGE = 'usage';
|
||||
const DELETE_TYPE_REALTIME = 'realtime';
|
||||
const DELETE_TYPE_BUCKETS = 'buckets';
|
||||
const DELETE_TYPE_SESSIONS = 'sessions';
|
||||
const DELETE_TYPE_VIDEOS = 'videos';
|
||||
// Mail Types
|
||||
const MAIL_TYPE_VERIFICATION = 'verification';
|
||||
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
|
||||
@@ -843,7 +844,7 @@ App::setResource('project', function ($dbForConsole, $request, $console) {
|
||||
/** @var Utopia\Database\Database $dbForConsole */
|
||||
/** @var Utopia\Database\Document $console */
|
||||
|
||||
$projectId = 'dev';
|
||||
//$projectId = 'dev';
|
||||
$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', 'console'));
|
||||
|
||||
if ($projectId === 'console') {
|
||||
|
||||
+5
-5
@@ -42,8 +42,8 @@ foreach (
|
||||
}
|
||||
}
|
||||
|
||||
//$preloader
|
||||
//->paths(realpath(__DIR__ . '/../app/config'))
|
||||
//->paths(realpath(__DIR__ . '/../app/controllers'))
|
||||
//->paths(realpath(__DIR__ . '/../src'))
|
||||
//->load();
|
||||
$preloader
|
||||
->paths(realpath(__DIR__ . '/../app/config'))
|
||||
->paths(realpath(__DIR__ . '/../app/controllers'))
|
||||
->paths(realpath(__DIR__ . '/../src'))
|
||||
->load();
|
||||
|
||||
@@ -68,6 +68,9 @@ class DeletesV1 extends Worker
|
||||
case DELETE_TYPE_BUCKETS:
|
||||
$this->deleteBucket($document, $project->getId());
|
||||
break;
|
||||
case DELETE_TYPE_VIDEOS:
|
||||
$this->deleteVideo($document, $project->getId());
|
||||
break;
|
||||
default:
|
||||
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
|
||||
break;
|
||||
@@ -621,4 +624,43 @@ class DeletesV1 extends Worker
|
||||
|
||||
$device->deletePath($document->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $document database document
|
||||
* @param string $projectId
|
||||
*/
|
||||
protected function deleteVideo(Document $document, string $projectId): void
|
||||
{
|
||||
|
||||
$videoId = $document->getId();
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
$renditions = Authorization::skip(fn() => $dbForProject->find('videos_renditions', [
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$videoId])]));
|
||||
foreach ($renditions as $rendition) {
|
||||
$subtitles = Authorization::skip(fn() => $dbForProject->find('videos_subtitles', [
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$videoId])]));
|
||||
foreach ($subtitles as $subtitle) {
|
||||
$segments = Authorization::skip(fn() => $dbForProject->find('videos_subtitles_segments', [
|
||||
new Query('subtitleId', Query::TYPE_EQUAL, [$subtitle->getId()])]));
|
||||
foreach ($segments as $segment) {
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_subtitles_segments', $segment->getId()));
|
||||
}
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_subtitles', $subtitle->getId()));
|
||||
}
|
||||
|
||||
$this->deleteByGroup('videos_renditions_segments', [
|
||||
new Query('renditionId', Query::TYPE_EQUAL, [$rendition->getId()])
|
||||
], $dbForProject);
|
||||
|
||||
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_renditions', $rendition->getId()));
|
||||
}
|
||||
|
||||
$videosDevice = $this->getVideoDevice($projectId);
|
||||
$videosPath = $videosDevice->getPath($videoId);
|
||||
if ($videosDevice->deletePath($videosPath)) {
|
||||
Console::success('Deleted video directory: ' . $videosPath);
|
||||
} else {
|
||||
Console::error('Failed to delete video directory: ' . $videosPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+88
-96
@@ -12,12 +12,12 @@ use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use FFMpeg\FFProbe\DataMapping\StreamCollection;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Captioning\Format\SubripFile;
|
||||
use Utopia\Storage\Device;
|
||||
|
||||
require_once __DIR__ . '/../init.php';
|
||||
|
||||
@@ -87,51 +87,46 @@ class TranscodingV1 extends Worker
|
||||
|
||||
$bucket = Authorization::skip(fn() => $this->database->getDocument('buckets', $sourceVideo['bucketId']));
|
||||
$file = Authorization::skip(fn() => $this->database->getDocument('bucket_' . $bucket->getInternalId(), $sourceVideo['fileId']));
|
||||
$data = $this->getFilesDevice($project->getId())->read($file->getAttribute('path'));
|
||||
$fileName = basename($file->getAttribute('path'));
|
||||
$inPath = $this->inDir . $fileName;
|
||||
$collection = 'videos_renditions';
|
||||
|
||||
if (!empty($file->getAttribute('openSSLCipher'))) {
|
||||
$data = OpenSSL::decrypt(
|
||||
$data,
|
||||
$file->getAttribute('openSSLCipher'),
|
||||
App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')),
|
||||
0,
|
||||
\hex2bin($file->getAttribute('openSSLIV')),
|
||||
\hex2bin($file->getAttribute('openSSLTag'))
|
||||
);
|
||||
if (
|
||||
!empty($file->getAttribute('openSSLCipher')) ||
|
||||
!empty($file->getAttribute('algorithm', ''))
|
||||
) {
|
||||
$data = $this->getFilesDevice($project->getId())->read($file->getAttribute('path'));
|
||||
if (!empty($file->getAttribute('openSSLCipher'))) {
|
||||
$data = OpenSSL::decrypt(
|
||||
$data,
|
||||
$file->getAttribute('openSSLCipher'),
|
||||
App::getEnv('_APP_OPENSSL_KEY_V' . $file->getAttribute('openSSLVersion')),
|
||||
0,
|
||||
\hex2bin($file->getAttribute('openSSLIV')),
|
||||
\hex2bin($file->getAttribute('openSSLTag'))
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($file->getAttribute('algorithm', ''))) {
|
||||
$compressor = new GZIP();
|
||||
$data = $compressor->decompress($data);
|
||||
}
|
||||
|
||||
$this->getFilesDevice($project->getId())->write($this->inDir . $fileName, $data, $file->getAttribute('mimeType'));
|
||||
} else {
|
||||
$this->getFilesDevice($project->getId())->transfer($file->getAttribute('path'), $this->inDir . $fileName, $this->getFilesDevice($project->getId()));
|
||||
}
|
||||
|
||||
if (!empty($file->getAttribute('algorithm', ''))) {
|
||||
$compressor = new GZIP();
|
||||
$data = $compressor->decompress($data);
|
||||
}
|
||||
|
||||
$this->getFilesDevice($project->getId())->write($this->inDir . $fileName, $data, $file->getAttribute('mimeType'));
|
||||
|
||||
$ffprobe = FFMpeg\FFProbe::create([]);
|
||||
$ffmpeg = Streaming\FFMpeg::create([]);
|
||||
$ffprobe = FFMpeg\FFProbe::create();
|
||||
$ffmpeg = Streaming\FFMpeg::create([
|
||||
'timeout' => 0,
|
||||
'ffmpeg.threads' => 12
|
||||
]);
|
||||
|
||||
if (!$ffprobe->isValid($inPath)) {
|
||||
throw new Exception('Not an valid FFMpeg file "' . $inPath . '"');
|
||||
}
|
||||
|
||||
//Delete prev rendition
|
||||
$queries = [
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$sourceVideo->getId()]),
|
||||
new Query('profileId', Query::TYPE_EQUAL, [$profile->getId()])
|
||||
];
|
||||
|
||||
$rendition = Authorization::skip(fn() => $this->database->findOne($collection, $queries));
|
||||
if (!empty($rendition)) {
|
||||
Authorization::skip(fn() => $this->database->deleteDocument($collection, $rendition->getId()));
|
||||
$deviceFiles = $this->getVideoDevice($project->getId());
|
||||
if (!empty($rendition['path'])) {
|
||||
$deviceFiles->deletePath($rendition['path']);
|
||||
}
|
||||
}
|
||||
|
||||
$general = $this->getVideoSourceInfo($ffprobe->streams($inPath));
|
||||
if (!empty($general)) {
|
||||
foreach ($general as $key => $value) {
|
||||
@@ -152,11 +147,10 @@ class TranscodingV1 extends Worker
|
||||
$subtitles = Authorization::skip(fn () => $this->database->find('videos_subtitles', [
|
||||
new Query('status', Query::TYPE_EQUAL, ['']),
|
||||
new Query('videoId', Query::TYPE_EQUAL, [$this->args['videoId']])
|
||||
], 12, 0, [], ['ASC']));
|
||||
]));
|
||||
|
||||
foreach ($subtitles as $subtitle) {
|
||||
$subtitle->setAttribute('status', self::STATUS_START);
|
||||
$subtitle->setAttribute('path', $this->getRenditionName());
|
||||
Authorization::skip(fn() => $this->database->updateDocument(
|
||||
'videos_subtitles',
|
||||
$subtitle->getId(),
|
||||
@@ -165,26 +159,35 @@ class TranscodingV1 extends Worker
|
||||
|
||||
$subtitleBucket = Authorization::skip(fn() => $this->database->getDocument('buckets', $subtitle->getAttribute('bucketId')));
|
||||
$subtitleFile = Authorization::skip(fn() => $this->database->getDocument('bucket_' . $subtitleBucket->getInternalId(), $subtitle->getAttribute('fileId')));
|
||||
$subtitleData = $this->getFilesDevice($project->getId())->read($subtitleFile->getAttribute('path'));
|
||||
$subtitleFileName = basename($subtitleFile->getAttribute('path'));
|
||||
|
||||
if (!empty($subtitleFile->getAttribute('openSSLCipher'))) {
|
||||
$subtitleData = OpenSSL::decrypt(
|
||||
$subtitleData,
|
||||
$subtitleFile->getAttribute('openSSLCipher'),
|
||||
App::getEnv('_APP_OPENSSL_KEY_V' . $subtitleFile->getAttribute('openSSLVersion')),
|
||||
0,
|
||||
\hex2bin($subtitleFile->getAttribute('openSSLIV')),
|
||||
\hex2bin($subtitleFile->getAttribute('openSSLTag'))
|
||||
);
|
||||
if (
|
||||
!empty($subtitleFile->getAttribute('openSSLCipher')) ||
|
||||
!empty($subtitleFile->getAttribute('algorithm', ''))
|
||||
) {
|
||||
$subtitleData = $this->getFilesDevice($project->getId())->read($subtitleFile->getAttribute('path'));
|
||||
|
||||
if (!empty($subtitleFile->getAttribute('openSSLCipher'))) {
|
||||
$subtitleData = OpenSSL::decrypt(
|
||||
$subtitleData,
|
||||
$subtitleFile->getAttribute('openSSLCipher'),
|
||||
App::getEnv('_APP_OPENSSL_KEY_V' . $subtitleFile->getAttribute('openSSLVersion')),
|
||||
0,
|
||||
\hex2bin($subtitleFile->getAttribute('openSSLIV')),
|
||||
\hex2bin($subtitleFile->getAttribute('openSSLTag'))
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($subtitleFile->getAttribute('algorithm', ''))) {
|
||||
$compressor = new GZIP();
|
||||
$subtitleData = $compressor->decompress($subtitleData);
|
||||
}
|
||||
|
||||
$this->getFilesDevice($project->getId())->write($this->inDir . $subtitleFileName, $subtitleData, $subtitleFile->getAttribute('mimeType'));
|
||||
} else {
|
||||
$this->getFilesDevice($project->getId())->transfer($subtitleFile->getAttribute('path'), $this->inDir . $subtitleFileName, $this->getFilesDevice($project->getId()));
|
||||
}
|
||||
|
||||
if (!empty($subtitleFile->getAttribute('algorithm', ''))) {
|
||||
$compressor = new GZIP();
|
||||
$subtitleData = $compressor->decompress($subtitleData);
|
||||
}
|
||||
|
||||
$this->getFilesDevice($project->getId())->write($this->inDir . $subtitleFileName, $subtitleData, $subtitleFile->getAttribute('mimeType'));
|
||||
$ext = pathinfo($subtitleFileName, PATHINFO_EXTENSION);
|
||||
|
||||
if ($ext === 'srt') {
|
||||
@@ -198,7 +201,7 @@ class TranscodingV1 extends Worker
|
||||
'path' => $this->inDir . $this->args['videoId'] . '.vtt',
|
||||
];
|
||||
}
|
||||
try {
|
||||
|
||||
$query = Authorization::skip(function () use ($collection, $profile) {
|
||||
return $this->database->createDocument($collection, new Document([
|
||||
'videoId' => $this->args['videoId'],
|
||||
@@ -209,10 +212,9 @@ class TranscodingV1 extends Worker
|
||||
'stream' => $profile['stream'],
|
||||
]));
|
||||
});
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Video rendition already exists', 409, Exception::VIDEO_RENDITION_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$renditionRootPath = $this->getVideoDevice($project->getId())->getPath($this->args['videoId']) . '/';
|
||||
$renditionPath = $renditionRootPath . $this->getRenditionName() . '-' . $query->getId() . '/';
|
||||
|
||||
try {
|
||||
$representation = (new Representation())->
|
||||
@@ -243,12 +245,12 @@ class TranscodingV1 extends Worker
|
||||
$m3u8 = $this->parseM3u8($this->outPath . '_' . $representation->getHeight() . 'p.m3u8');
|
||||
if (!empty($m3u8['segments'])) {
|
||||
foreach ($m3u8['segments'] as $segment) {
|
||||
Authorization::skip(function () use ($segment, $project, $query) {
|
||||
Authorization::skip(function () use ($segment, $project, $query, $renditionPath) {
|
||||
return $this->database->createDocument('videos_renditions_segments', new Document([
|
||||
'renditionId' => $query->getId(),
|
||||
'representationId' => 0,
|
||||
'fileName' => $segment['fileName'],
|
||||
'path' => $this->getVideoDevice($project->getId())->getPath($this->args['videoId']) . '/' . $this->getRenditionName() . '/',
|
||||
'path' => $renditionPath,
|
||||
'duration' => $segment['duration'],
|
||||
]));
|
||||
});
|
||||
@@ -256,16 +258,15 @@ class TranscodingV1 extends Worker
|
||||
}
|
||||
$query->setAttribute('targetDuration', $m3u8['targetDuration']);
|
||||
} else {
|
||||
|
||||
$mpd = $this->parseMpd($this->outPath . '.mpd');
|
||||
if (!empty($mpd['segments'])) {
|
||||
foreach ($mpd['segments'] as $segment) {
|
||||
Authorization::skip(function () use ($segment, $project, $query) {
|
||||
Authorization::skip(function () use ($segment, $project, $query, $renditionPath) {
|
||||
return $this->database->createDocument('videos_renditions_segments', new Document([
|
||||
'renditionId' => $query->getId(),
|
||||
'representationId' => $segment['representationId'],
|
||||
'fileName' => $segment['fileName'],
|
||||
'path' => $this->getVideoDevice($project->getId())->getPath($this->args['videoId']) . '/' . $this->getRenditionName() . '/',
|
||||
'path' => $renditionPath,
|
||||
'isInit' => $segment['isInit'],
|
||||
]));
|
||||
});
|
||||
@@ -273,7 +274,7 @@ class TranscodingV1 extends Worker
|
||||
}
|
||||
|
||||
if (!empty($mpd['metadata'])) {
|
||||
$query->setAttribute('metadata', json_encode(['xml' => $mpd['metadata']]));
|
||||
$query->setAttribute('metadata', json_encode(['mpd' => $mpd['metadata']]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,11 +287,11 @@ class TranscodingV1 extends Worker
|
||||
if ($profile['stream'] === 'hls') {
|
||||
$m3u8 = $this->parseM3u8($this->outPath . '_subtitles_' . $subtitle['code'] . '.m3u8');
|
||||
foreach ($m3u8['segments'] as $segment) {
|
||||
Authorization::skip(function () use ($segment, $project, $subtitle) {
|
||||
Authorization::skip(function () use ($segment, $project, $subtitle, $renditionRootPath) {
|
||||
return $this->database->createDocument('videos_subtitles_segments', new Document([
|
||||
'subtitleId' => $subtitle->getId(),
|
||||
'fileName' => $segment['fileName'],
|
||||
'path' => $this->getVideoDevice($project->getId())->getPath($this->args['videoId']) . '/' ,
|
||||
'path' => $renditionRootPath ,
|
||||
'duration' => $segment['duration'],
|
||||
]));
|
||||
});
|
||||
@@ -299,6 +300,7 @@ class TranscodingV1 extends Worker
|
||||
}
|
||||
|
||||
$subtitle->setAttribute('status', self::STATUS_READY);
|
||||
$subtitle->setAttribute('path', $renditionRootPath);
|
||||
Authorization::skip(fn() => $this->database->updateDocument(
|
||||
'videos_subtitles',
|
||||
$subtitle->getId(),
|
||||
@@ -306,7 +308,7 @@ class TranscodingV1 extends Worker
|
||||
));
|
||||
}
|
||||
}
|
||||
/** Upload & remove files **/
|
||||
/** Upload & cleanup **/
|
||||
$start = 0;
|
||||
$fileNames = scandir($this->outDir);
|
||||
|
||||
@@ -316,38 +318,31 @@ class TranscodingV1 extends Worker
|
||||
continue;
|
||||
}
|
||||
|
||||
$devicePath = $this->getVideoDevice($project->getId())->getPath($this->args['videoId']);
|
||||
$data = $this->getFilesDevice($project->getId())->read($this->outDir . $fileName);
|
||||
$to = $devicePath . '/' . $this->getRenditionName() . '/';
|
||||
$to = $renditionPath;
|
||||
if (str_contains($fileName, "_subtitles_") || str_contains($fileName, ".vtt")) {
|
||||
$to = $devicePath . '/';
|
||||
$to = $renditionRootPath;
|
||||
}
|
||||
|
||||
$this->getVideoDevice($project->getId())->write($to . $fileName, $data, \mime_content_type($this->outDir . $fileName));
|
||||
if ($start === 0) {
|
||||
$query->setAttribute('status', self::STATUS_UPLOADING);
|
||||
$query->setAttribute('path', $devicePath . '/' . $this->getRenditionName());
|
||||
$query->setAttribute('path', $renditionPath);
|
||||
Authorization::skip(fn() => $this->database->updateDocument($collection, $query->getId(), $query));
|
||||
$start = 1;
|
||||
}
|
||||
|
||||
//$metadata=[];
|
||||
//$chunksUploaded = $deviceFiles->upload($file, $path, -1, 1, $metadata);
|
||||
//var_dump($chunksUploaded);
|
||||
// if (empty($chunksUploaded)) {
|
||||
// throw new Exception('Failed uploading file', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
//}
|
||||
// }
|
||||
|
||||
//@unlink($this->outDir . $fileName);
|
||||
}
|
||||
|
||||
$query->setAttribute('status', self::STATUS_READY);
|
||||
Authorization::skip(fn() => $this->database->updateDocument($collection, $query->getId(), $query));
|
||||
} catch (\Throwable $th) {
|
||||
var_dump($th->getCode());
|
||||
var_dump($th->getMessage());
|
||||
$query->setAttribute('metadata', json_encode([
|
||||
'code' => $th->getCode(),
|
||||
'message' => substr($th->getMessage(), 0, 2048),
|
||||
'message' => substr($th->getMessage(), 0, 3800),
|
||||
]));
|
||||
|
||||
$query->setAttribute('status', self::STATUS_ERROR);
|
||||
@@ -365,14 +360,13 @@ class TranscodingV1 extends Worker
|
||||
*/
|
||||
private function transcode(string $stream, Media $video, StreamFormat $format, Representation $representation, array $subtitles): string | array
|
||||
{
|
||||
|
||||
$additionalParams = [
|
||||
'-dn',
|
||||
'-sn',
|
||||
'-vf', 'scale=iw:-2:force_original_aspect_ratio=increase,setsar=1:1'
|
||||
'-vf', 'scale=iw:-2:force_original_aspect_ratio=increase,setsar=1:1',
|
||||
];
|
||||
|
||||
$segmentSize = 10;
|
||||
$segmentSize = 8;
|
||||
|
||||
if ($stream === 'dash') {
|
||||
$dash = $video->dash()
|
||||
@@ -481,15 +475,14 @@ class TranscodingV1 extends Worker
|
||||
*/
|
||||
private function getVideoSourceInfo(StreamCollection $streams): array
|
||||
{
|
||||
|
||||
return [
|
||||
'duration' => $streams->videos()->count() ? $streams->videos()->first()->get('duration') : '0',
|
||||
'height' => $streams->videos()->count() ? $streams->videos()->first()->get('height') : 0,
|
||||
'width' => $streams->videos()->count() ? $streams->videos()->first()->get('width') : 0,
|
||||
'videoCodec' => $streams->videos()->count() ? $streams->videos()->first()->get('codec_name') . ',' . $streams->videos()->first()->get('codec_tag_string') : '',
|
||||
'videoFramerate' => $streams->videos()->count() ? $streams->videos()->first()->get('avg_frame_rate') : '',
|
||||
'duration' => $streams->videos()->count()> 0 ? $streams->videos()->first()->get('duration') : '0',
|
||||
'height' => $streams->videos()->count()> 0 ? $streams->videos()->first()->get('height') : 0,
|
||||
'width' => $streams->videos()->count() > 0 ? $streams->videos()->first()->get('width') : 0,
|
||||
'videoCodec' => $streams->videos()->count() > 0 ? $streams->videos()->first()->get('codec_name') : '',
|
||||
'videoFramerate' => $streams->videos()->count() > 0 ? $streams->videos()->first()->get('avg_frame_rate') : '',
|
||||
'videoBitrate' => $streams->videos()->count() > 0 ? (int)$streams->videos()->first()->get('bit_rate') : 0,
|
||||
'audioCodec' => $streams->audios()->count() > 0 ? $streams->audios()->first()->get('codec_name') . ',' . $streams->audios()->first()->get('codec_tag_string') : '',
|
||||
'audioCodec' => $streams->audios()->count() > 0 ? $streams->audios()->first()->get('codec_name') : '',
|
||||
'audioSamplerate' => $streams->audios()->count() > 0 ? (int)$streams->audios()->first()->get('sample_rate') : 0,
|
||||
'audioBitrate' => $streams->audios()->count() > 0 ? (int)$streams->audios()->first()->get('bit_rate') : 0,
|
||||
];
|
||||
@@ -508,19 +501,18 @@ class TranscodingV1 extends Worker
|
||||
// }
|
||||
$info['width'] = $representation->getWidth();
|
||||
$info['height'] = $representation->getHeight();
|
||||
if (!empty($metadata['video']['streams'])) {
|
||||
foreach ($metadata['video']['streams'] as $streams) {
|
||||
|
||||
foreach ($metadata['video']['streams'] ?? [] as $streams) {
|
||||
if ($streams['codec_type'] === 'video') {
|
||||
$info['duration'] = !empty($streams['duration']) ? $streams['duration'] : '0';
|
||||
$info['videoCodec'] = !empty($streams['codec_name']) ? $streams['codec_name'] . ',' . $streams['codec_tag_string'] : '';
|
||||
$info['videoBitrate'] = !empty($streams['bit_rate']) ? (int)$streams['bit_rate'] : $representation->getKiloBitrate() * 1024;
|
||||
$info['videoCodec'] = !empty($streams['codec_name']) ? $streams['codec_name'] : '';
|
||||
$info['videoBitrate'] = !empty($streams['bit_rate']) ? (int)$streams['bit_rate'] : $representation->getKiloBitrate();
|
||||
$info['videoFramerate'] = !empty($streams['avg_frame_rate']) ? $streams['avg_frame_rate'] : '';
|
||||
} elseif ($streams['codec_type'] === 'audio') {
|
||||
$info['audioCodec'] = !empty($streams['codec_name']) ? $streams['codec_name'] . ',' . $streams['codec_tag_string'] : '' ;
|
||||
$info['audioCodec'] = !empty($streams['codec_name']) ? $streams['codec_name'] : '' ;
|
||||
$info['audioSamplerate'] = !empty($streams['sample_rate']) ? (int)$streams['sample_rate'] : 0;
|
||||
$info['audioBitrate'] = !empty($streams['bit_rate']) ? (int)$streams['bit_rate'] : $representation->getAudioKiloBitrate() * 1024;
|
||||
$info['audioBitrate'] = !empty($streams['bit_rate']) ? (int)$streams['bit_rate'] : $representation->getAudioKiloBitrate();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
|
||||
Generated
-9243
File diff suppressed because it is too large
Load Diff
@@ -14,9 +14,8 @@ class VideoCustomServerTest extends Scope
|
||||
use VideoCustom;
|
||||
use SideServer;
|
||||
|
||||
public function testCreateVideoProfile()
|
||||
public function testCreateProfile(): string
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/profiles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -30,11 +29,21 @@ class VideoCustomServerTest extends Scope
|
||||
'stream' => 'hls',
|
||||
]);
|
||||
|
||||
$profileId = $response['body']['$id'];
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/videos/profiles/' . $response['body']['$id'], [
|
||||
return $profileId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateProfile
|
||||
*/
|
||||
public function testUpdateProfile(string $profileId)
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/videos/profiles/' . $profileId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
@@ -44,14 +53,20 @@ class VideoCustomServerTest extends Scope
|
||||
'audioBitrate' => 120,
|
||||
'width' => 300,
|
||||
'height' => 400,
|
||||
'stream' => 'hls',
|
||||
'stream' => 'dash',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
}
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles/' . $response['body']['$id'], [
|
||||
/**
|
||||
* @depends testCreateProfile
|
||||
*/
|
||||
public function testGetProfile(string $profileId)
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles/' . $profileId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
@@ -63,8 +78,16 @@ class VideoCustomServerTest extends Scope
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals('My updated test profile', $response['body']['name']);
|
||||
$this->assertEquals(300, $response['body']['width']);
|
||||
$this->assertEquals(400, $response['body']['height']);
|
||||
}
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/videos/profiles/' . $response['body']['$id'], [
|
||||
/**
|
||||
* @depends testCreateProfile
|
||||
*/
|
||||
public function testDeleteProfile(string $profileId)
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/videos/profiles/' . $profileId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
@@ -93,10 +116,45 @@ class VideoCustomServerTest extends Scope
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
}
|
||||
|
||||
|
||||
public function testCreateVideo(): string
|
||||
public function testDeleteAllProfiles()
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
$profiles = $response['body']['profiles'];
|
||||
foreach ($profiles as $profile) {
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/videos/profiles/' . $profile['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles/' . $profile['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals('Video profile not found', $response['body']['message']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testDeleteAllProfiles
|
||||
*/
|
||||
public function testCreateVideo(): string
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -116,9 +174,8 @@ class VideoCustomServerTest extends Scope
|
||||
/**
|
||||
* @depends testCreateVideo
|
||||
*/
|
||||
public function testCreateVideoSubtitle($videoId)
|
||||
public function testCreateSubtitles($videoId)
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -135,6 +192,42 @@ class VideoCustomServerTest extends Scope
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'Italian',
|
||||
'code' => 'It',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'Hebrew',
|
||||
'code' => 'Heb',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateVideo
|
||||
*/
|
||||
public function testGetSubtitles($videoId): array
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -143,12 +236,25 @@ class VideoCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
$this->assertNotEmpty($response['body']['subtitles']);
|
||||
$this->assertNotEmpty($response['body']['subtitles'][0]['$id']);
|
||||
$this->assertEquals('English', $response['body']['subtitles'][0]['name']);
|
||||
$this->assertEquals('Eng', $response['body']['subtitles'][0]['code']);
|
||||
$this->assertEquals(true, $response['body']['subtitles'][0]['default']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/videos/' . $videoId . '/subtitles/' . $response['body']['subtitles'][0]['$id'], [
|
||||
return $response['body']['subtitles'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGetSubtitles
|
||||
*/
|
||||
public function testUpdateSubtitle($subtitles): array
|
||||
{
|
||||
$subtitleId = $subtitles[1]['$id'];
|
||||
$videoId = $subtitles[1]['videoId'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/videos/' . $videoId . '/subtitles/' . $subtitleId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
@@ -157,7 +263,6 @@ class VideoCustomServerTest extends Scope
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'Polish',
|
||||
'code' => 'Pol',
|
||||
'default' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
@@ -170,49 +275,48 @@ class VideoCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
$this->assertNotEmpty($response['body']['subtitles']);
|
||||
$this->assertNotEmpty($response['body']['subtitles'][0]['$id']);
|
||||
$this->assertEquals('Polish', $response['body']['subtitles'][0]['name']);
|
||||
$this->assertNotEmpty($response['body']['subtitles'][1]['$id']);
|
||||
$this->assertEquals('Pol', $response['body']['subtitles'][1]['code']);
|
||||
$this->assertEquals('Polish', $response['body']['subtitles'][1]['name']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/videos/' . $videoId . '/subtitles/' . $response['body']['subtitles'][0]['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
return $response['body']['subtitles'];
|
||||
}
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
/**
|
||||
* @depends testGetSubtitles
|
||||
*/
|
||||
public function testDeleteSubtitle($subtitles)
|
||||
{
|
||||
$videoId = $subtitles[0]['videoId'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
foreach ($subtitles as $subtitle) {
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/videos/' . $subtitle['videoId'] . '/subtitles/' . $subtitle['$id'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @depends testCreateVideo
|
||||
*/
|
||||
public function testTranscodeWithSubs(): array
|
||||
public function testTranscodeWithSubs($videoId): string
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getVideo()['$id']
|
||||
]);
|
||||
|
||||
$videoId = $response['body']['$id'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -220,110 +324,144 @@ class VideoCustomServerTest extends Scope
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'hebrew',
|
||||
'code' => 'heb',
|
||||
]);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'english',
|
||||
'code' => 'eng',
|
||||
'name' => 'English',
|
||||
'code' => 'Eng',
|
||||
'default' => true,
|
||||
]);
|
||||
|
||||
$subtitleId = $response['body']['$id'];
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles', [
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/subtitles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getSubtitle()['$id'],
|
||||
'name' => 'Italian',
|
||||
'code' => 'It',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
|
||||
$profileId = $response['body']['profiles'][0]['$id'];
|
||||
|
||||
/**
|
||||
* Try to transcode with wrong profileId
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/rendition', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'profileId' => $profileId,
|
||||
'profileId' => $videoId,
|
||||
]);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals('Video profile not found', $response['body']['message']);
|
||||
|
||||
return [
|
||||
'videoId' => $videoId,
|
||||
'subtitleId' => $subtitleId
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function testTranscodingRendition(): array
|
||||
{
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/video', [
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/profiles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'bucketId' => $this->getBucket()['$id'],
|
||||
'fileId' => $this->getVideo()['$id']
|
||||
'name' => 'Profile A',
|
||||
'videoBitrate' => 770,
|
||||
'audioBitrate' => 64,
|
||||
'width' => 600,
|
||||
'height' => 400,
|
||||
'stream' => 'hls',
|
||||
]);
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/profiles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'name' => 'Profile B',
|
||||
'videoBitrate' => 570,
|
||||
'audioBitrate' => 64,
|
||||
'width' => 300,
|
||||
'height' => 200,
|
||||
'stream' => 'dash',
|
||||
]);
|
||||
|
||||
$videoId = $response['body']['$id'];
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/profiles', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, $response['body']['total']);
|
||||
|
||||
$profiles = $response['body']['profiles'];
|
||||
|
||||
foreach ($response['body']['profiles'] as $profile) {
|
||||
$profileId = $profile['$id'];
|
||||
/**
|
||||
* Try to transcode with wrong videoId
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $response['body']['profiles'][0]['$id'] . '/rendition', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'profileId' => $response['body']['profiles'][0]['$id'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
$this->assertEquals('Video not found', $response['body']['message']);
|
||||
|
||||
foreach ($profiles as $profile) {
|
||||
$response = $this->client->call(Client::METHOD_POST, '/videos/' . $videoId . '/rendition', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], [
|
||||
'profileId' => $profileId,
|
||||
'profileId' => $profile['$id'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
return [
|
||||
'videoId' => $videoId,
|
||||
];
|
||||
return $videoId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testTranscodeWithSubs
|
||||
*/
|
||||
public function testGetRenditions(array $data): array
|
||||
public function testGetRenditionsWithSubs(string $videoId): string
|
||||
{
|
||||
|
||||
sleep(30);
|
||||
sleep(50);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . '/renditions', [
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/renditions', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(2, $response['body']['total']);
|
||||
$this->assertNotEmpty($response['body']['renditions']);
|
||||
|
||||
$videoId = $response['body']['renditions'][0]['videoId'];
|
||||
$renditionId = $response['body']['renditions'][0]['$id'];
|
||||
$profileId = $response['body']['renditions'][0]['profileId'];
|
||||
$profileName = $response['body']['renditions'][0]['name'];
|
||||
$stream = $response['body']['renditions'][0]['stream'];
|
||||
|
||||
foreach ($response['body']['renditions'] as $rendition) {
|
||||
$this->assertEquals('ready', $rendition['status']);
|
||||
$this->assertEquals('99', $rendition['progress']);
|
||||
$this->assertNotEmpty($rendition['videoBitrate']);
|
||||
$this->assertNotEmpty($rendition['videoCodec']);
|
||||
}
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . '/rendition/' . $renditionId, [
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/rendition/' . $renditionId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
@@ -331,16 +469,134 @@ class VideoCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals($renditionId, $response['body']['$id']);
|
||||
//var_dump($response['body']);
|
||||
|
||||
return [
|
||||
'renditionId' => $renditionId,
|
||||
'videoId' => $videoId,
|
||||
'profileId' => $profileId,
|
||||
'profileName' => $profileName,
|
||||
'subtitleId' => $data['subtitleId'],
|
||||
'stream' => $stream
|
||||
];
|
||||
return $videoId;
|
||||
}
|
||||
/**
|
||||
* @depends testGetRenditionsWithSubs
|
||||
*/
|
||||
public function testStreamManifest($videoId): void
|
||||
{
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/hls', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
$this->assertEquals(3, count($match[0]));
|
||||
$subtitleUri = $match[0][0];
|
||||
$renditionUri = $match[0][2];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $renditionUri, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
$this->assertEquals(12, count($match[0]));
|
||||
|
||||
$segmentUri = $match[0][0];
|
||||
$response = $this->client->call(Client::METHOD_GET, $segmentUri, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, strlen($response['body']));
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $subtitleUri, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
$segmentUri = $match[0][0];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $segmentUri, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1506, strlen($response['body']));
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/dash', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
|
||||
$xml = simplexml_load_string($response['body']);
|
||||
foreach ($xml->Period->AdaptationSet as $adaptation) {
|
||||
if ((string) $adaptation['contentType'] === 'video') {
|
||||
$this->assertEquals("50/1", $adaptation['frameRate']);
|
||||
$this->assertEquals("300", $adaptation['maxWidth']);
|
||||
$this->assertEquals("30:17", $adaptation['par']);
|
||||
$this->assertEquals("und", $adaptation['lang']);
|
||||
foreach ($adaptation->Representation as $representation) {
|
||||
$this->assertEquals("video/mp4", $representation['mimeType']);
|
||||
$this->assertEquals("avc1.640015", $representation['codecs']);
|
||||
$this->assertEquals("300", $representation['width']);
|
||||
$this->assertEquals("200", $representation['height']);
|
||||
$this->assertEquals("20:17", $representation['sar']);
|
||||
$this->assertEquals(10, $representation->SegmentList->SegmentURL->count());
|
||||
$videoSegmentBaseUrl = (string)$representation->BaseURL;
|
||||
$videoSegmentInitialization = (string)$representation->SegmentList->Initialization['sourceURL'];
|
||||
$videoSegmentId = (string)$representation->SegmentList->SegmentURL['media'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $videoSegmentBaseUrl . $videoSegmentInitialization, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, strlen($response['body']));
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $videoSegmentBaseUrl . $videoSegmentId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, strlen($response['body']));
|
||||
}
|
||||
} elseif ((string) $adaptation['contentType'] === 'audio') {
|
||||
foreach ($adaptation->Representation as $representation) {
|
||||
$this->assertEquals("audio/mp4", $representation['mimeType']);
|
||||
$this->assertEquals("mp4a.40.2", $representation['codecs']);
|
||||
$this->assertEquals(12, $representation->SegmentList->SegmentURL->count());
|
||||
$audioSegmentBaseUrl = (string)$representation->BaseURL;
|
||||
$audioSegmentInitialization = (string)$representation->SegmentList->Initialization['sourceURL'];
|
||||
$audioSegmentId = (string)$representation->SegmentList->SegmentURL['media'];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $audioSegmentBaseUrl . $audioSegmentInitialization, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, strlen($response['body']));
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $audioSegmentBaseUrl . $audioSegmentId, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, strlen($response['body']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,67 +612,53 @@ class VideoCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
var_dump($response['body']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . $data['stream'] . '/renditions/' . $data['renditionId'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
var_dump($response['body']);
|
||||
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
|
||||
$segmentUrl = $match[0][0];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $segmentUrl, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
//var_dump($response['body']);
|
||||
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . '/streams/' . $data['stream'] . '/subtitles/' . $data['subtitleId'], [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
//var_dump($response['body']);
|
||||
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
|
||||
$segmentUrl = $match[0][0];
|
||||
|
||||
var_dump($segmentUrl);
|
||||
$response = $this->client->call(Client::METHOD_GET, $segmentUrl, [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
//var_dump($response['body']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @depends testGetRenditions
|
||||
*/
|
||||
public function testDashStreamRender($data): void
|
||||
{
|
||||
|
||||
sleep(20);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . '/streams/dash', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
var_dump($response['body']);
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * @depends testGetRenditions
|
||||
// */
|
||||
// public function testDashStreamRender($data): void
|
||||
// {
|
||||
//
|
||||
// sleep(20);
|
||||
//
|
||||
// $response = $this->client->call(Client::METHOD_GET, '/videos/' . $data['videoId'] . '/streams/dash', [
|
||||
// 'content-type' => 'application/json',
|
||||
// 'x-appwrite-project' => $this->getProject()['$id'],
|
||||
// 'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
// ]);
|
||||
//
|
||||
// var_dump($response['body']);
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user