|
|
@@ -1,6 +1,6 @@
|
|
|
-import { parentPort } from 'worker_threads';
|
|
|
import fs from 'fs';
|
|
|
import path from 'path';
|
|
|
+import { parentPort } from 'worker_threads';
|
|
|
|
|
|
function isVideoFile(file: string): boolean {
|
|
|
const ext = path.extname(file).toLowerCase();
|
|
|
@@ -10,23 +10,56 @@ function isVideoFile(file: string): boolean {
|
|
|
|
|
|
function isValidVideoFile(file: string): boolean {
|
|
|
try {
|
|
|
- // Read first 64KB to check for video headers
|
|
|
- const buffer = fs.readFileSync(file, { length: 65536 });
|
|
|
- // Simple check for common video signatures
|
|
|
- const signatures = [
|
|
|
- Buffer.from([0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70]), // MP4
|
|
|
- Buffer.from([0x1A, 0x45, 0xDF, 0xA3]), // MKV/WebM
|
|
|
- Buffer.from([0x52, 0x49, 0x46, 0x46]), // AVI
|
|
|
- Buffer.from([0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70, 0x71, 0x74, 0x20, 0x20]), // MOV
|
|
|
- ];
|
|
|
- for (const sig of signatures) {
|
|
|
- if (buffer.indexOf(sig) !== -1) {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ // Check if file exists and is readable
|
|
|
+ if (!fs.existsSync(file)) {
|
|
|
+ return false;
|
|
|
}
|
|
|
- return false;
|
|
|
+
|
|
|
+ const stats = fs.statSync(file);
|
|
|
+ if (stats.size === 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Read first few bytes to check for video file signatures
|
|
|
+ const buffer = Buffer.alloc(12);
|
|
|
+ const fd = fs.openSync(file, 'r');
|
|
|
+ try {
|
|
|
+ fs.readSync(fd, buffer, 0, 12, 0);
|
|
|
+ } finally {
|
|
|
+ fs.closeSync(fd);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check for common video file signatures
|
|
|
+ const signature = buffer.toString('hex');
|
|
|
+
|
|
|
+ // MP4 signature (ftyp box)
|
|
|
+ if (signature.includes('66747970')) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // MKV/WebM signature (EBML)
|
|
|
+ if (signature.startsWith('1a45dfa3')) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // AVI signature (RIFF)
|
|
|
+ if (
|
|
|
+ signature.startsWith('52494646') &&
|
|
|
+ buffer.toString('ascii', 8, 12) === 'AVI '
|
|
|
+ ) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // MOV signature (ftyp)
|
|
|
+ if (signature.includes('66747971') || signature.includes('66747970')) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // For other formats, just check if file is large enough to be a video (> 1MB)
|
|
|
+ // This is a basic heuristic since not all video formats have easily detectable headers
|
|
|
+ return stats.size > 1024 * 1024;
|
|
|
} catch (error) {
|
|
|
- console.warn(`Failed to validate file ${file}: ${error}`);
|
|
|
+ console.warn(`Error validating video file ${file}: ${error}`);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
@@ -43,4 +76,4 @@ parentPort?.on('message', (message) => {
|
|
|
isValid,
|
|
|
});
|
|
|
}
|
|
|
-});
|
|
|
+});
|