basyx commited on
Commit
8e2cafe
·
verified ·
1 Parent(s): 8788270

Document Whisper word timestamps and automatic speaker diarization

Browse files
Files changed (1) hide show
  1. README.md +71 -0
README.md CHANGED
@@ -950,6 +950,7 @@ All protected examples below assume `MEDIAFORGE_API_KEY` is set and include `Aut
950
  | Image | `/v1/image/resize`, `crop`, `convert`, `slideshow`, `sequence`, `video`, `watermark`, `overlay` |
951
  | yt-dlp | `/v1/ytdlp/download` |
952
  | Whisper | `/v1/whisper/transcribe`, `subtitles`, `detect-language` |
 
953
  | Templates | `GET /v1/templates`, `GET /v1/templates/categories`, `GET /v1/templates/{reference}`, `POST /v1/templates/run` |
954
 
955
  Common video parameters include `format`, `width`, `height`, `fit`, `crf`, `preset`, `start`, `end`, `duration`, `fps`, `bitrate`, `factor`, `position`, and `opacity`. Swagger lists every route; the defaults and bounds are enforced by the operation that consumes each field.
@@ -986,6 +987,69 @@ curl -X POST http://localhost:7860/v1/ytdlp/download \
986
 
987
  Models: `tiny`, `base`, `small`, `medium`, and `large-v3`. The default is `small`. Models load only on their first request and always use `device="cpu"` and `compute_type="int8"`. Tasks are `transcribe` and `translate`; omit `language` for automatic language detection. Formats are `txt`, `srt`, `vtt`, `json`, and `tsv`.
988
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
989
  ```bash
990
  curl -X POST http://localhost:7860/v1/whisper/transcribe \
991
  -H "Authorization: Bearer $MEDIAFORGE_API_KEY" \
@@ -1093,6 +1157,11 @@ For large files, prefer n8n's multipart binary option or raw binary body; JSON B
1093
  | `TEMPLATE_DIR` | built-in `app/templates/categories` | Recursively scanned YAML workflow catalog |
1094
  | `MAX_UPLOAD_SIZE` | `1073741824` | Maximum bytes for each upload/download |
1095
  | `WHISPER_MODEL` | `small` | Default faster-whisper model |
 
 
 
 
 
1096
  | `CLEANUP_MINUTES` | `60` | TTL for request workspaces and outputs |
1097
  | `CLEANUP_INTERVAL_SECONDS` | `60` | Cleanup scan interval |
1098
  | `MAX_WORKERS` | `2` | Shared per-service CPU process/task concurrency |
@@ -1150,6 +1219,8 @@ This contract keeps new operations independent of multipart, URLs, Base64, n8n,
1150
 
1151
  - **Space is out of memory:** use `tiny`, `base`, or `small`; set `MAX_WORKERS=1`; do not launch multiple Uvicorn workers. `medium` and `large-v3` require substantially more RAM even with int8.
1152
  - **First transcription is slow:** the model is downloaded and initialized lazily. Use persistent Space storage or pre-warm with a short request after deployment.
 
 
1153
  - **FFmpeg reports incompatible streams during concat:** leave `stream_copy` false (the default), which normalizes dimensions and re-encodes. Enable it only for files with identical stream layout, codec, time base, and parameters.
1154
  - **Remote URL is rejected:** private and non-global addresses are blocked intentionally. Set `ALLOW_PRIVATE_URLS=true` only in a trusted network and never on a public Space.
1155
  - **Download URL returns 404:** the request TTL expired, the Space restarted without persistent storage, or the filename/request ID was changed. Download results promptly.
 
950
  | Image | `/v1/image/resize`, `crop`, `convert`, `slideshow`, `sequence`, `video`, `watermark`, `overlay` |
951
  | yt-dlp | `/v1/ytdlp/download` |
952
  | Whisper | `/v1/whisper/transcribe`, `subtitles`, `detect-language` |
953
+ | Diarization | `/v1/diarization/diarize` — automatic speaker diarization using pyannote |
954
  | Templates | `GET /v1/templates`, `GET /v1/templates/categories`, `GET /v1/templates/{reference}`, `POST /v1/templates/run` |
955
 
956
  Common video parameters include `format`, `width`, `height`, `fit`, `crf`, `preset`, `start`, `end`, `duration`, `fps`, `bitrate`, `factor`, `position`, and `opacity`. Swagger lists every route; the defaults and bounds are enforced by the operation that consumes each field.
 
987
 
988
  Models: `tiny`, `base`, `small`, `medium`, and `large-v3`. The default is `small`. Models load only on their first request and always use `device="cpu"` and `compute_type="int8"`. Tasks are `transcribe` and `translate`; omit `language` for automatic language detection. Formats are `txt`, `srt`, `vtt`, `json`, and `tsv`.
989
 
990
+ #### Word-level timestamps and speaker diarization
991
+
992
+ Whisper transcription supports canonical word-level timestamps and optional speaker attribution. The JSON transcript schema is versioned and includes segment-level and word-level timing; when diarization is applied, segments and words can carry a stable speaker label such as `SPEAKER_00`.
993
+
994
+ Diarization can be supplied in three ways:
995
+
996
+ 1. **Automatic remote diarization** — set `diarization=true` and configure MediaRouter's `DIARIZATION_URL` and `DIARIZATION_API_KEY`. The backend can call this Space's `POST /v1/diarization/diarize` endpoint.
997
+ 2. **Inline spans** — provide a `diarization` array containing objects with `speaker`, `start`, and `end`.
998
+ 3. **Diarization JSON input** — provide a second input containing a JSON document with `spans`, `segments`, or `speakers`.
999
+
1000
+ The dedicated diarization API in this Space uses `pyannote/speaker-diarization-3.1`, converts the source media to mono 16 kHz PCM for analysis, and returns normalized speaker spans:
1001
+
1002
+ ```json
1003
+ {
1004
+ "spans": [
1005
+ {"speaker": "SPEAKER_00", "start": 0.0, "end": 3.42},
1006
+ {"speaker": "SPEAKER_01", "start": 3.42, "end": 7.18}
1007
+ ],
1008
+ "speakers": ["SPEAKER_00", "SPEAKER_01"],
1009
+ "filename": "interview.mp4"
1010
+ }
1011
+ ```
1012
+
1013
+ The diarization endpoint is protected by the normal API-key authentication/scope layer and additionally requires `DIARIZATION_API_KEY` to be configured on the Space. The configured key must have `operations:execute`. Access to the gated pyannote model also requires `HF_TOKEN` with the model's access granted.
1014
+
1015
+ **Diarization endpoint:**
1016
+
1017
+ ```http
1018
+ POST /v1/diarization/diarize
1019
+ Authorization: Bearer <api-key>
1020
+ Content-Type: application/octet-stream
1021
+ X-Filename: interview.mp4
1022
+ X-Min-Speakers: 2
1023
+ X-Max-Speakers: 4
1024
+ ```
1025
+
1026
+ The request body is the raw media bytes. `X-Min-Speakers` and `X-Max-Speakers` are optional bounds from 1–32. The service enforces bounded input/response sizes and returns normalized spans ordered by start time. It does not expose model or subprocess internals in API errors.
1027
+
1028
+ Example:
1029
+
1030
+ ```bash
1031
+ curl -X POST "https://<owner>-<space>.hf.space/v1/diarization/diarize" \
1032
+ -H "Authorization: Bearer $MEDIAFORGE_API_KEY" \
1033
+ -H "Content-Type: application/octet-stream" \
1034
+ -H "X-Filename: interview.mp4" \
1035
+ --data-binary "@interview.mp4"
1036
+ ```
1037
+
1038
+ For a complete transcription with speaker labels through MediaRouter, enable diarization in the transcription request:
1039
+
1040
+ ```bash
1041
+ curl -X POST "https://<media-router-space>.hf.space/v1/whisper/transcribe" \
1042
+ -H "Authorization: Bearer $MEDIAFORGE_API_KEY" \
1043
+ -F "file=@interview.mp4" \
1044
+ -F "model=small" \
1045
+ -F "output_format=json" \
1046
+ -F "word_timestamps=true" \
1047
+ -F "diarization=true"
1048
+ ```
1049
+
1050
+ The resulting canonical JSON contains `schema_version: "1.1"`, `speakers`, and speaker fields on matching segments/words. SRT/VTT continue to use the canonical timing data; use JSON when downstream automation needs machine-readable speaker attribution.
1051
+
1052
+
1053
  ```bash
1054
  curl -X POST http://localhost:7860/v1/whisper/transcribe \
1055
  -H "Authorization: Bearer $MEDIAFORGE_API_KEY" \
 
1157
  | `TEMPLATE_DIR` | built-in `app/templates/categories` | Recursively scanned YAML workflow catalog |
1158
  | `MAX_UPLOAD_SIZE` | `1073741824` | Maximum bytes for each upload/download |
1159
  | `WHISPER_MODEL` | `small` | Default faster-whisper model |
1160
+ | `DIARIZATION_API_KEY` | empty | Dedicated bearer secret for the diarization endpoint; must also correspond to an authenticated API key with `operations:execute` |
1161
+ | `DIARIZATION_MODEL_ID` | `pyannote/speaker-diarization-3.1` | pyannote diarization pipeline |
1162
+ | `DIARIZATION_MAX_INPUT_BYTES` | `1073741824` | Maximum diarization request body |
1163
+ | `DIARIZATION_MAX_RESPONSE_SPANS` | `10000` | Maximum normalized diarization spans returned |
1164
+ | `HF_TOKEN` | empty | Hugging Face token with access to the gated diarization model |
1165
  | `CLEANUP_MINUTES` | `60` | TTL for request workspaces and outputs |
1166
  | `CLEANUP_INTERVAL_SECONDS` | `60` | Cleanup scan interval |
1167
  | `MAX_WORKERS` | `2` | Shared per-service CPU process/task concurrency |
 
1219
 
1220
  - **Space is out of memory:** use `tiny`, `base`, or `small`; set `MAX_WORKERS=1`; do not launch multiple Uvicorn workers. `medium` and `large-v3` require substantially more RAM even with int8.
1221
  - **First transcription is slow:** the model is downloaded and initialized lazily. Use persistent Space storage or pre-warm with a short request after deployment.
1222
+ - **Speaker diarization returns 503:** configure `DIARIZATION_API_KEY` on the Space and ensure the bearer key is a valid authenticated API key with `operations:execute`; configure `HF_TOKEN` and accept access to `pyannote/speaker-diarization-3.1`. The model is loaded lazily on the first diarization request.
1223
+ - **Speaker diarization is unavailable through MediaRouter:** set MediaRouter `DIARIZATION_URL` to `https://<owner>-<space>.hf.space/v1/diarization/diarize` and configure the same `DIARIZATION_API_KEY`. Keep the URL HTTPS in production.
1224
  - **FFmpeg reports incompatible streams during concat:** leave `stream_copy` false (the default), which normalizes dimensions and re-encodes. Enable it only for files with identical stream layout, codec, time base, and parameters.
1225
  - **Remote URL is rejected:** private and non-global addresses are blocked intentionally. Set `ALLOW_PRIVATE_URLS=true` only in a trusted network and never on a public Space.
1226
  - **Download URL returns 404:** the request TTL expired, the Space restarted without persistent storage, or the filename/request ID was changed. Download results promptly.