246 lines
8.8 KiB
Markdown
246 lines
8.8 KiB
Markdown
# ARCHITECTURE.md — Speech2Text MBIP
|
|
|
|
## Gambaran Keseluruhan
|
|
|
|
Sistem Speech-to-Text MBIP ialah aplikasi web dalaman yang membolehkan pengguna jabatan muat naik fail audio dan mendapatkan transkripsi teks Bahasa Melayu secara automatik. Semua pemprosesan berlaku dalam persekitaran Docker yang self-hosted, tanpa hantar data ke cloud luaran.
|
|
|
|
---
|
|
|
|
## Stack Teknologi
|
|
|
|
| Lapisan | Teknologi |
|
|
|---|---|
|
|
| Web Framework | Laravel 11 (PHP 8.3+) |
|
|
| Database | MySQL 8 |
|
|
| Cache / Queue | Redis |
|
|
| Frontend | Bootstrap 5 + jQuery |
|
|
| Web Server | Nginx + PHP-FPM |
|
|
| Queue Worker | Laravel Queue (Redis driver) |
|
|
| Transcription Engine | faster-whisper (Python) via HTTP API |
|
|
| Post-processing (optional) | Ollama (local LLM) |
|
|
| Container | Docker Compose |
|
|
| Storage | Laravel Private Disk (local filesystem) |
|
|
|
|
---
|
|
|
|
## Seni Bina Perkhidmatan (Docker Compose)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ DOCKER NETWORK │
|
|
│ │
|
|
│ ┌───────────┐ ┌───────────┐ ┌──────────────────────┐ │
|
|
│ │ nginx │───▶│ app │───▶│ mysql │ │
|
|
│ │ :80/443 │ │ (php-fpm) │ │ :3306 │ │
|
|
│ └───────────┘ └─────┬─────┘ └──────────────────────┘ │
|
|
│ │ │
|
|
│ ┌────▼────┐ ┌──────────────────────┐ │
|
|
│ │ redis │ │ transcription-worker│ │
|
|
│ │ :6379 │ │ (Python FastAPI) │ │
|
|
│ └─────────┘ │ :8000 │ │
|
|
│ │ └──────────────────────┘ │
|
|
│ ┌──────────┴───┐ ┌──────────────────────┐ │
|
|
│ │queue-worker │ │ ollama (optional) │ │
|
|
│ │(Laravel) │ │ :11434 │ │
|
|
│ └──────────────┘ └──────────────────────┘ │
|
|
│ ┌──────────────┐ │
|
|
│ │ scheduler │ │
|
|
│ │(Laravel cron)│ │
|
|
│ └──────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Perkhidmatan Docker
|
|
|
|
#### `app` — Laravel PHP-FPM
|
|
- Image: php:8.3-fpm (custom Dockerfile)
|
|
- Mount: `/svr/speech2text/app` → `/var/www/html`
|
|
- Tanggungjawab: serve HTTP request, jalankan Artisan commands
|
|
|
|
#### `nginx`
|
|
- Image: nginx:alpine
|
|
- Port: 80, 443
|
|
- Proxy pass ke `app:9000`
|
|
|
|
#### `mysql`
|
|
- Image: mysql:8
|
|
- Volume: data persistent
|
|
- Database: `speech2text`
|
|
|
|
#### `redis`
|
|
- Image: redis:alpine
|
|
- Digunakan untuk: queue, cache, session
|
|
|
|
#### `queue-worker`
|
|
- Build dari image `app` yang sama
|
|
- Command: `php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600`
|
|
- Proses job transcription, notification, audit
|
|
|
|
#### `scheduler`
|
|
- Build dari image `app` yang sama
|
|
- Command: `php artisan schedule:work`
|
|
- Proses scheduled tasks (cleanup, retention policy)
|
|
|
|
#### `transcription-worker`
|
|
- Image: Python 3.11 + faster-whisper (custom Dockerfile)
|
|
- Port: 8000 (internal sahaja)
|
|
- Expose endpoint `/transcribe` (POST)
|
|
- Tidak accessible dari luar Docker network
|
|
|
|
#### `ollama` (optional)
|
|
- Image: ollama/ollama
|
|
- Hanya diaktifkan jika `OLLAMA_ENABLED=true`
|
|
- Digunakan untuk post-processing teks selepas transcription
|
|
|
|
---
|
|
|
|
## Aliran Data Transcription
|
|
|
|
```
|
|
User Upload Audio
|
|
│
|
|
▼
|
|
[Laravel Controller]
|
|
- Validate file (type, size)
|
|
- Simpan ke storage/app/private/transcriptions/{uuid}/audio/
|
|
- Cipta rekod TranscriptionProject (status: pending)
|
|
- Dispatch TranscribeAudioJob ke Redis queue
|
|
│
|
|
▼
|
|
[Queue Worker — TranscribeAudioJob]
|
|
- Update status: processing
|
|
- Baca fail audio dari private storage
|
|
- Hantar ke transcription-worker via HTTP POST
|
|
│
|
|
▼
|
|
[transcription-worker — Python FastAPI]
|
|
- Terima audio (base64 atau multipart)
|
|
- Jalankan faster-whisper dengan model yang dikonfig
|
|
- Return transcript JSON
|
|
│
|
|
▼
|
|
[Queue Worker — callback]
|
|
- Simpan transcript ke database
|
|
- Update status: completed / failed
|
|
- Log audit
|
|
- (Optional) Dispatch OllamaPostProcessJob
|
|
│
|
|
▼
|
|
[User melihat hasil transcript]
|
|
```
|
|
|
|
---
|
|
|
|
## Struktur Direktori Laravel
|
|
|
|
```
|
|
app/
|
|
├── Actions/ # Single-purpose action classes
|
|
│ ├── CreateUserAction.php
|
|
│ ├── DeactivateUserAction.php
|
|
│ ├── TransferProjectOwnerAction.php
|
|
│ └── ...
|
|
├── Http/
|
|
│ ├── Controllers/
|
|
│ │ ├── Admin/
|
|
│ │ │ ├── DashboardController.php
|
|
│ │ │ ├── UserController.php
|
|
│ │ │ ├── ProjectMetadataController.php
|
|
│ │ │ ├── TransferOwnershipController.php
|
|
│ │ │ └── AuditLogController.php
|
|
│ │ └── User/
|
|
│ │ ├── DashboardController.php
|
|
│ │ ├── ProjectController.php
|
|
│ │ ├── AudioController.php
|
|
│ │ ├── TranscriptController.php
|
|
│ │ ├── CollaboratorController.php
|
|
│ │ ├── CommentController.php
|
|
│ │ └── TranscriptVersionController.php
|
|
│ ├── Requests/ # Form Request validation
|
|
│ └── Middleware/
|
|
│ ├── EnsureUserIsActive.php
|
|
│ └── EnsureAdminCannotAccessContent.php
|
|
├── Jobs/
|
|
│ ├── TranscribeAudioJob.php
|
|
│ └── OllamaPostProcessJob.php
|
|
├── Models/
|
|
│ ├── User.php
|
|
│ ├── Department.php
|
|
│ ├── TranscriptionProject.php
|
|
│ ├── ProjectCollaborator.php
|
|
│ ├── TranscriptVersion.php
|
|
│ ├── ProjectComment.php
|
|
│ └── AuditLog.php
|
|
├── Policies/
|
|
│ ├── TranscriptionProjectPolicy.php
|
|
│ ├── CommentPolicy.php
|
|
│ ├── TranscriptVersionPolicy.php
|
|
│ └── UserPolicy.php
|
|
├── Services/
|
|
│ ├── TranscriptionService.php
|
|
│ ├── OllamaService.php
|
|
│ ├── AuditLogService.php
|
|
│ └── StorageService.php
|
|
└── ...
|
|
|
|
resources/
|
|
├── views/
|
|
│ ├── layouts/
|
|
│ │ ├── app.blade.php # Layout pengguna
|
|
│ │ └── admin.blade.php # Layout admin
|
|
│ ├── auth/
|
|
│ ├── admin/
|
|
│ │ ├── dashboard.blade.php
|
|
│ │ ├── users/
|
|
│ │ ├── projects/
|
|
│ │ └── audit-logs/
|
|
│ └── user/
|
|
│ ├── dashboard.blade.php
|
|
│ ├── projects/
|
|
│ └── ...
|
|
```
|
|
|
|
---
|
|
|
|
## Authorization Model (Ringkas)
|
|
|
|
```
|
|
Admin:
|
|
✓ Urus pengguna (CRUD metadata)
|
|
✓ Lihat statistik
|
|
✓ Lihat metadata projek sahaja
|
|
✓ Transfer ownership dengan justifikasi
|
|
✓ Lihat audit log pentadbiran
|
|
✗ Dengar / download audio
|
|
✗ Baca transcript
|
|
✗ Lihat komen
|
|
✗ Masuk detail projek (kandungan)
|
|
|
|
Owner:
|
|
✓ Semua akses ke projek sendiri
|
|
✓ Urus collaborators
|
|
✓ Delete projek / audio / teks
|
|
✓ Retry transcription
|
|
|
|
Collaborator:
|
|
✓ Lihat / edit transcript
|
|
✓ Dengar audio
|
|
✓ Buat komen
|
|
✗ Delete projek
|
|
✗ Transfer ownership
|
|
✗ Urus collaborators lain
|
|
```
|
|
|
|
---
|
|
|
|
## Prinsip Reka Bentuk
|
|
|
|
1. **Thin Controller** — logic dalam Action class atau Service, bukan dalam controller.
|
|
2. **Policy Enforcement** — setiap action semak Policy, bukan hanya UI.
|
|
3. **Private Storage** — tiada fail audio/teks dalam `public/` atau `storage/app/public/`.
|
|
4. **UUID Routes** — gunakan UUID bukan ID integer dalam URL projek.
|
|
5. **Audit Everything** — semua tindakan sensitif direkod dalam `audit_logs`.
|
|
6. **Queue All Transcription** — proses transcription tidak boleh block HTTP request.
|
|
7. **No Cloud Dependency** — semua AI/ML processing dalam Docker network sahaja.
|
|
8. **Local-only Default** — Ollama disabled by default; hanya aktif jika eksplisit dikonfig.
|