lossless-cut/src/edlStore.js

134 wiersze
5.1 KiB
JavaScript

import JSON5 from 'json5';
import i18n from 'i18next';
import { parseCuesheet, parseXmeml, parseFcpXml, parseCsv, parsePbf, parseMplayerEdl, formatCsvHuman, formatTsv, formatCsvFrames, formatCsvSeconds, getTimeFromFrameNum } from './edlFormats';
import { askForYouTubeInput } from './dialogs';
const fs = window.require('fs-extra');
const cueParser = window.require('cue-parser');
const { basename } = window.require('path');
const electron = window.require('electron'); // eslint-disable-line
const { dialog } = electron.remote;
export async function loadCsvSeconds(path) {
return parseCsv(await fs.readFile(path, 'utf-8'));
}
export async function loadCsvFrames(path, fps) {
if (!fps) throw new Error('The loaded file has an unknown framerate');
return parseCsv(await fs.readFile(path, 'utf-8'), (frameNum) => getTimeFromFrameNum(fps, frameNum));
}
export async function loadXmeml(path) {
return parseXmeml(await fs.readFile(path, 'utf-8'));
}
export async function loadFcpXml(path) {
return parseFcpXml(await fs.readFile(path, 'utf-8'));
}
export async function loadPbf(path) {
return parsePbf(await fs.readFile(path));
}
export async function loadMplayerEdl(path) {
return parseMplayerEdl(await fs.readFile(path, 'utf-8'));
}
export async function loadCue(path) {
return parseCuesheet(cueParser.parse(path));
}
export async function saveCsv(path, cutSegments) {
await fs.writeFile(path, await formatCsvSeconds(cutSegments));
}
export async function saveCsvHuman(path, cutSegments) {
await fs.writeFile(path, await formatCsvHuman(cutSegments));
}
export async function saveCsvFrames({ path, cutSegments, getFrameCount }) {
await fs.writeFile(path, await formatCsvFrames({ cutSegments, getFrameCount }));
}
export async function saveTsv(path, cutSegments) {
await fs.writeFile(path, await formatTsv(cutSegments));
}
export async function saveLlcProject({ savePath, filePath, cutSegments }) {
const projectData = {
version: 1,
mediaFileName: basename(filePath),
cutSegments: cutSegments.map(({ start, end, name, tags }) => ({ start, end, name, tags })),
};
await fs.writeFile(savePath, JSON5.stringify(projectData, null, 2));
}
export async function loadLlcProject(path) {
return JSON5.parse(await fs.readFile(path));
}
export async function readEdlFile({ type, path, fps }) {
if (type === 'csv') return loadCsvSeconds(path);
if (type === 'csv-frames') return loadCsvFrames(path, fps);
if (type === 'xmeml') return loadXmeml(path);
if (type === 'fcpxml') return loadFcpXml(path);
if (type === 'cue') return loadCue(path);
if (type === 'pbf') return loadPbf(path);
if (type === 'mplayer') return loadMplayerEdl(path);
if (type === 'llc') {
const project = await loadLlcProject(path);
return project.cutSegments;
}
throw new Error('Invalid EDL type');
}
export async function askForEdlImport({ type, fps }) {
if (type === 'youtube') return askForYouTubeInput();
let filters;
if (type === 'csv' || type === 'csv-frames') filters = [{ name: i18n.t('CSV files'), extensions: ['csv'] }];
else if (type === 'xmeml') filters = [{ name: i18n.t('XML files'), extensions: ['xml'] }];
else if (type === 'fcpxml') filters = [{ name: i18n.t('FCPXML files'), extensions: ['fcpxml'] }];
else if (type === 'cue') filters = [{ name: i18n.t('CUE files'), extensions: ['cue'] }];
else if (type === 'pbf') filters = [{ name: i18n.t('PBF files'), extensions: ['pbf'] }];
else if (type === 'mplayer') filters = [{ name: i18n.t('MPlayer EDL'), extensions: ['*'] }];
else if (type === 'llc') filters = [{ name: i18n.t('LosslessCut project'), extensions: ['llc'] }];
const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'], filters });
if (canceled || filePaths.length < 1) return [];
return readEdlFile({ type, path: filePaths[0], fps });
}
export async function exportEdlFile({ type, cutSegments, filePath, getFrameCount }) {
let filters;
let ext;
if (type === 'csv') {
ext = 'csv';
filters = [{ name: i18n.t('CSV files'), extensions: [ext, 'txt'] }];
} else if (type === 'tsv-human') {
ext = 'tsv';
filters = [{ name: i18n.t('TXT files'), extensions: [ext, 'txt'] }];
} else if (type === 'csv-human') {
ext = 'csv';
filters = [{ name: i18n.t('TXT files'), extensions: [ext, 'txt'] }];
} else if (type === 'csv-frames') {
ext = 'csv';
filters = [{ name: i18n.t('TXT files'), extensions: [ext, 'txt'] }];
} else if (type === 'llc') {
ext = 'llc';
filters = [{ name: i18n.t('LosslessCut project'), extensions: [ext, 'llc'] }];
}
const { canceled, filePath: savePath } = await dialog.showSaveDialog({ defaultPath: `${new Date().getTime()}.${ext}`, filters });
if (canceled || !savePath) return;
console.log('Saving', type, savePath);
if (type === 'csv') await saveCsv(savePath, cutSegments);
else if (type === 'tsv-human') await saveTsv(savePath, cutSegments);
else if (type === 'csv-human') await saveCsvHuman(savePath, cutSegments);
else if (type === 'csv-frames') await saveCsvFrames({ path: savePath, cutSegments, getFrameCount });
else if (type === 'llc') await saveLlcProject({ savePath, filePath, cutSegments });
}