This commit is contained in:
shimon
2023-03-05 19:21:51 +02:00
parent 7a0255d011
commit d6d6a7753a
6 changed files with 211 additions and 228 deletions
+1 -12
View File
@@ -4019,23 +4019,12 @@ $collections = [
'array' => false,
'filters' => [],
],
[
'$id' => 'output',
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => '_key_profile',
'type' => Database::INDEX_KEY,
'attributes' => ['output', 'width', 'height', 'videoBitRate', 'audioBitRate' ],
'attributes' => ['width', 'height', 'videoBitRate', 'audioBitRate' ],
'lengths' => [],
'orders' => [],
],
-31
View File
@@ -8,7 +8,6 @@ return [
'audioBitRate' => 64, //audio BitRate in Kbps
'width' => 640, //width resolution in px
'height' => 360, //height resolution in px
'output' => 'hls'
],
[
'name' => '576p',
@@ -16,7 +15,6 @@ return [
'audioBitRate' => 128,
'width' => 1024,
'height' => 576,
'output' => 'hls'
],
[
'name' => '720p',
@@ -24,34 +22,5 @@ return [
'audioBitRate' => 128,
'width' => 1280,
'height' => 720,
'output' => 'hls'
],
[
'name' => '360p',
'videoBitRate' => 890, //video BitRate in Kbps
'audioBitRate' => 64, //audio BitRate in Kbps
'width' => 640, //width resolution in px
'height' => 360, //height resolution in px
'output' => 'dash'
],
[
'name' => '576p',
'videoBitRate' => 2538,
'audioBitRate' => 128,
'width' => 1024,
'height' => 576,
'output' => 'dash'
],
[
'name' => '720p',
'videoBitRate' => 3551,
'audioBitRate' => 128,
'width' => 1280,
'height' => 720,
'output' => 'dash'
],
];
+1 -2
View File
@@ -177,8 +177,7 @@ App::post('/v1/projects')
'videoBitRate' => $profile['videoBitRate'],
'audioBitRate' => $profile['audioBitRate'],
'width' => $profile['width'],
'height' => $profile['height'],
'output' => $profile['output']
'height' => $profile['height']
]));
});
}
+166 -167
View File
@@ -97,6 +97,83 @@ App::post('/v1/videos')
$response->dynamic($video, Response::MODEL_VIDEO);
});
App::get('/v1/videos/:videoId')
->desc('Get video ')
->groups(['api', 'videos'])
->label('scope', 'videos.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'videos')
->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/videos/get-video.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_VIDEO)
->param('videoId', '', new UID(), 'Video unique ID.')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $videoId, Response $response, Database $dbForProject, string $mode) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$response->dynamic($video, Response::MODEL_VIDEO);
});
App::put('/v1/videos/:videoId')
->desc('Update video')
->groups(['api', 'videos'])
->label('scope', 'videos.write')
->label('audits.event', 'video.update')
->label('audits.resource', 'video/{request.videoId}')
->label('sdk.namespace', 'videos')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'update')
->label('sdk.description', '/docs/references/videos/update.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_VIDEO)
->param('videoId', '', new UID(), 'Video unique ID.')
->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
->param('fileId', '', new CustomId(), 'File ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->inject('response')
->inject('project')
->inject('dbForProject')
->inject('mode')
->action(function (string $videoId, $bucketId, $fileId, Response $response, Document $project, Database $dbForProject, string $mode) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$file = validateFilePermissions($dbForProject, $bucketId, $fileId, $mode);
$video = Authorization::skip(fn() =>
$dbForProject->updateDocument('videos', $videoId, new Document([
'bucketId' => $bucketId,
'fileId' => $file->getId(),
'size' => $file->getAttribute('sizeOriginal'),
'duration' => null,
'width' => null,
'height' => null,
'videoCodec' => null,
'videoBitRate' => null,
'videoFrameRate' => null,
'audioCodec' => null,
'audioBitRate' => null,
'audioSampleRate' => null,
])));
$response->dynamic($video, Response::MODEL_VIDEO);
});
App::delete('/v1/videos/:videoId')
->desc('Delete video')
->groups(['api', 'videos'])
@@ -137,83 +214,6 @@ App::delete('/v1/videos/:videoId')
$response->noContent();
});
App::put('/v1/videos/:videoId')
->desc('Update video')
->groups(['api', 'videos'])
->label('scope', 'videos.write')
->label('audits.event', 'video.update')
->label('audits.resource', 'video/{request.videoId}')
->label('sdk.namespace', 'videos')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'update')
->label('sdk.description', '/docs/references/videos/update.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_VIDEO)
->param('videoId', '', new UID(), 'Video unique ID.')
->param('bucketId', null, new UID(), 'Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](/docs/server/storage#createBucket).')
->param('fileId', '', new CustomId(), 'File ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.')
->inject('response')
->inject('project')
->inject('dbForProject')
->inject('mode')
->action(function (string $videoId, $bucketId, $fileId, Response $response, Document $project, Database $dbForProject, string $mode) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$file = validateFilePermissions($dbForProject, $bucketId, $fileId, $mode);
$video = Authorization::skip(fn() =>
$dbForProject->updateDocument('videos', $videoId, new Document([
'bucketId' => $bucketId,
'fileId' => $file->getId(),
'size' => $file->getAttribute('sizeOriginal'),
'duration' => null,
'width' => null,
'height' => null,
'videoCodec' => null,
'videoBitRate' => null,
'videoFrameRate' => null,
'audioCodec' => null,
'audioBitRate' => null,
'audioSampleRate' => null,
])));
$response->dynamic($video, Response::MODEL_VIDEO);
});
App::get('/v1/videos/:videoId')
->desc('Get video ')
->groups(['api', 'videos'])
->label('scope', 'videos.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'videos')
->label('sdk.method', 'get')
->label('sdk.description', '/docs/references/videos/get-video.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_VIDEO)
->param('videoId', '', new UID(), 'Video unique ID.')
->inject('response')
->inject('dbForProject')
->inject('mode')
->action(function (string $videoId, Response $response, Database $dbForProject, string $mode) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$response->dynamic($video, Response::MODEL_VIDEO);
});
App::get('/v1/videos')
->desc('Get video list')
->groups(['api', 'videos'])
@@ -299,6 +299,38 @@ App::post('/v1/videos/:videoId/subtitles')
$response->dynamic($subtitle, Response::MODEL_SUBTITLE);
});
App::get('/v1/videos/:videoId/subtitles')
->desc('Get video subtitles')
->groups(['api', 'videos'])
->label('scope', 'videos.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'videos')
->label('sdk.method', 'getSubtitles')
->label('sdk.description', '/docs/references/videos/get-subtitles.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SUBTITLE_LIST)
->param('videoId', null, new UID(), 'Video unique ID.')
->inject('response')
->inject('dbForProject')
->action(function ($videoId, Response $response, Database $dbForProject) {
$query = [
Query::equal('videoId', [$videoId]),
];
$subtitles = Authorization::skip(fn () => $dbForProject->find('videos_subtitles', $query));
if (empty($subtitles)) {
throw new Exception(Exception::VIDEO_SUBTITLE_NOT_FOUND);
}
$response->dynamic(new Document([
'total' => $dbForProject->count('videos_subtitles', $query, APP_LIMIT_COUNT),
'subtitles' => $subtitles,
]), Response::MODEL_SUBTITLE_LIST);
});
App::patch('/v1/videos/:videoId/subtitles/:subtitleId')
->desc('Update video subtitle')
->groups(['api', 'videos'])
@@ -383,38 +415,6 @@ App::delete('/v1/videos/:videoId/subtitles/:subtitleId')
$response->noContent();
});
App::get('/v1/videos/:videoId/subtitles')
->desc('Get video subtitles')
->groups(['api', 'videos'])
->label('scope', 'videos.read')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'videos')
->label('sdk.method', 'getSubtitles')
->label('sdk.description', '/docs/references/videos/get-subtitles.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_SUBTITLE_LIST)
->param('videoId', null, new UID(), 'Video unique ID.')
->inject('response')
->inject('dbForProject')
->action(function ($videoId, Response $response, Database $dbForProject) {
$query = [
Query::equal('videoId', [$videoId]),
];
$subtitles = Authorization::skip(fn () => $dbForProject->find('videos_subtitles', $query));
if (empty($subtitles)) {
throw new Exception(Exception::VIDEO_SUBTITLE_NOT_FOUND);
}
$response->dynamic(new Document([
'total' => $dbForProject->count('videos_subtitles', $query, APP_LIMIT_COUNT),
'subtitles' => $subtitles,
]), Response::MODEL_SUBTITLE_LIST);
});
App::post('/v1/videos/:videoId/rendition')
->alias('/v1/videos/:videoId/rendition', [])
->desc('Create video rendition')
@@ -430,12 +430,13 @@ App::post('/v1/videos/:videoId/rendition')
->label('sdk.response.model', Response::MODEL_NONE)
->param('videoId', null, new UID(), 'Video unique ID.')
->param('profileId', '', new CustomId(), 'Profile unique ID.')
->param('output', '', new WhiteList(['hls', 'dash']), 'output name')
->inject('request')
->inject('response')
->inject('dbForProject')
->inject('project')
->inject('mode')
->action(action: function (string $videoId, string $profileId, Request $request, Response $response, Database $dbForProject, Document $project, string $mode) {
->action(action: function (string $videoId, string $profileId, string $output, Request $request, Response $response, Database $dbForProject, Document $project, string $mode) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
@@ -452,6 +453,7 @@ App::post('/v1/videos/:videoId/rendition')
$transcoder = new Transcoding();
$transcoder
->setOutput($output)
->setProject($project)
->setVideo($video)
->setProfile($profile)
@@ -460,54 +462,6 @@ App::post('/v1/videos/:videoId/rendition')
$response->noContent();
});
App::delete('/v1/videos/:videoId/renditions/:renditionId')
->desc('Delete video rendition')
->groups(['api', 'videos'])
->label('scope', 'videos.write')
->label('event', 'videos.[videoIdId].renditions.[renditionId].delete')
->label('audits.event', 'rendition.delete')
->label('audits.resource', 'video/{request.videoId}/rendition/{request.$id}')
->label('sdk.namespace', 'videos')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'deleteRendition')
->label('sdk.description', '/docs/references/videos/delete-rendition.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('videoId', '', new UID(), 'Video unique ID.')
->param('renditionId', '', new UID(), 'Video rendition unique ID.')
->inject('response')
->inject('dbForProject')
->inject('mode')
->inject('deviceVideos')
->action(function (string $videoId, string $renditionId, Response $response, Database $dbForProject, string $mode, Device $deviceVideos) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$rendition = Authorization::skip(fn() => $dbForProject->getDocument('videos_renditions', $renditionId));
if ($rendition->isEmpty()) {
throw new Exception(Exception::VIDEO_RENDITION_NOT_FOUND);
}
$deleted = $dbForProject->deleteDocument('videos_renditions', $renditionId);
if (!$deleted) {
throw new Exception(Exception::GENERAL_SERVER_ERROR);
}
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_renditions', $rendition->getId()));
if (!empty($rendition['path'])) {
$deviceVideos->deletePath($rendition['path']);
}
$response->noContent();
});
App::get('/v1/videos/:videoId/renditions/:renditionId')
->desc('Get a single video rendition')
->groups(['api', 'videos'])
@@ -581,6 +535,54 @@ App::get('/v1/videos/:videoId/renditions')
]), Response::MODEL_RENDITION_LIST);
});
App::delete('/v1/videos/:videoId/renditions/:renditionId')
->desc('Delete video rendition')
->groups(['api', 'videos'])
->label('scope', 'videos.write')
->label('event', 'videos.[videoIdId].renditions.[renditionId].delete')
->label('audits.event', 'rendition.delete')
->label('audits.resource', 'video/{request.videoId}/rendition/{request.$id}')
->label('sdk.namespace', 'videos')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'deleteRendition')
->label('sdk.description', '/docs/references/videos/delete-rendition.md') // TODO: Create markdown
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.model', Response::MODEL_NONE)
->param('videoId', '', new UID(), 'Video unique ID.')
->param('renditionId', '', new UID(), 'Video rendition unique ID.')
->inject('response')
->inject('dbForProject')
->inject('mode')
->inject('deviceVideos')
->action(function (string $videoId, string $renditionId, Response $response, Database $dbForProject, string $mode, Device $deviceVideos) {
$video = Authorization::skip(fn() => $dbForProject->getDocument('videos', $videoId));
if ($video->isEmpty()) {
throw new Exception(Exception::VIDEO_NOT_FOUND);
}
validateFilePermissions($dbForProject, $video['bucketId'], $video['fileId'], $mode);
$rendition = Authorization::skip(fn() => $dbForProject->getDocument('videos_renditions', $renditionId));
if ($rendition->isEmpty()) {
throw new Exception(Exception::VIDEO_RENDITION_NOT_FOUND);
}
$deleted = $dbForProject->deleteDocument('videos_renditions', $renditionId);
if (!$deleted) {
throw new Exception(Exception::GENERAL_SERVER_ERROR);
}
Authorization::skip(fn() => $dbForProject->deleteDocument('videos_renditions', $rendition->getId()));
if (!empty($rendition['path'])) {
$deviceVideos->deletePath($rendition['path']);
}
$response->noContent();
});
App::get('/v1/videos/:videoId/outputs/:output')
->desc('Get video master renditions manifest')
->groups(['api', 'videos'])
@@ -593,7 +595,7 @@ App::get('/v1/videos/:videoId/outputs/:output')
->label('sdk.methodType', 'location')
->label('scope', 'videos.read')
->param('videoId', null, new UID(), 'Video unique ID.')
->param('output', '', new WhiteList(['hls', 'dash']), 'protocol name')
->param('output', '', new WhiteList(['hls', 'dash']), 'output name')
->inject('response')
->inject('dbForProject')
->inject('mode')
@@ -961,19 +963,17 @@ 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('output', false, new WhiteList(['hls', 'dash']), 'Video profile output.')
->inject('response')
->inject('dbForProject')
->action(action: function (string $name, string $videoBitRate, string $audioBitRate, string $width, string $height, string $output, Response $response, Database $dbForProject) {
->action(action: function (string $name, string $videoBitRate, string $audioBitRate, string $width, string $height, Response $response, Database $dbForProject) {
$profile = Authorization::skip(function () use ($dbForProject, $name, $videoBitRate, $audioBitRate, $width, $height, $output) {
$profile = Authorization::skip(function () use ($dbForProject, $name, $videoBitRate, $audioBitRate, $width, $height) {
return $dbForProject->createDocument('videos_profiles', new Document([
'name' => $name,
'videoBitRate' => (int)$videoBitRate,
'audioBitRate' => (int)$audioBitRate,
'width' => (int)$width,
'height' => (int)$height,
'output' => $output,
]));
});
@@ -1000,10 +1000,9 @@ 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('output', false, new WhiteList(['hls', 'dash']), 'Video profile output.')
->inject('response')
->inject('dbForProject')
->action(action: function (string $profileId, string $name, string $videoBitRate, string $audioBitRate, string $width, string $height, string $output, Response $response, Database $dbForProject) {
->action(action: function (string $profileId, string $name, string $videoBitRate, string $audioBitRate, string $width, string $height, Response $response, Database $dbForProject) {
$profile = Authorization::skip(fn() => $dbForProject->getDocument('videos_profiles', $profileId));
if ($profile->isEmpty()) {
@@ -1014,8 +1013,8 @@ App::patch('/v1/videos/profiles/:profileId')
->setAttribute('videoBitRate', (int)$videoBitRate)
->setAttribute('audioBitRate', (int)$audioBitRate)
->setAttribute('width', (int)$width)
->setAttribute('height', (int)$height)
->setAttribute('output', $output);
->setAttribute('height', (int)$height);
$profile = Authorization::skip(fn() => $dbForProject->updateDocument('videos_profiles', $profile->getId(), $profile));
+16 -16
View File
@@ -1,6 +1,7 @@
<?php
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Messaging\Adapter\Realtime;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Resque\Worker;
@@ -87,7 +88,7 @@ class TranscodingV1 extends Worker
public function run(): void
{
$startTime = \microtime(true);
$startTime = time();
$this->database = $this->getProjectDB($this->project->getId());
$this->bucket = $this->database->getDocument('buckets', $this->video->getAttribute('bucketId'));
$this->file = $this->database->getDocument('bucket_' . $this->bucket->getInternalId(), $this->video->getAttribute('fileId'));
@@ -101,6 +102,11 @@ class TranscodingV1 extends Worker
console::error('Storage transfer error');
}
$this->renditionName = $this->profile->getAttribute('width')
. 'X' . $this->profile->getAttribute('height')
. '@' . ($this->profile->getAttribute('videoBitRate') + $this->profile->getAttribute('audioBitRate'));
/**
* FFMpeg init
*/
@@ -156,10 +162,6 @@ class TranscodingV1 extends Worker
$media = $this->ffmpeg->open($inPath);
$this->renditionName = $this->profile->getAttribute('width')
. 'X' . $this->profile->getAttribute('height')
. '@' . ($this->profile->getAttribute('videoBitRate') + $this->profile->getAttribute('audioBitRate'));
$subs = [];
$subtitles = $this->database->find('videos_subtitles', [
Query::equal('videoId', [$this->video->getId()]),
@@ -198,7 +200,7 @@ class TranscodingV1 extends Worker
'name' => $this->renditionName,
'startedAt' => DateTime::now(),
'status' => self::STATUS_START,
'output' => $this->profile->getAttribute('output'),
'output' => $this->args['output'],
]));
$this->send($query);
$renditionRootPath = $this->getVideoDevice($this->project->getId())->getPath($this->video->getId()) . '/';
@@ -228,17 +230,17 @@ class TranscodingV1 extends Worker
}
});
$this->transcode($this->profile->getAttribute('output'), $media, $format, $representation, $subs);
$this->transcode($media, $format, $representation, $subs);
unset($media);
//exec('/usr/bin/ffmpeg -y -i /usr/src/code/tests/tmp/637f59c88f9ff0fe3b1f/637e1b82aeab8980400e/in/637f59ab5bce0e36d05e.mp4 -c:v libx264 -c:a aac -bf 1 -keyint_min 25 -g 250 -sc_threshold 40 -use_timeline 0 -use_template 0 -seg_duration 10 -hls_playlist 0 -f dash -dn -sn -vf scale=iw:-2:force_original_aspect_ratio=increase,setsar=1:1 -b_strategy 1 -bf 3 -force_key_frames "expr:gte(t,n_forced*2)" -map 0 -s:v:0 1024x576 -b:v:0 2538k -b:a:0 128k -strict -2 -threads 12 /usr/src/code/tests/tmp/637f59c88f9ff0fe3b1f/637e1b82aeab8980400e/out/637f59c88f9ff0fe3b1f.mpd2>&1', $o, $v);
//var_dump($o);
//var_dump($v);
if ($this->profile->getAttribute('output') === self::OUTPUT_HLS) {
if ($this->args['output'] === self::OUTPUT_HLS) {
$streams = $this->getHlsSegmentsUrls($this->outDir . 'master.m3u8');
foreach ($streams as $stream) {
$m3u8 = $this->getSegments(self::OUTPUT_HLS, $this->outDir . $stream['path']);
$m3u8 = $this->getSegments($this->outDir . $stream['path']);
if (!empty($m3u8['segments'])) {
foreach ($m3u8['segments'] as $segment) {
$this->database->createDocument('videos_renditions_segments', new Document([
@@ -255,7 +257,7 @@ class TranscodingV1 extends Worker
$query->setAttribute('targetDuration', $m3u8['targetDuration']);
}
} else {
$mpd = $this->getSegments(self::OUTPUT_DASH, $this->outPath . '.mpd');
$mpd = $this->getSegments($this->outPath . '.mpd');
if (!empty($mpd['segments'])) {
foreach ($mpd['segments'] as $segment) {
$this->database->createDocument('videos_renditions_segments', new Document([
@@ -350,14 +352,13 @@ class TranscodingV1 extends Worker
}
/**
* @param string $output
* @param $media Media
* @param $format StreamFormat
* @param $representation Representation
* @param array $subtitles
* @return void
*/
private function transcode(string $output, Media $media, StreamFormat $format, Representation $representation, array $subtitles): void
private function transcode(Media $media, StreamFormat $format, Representation $representation, array $subtitles): void
{
$additionalParams = [
@@ -371,7 +372,7 @@ class TranscodingV1 extends Worker
$segmentSize = 10;
if ($output === self::OUTPUT_DASH) {
if ($this->args['output'] === self::OUTPUT_DASH) {
$media->dash()
->setFormat($format)
->setSegDuration($segmentSize)
@@ -397,15 +398,14 @@ class TranscodingV1 extends Worker
}
/**
* @param string $output
* @param string $path
* @return array
*/
private function getSegments(string $output, string $path): array
private function getSegments(string $path): array
{
$segments = [];
if ($output === self::OUTPUT_DASH) {
if ($this->args['output'] === self::OUTPUT_DASH) {
$metadata = null;
$handle = fopen($path, "r");
if ($handle) {
+27
View File
@@ -11,11 +11,37 @@ class Transcoding extends Event
protected Document $profile;
protected string $output;
public function __construct()
{
parent::__construct(Event::TRANSCODING_QUEUE_NAME, Event::TRANSCODING_CLASS_NAME);
}
/**
* Sets output.
*
* @param string $output
* @return self
*/
public function setOutput(string $output): self
{
$this->output = $output;
return $this;
}
/**
* Returns output.
*
* @return string
*/
public function getOutput(): string
{
return $this->output;
}
/**
* Sets video.
*
@@ -71,6 +97,7 @@ class Transcoding extends Event
public function trigger(): string|bool
{
return Resque::enqueue($this->queue, $this->class, [
'output' => $this->output,
'project' => $this->project,
'user' => $this->user,
'video' => $this->video,