Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export interface IOptions {
logger?: Console
}

export async function nodewhisper(filePath: string, options: IOptions) {
export type FilePath = string

export async function nodewhisper(audioSrc: FilePath | Buffer, options: IOptions) {
const { removeWavFileAfterTranscription = false, logger = console } = options

try {
Expand All @@ -27,11 +29,14 @@ export async function nodewhisper(filePath: string, options: IOptions) {
await autoDownloadModel(logger, options.autoDownloadModelName, options.withCuda)
}

logger.debug(`[Nodejs-whisper] Checking file existence: ${filePath}`)
checkIfFileExists(filePath)
logger.debug(`[Nodejs-whisper] Checking file existence: ${audioSrc}`)
if (!Buffer.isBuffer(audioSrc)) {
logger.debug(`[Nodejs-whisper] Checking file existence: ${audioSrc}`)
checkIfFileExists(audioSrc)
}

logger.debug(`[Nodejs-whisper] Converting file to WAV format: ${filePath}`)
const outputFilePath = await convertToWavType(filePath, logger)
logger.debug(`[Nodejs-whisper] Converting file to WAV format: ${audioSrc}`)
const outputFilePath = await convertToWavType(audioSrc, logger)

logger.debug(`[Nodejs-whisper] Constructing command for file: ${outputFilePath}`)
const command = constructCommand(outputFilePath, options)
Expand Down
65 changes: 55 additions & 10 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs'
import path from 'path'
import shell from 'shelljs'
import { FilePath } from '.'

export const checkIfFileExists = (filePath: string) => {
if (!fs.existsSync(filePath)) {
Expand Down Expand Up @@ -28,38 +29,82 @@ async function isValidWavHeader(filePath) {
})
}

export const convertToWavType = async (inputFilePath, logger = console) => {
const fileExtension = path.extname(inputFilePath).toLowerCase()
export const convertToWavType = async (inputAudioSrc: FilePath | Buffer, logger = console) => {
//When Buffer data is received
if (Buffer.isBuffer(inputAudioSrc)) {
logger.debug('[Nodejs-whisper] Starting audio buffer conversion process')

logger.debug(`[Nodejs-whisper] Checking if the file is a valid WAV: ${inputFilePath}`)
//Create temporary input file
const tempInputPath = `Nodejs-whisper-input_${Date.now()}`
fs.writeFileSync(tempInputPath, inputAudioSrc)
logger.debug(`[Nodejs-whisper] Temporary input file created: ${tempInputPath}`)
Comment on lines +38 to +40
Copy link
Contributor

@MrSwitch MrSwitch Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the output is the name of this wav file plus ".srt" or ".json" or ".vtt" etc..

So with this change having a generated filepath to the .wav would make the corresponding output file paths indeterminate.

(at least that's my understanding #120 (comment))


//Set output WAV file path
const outputFilePath = `Nodejs-whisper-temp_${Date.now()}.wav`
logger.debug(`[Nodejs-whisper] Output WAV path set: ${outputFilePath}`)

try {
//Same logic as before
const command = `ffmpeg -nostats -loglevel error -y -i "${tempInputPath}" -ar 16000 -ac 1 -c:a pcm_s16le "${outputFilePath}"`
logger.debug(`[Nodejs-whisper] Executing ffmpeg command: ${command}`)

const result = shell.exec(command)
if (result.code !== 0) {
console.error(`[Nodejs-whisper] Conversion failed with code ${result.code}`)
throw new Error(`[Nodejs-whisper] Failed to convert buffer to WAV: ${result.stderr}`)
}

logger.debug('[Nodejs-whisper] Audio conversion completed successfully')

fs.unlinkSync(tempInputPath)
logger.debug(`[Nodejs-whisper] Temporary input file cleaned up: ${tempInputPath}`)

return outputFilePath
} catch (error) {
console.error('[Nodejs-whisper] Error during conversion:', error)
if (fs.existsSync(tempInputPath)) {
fs.unlinkSync(tempInputPath)
logger.debug(`[Nodejs-whisper] Cleaned up temp input file: ${tempInputPath}`)
}
if (fs.existsSync(outputFilePath)) {
fs.unlinkSync(outputFilePath)
logger.debug(`[Nodejs-whisper] Cleaned up output file: ${outputFilePath}`)
}
throw error
}
}

const fileExtension = path.extname(inputAudioSrc).toLowerCase()

logger.debug(`[Nodejs-whisper] Checking if the file is a valid WAV: ${inputAudioSrc}`)

if (fileExtension === '.wav') {
const isWav = await isValidWavHeader(inputFilePath)
const isWav = await isValidWavHeader(inputAudioSrc)
if (isWav) {
logger.debug(`[Nodejs-whisper] File is a valid WAV file.`)

return inputFilePath
return inputAudioSrc
} else {
logger.debug(`[Nodejs-whisper] File has a .wav extension but is not a valid WAV, overwriting...`)

// Overwrite the original WAV file
const command = `ffmpeg -nostats -loglevel error -y -i "${inputFilePath}" -ar 16000 -ac 1 -c:a pcm_s16le "${inputFilePath}"`
const command = `ffmpeg -nostats -loglevel error -y -i "${inputAudioSrc}" -ar 16000 -ac 1 -c:a pcm_s16le "${inputAudioSrc}"`
const result = shell.exec(command)
if (result.code !== 0) {
throw new Error(`[Nodejs-whisper] Failed to convert audio file: ${result.stderr}`)
}
return inputFilePath
return inputAudioSrc
}
} else {
// Convert to a new WAV file
const outputFilePath = path.join(
path.dirname(inputFilePath),
`${path.basename(inputFilePath, fileExtension)}.wav`
path.dirname(inputAudioSrc),
`${path.basename(inputAudioSrc, fileExtension)}.wav`
)

logger.debug(`[Nodejs-whisper] 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 command = `ffmpeg -nostats -loglevel error -y -i "${inputAudioSrc}" -ar 16000 -ac 1 -c:a pcm_s16le "${outputFilePath}"`
const result = shell.exec(command)
if (result.code !== 0) {
throw new Error(`[Nodejs-whisper] Failed to convert audio file: ${result.stderr}`)
Expand Down