Pick a video in your Media Library, press one button, and get a subtitle file
attached to it. Visitors then see a subtitles button on the video player.
The speech-to-text runs in the browser, on the machine of whoever pressed
the button. Not on your server, and not on anyone’s API. That single decision
is what this plugin is, and everything below follows from it.
There are two ways to turn speech into text: send the audio somewhere and get
the words back, or run the model where the audio already is. This plugin does
the second.
For a marketing clip either way is fine. For patient education, legal
recordings, internal training, HR material or paid membership content, sending
the file to a third party is often the difference between allowed and not
allowed.
The browser reads the file, works on it, and writes the result back. The only
thing that ever downloads is the speech model itself, once.
.vtt is written beside the video andOr download .srt / .vtt instead and take it to YouTube, Vimeo or a video
editor.
[video] shortcode.pot file includedCaptions for prerecorded video are a WCAG 2.1 requirement (Success Criterion
1.2.2). If your site has an accessibility obligation, this is one of the items
on the list.
Most of this would normally be left out of a plugin page. It is here because
the wrong expectation wastes your time and mine.
.mov will not decode..vtt is saved beside the videoThe two files in assets/js/ are built, not written by hand. Their complete
source ships inside this plugin so nothing needs to be taken on trust:
src/ — all of the TypeScript and React that becomes thempackage.json, tsconfig.json, vite.config.ts, vite.worker.config.ts —To rebuild from that source:
npm install
npm run build
which regenerates assets/js/subtitles.js and
assets/js/transcribe-worker.js exactly as shipped.
Bundled into those two files by the build, both unmodified:
Two things are downloaded into the browser the first time you generate
subtitles, and then kept by the browser’s cache. Nothing is uploaded, no
account is needed, and no key is required.
https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1/dist/https://huggingface.co/Your video is never sent to either of them, or to anywhere else. It is read
from your own Media Library by your own browser and worked on there.
Terms and privacy: jsDelivr — https://www.jsdelivr.com/terms and
https://www.jsdelivr.com/terms/privacy-policy-jsdelivr-net · Hugging Face —
https://huggingface.co/terms-of-service and https://huggingface.co/privacy
If your site cannot reach an outside server — some government, medical and
internal deployments cannot, and jsDelivr is blocked in some countries — put
the files on your own host and point the plugin at them:
add_filter( 'bharti_subtitles_wasm_paths', function () {
return 'https://example.com/onnx/';
} );
The files to copy are the contents of @huggingface/transformers@3.8.1/dist/.
The model can be self-hosted the same way; see the Transformers.js
documentation for env.remoteHost.
Be honest with yourself about this before installing: if the first run cannot
reach these two servers, the plugin cannot generate subtitles. After that
first run it works offline.