To install the KeenASR Java Script library in your web projects perform the following steps:
1. Download keenasr-web SDK
Download the trial SDK and unpack it. The archive contains all the relevant resources: JS library, ASR Bundle, and several examples under examples/
directory.
For initial testing you can point your local web server to this directory and try the examples.
2. Conifigure the Web Server
SSL Server Configuration
Core speech recognition functionality is provided via WebAssembely, which requires the server to be setup with SSL.
Cross-Origin Server Configuration
For security purposes, in order to run Web Assembly (which keenasr-web SDK uses) you will need to configure the server to serve relevant pages in a cross-origin isolation state. Configuration will be server specific, but below we provide suggestion for nginx web server. Other web servers will likely have similar configuration settings.
Content-Encoding for .tgz Files
ASR Bundle is served as a gzipped tar archive (e.g. keenA1m-nnet3chain-en-us.tgz). The SDK expects the browser to unzip the archive, so your web server will need to set Content-Encoding
in the response header properly for files ending with .tgz.
For example, if you are using nginx, you will need something like this in your config file:
location ~* \.tgz$ {
add_header 'Content-Encoding' 'gzip';
# Disable nginx's own gzip compression (already compressed)
gzip off;
# Set the Content-Type to what it will be AFTER decompression
default_type application/x-tar;
}
3. Sample Configuration
If you are using nginx, this config snippet would address the requirements described above:
http {
include mime.types;
server {
listen 80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443 default_server ssl;
ssl_certificate /etc/nginx/ssl/cert.pem; # NOTE - YOU WILL NEED TO SETUP THE CERTIFICATE
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
root /usr/share/nginx/html/dist/keenasr-web;
index index.html;
autoindex on;
location ~* \.tgz$ {
add_header 'Content-Encoding' 'gzip';
# Disable nginx's own gzip compression (already compressed)
gzip off;
# Set the Content-Type to what it will be AFTER decompression
default_type application/x-tar;
}
# set Cross Origin headers for all HTML and JS files
location ~* \.(html|js)$ {
add_header 'Cross-Origin-Embedder-Policy' 'require-corp';
add_header 'Cross-Origin-Opener-Policy' 'same-origin';
}
}
}
}
If you are using node express web server (for local testing), this index.js file would satisfy all the requirements listed above (including SSL, using self-signed certificate).
import forge from 'node-forge';
import path from 'path';
import express from 'express';
import https from 'https';
import http from 'http';
import serveIndex from 'serve-index';
import { fileURLToPath } from 'url';
/**
* Generates a self-signed X.509 TLS certificate and RSA private key using node-forge.
*
* The certificate is valid for 1 year from the time of creation and is issued for
* the Common Name (CN) "localhost" with Subject Alternative Names (SAN) for "localhost" and "server".
*
* This function is intended for testing or development purposes only. The certificate
* and private key are returned as PEM-encoded strings and are not written to disk.
*
* @returns {{ cert: string, key: string }} An object containing
* - `cert`: The PEM-encoded self-signed certificate
* - `key`: The PEM-encoded private key corresponding to the certificate
*
* @example
* const { cert, key } = generateSelfSignedCert();
* https.createServer({ key, cert }, app).listen(4430);
*/
function generateSelfSignedCert() {
const pki = forge.pki;
const keys = pki.rsa.generateKeyPair(2048);
const cert = pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
const attrs = [{ name: 'commonName', value: 'localhost' }];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([
{
name: 'subjectAltName',
altNames: [
{ type: 2, value: 'localhost' }, // DNS
{ type: 2, value: 'server' }
]
}
]);
cert.sign(keys.privateKey, forge.md.sha256.create());
const certPem = pki.certificateToPem(cert);
const keyPem = pki.privateKeyToPem(keys.privateKey);
return { cert: certPem, key: keyPem };
}
// ESM __dirname workaround
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const DIST_PATH = path.join(__dirname, '..', 'dist', 'keenasr-web');
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url} ${JSON.stringify(req.params)}`);
// Apply COEP/COOP to all responses
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
if (/\.tgz$/.test(req.url)) {
res.setHeader('Content-Encoding', 'gzip');
}
next();
});
// Static files + autoindex
app.use(
express.static(DIST_PATH, { index: 'index.html' }),
serveIndex(DIST_PATH, { icons: true })
);
// HTTPS server
const sslOptions = generateSelfSignedCert();
https.createServer(sslOptions, app).listen(443, () => {
console.log('HTTPS server listening on port 443');
});
// HTTP to HTTPS redirect
http.createServer((req, res) => {
const host = req.headers.host.split(':')[0];
res.writeHead(301, {
Location: `https://${host}${req.url}`,
});
res.end();
}).listen(80, () => {
console.log('HTTP server listening on port 80 (redirecting to HTTPS)');
});