164 lines
5.6 KiB
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> |