mirror of
https://github.com/mifi/lossless-cut.git
synced 2024-11-25 11:43:17 +01:00
Allow turning off keyframe display #259
This commit is contained in:
parent
9e7a4e317f
commit
8d08fc5237
@ -174,7 +174,7 @@ const Timeline = memo(({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{mainVideoStream && shouldShowKeyframes && neighbouringFrames.filter(f => f.keyframe).map((f) => (
|
{shouldShowKeyframes && neighbouringFrames.filter(f => f.keyframe).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,1)', pointerEvents: 'none' }} />
|
<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,1)', pointerEvents: 'none' }} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { FaHandPointLeft, FaHandPointRight, FaStepBackward, FaStepForward, FaCaretLeft, FaCaretRight, FaPause, FaPlay, FaImages } from 'react-icons/fa';
|
import { FaHandPointLeft, FaHandPointRight, FaStepBackward, FaStepForward, FaCaretLeft, FaCaretRight, FaPause, FaPlay, FaImages, FaKey } from 'react-icons/fa';
|
||||||
import { GiSoundWaves } from 'react-icons/gi';
|
import { GiSoundWaves } from 'react-icons/gi';
|
||||||
// import useTraceUpdate from 'use-trace-update';
|
// import useTraceUpdate from 'use-trace-update';
|
||||||
|
|
||||||
import { getSegColors, parseDuration, formatDuration } from './util';
|
import { getSegColors, parseDuration, formatDuration } from './util';
|
||||||
import { primaryColor } from './colors';
|
import { primaryTextColor } from './colors';
|
||||||
|
|
||||||
|
|
||||||
const TimelineControls = memo(({
|
const TimelineControls = memo(({
|
||||||
@ -12,6 +12,7 @@ const TimelineControls = memo(({
|
|||||||
setCurrentSegIndex, cutStartTimeManual, setCutStartTimeManual, cutEndTimeManual, setCutEndTimeManual,
|
setCurrentSegIndex, cutStartTimeManual, setCutStartTimeManual, cutEndTimeManual, setCutEndTimeManual,
|
||||||
duration, jumpCutEnd, jumpCutStart, startTimeOffset, setCutTime, currentApparentCutSeg,
|
duration, jumpCutEnd, jumpCutStart, startTimeOffset, setCutTime, currentApparentCutSeg,
|
||||||
playing, shortStep, playCommand, setTimelineMode, hasAudio, hasVideo, timelineMode,
|
playing, shortStep, playCommand, setTimelineMode, hasAudio, hasVideo, timelineMode,
|
||||||
|
keyframesEnabled, setKeyframesEnabled,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
segActiveBgColor: currentSegActiveBgColor,
|
segActiveBgColor: currentSegActiveBgColor,
|
||||||
@ -118,7 +119,7 @@ const TimelineControls = memo(({
|
|||||||
{hasAudio && (
|
{hasAudio && (
|
||||||
<GiSoundWaves
|
<GiSoundWaves
|
||||||
size={24}
|
size={24}
|
||||||
style={{ padding: '0 5px', color: timelineMode === 'waveform' ? primaryColor : undefined }}
|
style={{ padding: '0 5px', color: timelineMode === 'waveform' ? primaryTextColor : undefined }}
|
||||||
role="button"
|
role="button"
|
||||||
title="Show waveform"
|
title="Show waveform"
|
||||||
onClick={() => setTimelineMode('waveform')}
|
onClick={() => setTimelineMode('waveform')}
|
||||||
@ -127,12 +128,20 @@ const TimelineControls = memo(({
|
|||||||
{hasVideo && (
|
{hasVideo && (
|
||||||
<FaImages
|
<FaImages
|
||||||
size={20}
|
size={20}
|
||||||
style={{ padding: '0 5px', color: timelineMode === 'thumbnails' ? primaryColor : undefined }}
|
style={{ padding: '0 5px', color: timelineMode === 'thumbnails' ? primaryTextColor : undefined }}
|
||||||
role="button"
|
role="button"
|
||||||
title="Show thumbnails"
|
title="Show thumbnails"
|
||||||
onClick={() => setTimelineMode('thumbnails')}
|
onClick={() => setTimelineMode('thumbnails')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<FaKey
|
||||||
|
size={16}
|
||||||
|
style={{ padding: '0 5px', color: keyframesEnabled ? primaryTextColor : undefined }}
|
||||||
|
role="button"
|
||||||
|
title="Show keyframes"
|
||||||
|
onClick={() => setKeyframesEnabled(v => !v)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ flexGrow: 1 }} />
|
<div style={{ flexGrow: 1 }} />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
export const saveColor = 'hsl(158, 100%, 43%)';
|
export const saveColor = 'hsl(158, 100%, 43%)';
|
||||||
export const primaryColor = 'hsl(194, 78%, 47%)';
|
export const primaryColor = 'hsl(194, 78%, 47%)';
|
||||||
|
export const primaryTextColor = 'hsla(194, 100%, 66%, 1)';
|
||||||
export const waveformColor = '#ffffff'; // Must be hex because used by ffmpeg
|
export const waveformColor = '#ffffff'; // Must be hex because used by ffmpeg
|
||||||
export const controlsBackground = '#6b6b6b';
|
export const controlsBackground = '#6b6b6b';
|
||||||
export const timelineBackground = '#444';
|
export const timelineBackground = '#444';
|
||||||
|
@ -147,10 +147,11 @@ const App = memo(() => {
|
|||||||
const [shortestFlag, setShortestFlag] = useState(false);
|
const [shortestFlag, setShortestFlag] = useState(false);
|
||||||
const [debouncedWaveformData, setDebouncedWaveformData] = useState();
|
const [debouncedWaveformData, setDebouncedWaveformData] = useState();
|
||||||
const [debouncedReadKeyframesData, setDebouncedReadKeyframesData] = useState();
|
const [debouncedReadKeyframesData, setDebouncedReadKeyframesData] = useState();
|
||||||
const [waveformEnabled, setWaveformEnabled] = useState(false);
|
|
||||||
const [thumbnailsEnabled, setThumbnailsEnabled] = useState(false);
|
|
||||||
const [zoomWindowStartTime, setZoomWindowStartTime] = useState(0);
|
const [zoomWindowStartTime, setZoomWindowStartTime] = useState(0);
|
||||||
|
|
||||||
|
const [keyframesEnabled, setKeyframesEnabled] = useState(false);
|
||||||
|
const [waveformEnabled, setWaveformEnabled] = useState(false);
|
||||||
|
const [thumbnailsEnabled, setThumbnailsEnabled] = useState(false);
|
||||||
const [showSideBar, setShowSideBar] = useState(true);
|
const [showSideBar, setShowSideBar] = useState(true);
|
||||||
|
|
||||||
// Segment related state
|
// Segment related state
|
||||||
@ -176,8 +177,8 @@ const App = memo(() => {
|
|||||||
}, 500, [filePath, commandedTime, duration, zoom, waveformEnabled, mainAudioStream]);
|
}, 500, [filePath, commandedTime, duration, zoom, waveformEnabled, mainAudioStream]);
|
||||||
|
|
||||||
const [, cancelReadKeyframeDataDebounce] = useDebounce(() => {
|
const [, cancelReadKeyframeDataDebounce] = useDebounce(() => {
|
||||||
setDebouncedReadKeyframesData({ filePath, commandedTime, duration, zoom, mainVideoStream });
|
setDebouncedReadKeyframesData({ keyframesEnabled, filePath, commandedTime, duration, zoom, mainVideoStream });
|
||||||
}, 500, [filePath, commandedTime, duration, zoom, mainVideoStream]);
|
}, 500, [keyframesEnabled, filePath, commandedTime, duration, zoom, mainVideoStream]);
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
const [captureFormat, setCaptureFormat] = useState(configStore.get('captureFormat'));
|
const [captureFormat, setCaptureFormat] = useState(configStore.get('captureFormat'));
|
||||||
@ -681,7 +682,7 @@ const App = memo(() => {
|
|||||||
setCutSegments(cutSegmentsNew);
|
setCutSegments(cutSegmentsNew);
|
||||||
}, [currentSegIndexSafe, cutSegments, setCutSegments]);
|
}, [currentSegIndexSafe, cutSegments, setCutSegments]);
|
||||||
|
|
||||||
const shouldShowKeyframes = calcShouldShowKeyframes(duration, zoom);
|
const shouldShowKeyframes = keyframesEnabled && !!mainVideoStream && calcShouldShowKeyframes(duration, zoom);
|
||||||
|
|
||||||
const thumnailsRef = useRef([]);
|
const thumnailsRef = useRef([]);
|
||||||
const thumnailsRenderingPromiseRef = useRef();
|
const thumnailsRenderingPromiseRef = useRef();
|
||||||
@ -722,7 +723,7 @@ const App = memo(() => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function run() {
|
async function run() {
|
||||||
const d = debouncedReadKeyframesData;
|
const d = debouncedReadKeyframesData;
|
||||||
if (!d || !d.filePath || !d.mainVideoStream || d.commandedTime == null || !calcShouldShowKeyframes(d.duration, d.zoom) || readingKeyframesPromise.current) return;
|
if (!d || !d.keyframesEnabled || !d.filePath || !d.mainVideoStream || d.commandedTime == null || !calcShouldShowKeyframes(d.duration, d.zoom) || readingKeyframesPromise.current) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const promise = ffmpeg.readFrames({ filePath: d.filePath, aroundTime: d.commandedTime, stream: d.mainVideoStream.index, window: ffmpegExtractWindow });
|
const promise = ffmpeg.readFrames({ filePath: d.filePath, aroundTime: d.commandedTime, stream: d.mainVideoStream.index, window: ffmpegExtractWindow });
|
||||||
@ -1650,6 +1651,8 @@ const App = memo(() => {
|
|||||||
timelineMode={timelineMode}
|
timelineMode={timelineMode}
|
||||||
hasAudio={hasAudio}
|
hasAudio={hasAudio}
|
||||||
hasVideo={hasVideo}
|
hasVideo={hasVideo}
|
||||||
|
keyframesEnabled={keyframesEnabled}
|
||||||
|
setKeyframesEnabled={setKeyframesEnabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
|
Loading…
Reference in New Issue
Block a user