一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
201 行
5.5 KiB
Markdown
201 行
5.5 KiB
Markdown
# Installation and Setup
|
|
|
|
## Configure Docker for Transcribe
|
|
|
|
The transcribe server embeds the llama.cpp binary directly in the Docker image. The AI models must be downloaded separately and mounted as a volume.
|
|
|
|
### 1. Create data directory and download models
|
|
|
|
```shell
|
|
mkdir -p ./data/models
|
|
chmod 755 ./data
|
|
wget -O ./data/models/Model-7.6B-Q4_K_M.gguf https://huggingface.co/openbmb/MiniCPM-o-2_6-gguf/resolve/main/Model-7.6B-Q4_K_M.gguf
|
|
wget -O ./data/models/mmproj-model-f16.gguf https://huggingface.co/openbmb/MiniCPM-o-2_6-gguf/resolve/main/mmproj-model-f16.gguf
|
|
```
|
|
|
|
### 2. Configure environment
|
|
|
|
1. Copy `.env-transcribe-sample` to your Docker configuration directory.
|
|
2. Rename it to `.env-transcribe`.
|
|
3. Set `API_KEY` to a secure value.
|
|
|
|
### 3. Run the server
|
|
|
|
```shell
|
|
docker run --rm --env-file .env-transcribe -p 4567:4567 \
|
|
-v ./data:/data \
|
|
joplin/transcribe:amd64-latest
|
|
```
|
|
|
|
The container automatically creates the following inside `/data`:
|
|
- `images/` - uploaded images
|
|
- `models/` - AI models (you provide these)
|
|
- `queue.sqlite3` - job queue database
|
|
|
|
## Using Docker Compose
|
|
|
|
The minimal configuration is provided in `.env-sample` and `docker-compose.server.yml`.
|
|
|
|
1. Run `cp .env-sample .env`
|
|
2. Update any options you need in `.env`
|
|
3. Start the server:
|
|
|
|
```shell
|
|
docker compose -f docker-compose.server.yml --profile full up --detached
|
|
```
|
|
|
|
For advanced configuration, refer to `.env-sample-transcribe`.
|
|
|
|
## Security
|
|
|
|
The transcribe container runs with these security measures:
|
|
|
|
- **Non-root user**: The application runs as the `transcribe` user, not root
|
|
- **Read-only filesystem**: The container filesystem is read-only (only `/app/packages/transcribe/images` and `/tmp` are writable)
|
|
- **Resource limits**: Memory and CPU limits prevent runaway processes
|
|
- **No Docker socket**: Unlike previous versions, no Docker socket mount is required
|
|
|
|
# Development Setup
|
|
|
|
## Testing
|
|
|
|
Integration tests requiring the full model **do not run by default (including on CI)**. Be cautious when modifying the model or prompts.
|
|
The disabled test is located at: `workers/JobProcessor.test.ts`.
|
|
|
|
Run all tests with:
|
|
|
|
```shell
|
|
yarn test-all
|
|
```
|
|
|
|
## Starting the Server
|
|
|
|
From `packages/transcribe`, run:
|
|
|
|
```shell
|
|
yarn start
|
|
```
|
|
|
|
### Environment variables
|
|
|
|
Required:
|
|
- `API_KEY`: Authentication key for API requests
|
|
- `DATA_DIR`: Base directory for all data (images, models, database)
|
|
- `HTR_CLI_BINARY_PATH`: Path to the llama-mtmd-cli binary
|
|
|
|
Optional:
|
|
- `QUEUE_DRIVER`: `sqlite` (default in Docker) or `pg` for PostgreSQL
|
|
|
|
The following paths are automatically derived from `DATA_DIR`:
|
|
- `$DATA_DIR/images` - uploaded images
|
|
- `$DATA_DIR/models` - AI models
|
|
- `$DATA_DIR/queue.sqlite3` - SQLite database (when using sqlite driver)
|
|
|
|
### GPU support
|
|
|
|
The server uses CPU by default. For NVIDIA GPU, run a CUDA-capable image with `--gpus all` and set `HTR_CLI_GPU_LAYERS=9999`.
|
|
|
|
```shell
|
|
docker run --rm --gpus all --env-file .env-transcribe -p 4567:4567 \
|
|
-e HTR_CLI_GPU_LAYERS=9999 \
|
|
-v ./data:/data \
|
|
joplin/transcribe:gpu-latest
|
|
```
|
|
|
|
This needs NVIDIA Container Toolkit on the host. Use `0` or leave it unset for CPU.
|
|
|
|
### Native Windows without Docker
|
|
|
|
On Windows, CUDA GPU acceleration can run in Docker using the NVIDIA instructions above, or natively on the host. For a native run, use a Windows x64 CUDA-enabled build of llama-mtmd-cli.exe, then set HTR_CLI_GPU_LAYERS to the number of layers you want offloaded to the GPU.
|
|
|
|
### Native macOS/Metal
|
|
|
|
On Apple Silicon, GPU acceleration runs natively on the host (Docker can't expose Metal to containers). Use a macOS ARM64 build of llama-mtmd-cli with Metal support, then set HTR_CLI_GPU_LAYERS to the number of layers you want offloaded to the GPU.
|
|
|
|
### Native GPU configuration
|
|
|
|
You can download the binary from the official llama.cpp releases page: <https://github.com/ggml-org/llama.cpp/releases>.
|
|
|
|
Native GPU settings:
|
|
|
|
```env
|
|
HTR_CLI_BINARY_PATH=/path/to/llama-mtmd-cli
|
|
HTR_CLI_GPU_LAYERS=9999
|
|
```
|
|
|
|
With this setup, the server passes `-ngl 9999` to `llama-mtmd-cli`. GPU support comes from the selected binary.
|
|
|
|
# API Endpoints
|
|
|
|
All requests must include the `Authorization` header with the value set to your `API_KEY`.
|
|
|
|
## POST `/transcribe`
|
|
|
|
Creates a transcription job. The uploaded image is resized, stored on disk, and assigned to a job record in the database.
|
|
|
|
**Request Body:**
|
|
|
|
* **Content-Type**: `multipart/form-data`
|
|
* **Field**: `file` (required) – the image file to process
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"jobId": "bcd2e633-eb10-44cb-a280-bf723238c12e"
|
|
}
|
|
```
|
|
|
|
**Example (cURL):**
|
|
|
|
```shell
|
|
curl --request POST \
|
|
--url http://localhost:4567/transcribe \
|
|
--header 'Authorization: api-key' \
|
|
--header 'Content-Type: multipart/form-data' \
|
|
--form file=@/home/js/Pictures/2025-07-24_17-42_1.png
|
|
```
|
|
|
|
## GET `/transcribe/{jobId}`
|
|
|
|
Fetches the result of a transcription job created with `POST /transcribe`.
|
|
|
|
**Request:**
|
|
|
|
* Requires a valid `jobId`.
|
|
|
|
**Example Responses:**
|
|
|
|
```json
|
|
{
|
|
"id": "57ebd2e2-b496-40ab-9008-5f861bcb7858",
|
|
"state": "created"
|
|
}
|
|
```
|
|
|
|
```json
|
|
{
|
|
"id": "07f09553-f5e9-467e-b98d-406778e61969",
|
|
"state": "active"
|
|
}
|
|
```
|
|
|
|
```json
|
|
{
|
|
"id": "57ebd2e2-b496-40ab-9008-5f861bcb7858",
|
|
"completedOn": "2025-06-11T18:20:22.000Z",
|
|
"output": {
|
|
"result": "markdown\r\n# Main title\r\n\r\nSome text here. This should take more than one line.\r\n\r\n## Sub title\r\n\r\n- One kind\r\n - of list\r\n - sub-item\r\n\r\n## Conclusion\r\n\r\nLet's finish here."
|
|
},
|
|
"state": "completed"
|
|
}
|
|
```
|
|
|
|
**Example (cURL):**
|
|
|
|
```shell
|
|
curl --request GET \
|
|
--url http://localhost:4567/transcribe/57ebd2e2-b496-40ab-9008-5f861bcb7858 \
|
|
--header 'Authorization: api-key'
|
|
```
|