feat: Meeting Assistant MVP - Complete implementation

Enterprise Meeting Knowledge Management System with:

Backend (FastAPI):
- Authentication proxy with JWT (pj-auth-api integration)
- MySQL database with 4 tables (users, meetings, conclusions, actions)
- Meeting CRUD with system code generation (C-YYYYMMDD-XX, A-YYYYMMDD-XX)
- Dify LLM integration for AI summarization
- Excel export with openpyxl
- 20 unit tests (all passing)

Client (Electron):
- Login page with company auth
- Meeting list with create/delete
- Meeting detail with real-time transcription
- Editable transcript textarea (single block, easy editing)
- AI summarization with conclusions/action items
- 5-second segment recording (efficient for long meetings)

Sidecar (Python):
- faster-whisper medium model with int8 quantization
- ONNX Runtime VAD (lightweight, ~20MB vs PyTorch ~2GB)
- Chinese punctuation processing
- OpenCC for Traditional Chinese conversion
- Anti-hallucination parameters
- Auto-cleanup of temp audio files

OpenSpec:
- add-meeting-assistant-mvp (47 tasks, archived)
- add-realtime-transcription (29 tasks, archived)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-10 20:17:44 +08:00
commit 8b6184ecc5
65 changed files with 10510 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
# frontend-transcript Specification
## Purpose
TBD - created by archiving change add-realtime-transcription. Update Purpose after archive.
## Requirements
### Requirement: Editable Transcript Segments
The frontend SHALL display transcribed text as individually editable segments that can be modified without disrupting ongoing transcription.
#### Scenario: Display new segment
- **WHEN** a new transcription segment is received from sidecar
- **THEN** a new editable text block SHALL appear in the transcript area
- **AND** the block SHALL be visually distinct (e.g., border, background)
- **AND** the block SHALL be immediately editable
#### Scenario: Edit existing segment
- **WHEN** user modifies text in a segment
- **THEN** only that segment's local data SHALL be updated
- **AND** new incoming segments SHALL continue to append below
- **AND** the edited segment SHALL show an "edited" indicator
#### Scenario: Save merged transcript
- **WHEN** user clicks Save button
- **THEN** all segments (edited and unedited) SHALL be concatenated in order
- **AND** the merged text SHALL be saved as transcript_blob
### Requirement: Real-time Streaming UI
The frontend SHALL provide clear visual feedback during streaming transcription.
#### Scenario: Recording active indicator
- **WHEN** streaming recording is active
- **THEN** a pulsing recording indicator SHALL be visible
- **AND** the current/active segment SHALL have distinct styling (e.g., highlighted border)
- **AND** the Start Recording button SHALL change to Stop Recording
#### Scenario: Processing indicator
- **WHEN** audio is being processed but no text has appeared yet
- **THEN** a "Processing..." indicator SHALL appear in the active segment area
- **AND** the indicator SHALL disappear when text arrives
#### Scenario: Streaming status display
- **WHEN** streaming session is active
- **THEN** the UI SHALL display segment count (e.g., "Segment 5/5")
- **AND** total recording duration
### Requirement: Audio Streaming IPC
The Electron main process SHALL provide IPC handlers for continuous audio streaming between renderer and sidecar.
#### Scenario: Start streaming
- **WHEN** renderer calls `startRecordingStream()`
- **THEN** main process SHALL send start_stream command to sidecar
- **AND** return session confirmation to renderer
#### Scenario: Stream audio data
- **WHEN** renderer sends audio chunk via `streamAudioChunk(arrayBuffer)`
- **THEN** main process SHALL convert WebM to PCM if needed
- **AND** forward to sidecar stdin as base64-encoded audio_chunk command
#### Scenario: Receive transcription
- **WHEN** sidecar emits a segment result on stdout
- **THEN** main process SHALL parse the JSON
- **AND** forward to renderer via `transcription-segment` IPC event