forked from agenticoding/agenticoding.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfix-wav-files.js
More file actions
151 lines (118 loc) Β· 3.95 KB
/
fix-wav-files.js
File metadata and controls
151 lines (118 loc) Β· 3.95 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env node
/**
* Fix existing WAV files by adding proper headers
* Converts raw PCM data to valid WAV format
*/
import { readdirSync, readFileSync, writeFileSync, statSync, renameSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const AUDIO_OUTPUT_DIR = join(__dirname, '../website/static/audio');
function createWavHeader(pcmDataLength) {
const header = Buffer.alloc(44);
// RIFF chunk descriptor
header.write('RIFF', 0);
header.writeUInt32LE(36 + pcmDataLength, 4);
header.write('WAVE', 8);
// fmt subchunk
header.write('fmt ', 12);
header.writeUInt32LE(16, 16);
header.writeUInt16LE(1, 20);
header.writeUInt16LE(1, 22);
header.writeUInt32LE(24000, 24);
header.writeUInt32LE(24000 * 1 * 2, 28);
header.writeUInt16LE(1 * 2, 32);
header.writeUInt16LE(16, 34);
// data subchunk
header.write('data', 36);
header.writeUInt32LE(pcmDataLength, 40);
return header;
}
function findWavFiles(dir) {
const files = [];
function traverse(currentDir) {
const items = readdirSync(currentDir);
for (const item of items) {
const fullPath = join(currentDir, item);
const stat = statSync(fullPath);
if (stat.isDirectory()) {
traverse(fullPath);
} else if (item.endsWith('.wav')) {
files.push(fullPath);
}
}
}
traverse(dir);
return files;
}
function isValidWav(buffer) {
if (buffer.length < 12) return false;
const header = buffer.slice(0, 12).toString('ascii', 0, 12);
return header.startsWith('RIFF') && header.includes('WAVE');
}
async function fixWavFile(filePath) {
console.log(`\nπ ${filePath}`);
const buffer = readFileSync(filePath);
// Check if already valid
if (isValidWav(buffer)) {
console.log(' β
Already valid WAV file - skipping');
return { status: 'skipped', path: filePath };
}
console.log(' π§ Adding WAV header...');
// Buffer is raw PCM - add WAV header
const wavHeader = createWavHeader(buffer.length);
const wavBuffer = Buffer.concat([wavHeader, buffer]);
// Backup original
const backupPath = filePath + '.bak';
renameSync(filePath, backupPath);
// Write fixed file
writeFileSync(filePath, wavBuffer);
// Verify
const verifyBuffer = readFileSync(filePath);
if (isValidWav(verifyBuffer)) {
console.log(' β
Fixed successfully');
console.log(` Original: ${(buffer.length / 1024 / 1024).toFixed(2)} MB`);
console.log(` Fixed: ${(wavBuffer.length / 1024 / 1024).toFixed(2)} MB`);
console.log(` Backup: ${backupPath}`);
return { status: 'fixed', path: filePath, backup: backupPath };
} else {
console.log(' β Fix failed - restoring backup');
renameSync(backupPath, filePath);
return { status: 'failed', path: filePath };
}
}
async function main() {
console.log('π§ WAV File Repair Utility\n');
console.log(`π Audio directory: ${AUDIO_OUTPUT_DIR}\n`);
const files = findWavFiles(AUDIO_OUTPUT_DIR);
console.log(`Found ${files.length} WAV files\n`);
if (files.length === 0) {
console.log('No WAV files to process.');
return;
}
console.log('='.repeat(60));
const results = { fixed: 0, skipped: 0, failed: 0 };
for (const file of files) {
try {
const result = await fixWavFile(file);
results[result.status]++;
} catch (error) {
console.error(` β Error: ${error.message}`);
results.failed++;
}
}
console.log('\n' + '='.repeat(60));
console.log('\nπ Summary:');
console.log(` β
Fixed: ${results.fixed}`);
console.log(` βοΈ Skipped (already valid): ${results.skipped}`);
console.log(` β Failed: ${results.failed}`);
if (results.fixed > 0) {
console.log('\nπ‘ Tip: .bak files can be deleted after verifying audio playback');
}
console.log('\n⨠Done!\n');
}
main().catch(error => {
console.error('\nπ₯ Fatal error:', error);
process.exit(1);
});