@opensubtitles/video-metadata-extractor
Version:
A comprehensive NPM package for video metadata extraction and subtitle processing using FFmpeg WASM. Supports metadata extraction, individual subtitle extraction, batch subtitle extraction with ZIP downloads, and memory-safe processing of files of any siz
141 lines • 4.45 kB
JavaScript
// Utility functions for file handling
// Video file extensions - only supported formats
export const VIDEO_EXTENSIONS = [
'.mp4', '.mkv', '.avi', '.mov', '.webm', '.flv', '.wmv', '.m4v',
'.ogv', '.3gp', '.3g2', '.f4v'
];
/**
* Check if a file is a supported video file based on extension only
* Only accepts formats that are explicitly supported by the metadata extractor
*/
export const isVideoFile = (file) => {
const fileName = file.name.toLowerCase();
const hasVideoExtension = VIDEO_EXTENSIONS.some(ext => fileName.endsWith(ext));
return hasVideoExtension;
};
/**
* Recursively scan a directory entry and extract all video files
*/
export const scanDirectory = async (entry) => {
const readDirectory = (dirEntry) => {
return new Promise((resolve) => {
const dirReader = dirEntry.createReader();
const allFiles = [];
const readEntries = () => {
dirReader.readEntries(async (entries) => {
if (entries.length === 0) {
resolve(allFiles);
return;
}
for (const entry of entries) {
if (entry.isFile) {
const file = await getFileFromEntry(entry);
if (file && isVideoFile(file)) {
allFiles.push(file);
}
}
else if (entry.isDirectory) {
const subFiles = await readDirectory(entry);
allFiles.push(...subFiles);
}
}
// Continue reading (there might be more entries)
readEntries();
});
};
readEntries();
});
};
return readDirectory(entry);
};
/**
* Get File object from FileSystemFileEntry
*/
export const getFileFromEntry = (entry) => {
return new Promise((resolve, reject) => {
entry.file(resolve, reject);
});
};
/**
* Process dropped items (files and directories)
*/
export const processDroppedItems = async (items) => {
const files = [];
const filteredFiles = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.kind === 'file') {
const entry = item.webkitGetAsEntry();
if (entry?.isFile) {
const file = await getFileFromEntry(entry);
if (isVideoFile(file)) {
files.push(file);
}
else {
filteredFiles.push(file.name);
}
}
else if (entry?.isDirectory) {
const dirFiles = await scanDirectory(entry);
files.push(...dirFiles);
}
}
}
return files;
};
/**
* Process selected files from input element
*/
export const processSelectedFiles = (fileList) => {
const files = [];
const filteredFiles = [];
for (let i = 0; i < fileList.length; i++) {
const file = fileList[i];
if (isVideoFile(file)) {
files.push(file);
}
else {
filteredFiles.push(file.name);
}
}
return files;
};
/**
* Format file size for display
*/
export const formatFileSize = (bytes) => {
if (bytes === 0)
return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
/**
* Extract directory path from file for grouping
*/
export const getDirectoryPath = (file) => {
// For files with webkitRelativePath, use the directory part
if (file.webkitRelativePath) {
const parts = file.webkitRelativePath.split('/');
return parts.slice(0, -1).join('/');
}
// For regular files, return empty string
return '';
};
/**
* Group files by directory
*/
export const groupFilesByDirectory = (files) => {
const groups = new Map();
files.forEach(file => {
const directory = getDirectoryPath(file);
const key = directory || 'root';
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key).push(file);
});
return groups;
};
//# sourceMappingURL=fileUtils.js.map