Improve duration logic #477

pull/508/head
Mikael Finstad 6 years ago
parent fd6b2d639f
commit 40694fe738

@ -46,6 +46,7 @@ import { saveCsv, loadCsv, loadXmeml, loadCue } from './edlStore';
import {
getOutPath, formatDuration, toast, errorToast, showFfmpegFail, setFileNameTitle, getOutDir, withBlur,
checkDirWriteAccess, dirExists, openDirToast, isMasBuild, isStoreBuild, dragPreventer, doesPlayerSupportFile,
isDurationValid,
} from './util';
import { askForOutDir, askForImportChapters, createNumSegments, createFixedDurationSegments, promptTimeOffset, askForHtml5ifySpeed, askForYouTubeInput, askForFileOpenAction } from './dialogs';
import { openSendReportDialog } from './reporting';
@ -133,8 +134,8 @@ const App = memo(() => {
const [debouncedCutSegments] = useDebounce(cutSegments, 500);
const durationSafe = duration || 1;
const zoomedDuration = duration != null ? duration / zoom : undefined;
const durationSafe = isDurationValid(duration) ? duration : 1;
const zoomedDuration = isDurationValid(duration) ? duration / zoom : undefined;
const isCustomFormatSelected = fileFormat !== detectedFileFormat;
@ -275,6 +276,7 @@ const App = memo(() => {
}, [seekAbs]);
const seekRelPercent = useCallback((val) => {
if (!isDurationValid(zoomedDuration)) return;
seekRel(val * zoomedDuration);
}, [seekRel, zoomedDuration]);
@ -301,7 +303,7 @@ const App = memo(() => {
if (canvasPlayerEnabled) setHideCanvasPreview(false);
}, [canvasPlayerEnabled]);
const comfortZoom = duration ? Math.max(duration / 100, 1) : undefined;
const comfortZoom = isDurationValid(duration) ? Math.max(duration / 100, 1) : undefined;
const toggleComfortZoom = useCallback(() => {
if (!comfortZoom) return;
@ -314,7 +316,7 @@ const App = memo(() => {
const getSegApparentEnd = useCallback((seg) => {
const time = seg.end;
if (time !== undefined) return time;
if (duration !== undefined) return duration;
if (isDurationValid(duration)) return duration;
return 0; // Haven't gotten duration yet
}, [duration]);
@ -348,7 +350,7 @@ const App = memo(() => {
});
if (foundOverlap) return undefined;
if (duration == null) return undefined;
if (!isDurationValid(duration)) return undefined;
const ret = [];
@ -379,6 +381,8 @@ const App = memo(() => {
}, [duration, haveInvalidSegs, sortedCutSegments]);
const setCutTime = useCallback((type, time) => {
if (!isDurationValid(duration)) return;
const currentSeg = currentCutSeg;
if (type === 'start' && time >= getSegApparentEnd(currentSeg)) {
throw new Error('Start time must precede end time');
@ -545,7 +549,10 @@ const App = memo(() => {
const onSartPlaying = useCallback(() => onPlayingChange(true), []);
const onDurationChange = useCallback((e) => {
// Some files report duration infinity first, then proper duration later
if (e.target.duration !== Infinity) setDuration(e.target.duration);
// Sometimes after seeking to end of file, duration might change
const { duration: durationNew } = e.target;
console.log('onDurationChange', durationNew);
if (isDurationValid(durationNew)) setDuration(durationNew);
}, []);
const onTimeUpdate = useCallback((e) => {
@ -688,8 +695,8 @@ const App = memo(() => {
}
}
if (duration) renderThumbnails();
}, 500, [zoomedDuration, duration, filePath, zoomWindowStartTime, thumbnailsEnabled]);
if (isDurationValid(zoomedDuration)) renderThumbnails();
}, 500, [zoomedDuration, filePath, zoomWindowStartTime, thumbnailsEnabled]);
// Cleanup removed thumbnails
useEffect(() => {
@ -1024,7 +1031,8 @@ const App = memo(() => {
]);
const capture = useCallback(async () => {
if (!filePath) return;
if (!filePath || !isDurationValid(duration)) return;
try {
const mustCaptureFfmpeg = html5FriendlyPath || dummyVideoPath;
const currentTime = currentTimeRef.current;
@ -1609,13 +1617,13 @@ const App = memo(() => {
}
async function createNumSegments2() {
if (!checkFileOpened()) return;
if (!checkFileOpened() || !isDurationValid(duration)) return;
const segments = await createNumSegments(duration);
if (segments) loadCutSegments(segments);
}
async function createFixedDurationSegments2() {
if (!checkFileOpened()) return;
if (!checkFileOpened() || !isDurationValid(duration)) return;
const segments = await createFixedDurationSegments(duration);
if (segments) loadCutSegments(segments);
}
@ -2011,7 +2019,6 @@ const App = memo(() => {
seekAbs={seekAbs}
seekRel={seekRel}
zoomRel={zoomRel}
duration={duration}
durationSafe={durationSafe}
apparentCutSegments={apparentCutSegments}
setCurrentSegIndex={setCurrentSegIndex}

@ -40,7 +40,7 @@ const Waveform = memo(({ calculateTimelinePercent, durationSafe, waveform, zoom,
const Timeline = memo(({
durationSafe, getCurrentTime, startTimeOffset, playerTime, commandedTime,
zoom, neighbouringFrames, seekAbs, seekRel, duration, apparentCutSegments, zoomRel,
zoom, neighbouringFrames, seekAbs, seekRel, apparentCutSegments, zoomRel,
setCurrentSegIndex, currentSegIndexSafe, invertCutSegments, inverseCutSegments, formatTimecode,
waveform, shouldShowWaveform, shouldShowKeyframes, timelineHeight, thumbnails,
onZoomWindowStartTimeChange, waveformEnabled, thumbnailsEnabled, wheelSensitivity,
@ -76,8 +76,8 @@ const Timeline = memo(({
}, [calculateTimelinePos, playerTime, zoom]);
const calcZoomWindowStartTime = useCallback(() => (timelineScrollerRef.current
? (timelineScrollerRef.current.scrollLeft / (timelineScrollerRef.current.offsetWidth * zoom)) * duration
: 0), [duration, zoom]);
? (timelineScrollerRef.current.scrollLeft / (timelineScrollerRef.current.offsetWidth * zoom)) * durationSafe
: 0), [durationSafe, zoom]);
// const zoomWindowStartTime = calcZoomWindowStartTime(duration, zoom);
@ -149,8 +149,8 @@ const Timeline = memo(({
const target = timelineWrapperRef.current;
const rect = target.getBoundingClientRect();
const relX = e.srcEvent.pageX - (rect.left + document.body.scrollLeft);
if (duration) seekAbs((relX / target.offsetWidth) * duration);
}, [duration, seekAbs]);
seekAbs((relX / target.offsetWidth) * durationSafe);
}, [durationSafe, seekAbs]);
const onWheel = useCallback((e) => {
const { pixelX, pixelY } = normalizeWheel(e);
@ -245,7 +245,7 @@ const Timeline = memo(({
))}
{shouldShowKeyframes && !areKeyframesTooClose && keyframes.map((f) => (
<div key={f.time} style={{ position: 'absolute', top: 0, bottom: 0, left: `${(f.time / duration) * 100}%`, marginLeft: -1, width: 1, background: 'rgba(0,0,0,0.4)', pointerEvents: 'none' }} />
<div key={f.time} style={{ position: 'absolute', top: 0, bottom: 0, left: `${(f.time / durationSafe) * 100}%`, marginLeft: -1, width: 1, background: 'rgba(0,0,0,0.4)', pointerEvents: 'none' }} />
))}
</div>
</div>

@ -6,7 +6,7 @@ import sortBy from 'lodash/sortBy';
import moment from 'moment';
import i18n from 'i18next';
import { formatDuration, getOutPath, transferTimestamps, filenamify } from './util';
import { formatDuration, getOutPath, transferTimestamps, filenamify, isDurationValid } from './util';
const execa = window.require('execa');
const { join, extname } = window.require('path');
@ -101,6 +101,7 @@ export function isCuttingStart(cutFrom) {
}
export function isCuttingEnd(cutTo, duration) {
if (!isDurationValid(duration)) return true;
return cutTo < duration;
}

@ -159,3 +159,5 @@ export function doesPlayerSupportFile(streams) {
export const isMasBuild = window.process.mas;
export const isStoreBuild = isMasBuild || window.process.windowsStore;
export const isDurationValid = (duration) => Number.isFinite(duration) && duration > 0;

Loading…
Cancel
Save