-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_ffmpeg.js
More file actions
112 lines (96 loc) · 3.82 KB
/
test_ffmpeg.js
File metadata and controls
112 lines (96 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const express = require('express'); //handles routing and request
const multer = require('multer'); //handles file uploads
const { setLogLevel, Model, Recognizer } = require('vosk');
const fs = require('fs');
const { existsSync } = require("fs");
const { spawn } = require("child_process");
const upload = multer({ dest: 'uploads/' });
const app = express();
const MODEL_PATH = ".\\vosk-model-en-us-0.22";
const SAMPLE_RATE = 16000; // audio quality is processed at 16,000 samples per second (16 kHz)
const BUFFER_SIZE = 4000; // size of audio data chunks processed at a time for vosk
if (!existsSync(MODEL_PATH)) {
console.log("Please download the model from https://alphacephei.com/vosk/models and unpack as " + MODEL_PATH + " in the current folder.");
process.exit();
}
setLogLevel(0);
const model = new Model(MODEL_PATH);
app.post('/transcribe', upload.single('audio'), async (req, res) => {
const startTime = Date.now(); // Start timing
if (!req.file) {
return res.status(400).send('No audio file uploaded.');
}
const FILE_NAME = req.file.path;
console.log('Processing file:', FILE_NAME);
let rec;
try {
rec = new Recognizer({ model: model, sampleRate: SAMPLE_RATE });
} catch (err) {
console.error('Error creating recognizer:', err);
return res.status(500).send('Recognizer error');
}
//recognizer class from Vosk: process audio and generates transcription
let ffmpeg_run;
try {
ffmpeg_run = spawn('ffmpeg', [
'-loglevel', 'quiet',
'-i', FILE_NAME,
'-ar', String(SAMPLE_RATE),
'-ac', '1',
'-f', 's16le',
'-bufsize', String(BUFFER_SIZE),
'-'
]);
} catch (err) {
console.error('Error spawning ffmpeg:', err);
rec.free();
return res.status(500).send('FFmpeg spawn error');
} //convert audio format into s161e raw format so can be processed by vosk
let fullResult = "";
ffmpeg_run.stdout.on('data', (stdout) => {
try {
if (rec.acceptWaveform(stdout)) {
const result = rec.result();
fullResult += result.text + " ";
console.log('Partial result:', result.text);
}
} catch (err) {
console.error('Error processing audio chunk:', err);
}
});
ffmpeg_run.on('close', (code, signal) => { //when ffmpeg finishes
try{
const endTime = Date.now(); // End timing
const duration = (endTime - startTime) / 1000; // seconds
console.log(`Transcription completed in ${duration.toFixed(2)} seconds.`);
console.log('FFmpeg process closed. Code:', code, 'Signal:', signal);
const final = rec.finalResult();
fullResult += final.text;
rec.free();
// model is not freed here since you want to reuse it for other requests
res.json({
transcript: fullResult.trim()
});
fs.unlink(FILE_NAME, (err) => {
if (err) console.error('Error deleting uploaded file:', err);
else console.log('Deleted uploaded file:', FILE_NAME);
});
} catch (err) {
console.error('Error finalizing transcript:', err);
rec.free();
res.status(500).send('Error finalizing transcript');
}
});
ffmpeg_run.on('error', (err) => { //handle ffmpeg error
rec.free();
res.status(500).send('Error running ffmpeg');
});
});
// Global error logging
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection:', reason);
});
app.listen(5500, () => console.log('Server started on port 5500'));