Signed-off-by: Marcel Klehr <mklehr@gmx.net>pull/37674/head
parent
c6645cbc46
commit
317521b607
@ -0,0 +1,107 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net> |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @author Julius Härtl <jus@bitgrid.net> |
||||
* @author Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
|
||||
namespace OC\SpeechToText; |
||||
|
||||
use InvalidArgumentException; |
||||
use OC\AppFramework\Bootstrap\Coordinator; |
||||
use OCP\BackgroundJob\IJobList; |
||||
use OCP\IServerContainer; |
||||
use OCP\PreConditionNotMetException; |
||||
use OCP\SpeechToText\ISpeechToTextManager; |
||||
use OCP\SpeechToText\ISpeechToTextProvider; |
||||
use Psr\Container\ContainerExceptionInterface; |
||||
use Psr\Container\NotFoundExceptionInterface; |
||||
use Psr\Log\LoggerInterface; |
||||
use Throwable; |
||||
|
||||
class SpeechToTextManager implements ISpeechToTextManager { |
||||
/** @var ?ISpeechToTextProvider[] */ |
||||
private ?array $providers = null; |
||||
|
||||
public function __construct( |
||||
private IServerContainer $serverContainer, |
||||
private Coordinator $coordinator, |
||||
private LoggerInterface $logger, |
||||
private IJobList $jobList, |
||||
) { } |
||||
|
||||
public function getProviders(): array { |
||||
$context = $this->coordinator->getRegistrationContext(); |
||||
if ($context === null) { |
||||
return []; |
||||
} |
||||
|
||||
if ($this->providers !== null) { |
||||
return $this->providers; |
||||
} |
||||
|
||||
$this->providers = []; |
||||
|
||||
foreach ($context->getSpeechToTextProviders() as $providerRegistration) { |
||||
$class = $providerRegistration->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->getTranslationProviders()); |
||||
} |
||||
|
||||
public function scheduleFileTranscription(string $path, array $context): void { |
||||
if (!$this->hasProviders()) { |
||||
throw new PreConditionNotMetException('No SpeechToText providers have been registered'); |
||||
} |
||||
$this->jobList->add(TranscriptionJob::class, [ 'path' => $path, 'context' => $context]); |
||||
} |
||||
|
||||
public function transcribeFile(string $path): string { |
||||
$provider = current($this->getProviders()); |
||||
if (!$provider) { |
||||
throw new PreConditionNotMetException('No SpeechToText providers have been registered'); |
||||
} |
||||
|
||||
if (!file_exists($path)) { |
||||
throw new InvalidArgumentException('File does not exist'); |
||||
} |
||||
|
||||
return $provider->transcribeFile($path); |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
<?php |
||||
|
||||
namespace OC\SpeechToText; |
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory; |
||||
use OCP\BackgroundJob\QueuedJob; |
||||
use OCP\EventDispatcher\IEventDispatcher; |
||||
use OCP\PreConditionNotMetException; |
||||
use OCP\SpeechToText\Events\TranscriptionFinishedEvent; |
||||
use OCP\SpeechToText\ISpeechToTextManager; |
||||
|
||||
class TranscriptionJob extends QueuedJob { |
||||
public function __construct( |
||||
ITimeFactory $timeFactory, |
||||
private ISpeechToTextManager $speechToTextManager, |
||||
private IEventDispatcher $eventDispatcher, |
||||
) { |
||||
parent::__construct($timeFactory); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @inheritDoc |
||||
*/ |
||||
protected function run($argument) { |
||||
try { |
||||
$result = $this->speechToTextManager->transcribeFile($argument['path']); |
||||
$this->eventDispatcher->dispatchTyped( |
||||
new TranscriptionFinishedEvent( |
||||
true, |
||||
$result, |
||||
'', |
||||
$argument['context'] |
||||
) |
||||
); |
||||
} catch (PreConditionNotMetException|\RuntimeException|\InvalidArgumentException $e) { |
||||
$this->eventDispatcher->dispatchTyped( |
||||
new TranscriptionFinishedEvent( |
||||
false, |
||||
'', |
||||
$e->getMessage(), |
||||
$argument['context'] |
||||
) |
||||
); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @author Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
namespace OCP\SpeechToText\Events; |
||||
|
||||
use OCP\EventDispatcher\Event; |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
class TranscriptionFinishedEvent extends Event { |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function __construct( |
||||
private bool $successful, |
||||
private string $transcription, |
||||
private string $errorMessage, |
||||
private array $context |
||||
) { |
||||
parent::__construct(); |
||||
} |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function getContext(): array { |
||||
return $this->context; |
||||
} |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function isSuccessful(): bool { |
||||
return $this->successful; |
||||
} |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function getErrorMessage(): string { |
||||
return $this->errorMessage; |
||||
} |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function getTranscription(): string { |
||||
return $this->transcription; |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2023 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @author Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
|
||||
namespace OCP\SpeechToText; |
||||
|
||||
use InvalidArgumentException; |
||||
use OCP\PreConditionNotMetException; |
||||
use RuntimeException; |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
interface ISpeechToTextManager { |
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function hasProviders(): bool; |
||||
|
||||
/** |
||||
* Will schedule a transcription process in the background. The result will become available |
||||
* with the \OCP\SpeechToText\Events\TranscriptionFinishedEvent |
||||
* You should add context information to the context array to re-identify the transcription result as |
||||
* as belonging to your transcription request. |
||||
* |
||||
* @since 27.0.0 |
||||
* @throws PreConditionNotMetException If no provider was registered but this method was still called |
||||
* @throws InvalidArgumentException If the file could not be found or is not of a supported type |
||||
* @throws RuntimeException If the transcription failed for other reasons |
||||
*/ |
||||
public function scheduleFileTranscription(string $path, array $context): void; |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
* @throws PreConditionNotMetException If no provider was registered but this method was still called |
||||
* @throws InvalidArgumentException If the file could not be found or is not of a supported type |
||||
* @throws RuntimeException If the transcription failed for other reasons |
||||
*/ |
||||
public function transcribeFile(string $path) : string; |
||||
} |
@ -0,0 +1,45 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @copyright Copyright (c) 2022 Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @author Marcel Klehr <mklehr@gmx.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
|
||||
namespace OCP\SpeechToText; |
||||
|
||||
use RuntimeException; |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
interface ISpeechToTextProvider { |
||||
/** |
||||
* @since 27.0.0 |
||||
*/ |
||||
public function getName(): string; |
||||
|
||||
/** |
||||
* @since 27.0.0 |
||||
* @throws RuntimeException If the text could not be transcribed |
||||
*/ |
||||
public function transcribeFile(string $path): string; |
||||
} |
Loading…
Reference in new issue