|
|
|
@ -94,9 +94,9 @@ const videoStyle = { width: '100%', height: '100%', objectFit: 'contain' };
|
|
|
|
|
|
|
|
|
|
|
|
const App = memo(() => {
|
|
|
|
const App = memo(() => {
|
|
|
|
// Per project state
|
|
|
|
// Per project state
|
|
|
|
const [html5FriendlyPath, setHtml5FriendlyPath] = useState();
|
|
|
|
const [previewFilePath, setPreviewFilePath] = useState();
|
|
|
|
const [working, setWorking] = useState();
|
|
|
|
const [working, setWorking] = useState();
|
|
|
|
const [dummyVideoPath, setDummyVideoPath] = useState(false);
|
|
|
|
const [usingDummyVideo, setUsingDummyVideo] = useState(false);
|
|
|
|
const [playing, setPlaying] = useState(false);
|
|
|
|
const [playing, setPlaying] = useState(false);
|
|
|
|
const [playerTime, setPlayerTime] = useState();
|
|
|
|
const [playerTime, setPlayerTime] = useState();
|
|
|
|
const [duration, setDuration] = useState();
|
|
|
|
const [duration, setDuration] = useState();
|
|
|
|
@ -271,15 +271,15 @@ const App = memo(() => {
|
|
|
|
}, [seekRel, detectedFps]);
|
|
|
|
}, [seekRel, detectedFps]);
|
|
|
|
|
|
|
|
|
|
|
|
/* useEffect(() => () => {
|
|
|
|
/* useEffect(() => () => {
|
|
|
|
if (dummyVideoPath) unlink(dummyVideoPath).catch(console.error);
|
|
|
|
if (usingDummyVideo && previewFilePath) unlink(previewFilePath).catch(console.error);
|
|
|
|
}, [dummyVideoPath]); */
|
|
|
|
}, [usingDummyVideo, previewFilePath]); */
|
|
|
|
|
|
|
|
|
|
|
|
// 360 means we don't modify rotation
|
|
|
|
// 360 means we don't modify rotation
|
|
|
|
const isRotationSet = rotation !== 360;
|
|
|
|
const isRotationSet = rotation !== 360;
|
|
|
|
const effectiveRotation = isRotationSet ? rotation : (mainVideoStream && mainVideoStream.tags && mainVideoStream.tags.rotate && parseInt(mainVideoStream.tags.rotate, 10));
|
|
|
|
const effectiveRotation = isRotationSet ? rotation : (mainVideoStream && mainVideoStream.tags && mainVideoStream.tags.rotate && parseInt(mainVideoStream.tags.rotate, 10));
|
|
|
|
|
|
|
|
|
|
|
|
const zoomRel = useCallback((rel) => setZoom(z => Math.min(Math.max(z + rel, 1), zoomMax)), []);
|
|
|
|
const zoomRel = useCallback((rel) => setZoom(z => Math.min(Math.max(z + rel, 1), zoomMax)), []);
|
|
|
|
const canvasPlayerRequired = !!(mainVideoStream && dummyVideoPath);
|
|
|
|
const canvasPlayerRequired = !!(mainVideoStream && usingDummyVideo);
|
|
|
|
const canvasPlayerWanted = !!(mainVideoStream && isRotationSet && !hideCanvasPreview);
|
|
|
|
const canvasPlayerWanted = !!(mainVideoStream && isRotationSet && !hideCanvasPreview);
|
|
|
|
// Allow user to disable it
|
|
|
|
// Allow user to disable it
|
|
|
|
const canvasPlayerEnabled = (canvasPlayerRequired || canvasPlayerWanted);
|
|
|
|
const canvasPlayerEnabled = (canvasPlayerRequired || canvasPlayerWanted);
|
|
|
|
@ -474,7 +474,7 @@ const App = memo(() => {
|
|
|
|
setCustomOutDir(newOutDir);
|
|
|
|
setCustomOutDir(newOutDir);
|
|
|
|
}, [outputDir, setCustomOutDir]);
|
|
|
|
}, [outputDir, setCustomOutDir]);
|
|
|
|
|
|
|
|
|
|
|
|
const effectiveFilePath = dummyVideoPath || html5FriendlyPath || filePath;
|
|
|
|
const effectiveFilePath = previewFilePath || filePath;
|
|
|
|
const fileUri = effectiveFilePath ? filePathToUrl(effectiveFilePath) : '';
|
|
|
|
const fileUri = effectiveFilePath ? filePathToUrl(effectiveFilePath) : '';
|
|
|
|
|
|
|
|
|
|
|
|
const getEdlFilePath = useCallback((fp) => getOutPath(customOutDir, fp, 'llc-edl.csv'), [customOutDir]);
|
|
|
|
const getEdlFilePath = useCallback((fp) => getOutPath(customOutDir, fp, 'llc-edl.csv'), [customOutDir]);
|
|
|
|
@ -724,8 +724,8 @@ const App = memo(() => {
|
|
|
|
video.playbackRate = 1;
|
|
|
|
video.playbackRate = 1;
|
|
|
|
|
|
|
|
|
|
|
|
setFileNameTitle();
|
|
|
|
setFileNameTitle();
|
|
|
|
setHtml5FriendlyPath();
|
|
|
|
setPreviewFilePath();
|
|
|
|
setDummyVideoPath();
|
|
|
|
setUsingDummyVideo(false);
|
|
|
|
setWorking();
|
|
|
|
setWorking();
|
|
|
|
setPlaying(false);
|
|
|
|
setPlaying(false);
|
|
|
|
setDuration();
|
|
|
|
setDuration();
|
|
|
|
@ -770,16 +770,19 @@ const App = memo(() => {
|
|
|
|
if (!hideAllNotifications) toast.fire({ text: i18n.t('Loaded existing preview file: {{ fileName }}', { fileName }) });
|
|
|
|
if (!hideAllNotifications) toast.fire({ text: i18n.t('Loaded existing preview file: {{ fileName }}', { fileName }) });
|
|
|
|
}, [hideAllNotifications]);
|
|
|
|
}, [hideAllNotifications]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const html5ifiedPrefix = 'html5ified-';
|
|
|
|
|
|
|
|
const html5dummySuffix = 'dummy';
|
|
|
|
|
|
|
|
|
|
|
|
const createDummyVideo = useCallback(async (cod, fp) => {
|
|
|
|
const createDummyVideo = useCallback(async (cod, fp) => {
|
|
|
|
const html5ifiedDummyPathDummy = getOutPath(cod, fp, 'html5ified-dummy.mkv');
|
|
|
|
const html5ifiedDummyPath = getOutPath(cod, fp, `${html5ifiedPrefix}${html5dummySuffix}.mkv`);
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
setCutProgress(0);
|
|
|
|
setCutProgress(0);
|
|
|
|
await html5ifyDummy({ filePath: fp, outPath: html5ifiedDummyPathDummy, onProgress: setCutProgress });
|
|
|
|
await html5ifyDummy({ filePath: fp, outPath: html5ifiedDummyPath, onProgress: setCutProgress });
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
setCutProgress();
|
|
|
|
setCutProgress();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setDummyVideoPath(html5ifiedDummyPathDummy);
|
|
|
|
setUsingDummyVideo(true);
|
|
|
|
setHtml5FriendlyPath();
|
|
|
|
setPreviewFilePath(html5ifiedDummyPath);
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
}, [html5ifyDummy, showUnsupportedFileMessage]);
|
|
|
|
}, [html5ifyDummy, showUnsupportedFileMessage]);
|
|
|
|
|
|
|
|
|
|
|
|
@ -826,7 +829,7 @@ const App = memo(() => {
|
|
|
|
|
|
|
|
|
|
|
|
const cleanupFiles = useCallback(async () => {
|
|
|
|
const cleanupFiles = useCallback(async () => {
|
|
|
|
// Because we will reset state before deleting files
|
|
|
|
// Because we will reset state before deleting files
|
|
|
|
const saved = { html5FriendlyPath, dummyVideoPath, filePath, edlFilePath };
|
|
|
|
const saved = { previewFilePath, filePath, edlFilePath };
|
|
|
|
|
|
|
|
|
|
|
|
if (!closeFile()) return;
|
|
|
|
if (!closeFile()) return;
|
|
|
|
|
|
|
|
|
|
|
|
@ -844,10 +847,8 @@ const App = memo(() => {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
setWorking(i18n.t('Cleaning up'));
|
|
|
|
setWorking(i18n.t('Cleaning up'));
|
|
|
|
|
|
|
|
|
|
|
|
if (deleteTmpFiles && saved.html5FriendlyPath) await trash(saved.html5FriendlyPath).catch(console.error);
|
|
|
|
if (deleteTmpFiles && saved.previewFilePath) await trash(saved.previewFilePath).catch(console.error);
|
|
|
|
if (deleteTmpFiles && saved.dummyVideoPath) await trash(saved.dummyVideoPath).catch(console.error);
|
|
|
|
|
|
|
|
if (deleteProjectFile && saved.edlFilePath) await trash(saved.edlFilePath).catch(console.error);
|
|
|
|
if (deleteProjectFile && saved.edlFilePath) await trash(saved.edlFilePath).catch(console.error);
|
|
|
|
|
|
|
|
|
|
|
|
// throw new Error('test');
|
|
|
|
// throw new Error('test');
|
|
|
|
if (deleteOriginal) await trash(saved.filePath);
|
|
|
|
if (deleteOriginal) await trash(saved.filePath);
|
|
|
|
toast.fire({ icon: 'info', title: i18n.t('Cleanup successful') });
|
|
|
|
toast.fire({ icon: 'info', title: i18n.t('Cleanup successful') });
|
|
|
|
@ -863,8 +864,7 @@ const App = memo(() => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
if (value) {
|
|
|
|
if (deleteTmpFiles && saved.html5FriendlyPath) await unlink(saved.html5FriendlyPath).catch(console.error);
|
|
|
|
if (deleteTmpFiles && saved.previewFilePath) await unlink(saved.previewFilePath).catch(console.error);
|
|
|
|
if (deleteTmpFiles && saved.dummyVideoPath) await unlink(saved.dummyVideoPath).catch(console.error);
|
|
|
|
|
|
|
|
if (deleteProjectFile && saved.edlFilePath) await unlink(saved.edlFilePath).catch(console.error);
|
|
|
|
if (deleteProjectFile && saved.edlFilePath) await unlink(saved.edlFilePath).catch(console.error);
|
|
|
|
if (deleteOriginal) await unlink(saved.filePath);
|
|
|
|
if (deleteOriginal) await unlink(saved.filePath);
|
|
|
|
toast.fire({ icon: 'info', title: i18n.t('Cleanup successful') });
|
|
|
|
toast.fire({ icon: 'info', title: i18n.t('Cleanup successful') });
|
|
|
|
@ -876,7 +876,7 @@ const App = memo(() => {
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
setWorking();
|
|
|
|
setWorking();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [filePath, html5FriendlyPath, dummyVideoPath, closeFile, edlFilePath]);
|
|
|
|
}, [filePath, previewFilePath, closeFile, edlFilePath]);
|
|
|
|
|
|
|
|
|
|
|
|
const outSegments = useMemo(() => (invertCutSegments ? inverseCutSegments : apparentCutSegments),
|
|
|
|
const outSegments = useMemo(() => (invertCutSegments ? inverseCutSegments : apparentCutSegments),
|
|
|
|
[invertCutSegments, inverseCutSegments, apparentCutSegments]);
|
|
|
|
[invertCutSegments, inverseCutSegments, apparentCutSegments]);
|
|
|
|
@ -1065,10 +1065,9 @@ const App = memo(() => {
|
|
|
|
if (!filePath) return;
|
|
|
|
if (!filePath) return;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const mustCaptureFfmpeg = html5FriendlyPath || dummyVideoPath;
|
|
|
|
|
|
|
|
const currentTime = currentTimeRef.current;
|
|
|
|
const currentTime = currentTimeRef.current;
|
|
|
|
const video = videoRef.current;
|
|
|
|
const video = videoRef.current;
|
|
|
|
const outPath = mustCaptureFfmpeg
|
|
|
|
const outPath = previewFilePath
|
|
|
|
? await captureFrameFfmpeg({ customOutDir, filePath, currentTime, captureFormat, enableTransferTimestamps })
|
|
|
|
? await captureFrameFfmpeg({ customOutDir, filePath, currentTime, captureFormat, enableTransferTimestamps })
|
|
|
|
: await captureFrameFromTag({ customOutDir, filePath, currentTime, captureFormat, video, enableTransferTimestamps });
|
|
|
|
: await captureFrameFromTag({ customOutDir, filePath, currentTime, captureFormat, video, enableTransferTimestamps });
|
|
|
|
|
|
|
|
|
|
|
|
@ -1077,7 +1076,7 @@ const App = memo(() => {
|
|
|
|
console.error(err);
|
|
|
|
console.error(err);
|
|
|
|
errorToast(i18n.t('Failed to capture frame'));
|
|
|
|
errorToast(i18n.t('Failed to capture frame'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [filePath, captureFormat, customOutDir, html5FriendlyPath, dummyVideoPath, outputDir, enableTransferTimestamps]);
|
|
|
|
}, [filePath, captureFormat, customOutDir, previewFilePath, outputDir, enableTransferTimestamps]);
|
|
|
|
|
|
|
|
|
|
|
|
const changePlaybackRate = useCallback((dir) => {
|
|
|
|
const changePlaybackRate = useCallback((dir) => {
|
|
|
|
if (canvasPlayerEnabled) {
|
|
|
|
if (canvasPlayerEnabled) {
|
|
|
|
@ -1096,8 +1095,6 @@ const App = memo(() => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [playing, canvasPlayerEnabled]);
|
|
|
|
}, [playing, canvasPlayerEnabled]);
|
|
|
|
|
|
|
|
|
|
|
|
const html5ifiedPrefix = 'html5ified-';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getHtml5ifiedPath = useCallback((cod, fp, type) => {
|
|
|
|
const getHtml5ifiedPath = useCallback((cod, fp, type) => {
|
|
|
|
// See also inside ffmpegHtml5ify
|
|
|
|
// See also inside ffmpegHtml5ify
|
|
|
|
const ext = (isMac && ['slowest', 'slow', 'slow-audio'].includes(type)) ? 'mp4' : 'mkv';
|
|
|
|
const ext = (isMac && ['slowest', 'slow', 'slow-audio'].includes(type)) ? 'mp4' : 'mkv';
|
|
|
|
@ -1174,7 +1171,7 @@ const App = memo(() => {
|
|
|
|
setWorking(i18n.t('Loading file'));
|
|
|
|
setWorking(i18n.t('Loading file'));
|
|
|
|
|
|
|
|
|
|
|
|
async function checkAndSetExistingHtml5FriendlyFile() {
|
|
|
|
async function checkAndSetExistingHtml5FriendlyFile() {
|
|
|
|
const speeds = ['slowest', 'slow-audio', 'slow', 'fast-audio', 'fast', 'fastest-audio'];
|
|
|
|
const speeds = ['slowest', 'slow-audio', 'slow', 'fast-audio', 'fast', 'fastest-audio', html5dummySuffix];
|
|
|
|
const prefix = `${getFileBaseName(fp)}-${html5ifiedPrefix}`;
|
|
|
|
const prefix = `${getFileBaseName(fp)}-${html5ifiedPrefix}`;
|
|
|
|
|
|
|
|
|
|
|
|
const outDir = getOutDir(cod, fp);
|
|
|
|
const outDir = getOutDir(cod, fp);
|
|
|
|
@ -1183,26 +1180,22 @@ const App = memo(() => {
|
|
|
|
let path;
|
|
|
|
let path;
|
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
|
|
for (const entry of dirEntries) {
|
|
|
|
for (const entry of dirEntries) {
|
|
|
|
const html5Match = entry.startsWith(prefix);
|
|
|
|
const prefixMatch = entry.startsWith(prefix);
|
|
|
|
if (html5Match) {
|
|
|
|
if (prefixMatch) {
|
|
|
|
path = pathJoin(outDir, entry);
|
|
|
|
|
|
|
|
const speedMatch = speeds.find((s) => new RegExp(`${s}\\..*$`).test(entry.replace(prefix, '')));
|
|
|
|
const speedMatch = speeds.find((s) => new RegExp(`${s}\\..*$`).test(entry.replace(prefix, '')));
|
|
|
|
if (speedMatch) {
|
|
|
|
if (!speedMatch || speedMatch !== html5dummySuffix) { // skip dummy, as it's not very useful
|
|
|
|
speed = speedMatch;
|
|
|
|
path = pathJoin(outDir, entry);
|
|
|
|
|
|
|
|
if (speedMatch) speed = speedMatch; // We want to also capture any custom user suffix (but NOT dummy)
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!path) return false;
|
|
|
|
if (!path) return false;
|
|
|
|
|
|
|
|
|
|
|
|
console.log('Found existing supported file', path, speed);
|
|
|
|
console.log('Found existing supported file', path, speed);
|
|
|
|
if (speed === 'fastest-audio') {
|
|
|
|
setUsingDummyVideo(speed === 'fastest-audio');
|
|
|
|
setDummyVideoPath(path);
|
|
|
|
setPreviewFilePath(path);
|
|
|
|
setHtml5FriendlyPath();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
setHtml5FriendlyPath(path);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
showPreviewFileLoadedMessage(basename(path));
|
|
|
|
showPreviewFileLoadedMessage(basename(path));
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
@ -1234,7 +1227,7 @@ const App = memo(() => {
|
|
|
|
if (streamFps != null) setDetectedFps(streamFps);
|
|
|
|
if (streamFps != null) setDetectedFps(streamFps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const shouldDefaultCopyStream = (stream) => {
|
|
|
|
const shouldCopyStreamByDefault = (stream) => {
|
|
|
|
if (!defaultProcessedCodecTypes.includes(stream.codec_type)) return false;
|
|
|
|
if (!defaultProcessedCodecTypes.includes(stream.codec_type)) return false;
|
|
|
|
// Don't enable thumbnail stream by default if we have a main video stream
|
|
|
|
// Don't enable thumbnail stream by default if we have a main video stream
|
|
|
|
// It's been known to cause issues: https://github.com/mifi/lossless-cut/issues/308
|
|
|
|
// It's been known to cause issues: https://github.com/mifi/lossless-cut/issues/308
|
|
|
|
@ -1244,7 +1237,7 @@ const App = memo(() => {
|
|
|
|
|
|
|
|
|
|
|
|
setMainStreams(streams);
|
|
|
|
setMainStreams(streams);
|
|
|
|
setCopyStreamIdsForPath(fp, () => fromPairs(streams.map((stream) => [
|
|
|
|
setCopyStreamIdsForPath(fp, () => fromPairs(streams.map((stream) => [
|
|
|
|
stream.index, shouldDefaultCopyStream(stream),
|
|
|
|
stream.index, shouldCopyStreamByDefault(stream),
|
|
|
|
])));
|
|
|
|
])));
|
|
|
|
|
|
|
|
|
|
|
|
setFileNameTitle(fp);
|
|
|
|
setFileNameTitle(fp);
|
|
|
|
@ -1259,11 +1252,12 @@ const App = memo(() => {
|
|
|
|
const validDuration = isDurationValid(parseFloat(fd.duration));
|
|
|
|
const validDuration = isDurationValid(parseFloat(fd.duration));
|
|
|
|
|
|
|
|
|
|
|
|
if (html5FriendlyPathRequested) {
|
|
|
|
if (html5FriendlyPathRequested) {
|
|
|
|
setHtml5FriendlyPath(html5FriendlyPathRequested);
|
|
|
|
setUsingDummyVideo(false);
|
|
|
|
|
|
|
|
setPreviewFilePath(html5FriendlyPathRequested);
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
} else if (dummyVideoPathRequested) {
|
|
|
|
} else if (dummyVideoPathRequested) {
|
|
|
|
setDummyVideoPath(dummyVideoPathRequested);
|
|
|
|
setUsingDummyVideo(true);
|
|
|
|
setHtml5FriendlyPath();
|
|
|
|
setPreviewFilePath(dummyVideoPathRequested);
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
showUnsupportedFileMessage();
|
|
|
|
} else if (
|
|
|
|
} else if (
|
|
|
|
!(await checkAndSetExistingHtml5FriendlyFile())
|
|
|
|
!(await checkAndSetExistingHtml5FriendlyFile())
|
|
|
|
@ -1559,9 +1553,8 @@ const App = memo(() => {
|
|
|
|
let audio;
|
|
|
|
let audio;
|
|
|
|
if (ha) {
|
|
|
|
if (ha) {
|
|
|
|
if (speed === 'slowest') audio = 'hq';
|
|
|
|
if (speed === 'slowest') audio = 'hq';
|
|
|
|
else if (speed === 'slow-audio') audio = 'lq';
|
|
|
|
else if (speed === 'slow-audio' || speed === 'fastest-audio') audio = 'lq';
|
|
|
|
else if (speed === 'fast-audio') audio = 'copy';
|
|
|
|
else if (speed === 'fast-audio') audio = 'copy';
|
|
|
|
else if (speed === 'fastest-audio') audio = 'silent-audio';
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let video;
|
|
|
|
let video;
|
|
|
|
@ -1624,7 +1617,7 @@ const App = memo(() => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
|
|
|
|
const MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
|
|
|
|
if (error.code === MEDIA_ERR_SRC_NOT_SUPPORTED && !dummyVideoPath) {
|
|
|
|
if (error.code === MEDIA_ERR_SRC_NOT_SUPPORTED && !usingDummyVideo) {
|
|
|
|
console.error('MEDIA_ERR_SRC_NOT_SUPPORTED');
|
|
|
|
console.error('MEDIA_ERR_SRC_NOT_SUPPORTED');
|
|
|
|
if (hasVideo) {
|
|
|
|
if (hasVideo) {
|
|
|
|
if (isDurationValid(await getDuration(filePath))) {
|
|
|
|
if (isDurationValid(await getDuration(filePath))) {
|
|
|
|
@ -1636,7 +1629,7 @@ const App = memo(() => {
|
|
|
|
await html5ifyAndLoad('fastest-audio');
|
|
|
|
await html5ifyAndLoad('fastest-audio');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [tryCreateDummyVideo, fileUri, dummyVideoPath, hasVideo, hasAudio, html5ifyAndLoad, hideAllNotifications, filePath]);
|
|
|
|
}, [tryCreateDummyVideo, fileUri, usingDummyVideo, hasVideo, hasAudio, html5ifyAndLoad, hideAllNotifications, filePath]);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
function showOpenAndMergeDialog2() {
|
|
|
|
function showOpenAndMergeDialog2() {
|
|
|
|
@ -1952,7 +1945,7 @@ const App = memo(() => {
|
|
|
|
}, []);
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO fastest-audio shows muted
|
|
|
|
// TODO fastest-audio shows muted
|
|
|
|
const VolumeIcon = muted || dummyVideoPath ? FaVolumeMute : FaVolumeUp;
|
|
|
|
const VolumeIcon = muted || usingDummyVideo ? FaVolumeMute : FaVolumeUp;
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
const keyScrollPreventer = (e) => {
|
|
|
|
const keyScrollPreventer = (e) => {
|
|
|
|
|