README: локальная программа для Windows — ключ OpenRouter, Whisper и Claude, стиль skillok.org, сохранение в репозиторий
Родитель:
e2fcdc4
· сравнить с родителем
1 файл
-
README.md +158 −155
Показать разницуСкрыть разницу
1 1 # Skillok Meet 2 2 3 −Рабочее название. Продукт Skillok, адрес — `meet.skillok.org`. 3 +Рабочее название. Продукт Skillok. 4 4 5 −Приложение для встреч в Zoom. Само начинает запись, когда начинается конференция, по ходу 6 −ведёт расшифровку, а после встречи собирает конспект, ревью, решения и задачи. 5 +Программа для Windows, которая работает на компьютере пользователя. Сама включает запись, 6 +когда начинается встреча в Zoom, по ходу ведёт расшифровку, а после встречи делает 7 +конспект, ревью, решения и задачи. Итог можно сохранить в свой репозиторий на skillok.org. 7 8 8 −Платформы: **Windows** и **Android**, плюс сервер. 9 +**Нашего сервера нет.** Пользователь вводит свой ключ OpenRouter — и всё. Звук и 10 +расшифровки лежат у него на диске. Наружу уходят только запросы к моделям по его 11 +собственному ключу. 9 12 10 13 --- 11 14 12 15 ## Что делает 13 16 14 −1. **Подключается к Zoom.** Два способа, см. «Интеграция с Zoom»: 15 − - локально на Windows; 16 − - через сервер Zoom (RTMS или облачная запись). 17 −2. **Сам начинает запись**, как только стартует встреча. Кнопку жать не нужно. 18 −3. **Ведёт расшифровку по ходу встречи.** Реплики подписаны именами участников из Zoom. 19 − Живой конспект обновляется раз в несколько минут. 20 −4. **Разбирает встречу после её окончания:** 17 +1. **Замечает, что началась встреча в Zoom, и включает запись.** Кнопку жать не нужно. 18 +2. **Ведёт расшифровку по ходу встречи.** Реплики разделены на «я» (микрофон) и 19 + «собеседники» (звук Zoom). 20 +3. **Каждые несколько минут обновляет живой конспект.** 21 +4. **После встречи делает разбор:** 21 22 - краткое содержание; 22 23 - ревью встречи: чего достигли, что осталось открытым, где ушли в сторону; 23 24 - решения; 24 25 - задачи с исполнителем и сроком, если они прозвучали; 25 26 - вопросы на следующую встречу. 26 − 27 − Задачи можно выгрузить. Выгрузка в трекеры — на следующих этапах. 27 +5. **Сохраняет итог в репозиторий на skillok.org** — одним нажатием или автоматически. 28 28 29 29 --- 30 30 31 −## Интеграция с Zoom: что возможно и где ограничения 32 − 33 −Всё, что сказано ниже про Zoom и платформы, подтверждено документацией. Ссылки — в каждом пункте. 34 − 35 −### Выбранная схема — гибрид 31 +## Как это работает 36 32 37 −| Путь | Стартует сам | В реальном времени | Где работает | Что нужно от пользователя | 38 −|---|---|---|---|---| 39 −| **A. Локальный захват на Windows** (MVP) | да | да | любая встреча, в том числе чужая | ничего от Zoom | 40 −| **B. RTMS** (этап 2) | да | да: звук и транскрипт Zoom | встречи, где хост разрешил наше приложение | авторизация приложения; кредиты Zoom Developer Pack | 41 −| **C. Облачная запись** (запасной путь) | да, через «автозапись» | **нет**: после встречи | встречи наших пользователей-хостов | план Pro или выше, включены облачная запись и транскрипция | 33 +``` 34 + Zoom.exe ──звук──┐ 35 + ├─► захват (WASAPI) ─► куски по ~30 с ─► OpenRouter: Whisper ─► расшифровка 36 + микрофон ────────┘ │ 37 + ▼ 38 + OpenRouter: Claude ◄── конспект / разбор 39 + │ 40 + диск пользователя ◄─────────────────────────┤ 41 + skillok.org (репозиторий) ◄── по желанию ───┘ 42 +``` 42 43 43 −#### A. Локальный захват на Windows 44 +### Захват звука Zoom 44 45 45 −- Звук берём только от процесса Zoom (process loopback) и отдельно с микрофона. 46 +- Звук берём **только от процесса Zoom** (process loopback) и отдельно с микрофона. 46 47 Системные звуки и музыка в запись не попадают. 47 48 См. [Application loopback sample](https://learn.microsoft.com/en-us/samples/microsoft/windows-classic-samples/applicationloopbackaudio-sample/) 48 49 и [ActivateAudioInterfaceAsync](https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/nf-mmdeviceapi-activateaudiointerfaceasync). 49 50 Нужна Windows 10 сборки 20438 или новее. 50 −- Начало встречи определяем по появлению звуковой сессии процесса Zoom и окна встречи. 51 −- API Zoom и одобрение в Marketplace не нужны. 52 −- **Минус:** Zoom участникам ничего не показывает. Предупреждать их обязан пользователь, 53 − см. «Согласие на запись». 54 − 55 −#### Android: локальный захват невозможен 56 − 57 −- Android даёт захватить чужой звук, только если он помечен как `USAGE_MEDIA`, `USAGE_GAME` 58 − или `USAGE_UNKNOWN`. Голос в звонке помечен как голосовая связь и не захватывается 59 − ([AudioPlaybackCaptureConfiguration](https://developer.android.com/reference/android/media/AudioPlaybackCaptureConfiguration)). 60 −- Микрофон тоже не выход: пока идёт голосовая связь (`VOICE_COMMUNICATION`), другие 61 − приложения получают тишину 62 − ([Sharing audio input](https://developer.android.com/media/platform/sharing-audio-input)). 63 −- Поэтому на Android встречи в Zoom записываются **только через сервер**: путь B или C. 64 − Локально на Android — только очные встречи через микрофон. 65 − 66 −#### B. RTMS (Realtime Media Streams) 67 − 68 −- Даёт живой звук по дорожкам, видео и транскрипт с разметкой: кто, что и когда сказал 69 − ([обзор RTMS](https://developers.zoom.us/docs/rtms/meetings/)). 70 −- Поток стартует тремя способами: автоматически, когда пользователь входит на встречу 71 − или запускает её; вызовом REST API; из Zoom App 72 − ([Getting started](https://developers.zoom.us/docs/rtms/meetings/getting-started/)). 73 −- Нужны кредиты Zoom Developer Pack. На форуме Zoom называют $0,01 за минуту потока 74 − без транскрипта ([devforum](https://devforum.zoom.us/t/rtms-developer-pack-pricing-for-business-account/144203)). 75 − Точную цену сверить в продаже Zoom. 76 −- Участники видят значок Active Apps Notifier: какое приложение и к чему получает доступ 77 − ([Zoom Library](https://library.zoom.com/zoom-workplace/zoom-meetings/securing-zoom-meetings-explainer/zoom-realtime-media-streams)). 78 −- Устройство участника неважно: поток идёт с сервера Zoom на наш. Поэтому путь B 79 − закрывает Android. 80 −- SDK: [zoom/rtms](https://github.com/zoom/rtms). 81 − 82 −#### C. Облачная запись и вебхуки 83 − 84 −- Автозапись в облако включается в настройках 85 − ([KB0067954](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0067954)). 86 −- Транскрипт: план Pro, Business, Education или Enterprise, и в настройках включён 87 − «Create audio transcript» 88 − ([KB0065911](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0065911)). 89 −- О готовности сообщают вебхуки `recording.completed` и `recording.transcript_completed`. 90 − Файл транскрипта имеет `file_type: TRANSCRIPT`, нужен scope `recording:read` 91 − ([Cloud recording](https://developers.zoom.us/docs/build/cloud-recording/)). 51 +- Начало встречи определяем по появлению звуковой сессии `Zoom.exe` и окна встречи. 52 + Конец — по их исчезновению. 53 +- API Zoom, аккаунт разработчика и одобрение в Marketplace **не нужны**. Работает на любой 54 + встрече и на любом плане Zoom, в том числе бесплатном и на чужой встрече. 55 + 56 +### Расшифровка — Whisper через OpenRouter 57 + 58 +- Эндпоинт `POST https://openrouter.ai/api/v1/audio/transcriptions`, тот же ключ, что для 59 + текстовых моделей. Модели: `openai/whisper-large-v3-turbo` (по умолчанию), 60 + `openai/whisper-large-v3`, `openai/whisper-1`. 61 + См. [документацию OpenRouter STT](https://openrouter.ai/docs/guides/overview/multimodal/stt). 62 +- Эндпоинт принимает файл целиком, потокового режима нет. Поэтому звук режем на куски 63 + по ~30 секунд по паузам в речи. Расшифровка отстаёт от живой речи на длину куска 64 + плюс время ответа. 65 +- Дорожки «я» и «собеседники» распознаём раздельно. Так реплики подписаны без узнавания 66 + людей по голосу. 67 + 68 +### Разбор — Claude через OpenRouter 69 + 70 +| Задача | Модель по умолчанию | Когда | 71 +|---|---|---| 72 +| Живой конспект | Claude Haiku 4.5 | каждые несколько минут | 73 +| Итоговый разбор: ревью, решения, задачи | Claude Opus 5.5 | после встречи | 92 74 93 −#### Почему не бот на Meeting SDK 75 +- Модели можно поменять в настройках на любую из доступных в OpenRouter. 76 +- Разбор приходит JSON строго по схеме: `summary`, `review`, `decisions[]`, 77 + `tasks[]` (текст, исполнитель, срок, цитата-основание), `open_questions[]`. 78 + Из JSON программа собирает Markdown. 79 +- У каждой задачи есть ссылка на момент расшифровки, где она прозвучала. 94 80 95 −- С 2 марта 2026 на встречах чужих аккаунтов нужен токен OBF. Бот не войдёт, пока на встрече 96 − нет авторизовавшего его пользователя, и выйдет вместе с ним. Для непрерывной записи 97 − Zoom сам советует RTMS 98 − ([OBF FAQ](https://developers.zoom.us/docs/meeting-sdk/obf-faq/)). 99 −- Чтобы получать звук, боту нужно разрешение хоста на запись. Для внешних пользователей — 100 − ещё и ревью в Marketplace. Выходит самый тяжёлый путь при тех же возможностях, что у RTMS. 81 +### Сохранение в репозиторий Skillok 101 82 102 −--- 83 +- Пользователь создаёт токен доступа на skillok.org (Settings → Access tokens) 84 + и выбирает репозиторий. 85 +- Программа кладёт файлы через API Skillok: 86 + - `POST /api/v1/repositories/{id}/files` — создать файл; 87 + - `PUT /api/v1/repositories/{id}/files/{path}` — обновить файл; 88 + - заголовок `Authorization: Bearer <токен>`. 89 +- Раскладка в репозитории: 103 90 104 −## Согласие на запись 91 + ``` 92 + meetings/2026-10-01-планёрка/ 93 + summary.md — конспект, ревью, решения, задачи 94 + transcript.md — расшифровка с временем 95 + ``` 105 96 106 −- **РФ, 152-ФЗ.** Голос — персональные данные, тайная запись запрещена. Если голос 107 − используется для узнавания человека, это биометрия, и нужно письменное согласие 108 − ([Консультант](https://www.consultant.ru/law/podborki/zapis_telefonnogo_razgovora_personalnye_dannye/)). 109 − Поэтому разметку «кто говорит» берём **только из имён Zoom**, отпечатки голоса не строим. 110 −- **ЕС (GDPR)** требует законного основания и уведомления. В ряде штатов США нужно 111 − согласие всех сторон. 112 −- **Что для этого делает продукт:** 113 − - перед записью показывает пользователю готовый текст объявления для участников; 114 − - в режиме A запись не стартует без отметки «участники предупреждены», 115 − отметку можно поставить заранее; 116 − - сохраняет, когда и кем было дано уведомление; 117 − - звук по умолчанию удаляется после расшифровки. 97 +- Звук в репозиторий не уходит. 118 98 119 99 --- 120 100 121 −## Расшифровка и разбор 101 +## Интерфейс — как у skillok.org 122 102 123 −**Распознавание речи** 103 +Та же система, что на skillok.org: 124 104 125 −- По умолчанию — Whisper large-v3 на своём сервере: хорошо знает русский, звук не уходит 126 − третьим лицам. 127 −- Для хранения данных в РФ — Yandex SpeechKit как запасной провайдер. 128 −- В режиме B можно взять транскрипт Zoom вместо своего распознавания. 105 +- бумажный фон, чернильный текст, терракотовый акцент; 106 +- шрифт iA Writer Quattro S, JetBrains Mono только для кода и времени в расшифровке; 107 +- кегль только из шкалы, не меньше 12px; 108 +- квадратные углы; 109 +- кнопки контурные, без заливки. 129 110 130 −**Разбор на Claude** (Anthropic API) 111 +Токены стиля берём из дизайн-системы Skillok, новых цветов не заводим. 131 112 132 −| Задача | Модель | Цена, вход / выход за 1M токенов | 133 −|---|---|---| 134 −| Живой конспект раз в несколько минут | `claude-haiku-4-5` | $1 / $5 | 135 −| Итоговое ревью, решения, задачи | `claude-opus-5-5` | $4 / $20 | 113 +**Экраны:** 136 114 137 −- Часовая встреча — это примерно 25 тыс. токенов, то есть порядка $0,15 на итоговый разбор. 138 −- Результат — JSON строго по схеме (structured outputs): `summary`, `review`, `decisions[]`, 139 − `tasks[]` (текст, исполнитель, срок, цитата-основание), `open_questions[]`. 140 −- У каждой задачи есть ссылка на момент расшифровки, где она прозвучала. 115 +- **Встречи** — список: дата, длительность, статус разбора. 116 +- **Встреча** — вкладки «Расшифровка», «Конспект», «Задачи», кнопка «Сохранить в Skillok». 117 +- **Идёт запись** — маленькое окно или значок в трее: время, уровень звука, стоп и пауза. 118 +- **Настройки:** 119 + - ключ OpenRouter; 120 + - модели; 121 + - папка хранения; 122 + - токен Skillok и репозиторий; 123 + - автосохранение; 124 + - текст предупреждения участникам. 141 125 142 126 --- 143 127 144 −## Архитектура 128 +## Стек 145 129 146 −``` 147 − Windows (Flutter + C++/WASAPI) ──┐ 148 − ├──► Сервер (Rust) ──► распознавание (Whisper) ──► Claude 149 − Android (Flutter + Kotlin) ──────┘ ▲ 150 − │ вебхуки, RTMS 151 − Zoom 152 −``` 130 +**Tauri 2**: ядро на Rust, интерфейс на HTML/CSS/TS. 153 131 154 −**Клиент — один код на Flutter для Windows и Android.** 132 +- Интерфейс в HTML/CSS — поэтому стиль skillok.org переносится один в один. 133 +- Ядро на Rust: 134 + - захват звука через крейт `windows` (WASAPI, process loopback); 135 + - разбивка звука на куски по паузам в речи; 136 + - запросы к OpenRouter и Skillok. 137 +- Небольшой установщик, есть автообновление. 138 +- Tauri 2 умеет Android — пригодится, если вернёмся к нему. 155 139 156 −- Захват звука в любом случае пишется нативно: на Windows — C++ (WASAPI), на Android — 157 − Kotlin (микрофон для очных встреч). Flutter даёт общий интерфейс поверх этого. 158 −- .NET MAUI на Windows слабее, у Kotlin Multiplatform интерфейс под Windows ещё сырой. 140 +**Хранение** 159 141 160 −**Сервер (Rust)** 142 +- Каждая встреча — отдельная папка: расшифровка, разбор и звук. 143 +- Звук по умолчанию удаляется после разбора. 144 +- Ключи лежат в Windows Credential Manager, не в файлах. 161 145 162 −- Приём звука от клиентов и живая расшифровка. 163 −- Вебхуки Zoom, OAuth-приложение Zoom, приём RTMS. Для RTMS на старте можно поставить 164 − рядом сервис на официальном SDK Node.js. 165 −- Распознавание речи, вызовы Claude, хранение встреч. 166 −- Вход через аккаунт Skillok. 146 +--- 167 147 168 −**Хранение** 148 +## Согласие на запись 149 + 150 +Zoom **не показывает** участникам, что идёт такая запись. Предупреждать их обязан 151 +пользователь. 169 152 170 −- Расшифровки и разборы — в Postgres. 171 −- Звук удаляется после расшифровки. Хранить его можно только с явного включения. 153 +- **РФ, 152-ФЗ.** Голос — персональные данные, тайная запись запрещена. Если голос 154 + используется для узнавания человека, это биометрия, и нужно письменное согласие 155 + ([Консультант](https://www.consultant.ru/law/podborki/zapis_telefonnogo_razgovora_personalnye_dannye/)). 156 + Поэтому отпечатки голоса мы не строим. 157 +- **ЕС (GDPR)** требует уведомления. В ряде штатов США нужно согласие всех сторон. 158 +- **Что делает программа:** 159 + - при старте записи показывает текст предупреждения, который можно скопировать 160 + в чат Zoom; 161 + - запись идёт только после отметки «участники предупреждены»; можно поставить 162 + «предупреждаю всегда сам». 172 163 173 164 --- 174 165 175 −## План работ 166 +## Почему не через API Zoom 176 167 177 −### Этап 0. Каркас 168 +Проверено и отложено: 169 + 170 +- **RTMS** (живой поток от Zoom): нужен сервер, который принимает поток, и кредиты 171 + Zoom Developer Pack ([RTMS](https://developers.zoom.us/docs/rtms/meetings/getting-started/)). 172 +- **Облачная запись**: план Pro или выше, только встречи, где пользователь хост, 173 + расшифровка — после встречи 174 + ([KB0065911](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0065911)). 175 +- **Бот на Meeting SDK**: с 2 марта 2026 на встречах чужих аккаунтов нужен токен OBF, 176 + плюс ревью в Marketplace ([OBF FAQ](https://developers.zoom.us/docs/meeting-sdk/obf-faq/)). 178 177 179 −- [ ] Монорепозиторий: `app/` (Flutter), `server/` (Rust), `docs/`. 180 −- [ ] Вход через аккаунт Skillok, список встреч. 181 −- [ ] Схема разбора (JSON) и промпты с набором проверочных расшифровок. 178 +## Android — позже 182 179 183 −### Этап 1. MVP — Windows, локальный захват 180 +Звук Zoom на Android локально не захватить. Системный захват не берёт голосовую связь 181 +([AudioPlaybackCaptureConfiguration](https://developer.android.com/reference/android/media/AudioPlaybackCaptureConfiguration)), 182 +а микрофон во время звонка отдаёт другим приложениям тишину 183 +([Sharing audio input](https://developer.android.com/media/platform/sharing-audio-input)). 184 184 185 −- [ ] Нативный модуль захвата: звук процесса Zoom и микрофон, две дорожки. 186 −- [ ] Автостарт при начале встречи и остановка в конце. Иконка в трее. 187 −- [ ] Экран согласия и текст объявления для участников. 188 −- [ ] Потоковая отправка на сервер, живая расшифровка в окне. 189 −- [ ] Живой конспект (Haiku) и итоговый разбор (Opus): ревью, решения, задачи. 190 −- [ ] Android: просмотр встреч и разборов, запись очной встречи с микрофона. 185 +Возможные пути на будущее: 191 186 192 −### Этап 2. RTMS — запись без десктопа, в том числе с Android 187 +- очные встречи через микрофон; 188 +- облачная запись Zoom после встречи; 189 +- импорт файла. 193 190 194 −- [ ] Приложение Zoom (OAuth), подписка на `meeting.rtms_started` и `meeting.rtms_stopped`. 195 −- [ ] Приём потока и транскрипта Zoom, та же цепочка разбора. 196 −- [ ] Автостарт для встреч, где хост — наш пользователь. 197 −- [ ] Учёт минут и расходов Developer Pack. 191 +--- 198 192 199 −### Этап 3. Облачная запись как запасной путь 193 +## План работ 200 194 201 −- [ ] Вебхуки `recording.completed` и `recording.transcript_completed`. 202 −- [ ] Разбор после встречи для тех, у кого нет RTMS. 195 +### Этап 0. Каркас 203 196 204 −### Дальше 197 +- [ ] Проект Tauri 2, стиль skillok.org, экраны «Встречи», «Встреча», «Настройки». 198 +- [ ] Ключ OpenRouter в Credential Manager, проверка ключа. 199 +- [ ] Схема разбора (JSON), промпты, набор проверочных расшифровок. 205 200 206 −- [ ] Выгрузка задач: трекер задач Skillok, календарь, почта. 207 −- [ ] Поиск по всем встречам и вопросы к архиву. 208 −- [ ] Шаблоны разбора: планёрка, собеседование, встреча с клиентом. 209 −- [ ] Ревью Zoom Marketplace — для пользователей из других аккаунтов Zoom. 201 +### Этап 1. MVP 210 202 211 −--- 203 +- [ ] Захват звука `Zoom.exe` и микрофона на две дорожки. 204 +- [ ] Автостарт и автостоп по встрече в Zoom, значок в трее. 205 +- [ ] Предупреждение участникам и отметка «предупреждены». 206 +- [ ] Куски по паузам → Whisper через OpenRouter → живая расшифровка. 207 +- [ ] Живой конспект и итоговый разбор через Claude. 208 +- [ ] Сохранение встречи на диск, экспорт в Markdown. 209 + 210 +### Этап 2. Skillok 212 211 213 −## Что должен сделать владелец 212 +- [ ] Токен Skillok, выбор репозитория. 213 +- [ ] Сохранение `summary.md` и `transcript.md` через API файлов, автосохранение. 214 +- [ ] Задачи из разбора — в трекер задач репозитория. 214 215 215 −- Создать приложение в Zoom App Marketplace (General App) и выдать ключи. 216 −- Решить вопрос с кредитами Developer Pack для RTMS. 217 −- Выдать ключ Anthropic API. 218 −- Утвердить название и настроить адрес `meet.skillok.org`. 216 +### Дальше 217 + 218 +- [ ] Поиск по встречам и вопросы к архиву. 219 +- [ ] Шаблоны разбора: планёрка, собеседование, встреча с клиентом. 220 +- [ ] Другие программы для встреч (Teams, Meet в браузере) — тот же захват по процессу. 221 +- [ ] Android.