7bc34c79ed
- 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.
118 lines
5.1 KiB
Markdown
118 lines
5.1 KiB
Markdown
# 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}` | تأیید دریافت |
|