{"id":358501,"date":"2026-09-02T12:42:17","date_gmt":"2026-09-02T12:42:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/localsub\/"},"modified":"2026-09-02T12:41:55","modified_gmt":"2026-09-02T12:41:55","slug":"bharti-subtitles","status":"publish","type":"plugin","link":"https:\/\/et.wordpress.org\/plugins\/bharti-subtitles\/","author":23542012,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"Bharti Subtitles","header_author":"Prashant Dhumane","header_description":"Generate subtitles for the videos in your Media Library \u2014 entirely in the browser. No API key, no per-minute cost, and the video is never uploaded anywhere.","assets_banners_color":"223954","last_updated":"2026-09-02 12:41:55","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":46,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"aiguru","date":"2026-09-02 12:41:55","revision":3678007}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3678007,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3678007,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3678028,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3678007,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3678007,"resolution":"1","location":"assets","locale":"","width":2880,"height":760},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3678007,"resolution":"2","location":"assets","locale":"","width":2880,"height":1220},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3678007,"resolution":"3","location":"assets","locale":"","width":2880,"height":1940},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3678007,"resolution":"4","location":"assets","locale":"","width":2880,"height":1340}},"screenshots":{"1":"Media &gt; Bharti Subtitles: pick a video and a language.","2":"Subtitles appearing while the model works.","3":"Editing a line before saving.","4":"The subtitles and the Captions control on the front end."}},"plugin_section":[],"plugin_tags":[1953,1981,20217,1982,222],"plugin_category":[34,50],"plugin_contributors":[276094],"plugin_business_model":[],"class_list":["post-358501","plugin","type-plugin","status-publish","hentry","plugin_tags-accessibility","plugin_tags-captions","plugin_tags-speech-to-text","plugin_tags-subtitles","plugin_tags-video","plugin_category-accessibility","plugin_category-media","plugin_contributors-aiguru","plugin_committers-aiguru"],"banners":{"banner":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/banner-772x250.png?rev=3678007","banner_2x":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/banner-1544x500.png?rev=3678028","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/icon-128x128.png?rev=3678007","icon_2x":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/icon-256x256.png?rev=3678007","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/screenshot-1.png?rev=3678007","caption":"Media &gt; Bharti Subtitles: pick a video and a language."},{"src":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/screenshot-2.png?rev=3678007","caption":"Subtitles appearing while the model works."},{"src":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/screenshot-3.png?rev=3678007","caption":"Editing a line before saving."},{"src":"https:\/\/ps.w.org\/bharti-subtitles\/assets\/screenshot-4.png?rev=3678007","caption":"The subtitles and the Captions control on the front end."}],"raw_content":"<!--section=description-->\n<p>Pick a video in your Media Library, press one button, and get a subtitle file\nattached to it. Visitors then see a subtitles button on the video player.<\/p>\n\n<p>The speech-to-text runs <strong>in the browser<\/strong>, on the machine of whoever pressed\nthe button. Not on your server, and not on anyone's API. That single decision\nis what this plugin is, and everything below follows from it.<\/p>\n\n<h4>Nothing leaves the computer<\/h4>\n\n<p>There are two ways to turn speech into text: send the audio somewhere and get\nthe words back, or run the model where the audio already is. This plugin does\nthe second.<\/p>\n\n<p>For a marketing clip either way is fine. For patient education, legal\nrecordings, internal training, HR material or paid membership content, sending\nthe file to a third party is often the difference between <em>allowed<\/em> and <em>not\nallowed<\/em>.<\/p>\n\n<p>The browser reads the file, works on it, and writes the result back. The only\nthing that ever downloads is the speech model itself, once.<\/p>\n\n<h4>No account, no key, no bill<\/h4>\n\n<ul>\n<li><strong>Nothing to sign up for.<\/strong> No OpenAI account, no API key to create, store,\nrotate or explain to a client.<\/li>\n<li><strong>No per-minute charge.<\/strong> Transcription services meter audio by the minute.\nNothing here is metered \u2014 caption the same course twice, or a hundred hours\nof it, and the cost does not change.<\/li>\n<li><strong>No server load.<\/strong> Your host never transcodes or transcribes anything, so\nthis runs on the cheapest shared hosting without a queue, a cron job or a\nworker process.<\/li>\n<\/ul>\n\n<h4>How it works<\/h4>\n\n<ol>\n<li>Go to <strong>Media &gt; Bharti Subtitles<\/strong>, choose a video and the spoken language, press\n<strong>Generate subtitles<\/strong><\/li>\n<li>Watch the lines appear, then fix anything the model misheard \u2014 names and\ntechnical words are usually where it slips<\/li>\n<li>Press <strong>Save to this video<\/strong>. The <code>.vtt<\/code> is written beside the video and\nattached to it<\/li>\n<\/ol>\n\n<p>Or download <code>.srt<\/code> \/ <code>.vtt<\/code> instead and take it to YouTube, Vimeo or a video\neditor.<\/p>\n\n<h4>What you get<\/h4>\n\n<ul>\n<li>17 languages, including <strong>Hindi, Marathi and Hinglish<\/strong> written in Roman\nscript<\/li>\n<li>Every line editable before you save<\/li>\n<li>Works with the Gutenberg <strong>Video<\/strong> block and the classic <code>[video]<\/code> shortcode<\/li>\n<li>Control how the subtitles look \u2014 font, size, bold, capitals, colour,\nbackground and opacity, shadow, position and alignment \u2014 with a live preview<\/li>\n<li>Translation ready, with a <code>.pot<\/code> file included<\/li>\n<\/ul>\n\n<h4>Accessibility<\/h4>\n\n<p>Captions for prerecorded video are a WCAG 2.1 requirement (Success Criterion\n1.2.2). If your site has an accessibility obligation, this is one of the items\non the list.<\/p>\n\n<h4>Honest limits<\/h4>\n\n<p>Most of this would normally be left out of a plugin page. It is here because\nthe wrong expectation wastes your time and mine.<\/p>\n\n<ul>\n<li><strong>The first run downloads the speech model<\/strong> \u2014 about 50 MB for most\nlanguages, about 250 MB for Hindi, Marathi and Hinglish, which need a larger\none. The browser keeps it, so it is once per machine, not once per video.<\/li>\n<li><strong>Speed depends on the machine, not the hosting.<\/strong> A modern laptop manages\nroughly real time or better. An old one will be slower.<\/li>\n<li><strong>No bulk or overnight processing.<\/strong> One video at a time, with a browser tab\nopen. Doing it in bulk would mean a server doing the work, and then the zero\ncost and the privacy both disappear.<\/li>\n<li><strong>Hindi, Marathi and Hinglish need more correcting than English.<\/strong> The model\nhas seen far less of them. What you get is a usable draft to fix, which is\nmuch faster than typing from nothing \u2014 but it is a draft, and the panel says\nso before you press the button.<\/li>\n<li><strong>The video must be one your browser can play.<\/strong> MP4 (H.264 + AAC) and WebM\nare safest. HEVC inside a <code>.mov<\/code> will not decode.<\/li>\n<\/ul>\n\n<h4>What it needs<\/h4>\n\n<ul>\n<li>A current version of Chrome, Edge, Firefox or Safari<\/li>\n<li>An internet connection the first time, to download the speech model<\/li>\n<li>A writable uploads folder \u2014 the <code>.vtt<\/code> is saved beside the video<\/li>\n<\/ul>\n\n<h3>Source code and build<\/h3>\n\n<p>The two files in <code>assets\/js\/<\/code> are built, not written by hand. Their complete\nsource ships inside this plugin so nothing needs to be taken on trust:<\/p>\n\n<ul>\n<li><code>src\/<\/code> \u2014 all of the TypeScript and React that becomes them<\/li>\n<li><code>package.json<\/code>, <code>tsconfig.json<\/code>, <code>vite.config.ts<\/code>, <code>vite.worker.config.ts<\/code> \u2014\nthe build configuration<\/li>\n<\/ul>\n\n<p>To rebuild from that source:<\/p>\n\n<pre><code>npm install\nnpm run build\n<\/code><\/pre>\n\n<p>which regenerates <code>assets\/js\/subtitles.js<\/code> and\n    assets\/js\/transcribe-worker.js exactly as shipped.<\/p>\n\n<h4>Third-party code<\/h4>\n\n<p>Bundled into those two files by the build, both unmodified:<\/p>\n\n<ul>\n<li><strong>React<\/strong> 18.3 \u2014 https:\/\/github.com\/facebook\/react \u2014 MIT<\/li>\n<li><strong>Transformers.js<\/strong> 3.8.1 \u2014 https:\/\/github.com\/huggingface\/transformers.js \u2014\nApache-2.0<\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>Two things are downloaded into the browser the first time you generate\nsubtitles, and then kept by the browser's cache. Nothing is uploaded, no\naccount is needed, and no key is required.<\/p>\n\n<h4>The speech engine<\/h4>\n\n<ul>\n<li><strong>What:<\/strong> ONNX Runtime Web, the WebAssembly engine that runs the model.\nPart of Transformers.js, pinned to version 3.8.1.<\/li>\n<li><strong>Server:<\/strong> jsDelivr \u2014 <code>https:\/\/cdn.jsdelivr.net\/npm\/@huggingface\/transformers@3.8.1\/dist\/<\/code><\/li>\n<li><strong>When:<\/strong> the first time you press Generate subtitles, once per browser.<\/li>\n<li><strong>Sent:<\/strong> nothing. It is a download.<\/li>\n<\/ul>\n\n<h4>The speech model<\/h4>\n\n<ul>\n<li><strong>What:<\/strong> an OpenAI Whisper model, converted for the browser. About 50 MB\nfor most languages, about 250 MB for Hindi, Marathi and Hinglish.<\/li>\n<li><strong>Server:<\/strong> Hugging Face \u2014 <code>https:\/\/huggingface.co\/<\/code><\/li>\n<li><strong>When:<\/strong> the first time you use a given language, once per browser.<\/li>\n<li><strong>Sent:<\/strong> nothing. It is a download.<\/li>\n<\/ul>\n\n<p>Your video is never sent to either of them, or to anywhere else. It is read\nfrom your own Media Library by your own browser and worked on there.<\/p>\n\n<p>Terms and privacy: jsDelivr \u2014 https:\/\/www.jsdelivr.com\/terms and\nhttps:\/\/www.jsdelivr.com\/terms\/privacy-policy-jsdelivr-net \u00b7 Hugging Face \u2014\nhttps:\/\/huggingface.co\/terms-of-service and https:\/\/huggingface.co\/privacy<\/p>\n\n<h4>Serving them yourself<\/h4>\n\n<p>If your site cannot reach an outside server \u2014 some government, medical and\ninternal deployments cannot, and jsDelivr is blocked in some countries \u2014 put\nthe files on your own host and point the plugin at them:<\/p>\n\n<pre><code>add_filter( 'bharti_subtitles_wasm_paths', function () {\n    return 'https:\/\/example.com\/onnx\/'; \n} );\n<\/code><\/pre>\n\n<p>The files to copy are the contents of <code>@huggingface\/transformers@3.8.1\/dist\/<\/code>.\nThe model can be self-hosted the same way; see the Transformers.js\ndocumentation for <code>env.remoteHost<\/code>.<\/p>\n\n<p>Be honest with yourself about this before installing: if the first run cannot\nreach these two servers, the plugin cannot generate subtitles. After that\nfirst run it works offline.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>, or install the ZIP\nthrough <strong>Plugins &gt; Add New &gt; Upload Plugin<\/strong>.<\/li>\n<li>Activate it.<\/li>\n<li>Go to <strong>Media &gt; Bharti Subtitles<\/strong>.<\/li>\n<li>Pick a video, pick the spoken language, press <strong>Generate subtitles<\/strong>.<\/li>\n<li>Check the lines, fix anything the model misheard, then <strong>Save to this\nvideo<\/strong>.<\/li>\n<\/ol>\n\n<p>Defaults live under <strong>Settings &gt; Bharti Subtitles<\/strong>.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20an%20openai%20key%20or%20any%20other%20account%3F\"><h3>Do I need an OpenAI key or any other account?<\/h3><\/dt>\n<dd><p>No. Nothing is sent to any API. The model runs inside your own browser.<\/p><\/dd>\n<dt id=\"is%20my%20video%20uploaded%20anywhere%3F\"><h3>Is my video uploaded anywhere?<\/h3><\/dt>\n<dd><p>No. The browser reads the file straight from your own Media Library and works\non it locally. The only thing downloaded is the speech model itself, once.<\/p><\/dd>\n<dt id=\"why%20is%20the%20first%20run%20slow%3F\"><h3>Why is the first run slow?<\/h3><\/dt>\n<dd><p>The speech model has to be downloaded the first time \u2014 about 50 MB for most\nlanguages, about 250 MB for Hindi, Marathi and Hinglish, which need a larger\none. After that the browser has it and there is no wait. Transcription speed\nthen depends on the machine, not on your hosting \u2014 a modern laptop does roughly\nreal time or better.<\/p><\/dd>\n<dt id=\"can%20i%20run%20it%20on%20the%20server%20instead%2C%20or%20in%20bulk%20overnight%3F\"><h3>Can I run it on the server instead, or in bulk overnight?<\/h3><\/dt>\n<dd><p>Not in this version. Everything is deliberately in the browser, which is what\nkeeps the cost at zero and the video private. Bulk generation would mean a\nserver doing the work, and that means both of those go away.<\/p><\/dd>\n<dt id=\"the%20subtitles%20do%20not%20show%20on%20the%20front%20end.\"><h3>The subtitles do not show on the front end.<\/h3><\/dt>\n<dd><p>Check three things: the video has subtitles saved (Media &gt; Bharti Subtitles will say\nso), <strong>Settings &gt; Bharti Subtitles &gt; \"Automatically show subtitles\"<\/strong> is on, and your\ntheme is not replacing the video player with its own. If it is, turn the\nsetting off and add the track yourself.<\/p><\/dd>\n<dt id=\"the%20subtitles%20show%2C%20but%20there%20is%20no%20cc%20button.\"><h3>The subtitles show, but there is no CC button.<\/h3><\/dt>\n<dd><p>The Video block has <strong>Playback controls<\/strong> switched off, so the player draws no\ncontrols at all. Select the video in the editor and turn that setting on.\nNothing is wrong with the subtitles \u2014 they are attached, which is why they\nappear on screen.<\/p><\/dd>\n<dt id=\"it%20says%20the%20browser%20could%20not%20read%20the%20audio.\"><h3>It says the browser could not read the audio.<\/h3><\/dt>\n<dd><p>The video is in a codec your browser will not decode \u2014 usually HEVC inside a\n    .mov. Convert it to MP4 (H.264 + AAC), re-upload, and it will work.<\/p><\/dd>\n<dt id=\"which%20languages%20work%3F\"><h3>Which languages work?<\/h3><\/dt>\n<dd><p>English, Spanish, French, German, Italian, Portuguese, Dutch, Russian, Polish,\nJapanese, Korean, Chinese, Turkish and Indonesian are the strong ones. Hindi,\nMarathi and Hinglish also work, with two honest caveats below. Only languages\nthe on-device model actually handles are offered \u2014 listing more would just\nproduce bad subtitles.<\/p><\/dd>\n<dt id=\"what%20is%20different%20about%20hindi%2C%20marathi%20and%20hinglish%3F\"><h3>What is different about Hindi, Marathi and Hinglish?<\/h3><\/dt>\n<dd><p>Two things, and the panel tells you both before you press the button.<\/p>\n\n<p>They need the larger speech model \u2014 about 250 MB instead of 50 MB, and slower\nto run. The smaller model does not write these languages down at all: it turns\nHindi into English and Marathi into Roman letters, so the size buys the script\nitself.<\/p>\n\n<p>And be realistic about the accuracy. The model has seen far less of these\nlanguages than of English, and on a Marathi test most lines came back with\nthe script correct but the words wrong \u2014 close enough to recognise what was\nsaid, not close enough to publish. Expect to rewrite most of them.<\/p>\n\n<p>What is reliably right is the timing. The tedious half of subtitling is\ndeciding which line shows when, and that comes out correct: fourteen cues,\neach three or four seconds, following the speech. Retyping the words into a\nfinished set of cues is still much faster than building the whole thing from\nnothing \u2014 but that is what you are getting, not a draft you lightly correct.<\/p>\n\n<p>English and the European languages do not have this problem.<\/p><\/dd>\n<dt id=\"does%20it%20work%20on%20mobile%3F\"><h3>Does it work on mobile?<\/h3><\/dt>\n<dd><p>The panel is for site owners, so it is built for a desktop browser. The\nsubtitles it produces show on every device, mobile included.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First release.<\/li>\n<\/ul>","raw_excerpt":"Generate subtitles for your Media Library videos in the browser. No API key, no per-minute cost, and the video is never uploaded anywhere.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/358501","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=358501"}],"author":[{"embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/aiguru"}],"wp:attachment":[{"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=358501"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=358501"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=358501"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=358501"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=358501"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/et.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=358501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}