Files
cc-1c-skills/docs/web-test-recording-guide.md
Nick Shirokov 6f36e36166 feat(web-test): per-caption voice + speechRate for multi-voice narration
- addNarration: use cap.voice override per caption (fallback to global)
- showCaption/showImage/showTitleSlide: pass opts.voice to caption entry
- showCaption: record caption when text is empty but speech is explicit
- startRecording: add speechRate option (default 70ms/char, 85 for ElevenLabs)
- run.mjs: increase exec timeout to 30min for long recordings
- docs: update recording.md and web-test-recording-guide.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:30:02 +03:00

18 KiB
Raw Permalink Blame History

Запись видеоинструкций

Навык /web-test умеет записывать видеоинструкции по работе в 1С: автоматические действия в браузере записываются в MP4 с субтитрами, подсветкой элементов и голосовой озвучкой. Результат — готовое обучающее видео.

сценарий → запись экрана → субтитры → подсветка → озвучка голосом → MP4

Предусловия

Все пути и настройки хранятся в .v8-project.json — см. справочник формата.

ffmpeg (обязательно)

Выберите один из вариантов:

  1. В проект (рекомендуется) — скачать essentials build с https://www.gyan.dev/ffmpeg/builds/, распаковать в tools/ffmpeg/. Код найдёт tools/ffmpeg/bin/ffmpeg.exe автоматически

  2. Глобально — скачать, распаковать в любой каталог, добавить bin/ в системный PATH

  3. Через конфиг — указать путь в .v8-project.json:

    { "ffmpegPath": "C:\\tools\\ffmpeg\\bin\\ffmpeg.exe" }
    

node-edge-tts (для озвучки)

npm install --prefix tools/tts node-edge-tts

Бесплатный, без API-ключа. Если не установлен — запись видео работает, только озвучка недоступна.

Конфигурация голоса в .v8-project.json

{
  "ffmpegPath": "tools/ffmpeg/bin/ffmpeg.exe",
  "tts": {
    "provider": "edge",
    "voice": "ru-RU-DmitryNeural"
  }
}

Быстрый старт

Минимальный сценарий — запись 3 шагов с озвучкой:

// Начинаем запись
await startRecording('recordings/demo.mp4');

// Субтитры + действия
await showCaption('Переходим в раздел «Продажи»');
await wait(1.5);
await navigateSection('Продажи');

await showCaption('Открываем заказы клиентов');
await wait(1.5);
await openCommand('Заказы клиентов');

await showCaption('Создаём новый заказ');
await wait(1.5);
await clickElement('Создать');
await wait(2);

// Завершаем запись
await hideCaption();
const video = await stopRecording();
console.log(`Записано: ${video.duration.toFixed(1)}s`);

// Озвучка
const narrated = await addNarration(video.file, {
  ffmpegPath: 'tools/ffmpeg/bin/ffmpeg.exe',
  voice: 'ru-RU-DmitryNeural',
});
console.log(`Озвучено: ${narrated.file}`);

Результат: recordings/demo-narrated.mp4 — видео с голосовым сопровождением.

Сценарии использования

Запись без озвучки

Простейший вариант — субтитры на экране, без голоса:

> Запиши видеоинструкцию: открой раздел Продажи, создай заказ клиента,
> заполни организацию и контрагента. Без озвучки

Claude запишет видео с субтитрами и подсветкой элементов.

Запись с озвучкой

Полный pipeline — голос озвучивает каждый шаг:

> Запиши озвученную видеоинструкцию по созданию заказа клиента.
> Голос — Светлана

Claude запишет видео, затем наложит голосовую дорожку. Субтитры показываются на экране, параллельно звучит голос.

Переозвучка другим голосом

Видео уже записано — хотите другой голос? Не нужно перезаписывать:

> Переозвучь recordings/demo.mp4 голосом Светланы

Claude вызовет addNarration с другим голосом. Тексты берутся из файла .captions.json, который сохраняется рядом с видео при записи.

Редактирование субтитров

После записи рядом с видео появляется файл video.captions.json:

{
  "videoTimestamps": true,
  "captions": [
    { "text": "Переходим в раздел «Продажи»", "speech": "Переходим в раздел Продажи", "time": 3160 },
    { "text": "Открываем заказы клиентов", "speech": "Открываем заказы клиентов", "time": 7040, "voice": "bqbHGIIO5oETYIqhWmfk" }
  ]
}

Можно отредактировать speech (текст озвучки) или добавить voice (голос для конкретной реплики) и переозвучить:

> Отредактируй субтитры в recordings/demo.captions.json — замени "Продажи" на
> "раздел Продажи", потом переозвучь

Приёмы

Титульный слайд

Полноэкранная заставка в начале видео. Поддерживает озвучку через speech:

await startRecording('recordings/demo.mp4');
await showTitleSlide('Создание заказа клиента', {
  subtitle: '1С:Бухгалтерия в примерах',
  speech: 'Создание заказа клиента. Бухгалтерия в примерах.'
});
await wait(1);
await hideTitleSlide();
// ... далее контент

Слайды из презентации

Показать изображение (скриншот слайда, схему и т.д.) как полноэкранный оверлей с озвучкой:

await showImage('slides/overview.png', {
  speech: 'На этом слайде показана общая схема процесса'
});
await wait(1);
await hideImage();

Стили оформления (style):

  • 'blur' (по умолчанию) — размытый фон из картинки + тень. Лучший для презентаций
  • 'dark' — тёмный фон + тень
  • 'light' — белый фон + тень
  • 'full' — на весь экран без отступов
await showImage('slides/diagram.png', { style: 'dark', speech: 'Диаграмма процесса' });

Подсветка элементов

Полупрозрачная рамка на элементе, который сейчас используется. Два режима:

  • АвторежимsetHighlight(true) перед началом действий. Каждая функция (navigateSection, clickElement, fillFields и т.д.) автоматически подсвечивает элемент перед действием
  • Ручнаяhighlight('Провести') для произвольной подсветки конкретного элемента
setHighlight(true);   // включить авто
// ... все действия подсвечиваются автоматически
setHighlight(false);  // выключить перед stopRecording

Паузы и ритм

Ритм «субтитр → пауза → действие» даёт зрителю время прочитать, что произойдёт:

await showCaption('Проводим документ');   // зритель читает
await wait(1.5);                           // пауза 1.5 сек
await clickElement('Провести');            // действие

Пауза после действия нужна только когда загружается следующая форма:

await clickElement('Создать');
await wait(2);   // форма загружается

Два голоса (подкаст / диалог)

Параметр voice в showCaption задаёт голос для конкретной реплики. addNarration автоматически использует его вместо глобального:

const MALE   = 'bqbHGIIO5oETYIqhWmfk'; // Alexander
const FEMALE = '0ArNnoIAWKlT4WweaVMY'; // Elena Gromova

// speechRate: 85 — ElevenLabs медленнее Edge TTS, нужен запас
await startRecording('podcast.mp4', { speechRate: 85 });

await showImage('slides/slide-01.png', { style: 'full', speech: false });
await showCaption('', { speech: 'Привет! Сегодня поговорим...', voice: MALE });
await wait(0.8);
await showCaption('', { speech: 'А я буду задавать вопросы...', voice: FEMALE });
await wait(0.8);

const video = await stopRecording();
const result = await addNarration(video.file, {
  provider: 'elevenlabs',
  apiKey: 'sk_...',
  // глобальный voice не нужен — каждый caption несёт свой
});

Приёмы:

  • showCaption('', { speech, voice }) — пустой текст (без субтитра на экране), но speech записывается для озвучки
  • showImage со speech: false — слайд без озвучки, реплики идут через showCaption
  • speechRate: 85 — для ElevenLabs увеличиваем множитель (по умолчанию 70мс/символ), чтобы фразы не наезжали друг на друга

Разделение текста и озвучки

Параметр speech в showCaption позволяет показывать одно, а озвучивать другое:

// Субтитр технический, озвучка человечная
await showCaption('Дт 60.02 — Кт 51', {
  speech: 'Дебет шестьдесят ноль два — кредит пятьдесят один'
});

// Показать субтитр, но НЕ озвучивать
await showCaption('Технические детали', { speech: false });

Это полезно для:

  • Бухгалтерских проводок — на экране формула, голосом — словами
  • Технических данных — показать, но не зачитывать
  • Информационных плашек — немой субтитр на несколько секунд

Доступные голоса и провайдеры

Какой провайдер выбрать?

Провайдер Тембр Произношение русского Цена
Edge TTS Синтетичнее Корректные ударения, правильная артикуляция Бесплатно
ElevenLabs Живее, естественнее Возможны ошибки в ударениях и артикуляции (напр. «докумЭнт», «крЕдит» вместо «кредИт») Платно (starter+)
OpenAI Зависит от голоса Зависит от сервиса Платно

Для русскоязычных видеоинструкций рекомендуется Edge TTS — он бесплатный и даёт надёжное качество русской речи. Голоса DmitryNeural и SvetlanaNeural специально обучены для русского языка: правильно расставляют ударения, корректно артикулируют и делают паузы в нужных местах.

ElevenLabs даёт более живой, «человечный» тембр — голос звучит менее синтетически. Однако мультиязычная модель иногда ошибается в произношении русских слов (особенно профессиональная терминология). Если выбираете ElevenLabs для русского контента — берите professional-голоса с образовательным или деловым профилем (например, Olga Orlova, Artem), они дают лучший результат, чем англоязычные premade-голоса через мультиязычную модель. Управлять ударениями через API нельзя — фонемные теги (SSML) поддерживаются только для английских моделей.

Edge TTS (бесплатный) — рекомендуется для русского

Голос Описание
ru-RU-DmitryNeural Мужской, русский — спокойный, деловой
ru-RU-SvetlanaNeural Женский, русский — чёткий, уверенный

Полный список: en-US-AriaNeural, en-US-GuyNeural, de-DE-ConradNeural и другие. Edge TTS поддерживает десятки языков.

Конфигурация не нужна — Edge TTS используется по умолчанию. Для смены голоса:

{
  "tts": {
    "voice": "ru-RU-SvetlanaNeural"
  }
}

ElevenLabs (платный) — живой тембр

Модель eleven_multilingual_v2 поддерживает русский. Тембр заметно живее, чем у Edge TTS, но возможны артикуляционные ошибки на русской терминологии.

Для русского контента выбирайте professional-голоса с образовательным/деловым профилем из Voice Library:

Голос ID Профиль
Olga Orlova d60rsXo2p0OwikDR5bS7 Clear and Engaging
Artem WTn2eCRCpoFAC50VD351 Friendly & Professional
Denis 0BcDz9UPwL3MpsnTeUlO Pleasant, Engaging and Friendly
Alexander bqbHGIIO5oETYIqhWmfk Pleasant, Warm and Natural
Elena Gromova 0ArNnoIAWKlT4WweaVMY Podcasts & Conversation
Victor 9fjVd0EYNNXHllJquVdT Moscow accent
{
  "tts": {
    "provider": "elevenlabs",
    "apiKey": "sk_...",
    "voice": "d60rsXo2p0OwikDR5bS7"
  }
}

voice — ID голоса (не имя). Professional-голоса добавляются в аккаунт через Voice Library в личном кабинете. Требуется платный тариф (starter и выше).

Особенности: лимит на параллельные запросы (2–3 одновременно), система автоматически ограничивает размер пакета.

OpenAI-compatible (платный)

{
  "tts": {
    "provider": "openai",
    "apiKey": "sk-...",
    "voice": "alloy"
  }
}

Голоса: alloy, echo, fable, onyx, nova, shimmer.

Поле apiUrl позволяет подключить любой OpenAI-совместимый сервис (например, локальный TTS-прокси).

Полный пример

Типовая структура озвученного сценария:

await startRecording('output.mp4');

// Титульный слайд с озвучкой
await showTitleSlide('Заголовок', {
  subtitle: 'Подзаголовок',
  speech: 'Заголовок. Подзаголовок.'
});
await wait(1);
await hideTitleSlide();

// Слайд из презентации (опционально)
await showImage('slides/overview.png', {
  speech: 'Описание слайда для озвучки'
});
await wait(1);
await hideImage();

setHighlight(true);

// ... шаги с showCaption + действия ...

await hideCaption();
setHighlight(false);
const video = await stopRecording();

const narrated = await addNarration(video.file, {
  ffmpegPath: 'tools/ffmpeg/bin/ffmpeg.exe',
  voice: 'ru-RU-SvetlanaNeural',
});

Типичные проблемы

Проблема Решение
ffmpeg not found Установите ffmpeg (см. Предусловия)
Файл записи 0 байт Проверьте права на запись в выходной каталог
Видео дёргается Добавьте wait() между шагами
Already recording Вызовите stopRecording() перед новой записью
No captions available Используйте showCaption() во время записи
TTS timeout Проверьте интернет-соединение (Edge TTS требует сеть)
Озвучка обрезается Увеличьте паузы wait() между субтитрами
Фразы наезжают друг на друга Увеличьте speechRate в startRecording (85 для ElevenLabs)

Связанные навыки