1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-22 10:22:31 +01:00

show commanded time in addition to player time

This commit is contained in:
Mikael Finstad 2020-02-20 13:45:38 +08:00
parent fc4c8873ac
commit b9c99afc5c

View File

@ -87,7 +87,7 @@ const App = memo(() => {
const [working, setWorking] = useState(false);
const [dummyVideoPath, setDummyVideoPath] = useState(false);
const [playing, setPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState();
const [playerTime, setPlayerTime] = useState();
const [duration, setDuration] = useState();
const [cutSegments, setCutSegments] = useState([createSegment()]);
const [currentSegIndex, setCurrentSegIndex] = useState(0);
@ -106,6 +106,7 @@ const App = memo(() => {
const [copyStreamIdsByFile, setCopyStreamIdsByFile] = useState({});
const [streamsSelectorShown, setStreamsSelectorShown] = useState(false);
const [zoom, setZoom] = useState(1);
const [commandedTime, setCommandedTime] = useState(0);
// Preferences
const [captureFormat, setCaptureFormat] = useState(configStore.get('captureFormat'));
@ -163,6 +164,7 @@ const App = memo(() => {
if (outVal > video.duration) outVal = video.duration;
video.currentTime = outVal;
setCommandedTime(outVal);
}
const seekRel = useCallback((val) => {
@ -175,6 +177,7 @@ const App = memo(() => {
const resetState = useCallback(() => {
const video = videoRef.current;
setCommandedTime(0);
video.currentTime = 0;
video.playbackRate = 1;
@ -301,19 +304,22 @@ const App = memo(() => {
return formatDuration({ seconds: sec, fps: timecodeShowFrames ? detectedFps : undefined });
}
const getCurrentTime = useCallback(() => (
playing ? playerTime : commandedTime), [commandedTime, playerTime, playing]);
const addCutSegment = useCallback(() => {
const cutStartTime = currentCutSeg.start;
const cutEndTime = currentCutSeg.end;
if (cutStartTime === undefined && cutEndTime === undefined) return;
const suggestedStart = currentTime;
const suggestedStart = getCurrentTime();
const suggestedEnd = suggestedStart + 10;
const cutSegmentsNew = [
...cutSegments,
createSegment({
start: currentTime,
start: suggestedStart,
end: suggestedEnd <= duration ? suggestedEnd : undefined,
}),
];
@ -322,32 +328,32 @@ const App = memo(() => {
setCutSegments(cutSegmentsNew);
setCurrentSegIndex(currentSegIndexNew);
}, [
currentCutSeg, cutSegments, currentTime, duration,
currentCutSeg, cutSegments, getCurrentTime, duration,
]);
const setCutStart = useCallback(() => {
// https://github.com/mifi/lossless-cut/issues/168
// If we are after the end of the last segment in the timeline,
// add a new segment that starts at currentTime
// add a new segment that starts at playerTime
if (currentCutSeg.end != null
&& currentTime > currentCutSeg.end) {
&& getCurrentTime() > currentCutSeg.end) {
addCutSegment();
} else {
try {
setCutTime('start', currentTime);
setCutTime('start', getCurrentTime());
} catch (err) {
errorToast(err.message);
}
}
}, [setCutTime, currentTime, currentCutSeg, addCutSegment]);
}, [setCutTime, getCurrentTime, currentCutSeg, addCutSegment]);
const setCutEnd = useCallback(() => {
try {
setCutTime('end', currentTime);
setCutTime('end', getCurrentTime());
} catch (err) {
errorToast(err.message);
}
}, [setCutTime, currentTime]);
}, [setCutTime, getCurrentTime]);
async function setOutputDir() {
const { filePaths } = await dialog.showOpenDialog({ properties: ['openDirectory'] });
@ -375,10 +381,10 @@ const App = memo(() => {
queue.add(async () => {
if (!frameRenderEnabled) return;
if (currentTime == null || !filePath) return;
if (playerTime == null || !filePath) return;
try {
const framePathNew = await ffmpeg.renderFrame(currentTime, filePath, effectiveRotation);
const framePathNew = await ffmpeg.renderFrame(playerTime, filePath, effectiveRotation);
setFramePath(framePathNew);
} catch (err) {
console.error(err);
@ -391,7 +397,7 @@ const App = memo(() => {
throttledRender();
}, [
filePath, currentTime, frameRenderEnabled, effectiveRotation,
filePath, playerTime, frameRenderEnabled, effectiveRotation,
]);
// Cleanup old frames
@ -399,14 +405,17 @@ const App = memo(() => {
function onPlayingChange(val) {
setPlaying(val);
if (!val) videoRef.current.playbackRate = 1;
if (!val) {
videoRef.current.playbackRate = 1;
setCommandedTime(videoRef.current.currentTime);
}
}
function onTimeUpdate(e) {
const { currentTime: ct } = e.target;
if (currentTime === ct) return;
const { currentTime } = e.target;
if (playerTime === currentTime) return;
setRotationPreviewRequested(false); // Reset this
setCurrentTime(ct);
setPlayerTime(currentTime);
}
function increaseRotation() {
@ -414,7 +423,7 @@ const App = memo(() => {
setRotationPreviewRequested(true);
}
const offsetCurrentTime = (currentTime || 0) + startTimeOffset;
const offsetCurrentTime = (getCurrentTime() || 0) + startTimeOffset;
const mergeFiles = useCallback(async ({ paths, allStreams }) => {
try {
@ -499,15 +508,18 @@ const App = memo(() => {
const durationSafe = duration || 1;
const currentTimeWidth = 1;
// Prevent it from overflowing (and causing scroll) when end of timeline
const currentTimePos = currentTime !== undefined && currentTime < durationSafe ? `${(currentTime / durationSafe) * 100}%` : undefined;
const calculateTimelinePos = (time) => (time !== undefined && time < durationSafe ? `${(time / durationSafe) * 100}%` : undefined);
const currentTimePos = calculateTimelinePos(playerTime);
const commandedTimePos = calculateTimelinePos(commandedTime);
const zoomed = zoom > 1;
useEffect(() => {
const { currentTime: ct } = videoRef.current;
const { currentTime } = videoRef.current;
timelineScrollerSkipEventRef.current = true;
if (zoom > 1) {
timelineScrollerRef.current.scrollLeft = (ct / durationSafe)
timelineScrollerRef.current.scrollLeft = (currentTime / durationSafe)
* (timelineWrapperRef.current.offsetWidth - timelineScrollerRef.current.offsetWidth);
}
}, [zoom, durationSafe]);
@ -680,12 +692,12 @@ const App = memo(() => {
return;
}
try {
await captureFrame(customOutDir, filePath, videoRef.current, currentTime, captureFormat);
await captureFrame(customOutDir, filePath, videoRef.current, playerTime, captureFormat);
} catch (err) {
console.error(err);
errorToast('Failed to capture frame');
}
}, [filePath, currentTime, captureFormat, customOutDir, html5FriendlyPath, dummyVideoPath]);
}, [filePath, playerTime, captureFormat, customOutDir, html5FriendlyPath, dummyVideoPath]);
const changePlaybackRate = useCallback((dir) => {
const video = videoRef.current;
@ -1427,7 +1439,8 @@ const App = memo(() => {
style={{ height: 36, width: `${zoom * 100}%`, position: 'relative', backgroundColor: '#444' }}
ref={timelineWrapperRef}
>
{currentTimePos !== undefined && <div style={{ position: 'absolute', bottom: 0, top: 0, left: currentTimePos, zIndex: 3, backgroundColor: 'rgba(255, 255, 255, 1)', width: currentTimeWidth, pointerEvents: 'none' }} />}
{currentTimePos !== undefined && <motion.div transition={{ type: 'spring', damping: 70, stiffness: 800 }} animate={{ left: currentTimePos }} style={{ position: 'absolute', bottom: 0, top: 0, zIndex: 3, backgroundColor: 'black', width: currentTimeWidth, pointerEvents: 'none' }} />}
{commandedTimePos !== undefined && <div style={{ left: commandedTimePos, position: 'absolute', bottom: 0, top: 0, zIndex: 4, backgroundColor: 'white', width: currentTimeWidth, pointerEvents: 'none' }} />}
{apparentCutSegments.map((seg, i) => (
<TimelineSeg