PHP SDK для сервиса транскрибации RARUS Echo с использованием стандартов PSR и компонентов Symfony.
beta - SDK покрывает текущую версию API.
- Асинхронная транскрибация аудио и видео файлов
- Поддержка 13 языков и автоопределения языка
- Различные типы транскрибации (обычная, с метками времени, с диаризацией)
- PSR-совместимость (PSR-3, PSR-7, PSR-17, PSR-18)
- Автоматическое обнаружение HTTP клиента (php-http/discovery)
- PHP 8.4 или 8.5
- Composer 2.x
- Расширения: json, curl, mbstring, fileinfo
composer require mesilov/rarus-echo-php-sdk:^0.4Самый короткий happy-path не требует локальной установки PHP-пакета: запустите CLI из готового Docker image. Docker использует локально закешированный tag, если он уже загружен; добавьте --pull=always к docker run, если нужно принудительно получить актуальный опубликованный image.
docker run --rm ghcr.io/mesilov/rarus-echo-php-sdk:cliImage использует rarus-echo как entrypoint, поэтому команды передаются сразу после имени image:
docker run --rm \
-e RARUS_ECHO_API_KEY=your-api-key-uuid \
-e RARUS_ECHO_USER_ID=your-user-id-uuid \
ghcr.io/mesilov/rarus-echo-php-sdk:cli queue --json
docker run --rm \
-e RARUS_ECHO_API_KEY=your-api-key-uuid \
-e RARUS_ECHO_USER_ID=your-user-id-uuid \
-v "$PWD/audio.ogg:/audio.ogg:ro" \
ghcr.io/mesilov/rarus-echo-php-sdk:cli submit /audio.ogg \
--task-type=diarization \
--language=ru \
--speakers-correction \
--timestamps-extended \
--wait \
--json
docker run --rm \
--env-file .env.local \
-v "$PWD/audio.ogg:/audio.ogg:ro" \
ghcr.io/mesilov/rarus-echo-php-sdk:cli submit /audio.ogg \
--language=ru \
--wait \
--raw-result > transcript.txtGitHub Actions собирает image для linux/amd64 и linux/arm64, проверяет сборку в pull request и публикует ghcr.io/mesilov/rarus-echo-php-sdk:cli при изменениях в dev, main или ручном запуске workflow.
Image собирается на официальной runtime-базе php:8.4-cli-alpine. По сравнению с прежней базой php:8.4-cli-bookworm это уменьшает опубликованный image примерно с 769MB до ~179MB по docker images и примерно со ~180MB до ~46MB по сжатому pull size. Поведение rarus-echo, расширения curl/fileinfo/mbstring, PHP-лимиты для локальных аудио-smoke и multi-arch публикация сохранены.
<?php
declare(strict_types=1);
use Rarus\Echo\Services\ServiceFactory;
use Rarus\Echo\Core\Credentials;
use Rarus\Echo\Enum\Language;
use Rarus\Echo\Enum\TaskType;
use Rarus\Echo\Services\Transcription\Request\TranscriptionOptions;
// Создание credentials
$credentials = Credentials::fromString(
apiKey: 'your-api-key-uuid',
userId: 'your-user-id-uuid'
);
// Инициализация SDK
$factory = new ServiceFactory($credentials);
// Настройка опций транскрибации
$options = TranscriptionOptions::create()
->withTaskType(TaskType::DIARIZATION) // С разбиением по говорящим
->withLanguage(Language::RU) // Русский язык
->withCensor(true) // С цензурой
->build();
// Отправка файла на транскрибацию
$result = $factory->getTranscriptionService()->submit(
files: ['/path/to/audio.mp3'],
transcriptionOptions: $options
);
$fileIds = $result->getFileIds();
$fileId = $fileIds[0]; // Uuid объект
echo "Файл отправлен: {$fileId->toRfc4122()}\n";
// Проверка статуса
$status = $factory->getStatusService()->getByFileId($fileId);
echo "Статус: {$status->transcriptionStatus->value}\n";
// Получение результата после завершения
if ($status->isSuccessful()) {
$transcript = $factory->getTranscriptionService()->getByFileId($fileId);
echo "Результат:\n{$transcript->result}\n";
}<?php
declare(strict_types=1);
use Rarus\Echo\Exception\FileException;
use Rarus\Echo\Exception\ValidationException;
use Rarus\Echo\Exception\AuthenticationException;
use Rarus\Echo\Exception\ApiException;
try {
$result = $factory->getTranscriptionService()->submit($files, $options);
} catch (FileException $e) {
// Ошибка файла (не найден, не читается, неверный формат)
echo "Ошибка файла: {$e->getMessage()}\n";
} catch (ValidationException $e) {
// Ошибка валидации (422)
echo "Ошибка валидации: {$e->getMessage()}\n";
} catch (AuthenticationException $e) {
// Ошибка аутентификации (401)
echo "Ошибка аутентификации: {$e->getMessage()}\n";
} catch (ApiException $e) {
// Общая ошибка API
echo "Ошибка API: {$e->getMessage()}\n";
}После установки через Composer доступен исполняемый файл:
vendor/bin/rarus-echo --helpCLI использует те же credentials, что и SDK:
export RARUS_ECHO_API_KEY=your-api-key-uuid
export RARUS_ECHO_USER_ID=your-user-id-uuid
export RARUS_ECHO_BASE_URL=https://production-ai-ui-api.ai.rarus-cloud.ru # опциональноЕсли в текущей рабочей директории есть .env, CLI загрузит значения из него перед выполнением сервисной команды.
При отправке больших файлов автоматически подобранный HTTP-клиент раньше обрывал загрузку с ошибкой Idle timeout reached ... (по умолчанию PHP default_socket_timeout ~60 с). Теперь SDK создаёт HTTP-клиент с idle timeout 600 секунд. Значение можно переопределить переменной окружения (положительное целое число секунд):
export RARUS_ECHO_HTTP_TIMEOUT=1200 # опционально, по умолчанию 600В коде SDK то же самое задаётся через ApiClientFactory::withHttpTimeout(); при передаче собственного PSR-18 клиента через withHttpClient() таймаут становится ответственностью вызывающего.
vendor/bin/rarus-echo queue
vendor/bin/rarus-echo status 11111111-1111-1111-1111-111111111111
vendor/bin/rarus-echo transcript 11111111-1111-1111-1111-111111111111
vendor/bin/rarus-echo submit /path/to/audio.ogg --task-type=diarization --language=ru --timestamps-extended
vendor/bin/rarus-echo submit /path/to/audio.ogg --language=ru --waitДля автоматизации добавьте --json:
vendor/bin/rarus-echo queue --json
vendor/bin/rarus-echo submit /path/to/audio.ogg --json
vendor/bin/rarus-echo submit /path/to/audio.ogg --wait --jsonsubmit --wait после отправки файла опрашивает результат транскрибации до терминального статуса. Финальный JSON содержит file_ids и results, а прогресс вида submitted: ..., polling: ... и completed: ... пишется в stderr, поэтому stdout остается безопасным для jq, редиректа и пайпов.
При SIGINT (Ctrl+C) или SIGTERM во время долгого ожидания команда пишет в stderr сообщение о завершении по сигналу и возвращает ненулевой signal-aware код выхода.
Для сырого текста одного файла:
vendor/bin/rarus-echo submit /path/to/audio.ogg --language=ru --wait --raw-result > transcript.txt
vendor/bin/rarus-echo submit /path/to/audio.ogg --language=ru --wait --output=transcript.txtИнтервал и общий лимит ожидания задаются в секундах:
vendor/bin/rarus-echo submit /path/to/audio.ogg --wait --poll-interval=10 --timeout=3600 --jsonПолный список ключей всех команд — в разделе Справочник команд и опций. Основной результат пишется в stdout, прогресс и ошибки — в stderr, успешные команды завершаются с кодом 0.
Ниже перечислены все ключи CLI. Каноническим источником является структура команд в src/Infrastructure/Console/Command/.
Доступны для всех команд RARUS Echo (queue, submit, status, transcript):
| Опция | Значение | Описание |
|---|---|---|
--json |
флаг | Вывести результат команды в формате JSON. |
-h, --help |
флаг | Показать справку по команде. |
--silent |
флаг | Полностью подавить вывод (никаких сообщений). Доступна только с Symfony Console ≥ 7.2. |
-q, --quiet |
флаг | Выводить только ошибки, остальной вывод подавляется. |
-v, -vv, -vvv, --verbose |
флаг | Уровень детализации вывода (1 — обычный, 2 — подробный, 3 — отладка). |
-V, --version |
флаг | Показать версию приложения. |
--ansi, --no-ansi |
флаг | Принудительно включить/выключить ANSI-раскраску. |
-n, --no-interaction |
флаг | Не задавать интерактивных вопросов. |
--json добавляется командами RARUS Echo и недоступна во встроенных командах Symfony (list, help). Остальные ключи — глобальные опции Symfony Console и доступны во всех командах приложения. --silent появился в Symfony Console 7.2; в опубликованном Docker image он есть, но при установке SDK как библиотеки с более старой разрешённой версией symfony/console (^6.4 || ^7.0) этого ключа не будет.
Показать агрегированную информацию по очереди транскрибации. Аргументов и собственных опций, кроме глобальных, нет.
vendor/bin/rarus-echo queue [--json]
Отправить один или несколько файлов на транскрибацию.
vendor/bin/rarus-echo submit [опции] [--] <files>...
Аргумент:
| Аргумент | Обязательный | Несколько | Описание |
|---|---|---|---|
files |
да | да | Пути к файлам для отправки. |
Опции (помимо глобальных):
| Опция | Значение | По умолчанию | Описание |
|---|---|---|---|
--task-type |
обязательно | transcription |
Тип задачи: transcription, timestamps, diarization, raw_transcription. |
--language |
обязательно | auto |
Код языка: auto, ru, en, de, fr, es, pt, hy, ja, tr, ar, zh, he, vi. |
--censor |
флаг | — | Включить цензуру. |
--speakers-correction |
флаг | — | Включить коррекцию говорящих. |
--timestamps-extended |
флаг | — | Включить расширенные таймкоды для диаризации. |
--no-store-file |
флаг | — | Не хранить отправленные файлы после обработки. |
--low-priority |
флаг | — | Отправить с низким приоритетом обработки. |
--request-source |
обязательно | — | Необязательный заголовок источника запроса. |
--wait |
флаг | — | Опрашивать результат до терминального статуса. |
--poll-interval |
обязательно | 30 |
Интервал опроса в секундах при --wait. |
--timeout |
обязательно | 7200 |
Максимальное время ожидания в секундах при --wait. |
--raw-result |
флаг | — | С --wait: писать в stdout только сам transcript (ровно один файл). |
--output |
обязательно | — | С --wait: записать transcript в файл (ровно один файл). |
--raw-result и --output требуют --wait и поддерживают только один отправляемый файл.
Показать статус транскрибации одного файла.
vendor/bin/rarus-echo status [--json] [--] <file-id>
Аргумент:
| Аргумент | Обязательный | Несколько | Описание |
|---|---|---|---|
file-id |
да | нет | UUID файла RARUS Echo. |
Показать результат транскрибации одного файла.
vendor/bin/rarus-echo transcript [--json] [--] <file-id>
Аргумент:
| Аргумент | Обязательный | Несколько | Описание |
|---|---|---|---|
file-id |
да | нет | UUID файла RARUS Echo. |
В репозитории есть skills-only plugin rarus-echo-transcription для Claude Code и Codex-compatible hosts. Он описывает безопасный workflow поверх существующего CLI: проверить очередь, отправить один или несколько локальных аудиофайлов, получить file_id, проверить статус, дождаться результата через submit --wait и забрать transcript без вывода credentials.
Исходники plugin:
.agent-plugins/rarus-echo-transcription/
Claude Code может загрузить plugin напрямую из checkout на одну сессию:
claude --plugin-dir ./.agent-plugins/rarus-echo-transcriptionИли поставить через repo-local marketplace из корня репозитория:
claude plugin marketplace add ./ --scope user
claude plugin install rarus-echo-transcription@rarus-echo-pluginsПосле установки в Claude Code namespaced invocation выглядит так:
/rarus-echo-transcription:transcribe downloads/audio.ogg --language=ru --task-type=diarization --speakers-correction
Repo-local marketplace files:
.claude-plugin/marketplace.json
.agents/plugins/marketplace.json
Codex-compatible hosts читают общий skill из skills/transcribe/SKILL.md; точный синтаксис invocation зависит от host и использует имя skill, например:
codex plugin marketplace add .
codex plugin add rarus-echo-transcription@rarus-echo-plugins$transcribe downloads/audio.ogg --language=ru --task-type=diarization --speakers-correction
CLI reference для skill генерируется из structured metadata текущего CLI и проверяется на drift. Проверка фиксирует только project-owned команды и опции, без framework-provided Symfony options:
.agent-plugins/rarus-echo-transcription/scripts/update-cli-reference.sh
make lint-agent-plugins<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Rarus\Echo\Services\ServiceFactory;
$factory = ServiceFactory::fromEnvironment();
$queue = $factory->getQueueService()->getQueueInfo();
printf(
"В очереди: %d файлов, %d MB, %d минут\n",
$queue->filesCount,
$queue->filesSize,
$queue->filesDuration
);<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Rarus\Echo\Enum\Language;
use Rarus\Echo\Enum\TaskType;
use Rarus\Echo\Services\ServiceFactory;
use Rarus\Echo\Services\Transcription\Request\TranscriptionOptions;
$factory = ServiceFactory::fromEnvironment();
$options = TranscriptionOptions::create()
->withTaskType(TaskType::DIARIZATION)
->withLanguage(Language::RU)
->withSpeakersCorrection()
->withTimestampsExtended()
->build();
$submitResult = $factory->getTranscriptionService()->submit(
files: ['/path/to/audio.ogg'],
transcriptionOptions: $options
);
$fileId = $submitResult->getFileIds()[0];
$status = $factory->getStatusService()->getByFileId($fileId);
printf(
"file_id=%s status=%s\n",
$fileId->toRfc4122(),
$status->transcriptionStatus->value
);<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Rarus\Echo\Core\Pagination;
use Rarus\Echo\Services\ServiceFactory;
use Symfony\Component\Uid\Uuid;
$factory = ServiceFactory::fromEnvironment();
$fileIds = [
Uuid::fromString('11111111-1111-1111-1111-111111111111'),
Uuid::fromString('22222222-2222-2222-2222-222222222222'),
];
$statusList = $factory->getStatusService()->getList(
fileIds: $fileIds,
pagination: new Pagination(page: 1, perPage: 10)
);
foreach ($statusList->getResults() as $status) {
printf(
"file_id=%s status=%s\n",
$status->fileId->toRfc4122(),
$status->transcriptionStatus->value
);
}
printf(
"page=%d per_page=%d total_pages=%d\n",
$statusList->pagination->page,
$statusList->pagination->perPage,
$statusList->pagination->total
);<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use Rarus\Echo\Services\ServiceFactory;
use Symfony\Component\Uid\Uuid;
$factory = ServiceFactory::fromEnvironment();
$fileId = Uuid::fromString('11111111-1111-1111-1111-111111111111');
$transcript = $factory->getTranscriptionService()->getByFileId($fileId);
if ($transcript->isSuccessful()) {
echo $transcript->result ?? '';
}transcription- обычная транскрипцияtimestamps- с метками времениdiarization- с разбиением по говорящимraw_transcription- сырой текст
Для диаризации с расширенными таймкодами используйте task-type=diarization вместе с опцией timestamps-extended=1: в SDK это withTimestampsExtended(), в CLI - --timestamps-extended.
ru, en, de, fr, es, pt, hy, ja, tr, ar, zh, he, vi, auto
waiting- ожидает в очередиprocessing- обрабатываетсяsuccess- завершено успешноfailure- ошибка
- OpenAPI спецификация - официальная API документация
- Docker & Docker Compose
- Make
- Node.js 20.19+ или 24+
- OpenSpec CLI 1.3.1 для OpenSpec workflow:
npm install -g @fission-ai/openspec@1.3.1 openspec --version
make docker-init # Инициализация Docker окружения и установка зависимостей
make docker-up # Запуск контейнеров
make dev-php-bash # Войти в контейнерmake lint-all # Запуск всех линтеров
make lint-openspec # Проверка OpenSpec артефактов
make lint-agent-plugins # Проверка agent plugin и CLI reference
make lint-php # Запуск PHP-линтеров
make lint-cs-fixer-fix # Исправление стиля кода
make lint-phpstan # Статический анализ
make test-unit # Юнит-тесты
make test-integration # Интеграционные тесты
make test-all # Все тесты
make ci # Полный CI pipeline локальноПолный список команд: make help
Integration tests делают реальные API-запросы и загружают короткие аудиофайлы из tests/Assets/ru/. Для локального запуска добавьте credentials в .env.local; файл уже игнорируется Git:
RARUS_ECHO_API_KEY=your-api-key-uuid
RARUS_ECHO_USER_ID=your-user-id-uuid
RARUS_ECHO_BASE_URL=https://production-ai-ui-api.ai.rarus-cloud.ruЕсли credentials не заданы или в .env остались placeholder-значения, integration tests будут пропущены.
make test-integration
make test-integration-core
make test-integration-queue
make test-integration-status
make test-integration-transcriptionПоддержка проекта идет от GitHub issue к Pull Request в ветку dev.
- Откройте или выберите issue и зафиксируйте ожидаемый результат.
- Создайте ветку от
dev:feature/<issue>-<slug>,bugfix/<issue>-<slug>илиdocs/<issue>-<slug>. - Для нетривиальных изменений публичного API, поведения SDK, архитектуры, CI или процесса поддержки создайте OpenSpec change в
openspec/changes/<change-id>/. - Для опечаток, обновлений зависимостей и небольших документационных правок OpenSpec можно не использовать, если отдельная спецификация не добавляет ясности.
- Перед PR запустите локальную проверку и откройте Pull Request в
dev. - Считайте issue завершенным только после зеленого CI в Pull Request.
OpenSpec change обычно содержит:
proposal.md- зачем нужно изменение и что меняется;design.md- технические решения, если они нужны;specs/<capability>/spec.md- требования и сценарии;tasks.md- чеклист реализации.
Основные команды для OpenSpec:
openspec list
openspec list --specs
make lint-openspecOpenSpec CLI генерирует repo-local commands/skills для Claude Code и Codex. После обновления CLI синхронизируйте эти файлы командой:
openspec update --forceПосле merge связанного PR завершенный change архивируется командой:
openspec archive <change-id> --yesДля agent-assisted поддержки используйте repo-local skill. Claude Code и Codex читают один общий русский skill через свои стандартные entrypoint-пути:
- Claude Code:
.claude/skills/rarus-echo-maintainer/SKILL.md - Codex:
.codex/skills/rarus-echo-maintainer/SKILL.md
Мы приветствуем вклад в развитие проекта! Пожалуйста, ознакомьтесь с CONTRIBUTING.md.
- Fork репозитория
- Создайте feature branch от
dev - Внесите изменения
- Запустите тесты и линтеры:
make ci - Создайте Pull Request в
dev
MIT License. См. LICENSE для деталей.
Если у вас возникли вопросы или проблемы, пожалуйста, создайте Issue.