# AndyTranscribe Upload pocket-recorder audio (MP3, WAV, OGG, and more), extract embedded metadata, and transcribe locally with [faster-whisper-server](https://github.com/fedirz/faster-whisper-server). Audio never leaves your machine. Built with Laravel 13, Blade, Alpine.js, Tailwind CSS 4, [Laravel Reverb](https://laravel.com/docs/reverb), FrankenPHP, and [Laravel AI](https://github.com/laravel/ai). ## Features - Upload common audio formats (MP3, WAV, OGG, FLAC, M4A, AAC, WebM, WMA, AIFF — up to 2 GB) - Automatic metadata extraction when tags are present (title, artist, album, duration, recorded date) - Search recordings by title, artist, or transcript - Queued local transcription (faster-whisper in Docker) - Live transcription progress over WebSockets (Reverb) on the list and detail pages - Stop or restart a run anytime - Copy finished transcripts from the recording detail page ## Requirements - [Docker](https://docs.docker.com/get-docker/) and Docker Compose - About 2 GB free disk for the Whisper model cache (first run downloads the model) Optional for native PHP development: PHP 8.3+ (8.5 recommended), Composer, Node.js & npm. ## Install These steps run the full stack with Docker: web app, queue worker, Reverb WebSockets, and Whisper. ### 1. Clone the repository ```bash git clone andyTranscibe cd andyTranscibe ``` ### 2. Create your environment file ```bash cp .env.example .env ``` ### 3. Generate an application key `APP_KEY` is required. Containers refuse to start if it is empty. **Option A — PHP installed on the host** ```bash php artisan key:generate ``` **Option B — Docker only** Print a key: ```bash docker run --rm php:8.5-cli php -r "echo 'base64:'.base64_encode(random_bytes(32)), PHP_EOL;" ``` Open `.env` and set: ```env APP_KEY=base64:paste-the-value-here ``` On Linux you can write it in one step: ```bash KEY=$(docker run --rm php:8.5-cli php -r "echo 'base64:'.base64_encode(random_bytes(32));") sed -i "s|^APP_KEY=.*|APP_KEY=${KEY}|" .env ``` ### 4. Start the stack ```bash docker compose up --build -d ``` On first start the app container will: - create `database/database.sqlite` if needed - run migrations - start FrankenPHP on port **8080** Whisper may take a minute or two while the model downloads. ### 5. Open the app | URL | Purpose | | --- | --- | | [http://localhost:8080/recordings](http://localhost:8080/recordings) | App UI | | [http://localhost:8080/up](http://localhost:8080/up) | Health check | Live transcription status uses WebSockets on port **8081** (Reverb). Keep that port reachable from your browser. ### 6. Verify services (optional) ```bash docker compose ps docker compose logs -f app queue whisper reverb ``` You should see `app`, `queue`, `reverb`, and `whisper` running. Whisper becomes healthy after `/health` succeeds. ### Stop / restart ```bash docker compose down docker compose up -d ``` Data under `./database`, `./storage/app`, and `./storage/logs` is kept on the host. ## Services and ports | Service | Host port | Role | | --- | --- | --- | | `app` | `8080` | FrankenPHP (Laravel web UI) | | `reverb` | `8081` | WebSockets for live transcription status | | `whisper` | `8090` | faster-whisper HTTP API | | `queue` | — | `php artisan queue:work` for transcription jobs | ### Persistent data | Host path | Container path | Contents | | --- | --- | --- | | `./database` | `/app/database` | SQLite database | | `./storage/app` | `/app/storage/app` | Uploaded audio (`private/recordings`) | | `./storage/logs` | `/app/storage/logs` | Application logs | Whisper model cache uses the Docker volume `whisper-huggingface-cache`. ### Useful environment variables Edit `.env` before `docker compose up` when you need different ports or models: | Variable | Purpose | Default | | --- | --- | --- | | `APP_KEY` | Required Laravel encryption key | — | | `APP_URL` | Public app URL | `http://localhost:8080` | | `APP_HOST_PORT` | Host port for the web app | `8080` | | `REVERB_HOST_PORT` | Host port for WebSockets | `8081` | | `WHISPER_HOST_PORT` | Host port for Whisper | `8090` | | `LOCAL_WHISPER_MODEL` | Whisper model id | `Systran/faster-whisper-base` | | `TRANSCRIPTION_TIMEOUT` | Job/HTTP timeout (seconds) | `600` | | `DB_QUEUE_RETRY_AFTER` | Must exceed `TRANSCRIPTION_TIMEOUT` | `660` | Inside Compose, Laravel talks to Whisper at `http://whisper:8000/v1` and publishes broadcasts to the `reverb` service. The browser connects to Reverb on `localhost:8081`. If you change `REVERB_APP_KEY` or browser-facing Reverb host/port settings, rebuild so Vite embeds the new values: ```bash docker compose up --build -d ``` ### GPU Whisper (optional) ```bash docker compose --profile gpu up -d --build ``` Use the GPU Whisper service instead of the CPU `whisper` service when you have an NVIDIA GPU and the NVIDIA Container Toolkit installed. ## Usage 1. Open **Recordings → Upload** and drop one or many audio files. 2. Transcription starts automatically (the `queue` service must be running). 3. Watch live progress on the list or detail page; stop or restart anytime. 4. Search by title, artist, or transcript text. 5. For older uploads still **Queued** with no progress, use **Queue pending transcriptions** on the recordings list. Finished transcripts are stored on each recording and are included in search. ## Native PHP development (optional) For hacking on the Laravel app outside the FrankenPHP image: ```bash composer setup docker compose up -d whisper reverb ``` Then in separate terminals: ```bash php artisan serve --port=8000 php artisan queue:work php artisan reverb:start npm run dev ``` Point `.env` at local services, for example: ```env APP_URL=http://localhost:8000 LOCAL_WHISPER_URL=http://127.0.0.1:8090/v1 REVERB_HOST=localhost REVERB_PORT=8080 VITE_REVERB_HOST=localhost VITE_REVERB_PORT=8080 VITE_REVERB_SCHEME=http ``` ## Tests ```bash composer test # or php artisan test ``` ## License MIT