Skip to main content

Recording → Transcription

Automatically transcribe any audio or video recording dropped into Nextcloud. The moment a file lands in the bucket, Decree generates a pre-signed URL, hands it to WhisperX, and saves a speaker-labelled transcript next to the original file — no manual steps, no intermediate storage.

How It Works​

1. Phone uploads the recording​

The Nextcloud mobile app auto-syncs your phone's recordings folder to Nextcloud. Any .mp3, .mp4, or .wav file uploaded this way flows into SeaweedFS via Nextcloud's S3 external storage.

2. SeaweedFS fires the webhook​

When the file lands in the bucket, it POSTs an s3:ObjectCreated event to the Decree webhook endpoint. The rclone_src and rclone_prefix in the webhook config tell s3-router how to construct the rclone path used in all subsequent steps.

3. s3-router matches the file​

s3-router scans every processor script in automation/lib/file-processors/ for a PATTERN= match against the full rclone path. The whisperx-transcribe processor declares:

PATTERN='\.[Mm][Pp][34]$|\.[Ww][Aa][Vv]$'
IS_PRE_SIGNED=true

It matches .mp3, .mp4, and .wav case-insensitively. Because IS_PRE_SIGNED=true, the outbox message carries is_pre_signed: true — telling file-processor not to download the file.

4. file-processor generates a signed URL​

Instead of downloading the file, file-processor calls rclone link to generate a pre-signed URL for the audio file and exports it as PRE_SIGNED_URL. No audio data touches the Decree container's disk.

5. whisperx-transcribe submits to WhisperX​

whisperx-transcribe.sh invokes whisperx-transcribe.ts, which:

  1. POSTs the PRE_SIGNED_URL to http://whisperx:8000/speech-to-text-url — WhisperX fetches the audio itself and runs the full transcribe → align → diarize pipeline
  2. Polls GET /task/{id} until the task reports completed (diarized runs take longer than plain transcription)
  3. Collapses the result's speaker-tagged segments into [SPEAKER_00] … lines
  4. Writes the speaker-labelled transcript to stdout

6. Transcript saved next to the original​

The bash processor pipes the transcription text through rclone rcat directly into Nextcloud at the same path as the audio file, with .transcript.txt appended:

recordings/2026-04-22 Meeting.mp3
recordings/2026-04-22 Meeting.mp3.transcript.txt ← created automatically

Prerequisites​

  • Nextcloud running with SeaweedFS configured as S3 external storage
  • SeaweedFS webhook sending file events to the Decree webhook endpoint (see File Processor)
  • WhisperX container running and reachable at http://whisperx:8000
  • rclone configured with a nextcloud remote (or whichever remote matches your rclone_src webhook setting)
  • Nextcloud mobile app with auto-upload enabled for your recordings folder

Setup​

Step 1 — object-store webhook​

Follow the SeaweedFS setup in File Processor to register the Decree webhook target and add your recordings path to path_prefixes in notification.toml. If recordings land in the nextcloud bucket, both are already done for you.

Step 2 — rclone remote​

Ensure your rclone config has a remote that can access the files SeaweedFS is receiving events for:

./existential.sh run rclone

The remote name must match rclone_src in services/automation/webhook/config.yml (default: nextcloud).

Step 3 — Enable WhisperX​

Start the WhisperX container if it isn't already running (all compose commands run from the repo root against the generated docker-compose.yml — never -f into a service's own directory):

docker compose up -d whisperx

WhisperX will download the default model on first use. No further configuration is required — the whisperx-transcribe processor defaults to letting WhisperX pick its own model.

Step 4 — Confirm the processor is active​

The whisperx-transcribe processor is auto-discovered from automation/lib/file-processors/. No registration step is needed. Verify the pre-checks pass:

docker exec automation decree routine file-processor

Step 5 — Configure Nextcloud mobile auto-upload​

In the Nextcloud mobile app, enable auto-upload for your phone's voice recordings or screen recordings folder. Files are uploaded to Nextcloud, synced to the bucket, and the transcription flow triggers automatically.

Customization​

Override any of these in the processor script or pass them as frontmatter params:

VariableDefaultDescription
FILE_SUFFIX.transcript.txtSuffix appended to the audio file path for the output
OUTPUT_RCLONEnextcloudrclone remote where the transcript is saved
WHISPERX_MODEL(empty — WhisperX default)Model name passed to the transcription API
WHISPERX_MIN_SPEAKERS(empty — auto-detect)Lower bound on diarized speaker count
WHISPERX_MAX_SPEAKERS(empty — auto-detect)Upper bound on diarized speaker count
WHISPERX_URLhttp://whisperx:8000WhisperX API base URL

Testing​

Send a synthetic file event to trigger the flow end-to-end:

# automation-webhook publishes no host port — it is reached over the exist
# bridge, so send the event from a container already on it.
docker exec automation curl -X POST http://automation-webhook:8801/s3 \
-H "Authorization: Bearer <EXIST_DECREE_S3_WEBHOOK_AUTH_TOKEN from .env.shared>" \
-H "Content-Type: application/json" \
-d '{"EventName":"s3:ObjectCreated:Put","Key":"recordings/test.mp3","Records":[]}'

Watch processing in real time:

docker logs -f automation

Inspect the completed run:

docker exec automation decree status
docker exec automation decree log <id-prefix>