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.
This commit is contained in:
vahidaskari
2026-06-12 00:31:32 +03:30
parent 602dcb7430
commit 7bc34c79ed
35 changed files with 1069 additions and 840 deletions
+117
View File
@@ -0,0 +1,117 @@
# 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}` | تأیید دریافت |