ai-code-writer
Version:
An AI code writer application using OpenAI APIs for audio transcription and chat completion.
136 lines (135 loc) • 5.35 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = require("stream");
const node_web_audio_api_1 = require("node-web-audio-api");
const node_microphone_1 = __importDefault(require("node-microphone"));
class RecordingHandler {
constructor(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
this.chunks = [];
this.isStopped = false;
this.passThrough = new stream_1.PassThrough();
this.audioContext = new node_web_audio_api_1.AudioContext();
this.silenceDuration = 0;
this.silenceThreshold = 0;
this.MAX_SILENCE_DURATION = 1500;
this.audioInputDetected = false;
this.isSilenceLevelAdjusted = false;
this.registerEvents();
}
startRecording() {
return __awaiter(this, void 0, void 0, function* () {
try {
this.micInstance = new node_microphone_1.default();
const micStream = this.micInstance.startRecording();
micStream.on('data', (chunk) => {
this.chunks.push(chunk);
if (this.passThrough.writable && !this.passThrough.writableEnded && !this.passThrough.writableFinished) {
this.passThrough.write(chunk);
}
if (this.isStopped)
return;
let isSilent = false;
if (this.isSilenceLevelAdjusted) {
isSilent = this.isSilentChunk(chunk);
}
if (this.chunks.length <= 3 && this.isSilenceLevelAdjusted == false) {
this.silenceThreshold = this.getSilenceLevel();
this.isSilenceLevelAdjusted = true;
console.log('Aufzeichnung läuft.');
}
if (isSilent)
this.silenceDuration += chunk.length / this.audioContext.sampleRate * 1000;
else {
this.silenceDuration = 0;
this.audioInputDetected = true;
}
if (this.silenceDuration >= this.MAX_SILENCE_DURATION && this.audioInputDetected) {
this.stopRecording();
}
});
micStream.on('end', () => this.streamEnded());
micStream.on('error', (error) => this.onError(error));
}
catch (error) {
this.reject(error);
}
});
}
getSilenceLevel() {
let sum = 0;
this.chunks.forEach(c => sum += this.getAudioLevel(c));
return sum / this.chunks.length;
}
isSilentChunk(chunk) {
const avg = this.getAudioLevel(chunk);
return avg <= this.silenceThreshold;
}
getAudioLevel(chunk) {
return Math.round(chunk.reduce((sum, value) => sum + Math.abs(value), 0) / chunk.length);
}
registerEvents() {
this.passThrough.on('end', this.onEnd.bind(this));
this.passThrough.on('error', this.onError.bind(this));
}
streamEnded() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.isStopped) {
this.stopRecording();
}
else {
this.onEnd();
}
});
}
onEnd() {
if (!this.isStopped) {
this.stopRecording();
}
this.resolve(Buffer.concat(this.chunks));
this.isStopped = true;
}
onError(error) {
if (!this.isStopped) {
this.stopRecording();
}
this.reject(error);
}
stopRecording() {
if (this.isStopped)
return;
this.isStopped = true;
if (this.micInstance) {
this.micInstance.stopRecording();
this.micInstance = undefined;
}
if (!this.passThrough.destroyed) {
this.passThrough.end();
}
this.audioContext.close().catch((error) => console.error('Error closing audio context:', error));
}
}
class NodeWebAudioAPIAudioRecorder {
startRecording() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const handler = new RecordingHandler(resolve, reject);
handler.startRecording();
});
});
}
}
exports.default = NodeWebAudioAPIAudioRecorder;