mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
dash
This commit is contained in:
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' => 'mpeg-dash'
|
||||
'stream' => 'dash'
|
||||
],
|
||||
[
|
||||
'name' => '576p',
|
||||
@@ -16,7 +16,7 @@ return [
|
||||
'audioBitrate' => 128,
|
||||
'width' => 1024,
|
||||
'height' => 576,
|
||||
'stream' => 'mpeg-dash'
|
||||
'stream' => 'dash'
|
||||
],
|
||||
[
|
||||
'name' => '720p',
|
||||
|
||||
@@ -90,7 +90,7 @@ App::post('/v1/videos/profiles')
|
||||
->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', 'mpeg-dash']), 'Video profile stream protocol.')
|
||||
->param('stream', false, new WhiteList(['hls', 'dash']), 'Video profile stream protocol.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->action(action: function (string $name, string $videoBitrate, string $audioBitrate, string $width, string $height, string $stream, Response $response, Database $dbForProject) {
|
||||
@@ -131,7 +131,7 @@ 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', 'mpeg-dash']), 'Video profile stream protocol.')
|
||||
->param('stream', false, new WhiteList(['hls', 'dash']), 'Video profile stream 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) {
|
||||
@@ -708,7 +708,7 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('scope', 'files.read')
|
||||
->param('videoId', null, new UID(), 'Video unique ID.')
|
||||
->param('streamId', '', new WhiteList(['hls', 'mpeg-dash']), 'stream protocol name')
|
||||
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('mode')
|
||||
@@ -767,16 +767,16 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
$response->setContentType('application/x-mpegurl')->send($template->render(false));
|
||||
} else {
|
||||
$adaptations = [];
|
||||
|
||||
foreach ($renditions as $rendition) {
|
||||
foreach ($renditions as $rendition) {
|
||||
$metadata = $rendition->getAttribute('metadata');
|
||||
if (!empty($metadata['Period']['AdaptationSet'])) {
|
||||
foreach ($metadata['Period']['AdaptationSet'] as $set) {
|
||||
foreach ($metadata['Period']['AdaptationSet'] as $adaptationId => $set) {
|
||||
$adaption = $set['@attributes'];
|
||||
$adaption['id'] = $adaptationId;
|
||||
//$adaption['baseUrl'] = $baseUrl . '/renditions/' . $rendition->getId() . '/' . 'segments/';
|
||||
$adaption['representation'] = $set['Representation']['@attributes'];
|
||||
|
||||
$adaption['representation']['baseUrl'] = $baseUrl . '/renditions/' . $rendition->getId();
|
||||
$adaption['representation']['SegmentList'] = $set['Representation']['SegmentList']['@attributes'];
|
||||
|
||||
$representationId = 0;
|
||||
$segments = Authorization::skip(fn() => $dbForProject->find('videos_renditions_segments', [
|
||||
new Query('renditionId', Query::TYPE_EQUAL, [$rendition->getId()]),
|
||||
@@ -784,11 +784,11 @@ App::get('/v1/videos/:videoId/streams/:streamId')
|
||||
], 1000, 0, ['representationId'], ['ASC']));
|
||||
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment->getAttribute('isInit') === 1) {
|
||||
$adaption['representation']['SegmentList']['Initialization'] = $baseUrl . '/renditions/' . $segment->getId() . '/';
|
||||
if ($segment->getAttribute('isInit')) {
|
||||
$adaption['representation']['SegmentList']['Initialization'] = $baseUrl . '/renditions/' . $rendition->getId() . '/' . 'segments/' . $segment->getId();
|
||||
continue;
|
||||
}
|
||||
$adaption['representation']['SegmentList']['media'][] = $segment->getId();
|
||||
$adaption['representation']['SegmentList']['media'][] = $baseUrl . '/renditions/' . $rendition->getId() . '/' . 'segments/' . $segment->getId();
|
||||
}
|
||||
$adaptations[] = $adaption;
|
||||
$representationId++;
|
||||
@@ -815,7 +815,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId')
|
||||
// TODO: Response model
|
||||
->label('scope', 'files.read')
|
||||
->param('videoId', null, new UID(), 'Video unique ID.')
|
||||
->param('streamId', '', new WhiteList(['hls', 'mpeg-dash']), 'stream protocol name')
|
||||
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
|
||||
->param('renditionId', '', new UID(), 'Rendition unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -845,26 +845,26 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId')
|
||||
throw new Exception('Rendition not found', 404, Exception::VIDEO_RENDITION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$segments = Authorization::skip(fn () => $dbForProject->find('videos_renditions_segments', [
|
||||
new Query('renditionId', Query::TYPE_EQUAL, [$renditionId]),
|
||||
], 4000, 0, [], ['ASC']));
|
||||
$segments = Authorization::skip(fn() => $dbForProject->find('videos_renditions_segments', [
|
||||
new Query('renditionId', Query::TYPE_EQUAL, [$renditionId]),
|
||||
], 4000));
|
||||
|
||||
if (empty($segments)) {
|
||||
throw new Exception('Rendition segments not found', 404, Exception::VIDEO_RENDITION_SEGMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$paramsSegments = [];
|
||||
$paramsSegments = [];
|
||||
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() ,
|
||||
];
|
||||
'duration' => $segment->getAttribute('duration'),
|
||||
'url' => 'http://127.0.0.1/v1/videos/' . $videoId . '/streams/' . $streamId . '/renditions/' . $renditionId . '/segments/' . $segment->getId(),
|
||||
];
|
||||
}
|
||||
|
||||
$template = new View(__DIR__ . '/../../views/videos/hls.phtml');
|
||||
$template->setParam('targetDuration', $rendition->getAttribute('targetDuration'));
|
||||
$template->setParam('paramsSegments', $paramsSegments);
|
||||
$response->setContentType('application/x-mpegurl')->send($template->render(false));
|
||||
$template = new View(__DIR__ . '/../../views/videos/hls.phtml');
|
||||
$template->setParam('targetDuration', $rendition->getAttribute('targetDuration'));
|
||||
$template->setParam('paramsSegments', $paramsSegments);
|
||||
$response->setContentType('application/x-mpegurl')->send($template->render(false));
|
||||
});
|
||||
|
||||
|
||||
@@ -880,15 +880,15 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
|
||||
// TODO: Response model
|
||||
->label('scope', 'files.read')
|
||||
->param('videoId', null, new UID(), 'Video unique ID.')
|
||||
->param('streamId', '', new WhiteList(['hls', 'mpeg-dash']), 'stream protocol name')
|
||||
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
|
||||
->param('renditionId', '', new UID(), 'Rendition unique ID.')
|
||||
->param('segmentId', '', new UID(), 'Segment unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('videosDevice')
|
||||
->inject('deviceVideos')
|
||||
->inject('mode')
|
||||
->inject('user')
|
||||
->action(function (string $videoId, string $streamId, string $renditionId, string $segmentId, Response $response, Database $dbForProject, Device $videosDevice, string $mode, Document $user) {
|
||||
->action(function (string $videoId, string $streamId, 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])
|
||||
@@ -919,8 +919,13 @@ App::get('/v1/videos/:videoId/streams/:streamId/renditions/:renditionId/segments
|
||||
throw new Exception('Rendition segments not found', 404, Exception::VIDEO_RENDITION_SEGMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$output = $videosDevice->read($segment->getAttribute('path') . $segment->getAttribute('fileName'));
|
||||
$response->setContentType('video/MP2T')->send($output);
|
||||
$output = $deviceVideos->read($segment->getAttribute('path') . $segment->getAttribute('fileName'));
|
||||
|
||||
if ($streamId === 'hls') {
|
||||
$response->setContentType('video/MP2T')->send($output);
|
||||
} else {
|
||||
$response->setContentType('video/iso.segment')->send($output);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -936,7 +941,7 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId')
|
||||
// TODO: Response model
|
||||
->label('scope', 'files.read')
|
||||
->param('videoId', null, new UID(), 'Video unique ID.')
|
||||
->param('streamId', '', new WhiteList(['hls', 'mpeg-dash']), 'stream protocol name')
|
||||
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
|
||||
->param('subtitleId', '', new UID(), 'Subtitle unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
@@ -998,15 +1003,15 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId/segments/:
|
||||
// TODO: Response model
|
||||
->label('scope', 'files.read')
|
||||
->param('videoId', null, new UID(), 'Video unique ID.')
|
||||
->param('streamId', '', new WhiteList(['hls', 'mpeg-dash']), 'stream protocol name')
|
||||
->param('streamId', '', new WhiteList(['hls', 'dash']), 'stream protocol name')
|
||||
->param('subtitleId', '', new UID(), 'Subtitle unique ID.')
|
||||
->param('segmentId', '', new UID(), 'Segment unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('videosDevice')
|
||||
->inject('deviceVideos')
|
||||
->inject('mode')
|
||||
->inject('user')
|
||||
->action(function (string $videoId, string $streamId, string $subtitleId, string $segmentId, Response $response, Database $dbForProject, Device $videosDevice, string $mode, Document $user) {
|
||||
->action(function (string $videoId, string $streamId, 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])
|
||||
@@ -1034,6 +1039,6 @@ App::get('/v1/videos/:videoId/streams/:streamId/subtitles/:subtitleId/segments/:
|
||||
throw new Exception('Subtitle segments not found', 404, Exception::VIDEO_SUBTITLE_SEGMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$output = $videosDevice->read($segment->getAttribute('path') . $segment->getAttribute('fileName'));
|
||||
$output = $deviceVideos->read($segment->getAttribute('path') . $segment->getAttribute('fileName'));
|
||||
$response->setContentType('text/vtt')->send($output);
|
||||
});
|
||||
|
||||
@@ -916,6 +916,10 @@ App::setResource('deviceFiles', function ($project) {
|
||||
return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceVideos', function ($project) {
|
||||
return getDevice(APP_STORAGE_VIDEOS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
App::setResource('deviceFunctions', function ($project) {
|
||||
return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
|
||||
}, ['project']);
|
||||
|
||||
@@ -6,16 +6,20 @@
|
||||
<ServiceDescription id="0"></ServiceDescription>
|
||||
<Period id="0" start="PT0.0S">
|
||||
<?php foreach ($this->getParam('params', []) as $param): ?>
|
||||
<AdaptationSet
|
||||
<?php if (isset($param['id'])):?> id="<?php echo $param['id']; ?>"<?php endif;?><?php if (isset($param['contentType'])): ?> contentType="<?php echo $param['contentType']; ?>"<?php endif;?><?php if (isset($param['startWithSAP'])): ?> startWithSAP="<?php echo $param['startWithSAP']; ?>"<?php endif;?><?php if (isset($param['segmentAlignment'])): ?> segmentAlignment="<?php echo $param['segmentAlignment']; ?>"<?php endif;?><?php if (isset($param['bitstreamSwitching'])): ?> bitstreamSwitching="<?php echo $param['bitstreamSwitching']; ?>"<?php endif;?><?php if (isset($param['frameRate'])): ?> frameRate="<?php echo $param['frameRate']; ?>"<?php endif;?><?php if (isset($param['maxWidth'])): ?> maxWidth="<?php echo $param['maxWidth']; ?>"<?php endif;?><?php if (isset($param['par'])): ?> par="<?php echo $param['par']; ?>"<?php endif;?><?php if (isset($param['lang'])): ?> lang="<?php echo $param['lang']; ?>"<?php endif;?>>
|
||||
<Representation<?php if (isset($param['representation']['id'])):?> id="<?php echo $param['representation']['id']; ?>"<?php endif;?><?php if (isset($param['representation']['mimeType'])):?> mimeType="<?php echo $param['representation']['mimeType']; ?>"<?php endif;?><?php if (isset($param['representation']['codecs'])):?> codecs="<?php echo $param['representation']['codecs']; ?>"<?php endif;?><?php if (isset($param['representation']['width'])):?> width="<?php echo $param['representation']['width']; ?>"<?php endif;?><?php if (isset($param['representation']['height'])):?> height="<?php echo $param['representation']['height']; ?>"<?php endif;?><?php if (isset($param['representation']['sar'])):?> sar="<?php echo $param['representation']['sar']; ?>"<?php endif;?><?php if (isset($param['representation']['audioSamplingRate'])):?> audioSamplingRate="<?php echo $param['representation']['audioSamplingRate']; ?>"<?php endif;?>>
|
||||
<BaseURL><?php if (isset($param['baseUrl'])): echo $param['baseUrl']; endif;?></BaseURL>
|
||||
<AdaptationSet <?php if (isset($param['id'])):?> id="<?php echo $param['id']; ?>"<?php endif;?><?php if (isset($param['contentType'])): ?> contentType="<?php echo $param['contentType']; ?>"<?php endif;?><?php if (isset($param['startWithSAP'])): ?> startWithSAP="<?php echo $param['startWithSAP']; ?>"<?php endif;?><?php if (isset($param['segmentAlignment'])): ?> segmentAlignment="<?php echo $param['segmentAlignment']; ?>"<?php endif;?><?php if (isset($param['bitstreamSwitching'])): ?> bitstreamSwitching="<?php echo $param['bitstreamSwitching']; ?>"<?php endif;?><?php if (isset($param['frameRate'])): ?> frameRate="<?php echo $param['frameRate']; ?>"<?php endif;?><?php if (isset($param['maxWidth'])): ?> maxWidth="<?php echo $param['maxWidth']; ?>"<?php endif;?><?php if (isset($param['par'])): ?> par="<?php echo $param['par']; ?>"<?php endif;?><?php if (isset($param['lang'])): ?> lang="<?php echo $param['lang']; ?>"<?php endif;?>>
|
||||
<Representation <?php if (isset($param['representation']['id'])):?> id="<?php echo $param['representation']['id']; ?>"<?php endif;?><?php if (isset($param['representation']['mimeType'])):?> mimeType="<?php echo $param['representation']['mimeType']; ?>"<?php endif;?><?php if (isset($param['representation']['codecs'])):?> codecs="<?php echo $param['representation']['codecs']; ?>"<?php endif;?><?php if (isset($param['representation']['width'])):?> width="<?php echo $param['representation']['width']; ?>"<?php endif;?><?php if (isset($param['representation']['height'])):?> height="<?php echo $param['representation']['height']; ?>"<?php endif;?><?php if (isset($param['representation']['sar'])):?> sar="<?php echo $param['representation']['sar']; ?>"<?php endif;?><?php if (isset($param['representation']['audioSamplingRate'])):?> audioSamplingRate="<?php echo $param['representation']['audioSamplingRate']; ?>"<?php endif;?>>
|
||||
<?php if ($param['contentType'] === 'audio'):?>
|
||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
|
||||
<?php endif;?>
|
||||
|
||||
<Initialization sourceURL="<?php if (isset($param['representation']['SegmentList']['Initialization'])):?><?php echo $param['representation']['SegmentList']['Initialization']; ?><?php endif;?>"/>
|
||||
<?php foreach ($param['representation']['SegmentList']['media'] as $segment): ?>
|
||||
<SegmentURL media="<?php if (isset($segment)):?><?php echo $segment; ?><?php endif;?>"/>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (isset($param['representation']['SegmentList']['media'])):?>
|
||||
<?php foreach ($param['representation']['SegmentList']['media'] as $segment): ?>
|
||||
<SegmentURL media="<?php if (isset($segment)):?><?php echo $segment; ?><?php endif;?>"/>
|
||||
<?php endforeach; ?>
|
||||
<?php endif;?>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@@ -36,7 +36,7 @@ class TranscodingV1 extends Worker
|
||||
const STATUS_ERROR = 'error';
|
||||
|
||||
const STREAM_HLS = 'hls';
|
||||
const STREAM_MPEG_DASH = 'mpeg-dash';
|
||||
const STREAM_MPEG_DASH = 'dash';
|
||||
|
||||
const BASE_URL_ENDPOINT = 'http://127.0.0.1/v1/videos';
|
||||
|
||||
@@ -246,7 +246,7 @@ class TranscodingV1 extends Worker
|
||||
Authorization::skip(function () use ($segment, $project, $query) {
|
||||
return $this->database->createDocument('videos_renditions_segments', new Document([
|
||||
'renditionId' => $query->getId(),
|
||||
'type' => 0,
|
||||
'representationId' => 0,
|
||||
'fileName' => $segment['fileName'],
|
||||
'path' => $this->getVideoDevice($project->getId())->getPath($this->args['videoId']) . '/' . $this->getRenditionName() . '/',
|
||||
'duration' => $segment['duration'],
|
||||
@@ -374,7 +374,7 @@ class TranscodingV1 extends Worker
|
||||
|
||||
$segmentSize = 10;
|
||||
|
||||
if ($stream === 'mpeg-dash') {
|
||||
if ($stream === 'dash') {
|
||||
$dash = $video->dash()
|
||||
->setFormat($format)
|
||||
->setSegDuration($segmentSize)
|
||||
@@ -430,7 +430,6 @@ class TranscodingV1 extends Worker
|
||||
];
|
||||
}
|
||||
}
|
||||
var_dump($segments);
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"appwrite/sdk-generator": "0.18.8",
|
||||
"appwrite/sdk-generator": "0.19.6",
|
||||
"phpunit/phpunit": "9.5.20",
|
||||
"swoole/ide-helper": "4.8.9",
|
||||
"textalk/websocket": "1.5.7"
|
||||
|
||||
@@ -51,7 +51,7 @@ class VideoProfile extends Model
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'http video stream type.',
|
||||
'default' => null,
|
||||
'example' => 'mpeg-dash',
|
||||
'example' => 'dash',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ class VideoCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals($renditionId, $response['body']['$id']);
|
||||
var_dump($response);
|
||||
//var_dump($response['body']);
|
||||
|
||||
return [
|
||||
'renditionId' => $renditionId,
|
||||
@@ -384,7 +384,7 @@ class VideoCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
var_dump($response['body']);
|
||||
//var_dump($response['body']);
|
||||
|
||||
preg_match_all('#\b/videos[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $response['body'], $match);
|
||||
|
||||
@@ -415,6 +415,20 @@ class VideoCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]);
|
||||
|
||||
var_dump($response);
|
||||
var_dump($response['body']);
|
||||
}
|
||||
|
||||
public function testBla(){
|
||||
$response = $this->client->call(Client::METHOD_GET, '/videos/62dfaeb69c97ea81c58c/streams/dash/renditions/62dfaeb83bc30e827719/segments/62dfaed714324026902c', [
|
||||
'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