Skip to content

Commit

Permalink
Add subtitle upload #355 (#702)
Browse files Browse the repository at this point in the history
* trying to access REST Endpoint to add track

* Implementing upload for de and en subtitles

* change to expected boolean

* Show and make caption files downloadable

* Use studip languages as available languages

* prettier upload buttons

* fiy typo

* load captions seperately

* Use gettext

---------

Co-authored-by: Till Glöggler <[email protected]>
  • Loading branch information
ssrahn and tgloeggl committed Jun 7, 2023
1 parent 9cb5a30 commit ff48b48
Show file tree
Hide file tree
Showing 17 changed files with 440 additions and 31 deletions.
1 change: 1 addition & 0 deletions app/controllers/contents.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ public function index_action()
PageLayout::setBodyElementId('opencast-plugin');

$this->studip_version = $this->getStudIPVersion();
$this->languages = json_encode($GLOBALS['CONTENT_LANGUAGES']);
}
}
1 change: 1 addition & 0 deletions app/controllers/course.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function index_action()
PageLayout::setBodyElementId('opencast-plugin');

$this->studip_version = $this->getStudIPVersion();
$this->languages = json_encode($GLOBALS['CONTENT_LANGUAGES']);

$this->render_template('course/index', $GLOBALS['template_factory']->open('layouts/base.php'));
}
Expand Down
17 changes: 17 additions & 0 deletions assets/css/opencast.scss
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,23 @@ h2.oc--loadingbar, .oc--loadingbar-title {
}
}

/* * * * * * * * * * * * * * * * * * */
/* U P L O A D E L E M E N T S */
/* * * * * * * * * * * * * * * * * * */

label.oc--file-upload {
cursor: pointer;
color: $base-color;

input[type=file] {
display: none;
}
.filename {
padding-left: 0.5em;
color: $light-gray-color-80;
}
}

/* * * * * * * * * * * * * * * * * * * * * */
/* S C R E E N S I Z E C L A S S E S */
/* * * * * * * * * * * * * * * * * * * * * */
Expand Down
18 changes: 18 additions & 0 deletions lib/Models/REST/ApiEventsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,22 @@ public function deleteEpisode($episode_id)
$response = $this->opencastApi->eventsApi->delete($episode_id);
return $response['code'] < 400;
}

/**
* Return media files
*
* @param
*
* @return array
*/
public function getMedia($eventId)
{
$response = $this->opencastApi->eventsApi->getMedia($eventId);

if ($response['code'] == 200) {
return $response['body'];
}

return false;
}
}
29 changes: 29 additions & 0 deletions lib/Models/Videos.php
Original file line number Diff line number Diff line change
Expand Up @@ -806,4 +806,33 @@ public static function addToCoursePlaylist($eventType, $episode, $video)
}
}
}

/**
* Fetch caption data for a given token
*
* @param string $token
*
* @return Array which contains urls for the caption files
*/
public static function getCaptionByToken($token)
{
$caption_download = [];
$video = self::findByToken($token);

// Get caption files
$api_event_client = ApiEventsClient::getInstance($video->config_id);
$media_tracks = $api_event_client->getMedia($video->episode);

foreach($media_tracks as $track) {
if (substr($track->flavor, 0, 9) === 'captions/' &&
$track->mimetype === 'text/vtt')
{
$caption_download[$track->flavor] = [
'url' => $track->uri
];
}
}

return $caption_download;
}
}
1 change: 1 addition & 0 deletions lib/RouteMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public function authenticatedRoutes()
$this->app->post('/videos/{token}/report', Routes\Video\VideoReport::class);
$this->app->post('/videos/{token}/playlists', Routes\Video\VideoAddToPlaylist::class);

$this->app->get('/videos/{token}/captions', Routes\Video\VideoCaptions::class);
$this->app->get('/videos/{token}/shares', Routes\Video\VideoSharesList::class);
$this->app->put('/videos/{token}/shares', Routes\Video\VideoSharesUpdate::class);
$this->app->post('/videos/{course_id}/copy', Routes\Video\VideoCopyToCourse::class);
Expand Down
13 changes: 7 additions & 6 deletions lib/Routes/Config/SimpleConfigList.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ public function __invoke(Request $request, Response $response, $args)

foreach ($config as $conf) {
$config_list[$conf->id] = [
'id' => $conf->id,
'name' => $conf->service_url,
'version' => $conf->service_version,
'ingest' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'ingest'", [$conf->id]))->service_url,
'studio' => $conf->service_url . '/studio/index.html',
'lti_num' => sizeof(LtiHelper::getLtiLinks($conf->id)) // used to iterate over all Opencast nodes
'id' => $conf->id,
'name' => $conf->service_url,
'version' => $conf->service_version,
'ingest' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'ingest'", [$conf->id]))->service_url,
'apievents' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'apievents'", [$conf->id]))->service_url,
'studio' => $conf->service_url . '/studio/index.html',
'lti_num' => sizeof(LtiHelper::getLtiLinks($conf->id)) // used to iterate over all Opencast nodes
];
}

Expand Down
27 changes: 27 additions & 0 deletions lib/Routes/Video/VideoCaptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Opencast\Routes\Video;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Opencast\Errors\AuthorizationFailedException;
use Opencast\Errors\Error;
use Opencast\OpencastTrait;
use Opencast\OpencastController;
use Opencast\Models\Filter;
use Opencast\Models\Videos;

class VideoCaptions extends OpencastController
{
use OpencastTrait;

public function __invoke(Request $request, Response $response, $args)
{
$token = $args['token'];
$captions = Videos::getCaptionByToken($token);

return $this->createResponse([
'caption' => $captions
], $response);
}
}
40 changes: 31 additions & 9 deletions vueapp/common/upload.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,41 @@ class UploadService {
let obj = this;
return files.reduce(function(promise, file) {
return promise.then(function (mediaPackage) {
return obj.addTrack(mediaPackage, file, onProgress);

var data = new FormData();
data.append('mediaPackage', mediaPackage);
data.append('flavor', file.flavor);
data.append('tags', '');
data.append('BODY', file.file, file.file.name);

return obj.addTrack(data, "/addTrack", onProgress);
});
}, Promise.resolve(mediaPackage))
}

addTrack(mediaPackage, track, onProgress) {
var media = track.file;
var data = new FormData();
data.append('mediaPackage', mediaPackage);
data.append('flavor', track.flavor);
data.append('tags', '');
data.append('BODY', media, media.name);
async uploadCaptions(files, episode_id, options) {
this.fixFilenames(files);
let onProgress = options.uploadProgress;
let uploadDone = options.uploadDone;

let obj = this;
return files.reduce(function(promise, file) {
return promise.then(function () {

var data = new FormData();
data.append('flavor', file.flavor);
data.append('overwriteExisting', file.overwriteExisting);
data.append('track', file.file);

return obj.addTrack(data, "/" + episode_id + "/track", onProgress);
});
}, Promise.resolve())
.then(() => {
uploadDone();
})
}

addTrack(data, url_path, onProgress) {
var fnOnProgress = function (event) {
onProgress(track, event.loaded, event.total);
};
Expand All @@ -191,7 +213,7 @@ class UploadService {
obj.request = axios.CancelToken.source();

return axios({
url: obj.service_url + "/addTrack",
url: obj.service_url + url_path,
method: "POST",
data: data,
processData: false,
Expand Down
Loading

0 comments on commit ff48b48

Please sign in to comment.