This commit is contained in:
shimon
2022-09-05 17:29:03 +03:00
parent 115b032f3a
commit ca0017ca40
18 changed files with 97 additions and 6422 deletions
+6 -6
View File
@@ -3337,7 +3337,7 @@ $collections = [
'filters' => [],
],
[
'$id' => 'stream',
'$id' => 'protocol',
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
@@ -3350,9 +3350,9 @@ $collections = [
],
'indexes' => [
[
'$id' => '_key_video_stream_profile',
'$id' => '_key_video_protocol_profile',
'type' => Database::INDEX_KEY,
'attributes' => ['videoId', 'stream', 'profileId'],
'attributes' => ['videoId', 'protocol', 'profileId'],
'lengths' => [],
'orders' => [],
],
@@ -3408,7 +3408,7 @@ $collections = [
'filters' => [],
],
[
'$id' => 'representationId',
'$id' => 'streamId',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
@@ -3501,7 +3501,7 @@ $collections = [
'filters' => [],
],
[
'$id' => 'stream',
'$id' => 'protocol',
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
@@ -3516,7 +3516,7 @@ $collections = [
[
'$id' => '_key_unique',
'type' => Database::INDEX_KEY,
'attributes' => ['stream', 'width', 'height', 'videoBitrate', 'audioBitrate' ],
'attributes' => ['protocol', 'width', 'height', 'videoBitrate', 'audioBitrate' ],
'lengths' => [],
'orders' => [],
],
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -8,7 +8,7 @@ return [
'audioBitrate' => 64, //audio bitrate in Kbps
'width' => 640, //width resolution in px
'height' => 360, //height resolution in px
'stream' => 'dash'
'protocol' => 'dash'
],
[
'name' => '576p',
@@ -16,7 +16,7 @@ return [
'audioBitrate' => 128,
'width' => 1024,
'height' => 576,
'stream' => 'dash'
'protocol' => 'dash'
],
[
'name' => '720p',
@@ -24,7 +24,7 @@ return [
'audioBitrate' => 128,
'width' => 1280,
'height' => 720,
'stream' => 'hls'
'protocol' => 'hls'
],
];
+1 -1
View File
@@ -166,7 +166,7 @@ App::post('/v1/projects')
'audioBitrate' => $profile['audioBitrate'],
'width' => $profile['width'],
'height' => $profile['height'],
'stream' => $profile['stream']
'protocol' => $profile['protocol']
]));
});
}
+38 -38
View File
@@ -592,7 +592,7 @@ App::get('/v1/videos/:videoId/renditions')
});
App::get('/v1/videos/:videoId/streams/:streamId')
App::get('/v1/videos/:videoId/protocols/:protocolId')
->desc('Get video master renditions manifest')
->groups(['api', 'video'])
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
@@ -603,12 +603,12 @@ App::get('/v1/videos/:videoId/streams/:streamId')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
->param('protocolId', '', new WhiteList(['hls', 'dash']), 'protocol name')
->inject('response')
->inject('dbForProject')
->inject('mode')
->inject('user')
->action(function (string $videoId, string $streamId, Response $response, Database $dbForProject, string $mode, Document $user) {
->action(function (string $videoId, string $protocolId, Response $response, Database $dbForProject, string $mode, Document $user) {
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [
new Query('_uid', Query::TYPE_EQUAL, [$videoId])
@@ -624,19 +624,19 @@ App::get('/v1/videos/:videoId/streams/:streamId')
new Query('videoId', Query::TYPE_EQUAL, [$video->getId()]),
new Query('endedAt', Query::TYPE_GREATER, [0]),
new Query('status', Query::TYPE_EQUAL, ['ready']),
new Query('stream', Query::TYPE_EQUAL, [$streamId]),
new Query('protocol', Query::TYPE_EQUAL, [$protocolId]),
]));
if (empty($renditions)) {
throw new Exception('Renditions not found', 404, Exception::VIDEO_RENDITION_NOT_FOUND);
}
$baseUrl = 'http://127.0.0.1/v1/videos/' . $videoId . '/streams/' . $streamId;
$baseUrl = 'http://127.0.0.1/v1/videos/' . $videoId . '/protocols/' . $protocolId;
$subtitles = Authorization::skip(fn() => $dbForProject->find('videos_subtitles', [new Query('videoId', Query::TYPE_EQUAL, [$video->getId()])]));
$_renditions = [];
$_subtitles = [];
if ($streamId === 'hls') {
if ($protocolId === 'hls') {
foreach ($subtitles ?? [] as $subtitle) {
$_subtitles[] = [
'name' => $subtitle->getAttribute('name'),
@@ -695,19 +695,19 @@ App::get('/v1/videos/:videoId/streams/:streamId')
$attributes = (array)$xml->attributes();
$mpd = $attributes['@attributes'] ?? [];
$representationId = 0;
$streamId = 0;
foreach ($xml->Period->AdaptationSet ?? [] as $adaptation) {
$representation = [];
$representation['id'] = $representationId;
$representation['id'] = $streamId;
$attributes = (array)$adaptation->Representation->attributes();
$representation['attributes'] = $attributes['@attributes'] ?? [];
$attributes = (array)$adaptation->Representation->SegmentList->attributes();
$representation['segmentList']['attributes'] = $attributes['@attributes'] ?? [];
$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']));
new Query('streamId', Query::TYPE_EQUAL, [$streamId]),
], 1000, 0, ['streamId']));
if (count($segments) === 0) {
continue;
@@ -730,7 +730,7 @@ App::get('/v1/videos/:videoId/streams/:streamId')
'representation' => $representation,
];
$adaptationId++;
$representationId++;
$streamId++;
}
}
@@ -755,7 +755,7 @@ App::get('/v1/videos/:videoId/streams/:streamId')
});
App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:typeId')
App::get('/v1/videos/:videoId/protocols/:protocolId/renditions/:renditionId/streams/:streamId')
->desc('Get video rendition manifest')
->groups(['api', 'video'])
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
@@ -767,14 +767,14 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:t
// TODO: Response model
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
->param('protocolId', '', new WhiteList(['hls']), 'protocol name')
->param('renditionId', '', new UID(), 'Rendition unique ID.')
->param('typeId', '', new Range(0, 10), 'Stream type id.')
->param('streamId', '', new Range(0, 10), 'Stream id.')
->inject('response')
->inject('dbForProject')
->inject('mode')
->inject('user')
->action(function (string $videoId, string $streamId, string $renditionId, string $typeId, Response $response, Database $dbForProject, string $mode, Document $user) {
->action(function (string $videoId, string $protocolId, string $renditionId, string $streamId, Response $response, Database $dbForProject, string $mode, Document $user) {
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [
new Query('_uid', Query::TYPE_EQUAL, [$videoId])
@@ -791,7 +791,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:t
new Query('videoId', Query::TYPE_EQUAL, [$video->getId()]),
new Query('endedAt', Query::TYPE_GREATER, [0]),
new Query('status', Query::TYPE_EQUAL, ['ready']),
new Query('stream', Query::TYPE_EQUAL, [$streamId]),
new Query('protocol', Query::TYPE_EQUAL, [$protocolId]),
]));
if (empty($rendition)) {
@@ -800,7 +800,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:t
$segments = Authorization::skip(fn() => $dbForProject->find('videos_renditions_segments', [
new Query('renditionId', Query::TYPE_EQUAL, [$renditionId]),
new Query('representationId', Query::TYPE_EQUAL, [$typeId]),
new Query('streamId', Query::TYPE_EQUAL, [$streamId]),
], 5000));
if (empty($segments)) {
@@ -811,7 +811,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:t
foreach ($segments as $segment) {
$paramsSegments[] = [
'duration' => $segment->getAttribute('duration'),
'url' => 'http://127.0.0.1/v1/videos/' . $videoId . '/streams/' . $streamId . '/renditions/' . $renditionId . '/segments/' . $segment->getId(),
'url' => 'http://127.0.0.1/v1/videos/' . $videoId . '/protocols/' . $protocolId . '/renditions/' . $renditionId . '/segments/' . $segment->getId(),
];
}
@@ -822,7 +822,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/types/:t
});
App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments/:segmentId')
App::get('/v1/videos/:videoId/protocols/:protocolId/renditions/:renditionId/segments/:segmentId')
->desc('Get video rendition segment')
->groups(['api', 'video'])
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
@@ -834,7 +834,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
// TODO: Response model
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
->param('protocolId', '', new WhiteList(['hls', 'dash']), 'Protocol name')
->param('renditionId', '', new UID(), 'Rendition unique ID.')
->param('segmentId', '', new UID(), 'Segment unique ID.')
->inject('response')
@@ -842,7 +842,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
->inject('deviceVideos')
->inject('mode')
->inject('user')
->action(function (string $videoId, string $streamId, string $renditionId, string $segmentId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
->action(function (string $videoId, string $protocolId, string $renditionId, string $segmentId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [
new Query('_uid', Query::TYPE_EQUAL, [$videoId])
@@ -859,7 +859,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
new Query('videoId', Query::TYPE_EQUAL, [$video->getId()]),
new Query('endedAt', Query::TYPE_GREATER, [0]),
new Query('status', Query::TYPE_EQUAL, ['ready']),
new Query('stream', Query::TYPE_EQUAL, [$streamId]),
new Query('protocol', Query::TYPE_EQUAL, [$protocolId]),
]));
if (empty($rendition)) {
@@ -875,7 +875,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
$output = $deviceVideos->read($segment->getAttribute('path') . $segment->getAttribute('fileName'));
if ($streamId === 'hls') {
if ($protocolId === 'hls') {
$response->setContentType('video/MP2T')->send($output);
} else {
$response->setContentType('video/iso.segment')->send($output);
@@ -883,7 +883,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
});
App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
App::get('/v1/videos/:videoId/protocols/:protocolId/subtitles/:subtitleId')
->desc('Get video subtitle')
->groups(['api', 'video'])
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
@@ -895,14 +895,14 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
// TODO: Response model
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
->param('protocolId', '', new WhiteList(['hls', 'dash']), 'Protocol name')
->param('subtitleId', '', new UID(), 'Subtitle unique ID.')
->inject('response')
->inject('dbForProject')
->inject('deviceVideos')
->inject('mode')
->inject('user')
->action(function (string $videoId, string $streamId, string $subtitleId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
->action(function (string $videoId, string $protocolId, string $subtitleId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [
new Query('_uid', Query::TYPE_EQUAL, [$videoId])
@@ -923,7 +923,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
throw new Exception('subtitle not found', 404, Exception::VIDEO_SUBTITLE_NOT_FOUND);
}
if ($streamId == 'hls') {
if ($protocolId == 'hls') {
$segments = Authorization::skip(fn() => $dbForProject->find('videos_subtitles_segments', [
new Query('subtitleId', Query::TYPE_EQUAL, [$subtitleId]),
], 4000));
@@ -936,7 +936,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
foreach ($segments as $segment) {
$paramsSegments[] = [
'duration' => $segment->getAttribute('duration'),
'url' => 'http://127.0.0.1/v1/videos/' . $videoId . '/streams/' . $streamId . '/subtitles/' . $subtitleId . '/segments/' . $segment->getId(),
'url' => 'http://127.0.0.1/v1/videos/' . $videoId . '/protocols/' . $protocolId . '/subtitles/' . $subtitleId . '/segments/' . $segment->getId(),
];
}
@@ -951,7 +951,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
});
App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId/segments/:segmentId')
App::get('/v1/videos/:videoId/protocols/:protocolId/subtitles/:subtitleId/segments/:segmentId')
->desc('Get video subtitle segment')
->groups(['api', 'video'])
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
@@ -963,7 +963,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId/segments/:
// TODO: Response model
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
->param('protocolId', '', new WhiteList(['hls', 'dash']), 'Protocol name')
->param('subtitleId', '', new UID(), 'Subtitle unique ID.')
->param('segmentId', '', new UID(), 'Segment unique ID.')
->inject('response')
@@ -971,7 +971,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId/segments/:
->inject('deviceVideos')
->inject('mode')
->inject('user')
->action(function (string $videoId, string $streamId, string $subtitleId, string $segmentId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
->action(function (string $videoId, string $protocolId, string $subtitleId, string $segmentId, Response $response, Database $dbForProject, Device $deviceVideos, string $mode, Document $user) {
$video = Authorization::skip(fn() => $dbForProject->findOne('videos', [
new Query('_uid', Query::TYPE_EQUAL, [$videoId])
@@ -1020,19 +1020,19 @@ App::post('/v1/videos/profiles')
->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.')
->param('protocol', false, new WhiteList(['hls', 'dash']), 'Video profile protocol.')
->inject('response')
->inject('dbForProject')
->action(action: function (string $name, string $videoBitrate, string $audioBitrate, string $width, string $height, string $stream, Response $response, Database $dbForProject) {
->action(action: function (string $name, string $videoBitrate, string $audioBitrate, string $width, string $height, string $protocol, Response $response, Database $dbForProject) {
try {
$profile = Authorization::skip(function () use ($dbForProject, $name, $videoBitrate, $audioBitrate, $width, $height, $stream) {
$profile = Authorization::skip(function () use ($dbForProject, $name, $videoBitrate, $audioBitrate, $width, $height, $protocol) {
return $dbForProject->createDocument('videos_profiles', new Document([
'name' => $name,
'videoBitrate' => (int)$videoBitrate,
'audioBitrate' => (int)$audioBitrate,
'width' => (int)$width,
'height' => (int)$height,
'stream' => $stream,
'protocol' => $protocol,
]));
});
} catch (DuplicateException $exception) {
@@ -1061,10 +1061,10 @@ App::patch('/v1/videos/profiles/:profileId')
->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('stream', false, new WhiteList(['hls', 'dash']), 'Video profile stream protocol.')
->param('protocol', false, new WhiteList(['hls', 'dash']), 'Video profile protocol.')
->inject('response')
->inject('dbForProject')
->action(action: function (string $profileId, string $name, string $videoBitrate, string $audioBitrate, string $width, string $height, string $stream, Response $response, Database $dbForProject) {
->action(action: function (string $profileId, string $name, string $videoBitrate, string $audioBitrate, string $width, string $height, string $protocol, Response $response, Database $dbForProject) {
$profile = Authorization::skip(fn() => $dbForProject->getDocument('videos_profiles', $profileId));
;
@@ -1077,7 +1077,7 @@ App::patch('/v1/videos/profiles/:profileId')
->setAttribute('audioBitrate', (int)$audioBitrate)
->setAttribute('width', (int)$width)
->setAttribute('height', (int)$height)
->setAttribute('stream', $stream);
->setAttribute('protocol', $protocol);
$profile = Authorization::skip(fn() => $dbForProject->updateDocument('videos_profiles', $profile->getId(), $profile));
+2 -2
View File
@@ -844,8 +844,8 @@ App::setResource('project', function ($dbForConsole, $request, $console) {
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Document $console */
$projectId = 'dev';
//$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', 'console'));
//$projectId = 'dev';
$projectId = $request->getParam('project', $request->getHeader('x-appwrite-project', 'console'));
if ($projectId === 'console') {
return $console;
+21 -20
View File
@@ -3,6 +3,7 @@
use Appwrite\Extend\Exception;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Resque\Worker;
use JetBrains\PhpStorm\ArrayShape;
use Streaming\Format\StreamFormat;
use Streaming\HLSSubtitle;
use Streaming\Media;
@@ -34,8 +35,8 @@ class TranscodingV1 extends Worker
private const STATUS_READY = 'ready';
private const STATUS_ERROR = 'error';
private const STREAM_HLS = 'hls';
private const STREAM_MPEG_DASH = 'dash';
private const PROTOCOL_HLS = 'hls';
private const PROTOCOL_MPEG_DASH = 'dash';
//private string $basePath = '/tmp/';
private string $basePath = '/usr/src/code/tests/tmp/';
@@ -221,7 +222,7 @@ class TranscodingV1 extends Worker
'name' => $this->getRenditionName(),
'startedAt' => time(),
'status' => self::STATUS_START,
'stream' => $profile['stream'],
'protocol' => $profile['protocol'],
]));
});
@@ -247,23 +248,23 @@ class TranscodingV1 extends Worker
}
});
$general = $this->transcode($profile['stream'], $video, $format, $representation, $subs);
$general = $this->transcode($profile['protocol'], $video, $format, $representation, $subs);
if (!empty($general)) {
foreach ($general as $key => $value) {
$query->setAttribute($key, (string)$value);
}
}
if ($profile['stream'] === 'hls') {
$refs = $this->getHlsSegmentsUrls($this->outDir . 'master.m3u8');
foreach ($refs as $ref) {
$m3u8 = $this->getHlsSegments($this->outDir . $ref['path']);
if ($profile['protocol'] === 'hls') {
$streams = $this->getHlsSegmentsUrls($this->outDir . 'master.m3u8');
foreach ($streams as $stream) {
$m3u8 = $this->getHlsSegments($this->outDir . $stream['path']);
if (!empty($m3u8['segments'])) {
foreach ($m3u8['segments'] as $segment) {
Authorization::skip(function () use ($segment, $project, $query, $renditionPath, $ref) {
Authorization::skip(function () use ($segment, $project, $query, $renditionPath, $stream) {
return $this->database->createDocument('videos_renditions_segments', new Document([
'renditionId' => $query->getId(),
'representationId' => $ref['id'] + 0,
'streamId' => (int)$stream['id'],
'fileName' => $segment['fileName'],
'path' => $renditionPath,
'duration' => $segment['duration'],
@@ -272,7 +273,7 @@ class TranscodingV1 extends Worker
}
}
$query->setAttribute('metadata', json_encode(['hls' => $refs]));
$query->setAttribute('metadata', json_encode(['hls' => $streams]));
$query->setAttribute('targetDuration', $m3u8['targetDuration']);
}
} else {
@@ -282,7 +283,7 @@ class TranscodingV1 extends Worker
Authorization::skip(function () use ($segment, $project, $query, $renditionPath) {
return $this->database->createDocument('videos_renditions_segments', new Document([
'renditionId' => $query->getId(),
'representationId' => $segment['representationId'],
'streamId' => $segment['streamId'],
'fileName' => $segment['fileName'],
'path' => $renditionPath,
'isInit' => $segment['isInit'],
@@ -301,7 +302,7 @@ class TranscodingV1 extends Worker
Authorization::skip(fn() => $this->database->updateDocument($collection, $query->getId(), $query));
foreach ($subtitles ?? [] as $subtitle) {
if ($profile['stream'] === 'hls') {
if ($profile['protocol'] === 'hls') {
$m3u8 = $this->getHlsSegments($this->outPath . '_subtitles_' . $subtitle['code'] . '.m3u8');
foreach ($m3u8['segments'] ?? [] as $segment) {
Authorization::skip(function () use ($segment, $project, $subtitle, $renditionRootPath) {
@@ -367,14 +368,14 @@ class TranscodingV1 extends Worker
}
/**
* @param string $stream
* @param string $protocol
* @param $video Media
* @param $format StreamFormat
* @param $representation Representation
* @param array $subtitles
* @return string|array
*/
private function transcode(string $stream, Media $video, StreamFormat $format, Representation $representation, array $subtitles): string | array
private function transcode(string $protocol, Media $video, StreamFormat $format, Representation $representation, array $subtitles): string | array
{
// $video->filters()
// ->framerate(new FFMpeg\Coordinate\FrameRate(24), 2)
@@ -390,9 +391,9 @@ class TranscodingV1 extends Worker
'-g', '120'
];
$segmentSize = 10;
$segmentSize = 8;
if ($stream === 'dash') {
if ($protocol === 'dash') {
$dash = $video->dash()
->setFormat($format)
->setSegDuration($segmentSize)
@@ -433,11 +434,11 @@ class TranscodingV1 extends Worker
$metadata = null;
$handle = fopen($path, "r");
if ($handle) {
$representationId = -1;
$streamId = -1;
while (($line = fgets($handle)) !== false) {
$line = str_replace([",","\r","\n"], "", $line);
if (str_contains($line, "<AdaptationSet")) {
$representationId++;
$streamId++;
}
if (!str_contains($line, "SegmentURL") && !str_contains($line, "Initialization")) {
@@ -445,7 +446,7 @@ class TranscodingV1 extends Worker
} else {
$segments[] = [
'isInit' => str_contains($line, "Initialization") ? 1 : 0,
'representationId' => $representationId,
'streamId' => $streamId,
'fileName' => trim(str_replace(["<SegmentURL media=\"", "<Initialization sourceURL=\"", "\"/>", "\" />"], "", $line)),
];
}
+1 -1
View File
@@ -83,7 +83,7 @@
}
],
"require-dev": {
"appwrite/sdk-generator": "0.19.6",
"appwrite/sdk-generator": "dev-shimon-video-test",
"phpunit/phpunit": "9.5.20",
"squizlabs/php_codesniffer": "^3.6",
"swoole/ide-helper": "4.8.9",
Generated
-6326
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -242,8 +242,8 @@ services:
- ./src:/usr/src/code/src
- appwrite-uploads:/storage/uploads:rw
- appwrite-videos:/storage/videos:rw
- ./tests:/usr/src/code/tests #TODO remove when done!!
- ./vendor:/usr/src/code/vendor #TODO remove when done!!
#- ./tests:/usr/src/code/tests #TODO remove when done!!
#- ./vendor:/usr/src/code/vendor #TODO remove when done!!
depends_on:
- redis
@@ -47,9 +47,9 @@ class Profile extends Model
'example' => 400,
])
->addRule('stream', [
->addRule('protocol', [
'type' => self::TYPE_STRING,
'description' => 'http video stream type.',
'description' => 'http video protocol type.',
'default' => null,
'example' => 'dash',
])
@@ -58,9 +58,9 @@ class Rendition extends Model
'default' => 0,
'example' => 88,
])
->addRule('stream', [
->addRule('protocol', [
'type' => self::TYPE_STRING,
'description' => 'Rendition trascoding stream protocol type',
'description' => 'Rendition trascoding protocol type',
'default' => null,
'example' => 'hls',
])
@@ -26,7 +26,7 @@ class VideoCustomServerTest extends Scope
'audioBitrate' => 120,
'width' => 600,
'height' => 400,
'stream' => 'hls',
'protocol' => 'hls',
]);
$profileId = $response['body']['$id'];
@@ -53,7 +53,7 @@ class VideoCustomServerTest extends Scope
'audioBitrate' => 120,
'width' => 300,
'height' => 400,
'stream' => 'dash',
'protocol' => 'dash',
]);
$this->assertEquals(200, $response['headers']['status-code']);
@@ -374,7 +374,7 @@ class VideoCustomServerTest extends Scope
'audioBitrate' => 64,
'width' => 600,
'height' => 400,
'stream' => 'hls',
'protocol' => 'hls',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@@ -388,7 +388,7 @@ class VideoCustomServerTest extends Scope
'audioBitrate' => 64,
'width' => 300,
'height' => 200,
'stream' => 'dash',
'protocol' => 'dash',
]);
$this->assertEquals(201, $response['headers']['status-code']);
@@ -477,10 +477,10 @@ class VideoCustomServerTest extends Scope
/**
* @depends testGetRenditions
*/
public function testStreamWithSubs($videoId): string
public function testProtocolWithSubs($videoId): string
{
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/hls', [
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/protocols/hls', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
@@ -527,7 +527,7 @@ class VideoCustomServerTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals(1508, strlen($response['body']));
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/dash', [
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/protocols/dash', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
@@ -624,7 +624,7 @@ class VideoCustomServerTest extends Scope
/**
* @depends testStreamWithSubs
* @depends testProtocolWithSubs
*/
public function testDeleteVideo($videoId): string
{
@@ -643,10 +643,10 @@ class VideoCustomServerTest extends Scope
/**
* @depends testDeleteVideo
*/
public function testStreamWithSubsAgain($videoId): string
public function testProtocolWithSubsAgain($videoId): string
{
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/hls', [
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/protocols/hls', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
@@ -711,12 +711,12 @@ class VideoCustomServerTest extends Scope
/**
* @depends testTranscodeWithoutSubs
*/
public function testStreamWithoutSubs($videoId)
public function testProtocolWithoutSubs($videoId)
{
sleep(50);
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/hls', [
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/protocols/hls', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
@@ -745,7 +745,7 @@ class VideoCustomServerTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertGreaterThan(0, strlen($response['body']));
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/streams/dash', [
$response = $this->client->call(Client::METHOD_GET, '/videos/' . $videoId . '/protocols/dash', [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],