Files
audio-voice-converter/meet-transcripts/README.md
T
vahidaskari 7bc34c79ed Refactor Google Meet Transcripts Extension for Local Use
- Removed all cloud-related functionalities, including login prompts and token handling.
- Disabled Laxis cloud features, ensuring no data is sent to external servers.
- Updated manifest to reflect the new local-only functionality.
- Added a new Python server to handle transcripts locally, including WebSocket support.
- Implemented storage management for transcripts, including deduplication and file writing.
- Created a smoke test for the WebSocket server to simulate transcript updates.
- Updated README with setup instructions and usage details for the new local server.
2026-06-12 00:31:32 +03:30

118 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# meet-transcripts — سرور MCP زیرنویس Google Meet
سرور پایتونی که caption های Google Meet را از افزونه‌ی Chrome می‌گیرد و آن‌ها را به‌صورت
transcript تمیز و **SRT** به Claude (از طریق MCP) می‌دهد. در یک پراسس دو کار می‌کند:
```
Google Meet (content script)
│ chrome.runtime.sendMessage({type:"TRANSCRIPT_UPDATE", …})
افزونه: service worker (bridge.js)
│ WebSocket ws://127.0.0.1:8765
ws_server.py ──▶ storage.py ──▶ transcripts/<sid>.{srt,txt,json}
mcp_server.py (MCP stdio) ─────────┘ ──▶ Claude Desktop
```
## ساختار
| فایل | کار |
|------|-----|
| `storage.py` | مدل داده، dedup (بر اساس `startedAt`)، رندر SRT/TXT، خواندن/نوشتن دیسک |
| `ws_server.py` | سرور WebSocket؛ caption را از افزونه می‌گیرد و به storage می‌دهد |
| `mcp_server.py` | **نقطه‌ی ورود**؛ WebSocket + MCP را با هم اجرا می‌کند |
| `_smoke_test.py` | تست بدون Chrome |
## اجرا (با venv)
```powershell
cd meet-transcripts
py -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
```
```powershell
python mcp_server.py # WebSocket + MCP (حالت عادی / برای Claude Desktop)
python mcp_server.py --ws-only # فقط WebSocket
python ws_server.py # فقط WebSocket (معادلِ بالا، برای تست دستی)
```
> همه‌ی لاگ‌ها روی **stderr** اند چون stdout برای پروتکل MCP (JSON-RPC) رزرو است.
> برای تستِ دستیِ WebSocket از `ws_server.py` یا `--ws-only` استفاده کن (وگرنه پراسس
> منتظر اتصال MCP روی stdin می‌ماند).
## تست بدون Chrome
```powershell
# ترمینال ۱:
python ws_server.py
# ترمینال ۲:
python _smoke_test.py
```
باید `PONG` + چند `ACK` بگیری و `transcripts/meeting-abc123.{srt,txt,json}` ساخته شود.
## اتصال به Claude Desktop (MCP)
به `claude_desktop_config.json` اضافه کن (مسیر را با مسیر واقعی عوض کن):
```jsonc
{
"mcpServers": {
"meet-transcripts": {
"command": "C:\\...\\audio-voice-converter\\meet-transcripts\\.venv\\Scripts\\python.exe",
"args": ["C:\\...\\audio-voice-converter\\meet-transcripts\\mcp_server.py"]
}
}
}
```
Claude Desktop خودش `mcp_server.py` را اجرا می‌کند؛ همان پراسس WebSocket را هم بالا می‌آورد.
اگر یک نمونه‌ی دیگر از قبل پورت ۸۷۶۵ را گرفته باشد، این نمونه فقط MCP را سرو می‌کند و
transcript ها را از روی دیسک می‌خواند (مشکلی پیش نمی‌آید).
### ابزارها / resourceها
| ابزار | کار |
|-------|-----|
| `list_sessions` | فهرست جلسه‌ها + تعداد segment + آخرین خط |
| `get_status(session_id?)` | **چک سبکِ تغییر** بدون متن: `latest_seq`, `count`, `updated_at` |
| `get_updates(session_id?, after_seq)` | **خواندن افزایشی**: فقط segmentهای بعد از `after_seq` |
| `get_latest_transcript()` | متن تمیزِ آخرین جلسه (با `[mm:ss]`) |
| `get_transcript(session_id)` | متن تمیزِ یک جلسه |
| `get_latest_srt()` / `get_srt(session_id)` | زیرنویس SRT |
| `transcript://{id}` , `srt://{id}` | resourceها |
### خواندن افزایشی (به‌جای خواندن کل transcript هر بار)
هر segment یک `seq` یکتا دارد. برای دنبال‌کردن یک جلسه‌ی زنده بدون خواندن دوباره‌ی همه‌چیز:
۱. `get_status` بزن (خیلی ارزان، بدون متن). اگر `latest_seq`/`updated_at` عوض شد →
۲. `get_updates(after_seq=<latest_seqِ قبلی>)` تا فقط موارد جدید + segmentِ در‌حالِ‌تکمیل را بگیری.
## dedup و SRT — چه‌طور کار می‌کند
افزونه برای هر «حرف» چند بار پیام می‌فرستد (snapshotِ روبه‌رشد) ولی `startedAt` ثابت می‌ماند.
سرور با همین `startedAt` می‌فهمد این‌ها یک segment‌اند و فقط کامل‌ترین نسخه را نگه می‌دارد —
پس متن تکراری ذخیره نمی‌شود. چون زمان شروع/پایان داریم، برای هر segment یک بلوک SRT با
تایم‌کد ساخته می‌شود. برای هر جلسه: `.srt` (زیرنویس)، `.txt` (متن خوانا با `[mm:ss]`
`.json` (داده‌ی خام برای resume).
## پروتکل پیام‌ها
افزونه → سرور:
| پیام | توضیح |
|------|-------|
| `{type:"PING", ts}` | heartbeat هر ۲۰ ثانیه |
| `{type:"TRANSCRIPT_UPDATE", sessionId, speaker, text, startedAt, endedAt}` | یک caption |
سرور → افزونه:
| پیام | توضیح |
|------|-------|
| `{type:"PONG", ts}` | پاسخ heartbeat |
| `{type:"ACK", ok:true}` | تأیید دریافت |