mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
ginga subtitle
This commit is contained in:
@@ -22,13 +22,17 @@ use Alchemy\Phrasea\Metadata\PhraseanetMetadataReader;
|
|||||||
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
|
use Alchemy\Phrasea\Metadata\PhraseanetMetadataSetter;
|
||||||
use Alchemy\Phrasea\Record\RecordWasRotated;
|
use Alchemy\Phrasea\Record\RecordWasRotated;
|
||||||
use DataURI\Parser;
|
use DataURI\Parser;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
use MediaAlchemyst\Alchemyst;
|
use MediaAlchemyst\Alchemyst;
|
||||||
use MediaVorus\MediaVorus;
|
use MediaVorus\MediaVorus;
|
||||||
use PHPExiftool\Reader;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class ToolsController extends Controller
|
class ToolsController extends Controller
|
||||||
{
|
{
|
||||||
|
const GINGER_BASE_URL = "https://test.api.ginger.studio/recognition/speech";
|
||||||
|
const GINGER_TOKEN = "39c6011d-3bbe-4f39-95d0-a327d320ded4";
|
||||||
|
const GINGER_TRANSCRIPT_FORMAT = "text/vtt";
|
||||||
|
|
||||||
use DataboxLoggerAware;
|
use DataboxLoggerAware;
|
||||||
use DispatcherAware;
|
use DispatcherAware;
|
||||||
use FilesystemAware;
|
use FilesystemAware;
|
||||||
@@ -45,7 +49,6 @@ class ToolsController extends Controller
|
|||||||
if (count($records) == 1) {
|
if (count($records) == 1) {
|
||||||
/** @var \record_adapter $record */
|
/** @var \record_adapter $record */
|
||||||
$record = $records->first();
|
$record = $records->first();
|
||||||
$databox = $record->getDatabox();
|
|
||||||
|
|
||||||
/**Array list of subdefs**/
|
/**Array list of subdefs**/
|
||||||
$listsubdef = array_keys($record-> get_subdefs());
|
$listsubdef = array_keys($record-> get_subdefs());
|
||||||
@@ -88,14 +91,13 @@ class ToolsController extends Controller
|
|||||||
$metadatas = true;
|
$metadatas = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$conf = $this->getConf();
|
|
||||||
|
|
||||||
return $this->render('prod/actions/Tools/index.html.twig', [
|
return $this->render('prod/actions/Tools/index.html.twig', [
|
||||||
'records' => $records,
|
'records' => $records,
|
||||||
'record' => $record,
|
'record' => $record,
|
||||||
'recordSubdefs' => $recordAccessibleSubdefs,
|
'recordSubdefs' => $recordAccessibleSubdefs,
|
||||||
'metadatas' => $metadatas,
|
'metadatas' => $metadatas,
|
||||||
'listsubdef' => $listsubdef
|
'listsubdef' => $listsubdef
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ class ToolsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
|
/** @var \media_subdef $subdef */
|
||||||
foreach ($record->get_subdefs() as $subdef) {
|
foreach ($record->get_subdefs() as $subdef) {
|
||||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||||
continue;
|
continue;
|
||||||
@@ -146,6 +149,7 @@ class ToolsController extends Controller
|
|||||||
|
|
||||||
foreach ($selection as $record) {
|
foreach ($selection as $record) {
|
||||||
$substituted = false;
|
$substituted = false;
|
||||||
|
/** @var \media_subdef $subdef */
|
||||||
foreach ($record->get_subdefs() as $subdef) {
|
foreach ($record->get_subdefs() as $subdef) {
|
||||||
if ($subdef->is_substituted()) {
|
if ($subdef->is_substituted()) {
|
||||||
$substituted = true;
|
$substituted = true;
|
||||||
@@ -362,14 +366,6 @@ class ToolsController extends Controller
|
|||||||
return $this->app->json($return);
|
return $this->app->json($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Reader
|
|
||||||
*/
|
|
||||||
private function getExifToolReader()
|
|
||||||
{
|
|
||||||
return $this->app['exiftool.reader'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Alchemyst
|
* @return Alchemyst
|
||||||
*/
|
*/
|
||||||
@@ -449,13 +445,130 @@ class ToolsController extends Controller
|
|||||||
try {
|
try {
|
||||||
$record->set_metadatas($metadatas);
|
$record->set_metadatas($metadatas);
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (\Exception $e) {
|
||||||
return $this->app->json(['success' => false, 'errorMessage' => $e->getMessage()]);
|
return $this->app->json(['success' => false, 'errorMessage' => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->app->json(['success' => true, 'errorMessage' => '']);
|
return $this->app->json(['success' => true, 'errorMessage' => '']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function autoSubtitleAction(Request $request)
|
||||||
|
{
|
||||||
|
$return = ['success' => false, 'errorMessage' => ''];
|
||||||
|
$record = new \record_adapter($this->app,
|
||||||
|
(int)$request->request->get("databox_id"),
|
||||||
|
(int)$request->request->get("record_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($record->has_preview() && ($previewLink = $record->get_preview()->get_permalink()) !== null && $request->request->get("meta_struct_id")) {
|
||||||
|
switch ($request->request->get("subtitle_language_source")) {
|
||||||
|
case 'En':
|
||||||
|
$language = 'en-GB';
|
||||||
|
break;
|
||||||
|
case 'De':
|
||||||
|
$language = 'de-DE';
|
||||||
|
break;
|
||||||
|
case 'Fr':
|
||||||
|
default:
|
||||||
|
$language = 'fr-FR';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$permalinkUrl = $previewLink->get_url()->__toString();
|
||||||
|
|
||||||
|
$gingerClient = new Client();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->post(self::GINGER_BASE_URL.'/media/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.self::GINGER_TOKEN
|
||||||
|
],
|
||||||
|
'json' => [
|
||||||
|
'url' => $permalinkUrl,
|
||||||
|
'language' => $language
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$return['errorMessage'] = $e->getMessage();
|
||||||
|
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 201) {
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
$responseMediaBody = $response->getBody()->getContents();
|
||||||
|
$responseMediaBody = json_decode($responseMediaBody,true);
|
||||||
|
|
||||||
|
$checkStatus = null;
|
||||||
|
do {
|
||||||
|
// first wait 5 second before check subtitling status
|
||||||
|
sleep(5);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->get(self::GINGER_BASE_URL.'/task/'.$responseMediaBody['task_id'].'/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.self::GINGER_TOKEN
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$checkStatus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$checkStatus = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$responseTaskBody = $response->getBody()->getContents();
|
||||||
|
$responseTaskBody = json_decode($responseTaskBody,true);
|
||||||
|
|
||||||
|
} while($responseTaskBody['status'] != 'SUCCESS');
|
||||||
|
|
||||||
|
if (!$checkStatus) {
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $gingerClient->get(self::GINGER_BASE_URL.'/media/'.$responseMediaBody['media']['uuid'].'/', [
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'token '.self::GINGER_TOKEN,
|
||||||
|
'ACCEPT' => self::GINGER_TRANSCRIPT_FORMAT
|
||||||
|
],
|
||||||
|
'query' => [
|
||||||
|
'language' => $language
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
if ($response->getStatusCode() !== 201) {
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
$transcriptContent = $response->getBody()->getContents();
|
||||||
|
|
||||||
|
$metadatas[0] = [
|
||||||
|
'meta_struct_id' => (int)$request->request->get("meta_struct_id"),
|
||||||
|
'meta_id' => '',
|
||||||
|
'value' => $transcriptContent
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$record->set_metadatas($metadatas);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$return['errorMessage'] = $e->getMessage();
|
||||||
|
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
$return['success'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->app->json($return);
|
||||||
|
}
|
||||||
|
|
||||||
public function videoEditorAction(Request $request)
|
public function videoEditorAction(Request $request)
|
||||||
{
|
{
|
||||||
$records = RecordsRequest::fromRequest($this->app, $request, false);
|
$records = RecordsRequest::fromRequest($this->app, $request, false);
|
||||||
@@ -491,7 +604,7 @@ class ToolsController extends Controller
|
|||||||
$fieldValue = array_pop($fieldValues);
|
$fieldValue = array_pop($fieldValues);
|
||||||
$field['value'] = $fieldValue->getValue();
|
$field['value'] = $fieldValue->getValue();
|
||||||
}
|
}
|
||||||
$videoTextTrackFields[] = $field;
|
$videoTextTrackFields[$meta->get_id()] = $field;
|
||||||
unset($field);
|
unset($field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,9 @@ class Tools implements ControllerProviderInterface, ServiceProviderInterface
|
|||||||
$controllers->post('/metadata/save/', 'controller.prod.tools:saveMetasAction')
|
$controllers->post('/metadata/save/', 'controller.prod.tools:saveMetasAction')
|
||||||
->bind('prod_tools_metadata_save');
|
->bind('prod_tools_metadata_save');
|
||||||
|
|
||||||
|
$controllers->post('/auto-subtitle/', 'controller.prod.tools:autoSubtitleAction')
|
||||||
|
->bind('prod_tools_auto_subtitle');
|
||||||
|
|
||||||
$controllers->get('/videoEditor', 'controller.prod.tools:videoEditorAction');
|
$controllers->get('/videoEditor', 'controller.prod.tools:videoEditorAction');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
|
@@ -242,9 +242,9 @@
|
|||||||
<p class="item">
|
<p class="item">
|
||||||
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Source Audio language" | trans }}</label>
|
<label>{{ "prod:videoeditor:subtitleRequestTab:label:: Source Audio language" | trans }}</label>
|
||||||
<select name="subtitle_language_source" id="subtitle_language_source">
|
<select name="subtitle_language_source" id="subtitle_language_source">
|
||||||
<option value="fr">Fr</option>
|
{% for videoTextTrackField in videoTextTrackFields %}
|
||||||
<option value="en">En</option>
|
<option value="{{ videoTextTrackField.meta_struct_id}}">{{ videoTextTrackField.label}}</option>
|
||||||
<option value="de">De</option>
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
<p class="item">
|
<p class="item">
|
||||||
@@ -352,4 +352,24 @@
|
|||||||
overlapChapters: {% if overlapChapters != NULL %}{{ overlapChapters }}{% else %}1{% endif %},
|
overlapChapters: {% if overlapChapters != NULL %}{{ overlapChapters }}{% else %}1{% endif %},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$('#submit-subtitle-request').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("auto-subtitle process");
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/prod/tools/auto-subtitle/',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
databox_id: {{ record.get_base_id }},
|
||||||
|
record_id: {{ record.get_record_id }},
|
||||||
|
meta_struct_id: $('#subtitle_language_source').val(),
|
||||||
|
subtitle_language_source: $('#subtitle_language_source option:selected').text()
|
||||||
|
},
|
||||||
|
success: function success(data) {
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Reference in New Issue
Block a user