mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
streamId
This commit is contained in:
@@ -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
@@ -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'
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -166,7 +166,7 @@ App::post('/v1/projects')
|
||||
'audioBitrate' => $profile['audioBitrate'],
|
||||
'width' => $profile['width'],
|
||||
'height' => $profile['height'],
|
||||
'stream' => $profile['stream']
|
||||
'protocol' => $profile['protocol']
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -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'],
|
||||
|
||||
Reference in New Issue
Block a user