nwhisper
Version:
Native Node.js bindings for OpenAI's Whisper using whisper.cpp. High-performance local speech-to-text with custom model support.
76 lines • 3.52 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertToWavType = exports.checkIfFileExists = void 0;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const shelljs_1 = __importDefault(require("shelljs"));
const checkIfFileExists = (filePath) => {
if (!node_fs_1.default.existsSync(filePath)) {
throw new Error(`[nwhisper] Error: No such file: ${filePath}`);
}
};
exports.checkIfFileExists = checkIfFileExists;
async function isValidWavHeader(filePath) {
return new Promise((resolve, reject) => {
const readable = node_fs_1.default.createReadStream(filePath, { end: 43 });
let data = Buffer.alloc(0);
readable.on('data', (chunk) => {
const bufferChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
data = Buffer.concat([data, bufferChunk]);
});
readable.on('end', () => {
const isWav = data.toString('binary', 0, 4) === 'RIFF' || data.toString('binary', 0, 4) === 'RIFX';
if (!isWav) {
resolve(false);
return;
}
if (data.length >= 28) {
const sampleRate = data.readUInt32LE(24);
resolve(sampleRate === 16000);
}
else {
resolve(false);
}
});
readable.on('error', err => reject(err));
});
}
const convertToWavType = async (inputFilePath, logger = console) => {
const fileExtension = node_path_1.default.extname(inputFilePath).toLowerCase();
logger.debug(`[nwhisper] Checking if the file is a valid WAV: ${inputFilePath}`);
if (fileExtension === '.wav') {
const isWav = await isValidWavHeader(inputFilePath);
if (isWav) {
logger.debug(`[nwhisper] File is a valid WAV file.`);
return inputFilePath;
}
else {
logger.debug(`[nwhisper] File has a .wav extension but is not a valid WAV, overwriting...`);
// Use a temporary file to avoid overwrite conflicts
const tempFile = `${inputFilePath}.temp.wav`;
const command = `ffmpeg -nostats -loglevel error -y -i "${inputFilePath}" -ar 16000 -ac 1 -c:a pcm_s16le "${tempFile}"`;
const result = shelljs_1.default.exec(command);
if (result.code !== 0) {
throw new Error(`[nwhisper] Failed to convert audio file: ${result.stderr}`);
}
node_fs_1.default.renameSync(tempFile, inputFilePath);
return inputFilePath;
}
}
else {
// Convert to a new WAV file
const outputFilePath = node_path_1.default.join(node_path_1.default.dirname(inputFilePath), `${node_path_1.default.basename(inputFilePath, fileExtension)}.wav`);
logger.debug(`[nwhisper] Converting to a new WAV file: ${outputFilePath}`);
const command = `ffmpeg -nostats -loglevel error -y -i "${inputFilePath}" -ar 16000 -ac 1 -c:a pcm_s16le "${outputFilePath}"`;
const result = shelljs_1.default.exec(command);
if (result.code !== 0) {
throw new Error(`[nwhisper] Failed to convert audio file: ${result.stderr}`);
}
return outputFilePath;
}
};
exports.convertToWavType = convertToWavType;
//# sourceMappingURL=utils.js.map