kopia lustrzana https://github.com/mifi/lossless-cut
add timestamp csv export #546
rodzic
da48d5bd1b
commit
b69c4728d7
|
@ -74,9 +74,15 @@ module.exports = (app, mainWindow, newVersion) => {
|
|||
label: 'Export project',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Human readable (TSV)',
|
||||
label: 'Timestamps (CSV)',
|
||||
click() {
|
||||
mainWindow.webContents.send('exportEdlFile', 'tsv');
|
||||
mainWindow.webContents.send('exportEdlFile', 'csv-human');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Timestamps (TSV/TXT)',
|
||||
click() {
|
||||
mainWindow.webContents.send('exportEdlFile', 'tsv-human');
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
16
src/App.jsx
16
src/App.jsx
|
@ -45,7 +45,7 @@ import {
|
|||
findNearestKeyFrameTime, html5ify as ffmpegHtml5ify, isStreamThumbnail, isAudioSupported, isIphoneHevc, tryReadChaptersToEdl,
|
||||
fixInvalidDuration, getDuration, getTimecodeFromStreams, createChaptersFromSegments,
|
||||
} from './ffmpeg';
|
||||
import { saveCsv, saveTsv, loadCsv, loadXmeml, loadCue, loadPbf } from './edlStore';
|
||||
import { saveCsv, saveTsv, loadCsv, loadXmeml, loadCue, loadPbf, saveCsvHuman } from './edlStore';
|
||||
import {
|
||||
getOutPath, formatDuration, toast, errorToast, showFfmpegFail, setFileNameTitle, getOutDir, withBlur,
|
||||
checkDirWriteAccess, dirExists, openDirToast, isMasBuild, isStoreBuild, dragPreventer, doesPlayerSupportFile,
|
||||
|
@ -1656,17 +1656,21 @@ const App = memo(() => {
|
|||
let ext;
|
||||
if (type === 'csv') {
|
||||
ext = 'csv';
|
||||
filters = [{ name: i18n.t('CSV files'), extensions: [ext] }];
|
||||
} else if (type === 'tsv') {
|
||||
ext = 'txt';
|
||||
filters = [{ name: i18n.t('TXT files'), extensions: [ext] }];
|
||||
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'] }];
|
||||
}
|
||||
|
||||
const { canceled, filePath: fp } = await dialog.showSaveDialog({ defaultPath: `${new Date().getTime()}.${ext}`, filters });
|
||||
if (canceled || !fp) return;
|
||||
console.log('Saving', type, fp);
|
||||
if (type === 'csv') await saveCsv(fp, cutSegments);
|
||||
else if (type === 'tsv') await saveTsv(fp, cutSegments);
|
||||
else if (type === 'tsv-human') await saveTsv(fp, cutSegments);
|
||||
else if (type === 'csv-human') await saveCsvHuman(fp, cutSegments);
|
||||
} catch (err) {
|
||||
errorToast(i18n.t('Failed to export project'));
|
||||
console.error('Failed to export project', type, err);
|
||||
|
|
|
@ -31,8 +31,16 @@ export async function saveCsv(path, cutSegments) {
|
|||
await fs.writeFile(path, str);
|
||||
}
|
||||
|
||||
export async function saveTsv(path, cutSegments) {
|
||||
// TODO escape tab, how?
|
||||
const rows = cutSegments.map(({ start, end, name }) => `${start != null ? formatDuration({ seconds: start }) : ''}\t${end != null ? formatDuration({ seconds: end }) : ''}\t${name}`);
|
||||
await fs.writeFile(path, rows.join('\n'));
|
||||
const formatDurationStr = (duration) => (duration != null ? formatDuration({ seconds: duration }) : '');
|
||||
|
||||
const mapSegments = (segments) => segments.map(({ start, end, name }) => [formatDurationStr(start), formatDurationStr(end), name])
|
||||
|
||||
export async function saveCsvHuman(path, cutSegments) {
|
||||
const str = await csvStringifyAsync(mapSegments(cutSegments));
|
||||
await fs.writeFile(path, str);
|
||||
}
|
||||
|
||||
export async function saveTsv(path, cutSegments) {
|
||||
const str = await csvStringifyAsync(mapSegments(cutSegments), { delimiter: '\t' });
|
||||
await fs.writeFile(path, str);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue