coordinator->getRegistrationContext(); if ($context === null) { return []; } if ($this->providers !== null) { return $this->providers; } $this->providers = []; foreach ($context->getSpeechToTextProviders() as $providerServiceRegistration) { $class = $providerServiceRegistration->getService(); try { $this->providers[$class] = $this->serverContainer->get($class); } catch (NotFoundExceptionInterface|ContainerExceptionInterface|Throwable $e) { $this->logger->error('Failed to load SpeechToText provider ' . $class, [ 'exception' => $e, ]); } } return $this->providers; } public function hasProviders(): bool { $context = $this->coordinator->getRegistrationContext(); if ($context === null) { return false; } return !empty($context->getSpeechToTextProviders()); } public function scheduleFileTranscription(File $file, ?string $userId, string $appId): void { if (!$this->hasProviders()) { throw new PreConditionNotMetException('No SpeechToText providers have been registered'); } try { $this->jobList->add(TranscriptionJob::class, [ 'fileId' => $file->getId(), 'owner' => $file->getOwner()->getUID(), 'userId' => $userId, 'appId' => $appId, ]); } catch (NotFoundException|InvalidPathException $e) { throw new InvalidArgumentException('Invalid file provided for file transcription: ' . $e->getMessage()); } } public function cancelScheduledFileTranscription(File $file, ?string $userId, string $appId): void { try { $jobArguments = [ 'fileId' => $file->getId(), 'owner' => $file->getOwner()->getUID(), 'userId' => $userId, 'appId' => $appId, ]; if (!$this->jobList->has(TranscriptionJob::class, $jobArguments)) { $this->logger->debug('Failed to cancel a Speech-to-text job for file ' . $file->getId() . '. No related job was found.'); return; } $this->jobList->remove(TranscriptionJob::class, $jobArguments); } catch (NotFoundException|InvalidPathException $e) { throw new InvalidArgumentException('Invalid file provided to cancel file transcription: ' . $e->getMessage()); } } public function transcribeFile(File $file, ?string $userId = null, string $appId = 'core'): string { // try to run a TaskProcessing core:audio2text task // this covers scheduling as well because OC\SpeechToText\TranscriptionJob calls this method try { if (isset($this->taskProcessingManager->getAvailableTaskTypes()['core:audio2text'])) { $taskProcessingTask = new Task( AudioToText::ID, ['input' => $file->getId()], $appId, $userId, 'from-SpeechToTextManager||' . $file->getId() . '||' . ($userId ?? '') . '||' . $appId, ); $resultTask = $this->taskProcessingManager->runTask($taskProcessingTask); if ($resultTask->getStatus() === Task::STATUS_SUCCESSFUL) { $output = $resultTask->getOutput(); if (isset($output['output']) && is_string($output['output'])) { return $output['output']; } } } } catch (Throwable $e) { throw new RuntimeException('Failed to run a Speech-to-text job from STTManager with TaskProcessing for file ' . $file->getId(), 0, $e); } if (!$this->hasProviders()) { throw new PreConditionNotMetException('No SpeechToText providers have been registered'); } $providers = $this->getProviders(); $json = $this->config->getAppValue('core', 'ai.stt_provider', ''); if ($json !== '') { $classNameOrId = json_decode($json, true); $provider = current(array_filter($providers, function ($provider) use ($classNameOrId) { if ($provider instanceof ISpeechToTextProviderWithId) { return $provider->getId() === $classNameOrId; } return $provider::class === $classNameOrId; })); if ($provider !== false) { $providers = [$provider]; } } foreach ($providers as $provider) { try { if ($provider instanceof ISpeechToTextProviderWithUserId) { $provider->setUserId($this->userSession->getUser()?->getUID()); } return $provider->transcribeFile($file); } catch (\Throwable $e) { $this->logger->info('SpeechToText transcription using provider ' . $provider->getName() . ' failed', ['exception' => $e]); throw new RuntimeException('SpeechToText transcription using provider "' . $provider->getName() . '" failed: ' . $e->getMessage()); } } throw new RuntimeException('Could not transcribe file'); } } href='#n7'>7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Tooltip - Custom Styling</title>
<link rel="stylesheet" href="../../themes/base/tooltip.css">
<link rel="stylesheet" href="../demos.css">
<script src="../../external/requirejs/require.js"></script>
<script src="../bootstrap.js">
$( document ).tooltip({
position: {
my: "center bottom-20",
at: "center top",
using: function( position, feedback ) {
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
});
</script>
<style>
.ui-tooltip, .arrow:after {
background: black;
border: 2px solid white;
}
.ui-tooltip {
padding: 10px 20px;
color: white;
border-radius: 20px;
font: bold 14px "Helvetica Neue", Sans-Serif;
text-transform: uppercase;
box-shadow: 0 0 7px black;
}
.arrow {
width: 70px;
height: 16px;
overflow: hidden;
position: absolute;
left: 50%;
margin-left: -35px;
bottom: -16px;
}
.arrow.top {
top: -16px;
bottom: auto;
}
.arrow.left {
left: 20%;
}
.arrow:after {
content: "";
position: absolute;
left: 20px;
top: -20px;
width: 25px;
height: 25px;
box-shadow: 6px 5px 9px -9px black;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.arrow.top:after {
bottom: -20px;
top: auto;
}
</style>
</head>
<body>
<p><a href="#" title="That's what this widget is">Tooltips</a> can be attached to any element. When you hover
the element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.</p>
<p>But as it's not a native tooltip, it can be styled. Any themes built with
<a href="http://jqueryui.com/themeroller/" title="ThemeRoller: jQuery UI's theme builder application">ThemeRoller</a>
will also style tooltips accordingly.</p>
<p>Tooltips are also useful for form elements, to show some additional information in the context of each field.</p>
<p><label for="age">Your age:</label> <input id="age" title="We ask for your age only for statistical purposes."></p>
<p>Hover the field to see the tooltip.</p>
<div class="demo-description">
<p>Hover the links above or use the tab key to cycle the focus on each element.</p>
</div>
</body>
</html>