ai.chat/transcribe.html

164 lines
5.6 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="contrib/lnstyles/css/lnstyles.css">
<link rel="icon" type="image/svg+xml" href="/contrib/lnstyles/svg/ln.svg">
<script type="application/javascript" src="showdown.min.js"></script>
<title>ai.chat - local ai test chat</title>
</head>
<body class="p-4">
<div class="container-md bg-lightgray border-radius-4 h-100 display-flex flex-column">
<div class="flex-grow-0 bg-lightblue p-1">
<h1>AI.transcribe</h1>
</div>
<div class="flex-grow-0 p-1">
<button id="btnConnect" class="bg-white text-black">Connect</button>
<button id="btnTranscribe" class="bg-white text-black">Transcribe</button>
</div>
<div class="bg-white p-2 m-4 border-radius-1 overflow-auto flex-grow-1">
<div id="transcription" class=""></div>
</div>
</div>
<script type="module">
import { LNS } from "./contrib/lnstyles/js/lnstyles.js";
var $ = LNS;
const markdown = new showdown.Converter();
let config = await fetch("config.json").then((r)=>r.json);
class TranscriptionAPI extends EventTarget
{
constructor(url = undefined) {
super();
this._url = url || "wss://" + location.host + "/websocket";
this._ws = null;
this._connected = false;
this._audioRunning = false;
navigator.mediaDevices.getUserMedia({
audio: true,
channelCount: 1,
sampleRate: 16000,
})
.then((userMedia)=>{
this._userMedia = userMedia;
this._audioContext = new AudioContext();
this._audioSource = this._audioContext.createMediaStreamSource(this._userMedia);
this._sampleRate = this._audioContext.sampleRate;
this._processor = this._audioContext.createScriptProcessor(512, 1, 0);
this._processor.addEventListener("audioprocess", (event)=>{
if (this._connected) {
this._ws.send(event.inputBuffer.getChannelData(0).buffer);
}
});
});
}
async startAudio(){
if (this._connected){
if (!this._audioRunning) {
this._ws.send(JSON.stringify({ samplerate: this._sampleRate, }));
this._audioSource.connect(this._processor);
this._audioRunning = true;
this.fireRecording();
}
} else {
console.log("TranscriptionAPI must be connected to start audio");
}
}
stopAudio(){
if (this._audioRunning){
this._audioSource.disconnect();
this._audioRunning = false;
this.fireMute();
}
}
connect(){
if (this._ws){
console.log("TranscriptionAPI: already connected");
} else {
console.log("TranscriptionAPI: connecting");
this._ws = new WebSocket(this._url);
this._ws.addEventListener("open", (event) => {
console.log("TranscriptionAPI: connected");
this._connected = true;
this._ws.send(JSON.stringify({
command: "start",
}));
this.fireConnected();
});
this._ws.addEventListener("message", (event) => {
console.log(event);
let data = JSON.parse(event.data);
if (data.type && (data.type === "text")) {
$("#transcription").get(0).innerText += data.text;
}
});
this._ws.addEventListener("close", (event) => {
this._ws = null;
this._connected = false;
if (this._audioRunning)
this.stopAudio();
this.fireDisconnected();
});
}
}
disconnect(){
this._ws.close();
}
get connected(){ return this._connected; }
get audioRunning(){ return this._audioRunning; }
fireConnected(){ this.dispatchEvent(new Event("connect")); };
fireDisconnected(){ this.dispatchEvent(new Event("disconnect")); };
fireRecording(){ this.dispatchEvent(new Event("record")); };
fireMute(){ this.dispatchEvent(new Event("mute")); };
}
var tApi = new TranscriptionAPI("ws://localhost:8080");
tApi.addEventListener("connect", ()=>{
console.log("connected to transcription service.");
$("#btnConnect").addClass("bg-green");
});
tApi.addEventListener("disconnect", ()=>{
console.log("disconnected from transcription service.");
$("#btnConnect").removeClass("bg-green");
})
tApi.addEventListener("record", ()=>{
console.log("recording started.");
$("#btnTranscribe").addClass("bg-green");
})
tApi.addEventListener("mute", ()=>{
console.log("recording stopped.");
$("#btnTranscribe").removeClass("bg-green");
})
$("#btnConnect").on("click", ()=>{
if (tApi.connected)
tApi.disconnect();
else
tApi.connect();
});
$("#btnTranscribe").on("click", ()=>{
if (tApi.audioRunning)
tApi.stopAudio();
else
tApi.startAudio();
});
</script>
</body>
</html>