allow frame seek with audio files too

regression: fixes #1079
pull/1089/head
Mikael Finstad 2022-03-17 18:28:59 +08:00
rodzic 0d423b5968
commit 44ca797526
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 25AB36E3E81CBC26
3 zmienionych plików z 18 dodań i 17 usunięć

Wyświetl plik

@ -308,12 +308,13 @@ const App = memo(() => {
}, [seekRel, zoomedDuration]);
const shortStep = useCallback((direction) => {
if (!detectedFps) return;
// If we don't know fps, just assume 30 (for example if audio file)
const fps = detectedFps || 30;
// try to align with frame
const currentTimeNearestFrameNumber = getFrameCountRaw(detectedFps, videoRef.current.currentTime);
const currentTimeNearestFrameNumber = getFrameCountRaw(fps, videoRef.current.currentTime);
const nextFrame = currentTimeNearestFrameNumber + direction;
seekAbs(nextFrame / detectedFps);
seekAbs(nextFrame / fps);
}, [seekAbs, detectedFps]);
// 360 means we don't modify rotation
@ -475,8 +476,6 @@ const App = memo(() => {
const getFrameCount = useCallback((sec) => getFrameCountRaw(detectedFps, sec), [detectedFps]);
const getTimeFromFrameNum = useCallback((frameNum) => getTimeFromFrameNumRaw(detectedFps, frameNum), [detectedFps]);
const formatTimecode = useCallback(({ seconds, shorten }) => {
if (timecodeFormat === 'frameCount') {
const frameCount = getFrameCount(seconds);
@ -1566,14 +1565,13 @@ const App = memo(() => {
const haveVideoStream = !!videoStream;
const haveAudioStream = !!audioStream;
const detectedFpsNew = haveVideoStream ? getStreamFps(videoStream) : undefined;
const copyStreamIdsForPathNew = fromPairs(fileMeta.streams.map((stream) => [
stream.index, shouldCopyStreamByDefault(stream),
]));
if (timecode) setStartTimeOffset(timecode);
if (detectedFpsNew != null) setDetectedFps(detectedFpsNew);
setDetectedFps(haveVideoStream ? getStreamFps(videoStream) : undefined);
if (isAudioDefinitelyNotSupported(fileMeta.streams)) {
toast.fire({ icon: 'info', text: i18n.t('The audio track is not supported. You can convert to a supported format from the menu') });
@ -2150,7 +2148,7 @@ const App = memo(() => {
if (!checkFileOpened()) return;
try {
const edl = await askForEdlImport({ type, getTimeFromFrameNum });
const edl = await askForEdlImport({ type, fps: detectedFps });
if (edl.length > 0) loadCutSegments(edl, true);
} catch (err) {
handleError(err);
@ -2187,7 +2185,7 @@ const App = memo(() => {
const entries = Object.entries(action);
entries.forEach(([key, value]) => electron.ipcRenderer.on(key, value));
return () => entries.forEach(([key, value]) => electron.ipcRenderer.removeListener(key, value));
}, [apparentCutSegments, askSetStartTimeOffset, checkFileOpened, clearSegments, closeBatch, closeFileWithConfirm, concatCurrentBatch, createFixedDurationSegments, createNumSegments, customOutDir, cutSegments, extractAllStreams, fileFormat, filePath, fillSegmentsGaps, getFrameCount, getTimeFromFrameNum, invertAllSegments, loadCutSegments, loadMedia, openSendReportDialogWithState, reorderSegsByStartTime, setWorking, shiftAllSegmentTimes, shuffleSegments, toggleHelp, toggleSettings, tryFixInvalidDuration, userHtml5ifyCurrentFile, userOpenFiles]);
}, [apparentCutSegments, askSetStartTimeOffset, checkFileOpened, clearSegments, closeBatch, closeFileWithConfirm, concatCurrentBatch, createFixedDurationSegments, createNumSegments, customOutDir, cutSegments, detectedFps, extractAllStreams, fileFormat, filePath, fillSegmentsGaps, getFrameCount, invertAllSegments, loadCutSegments, loadMedia, openSendReportDialogWithState, reorderSegsByStartTime, setWorking, shiftAllSegmentTimes, shuffleSegments, toggleHelp, toggleSettings, tryFixInvalidDuration, userHtml5ifyCurrentFile, userOpenFiles]);
const showAddStreamSourceDialog = useCallback(async () => {
try {

Wyświetl plik

@ -1,7 +1,7 @@
import JSON5 from 'json5';
import i18n from 'i18next';
import { parseCuesheet, parseXmeml, parseCsv, parsePbf, parseMplayerEdl, formatCsvHuman, formatTsv, formatCsvFrames, formatCsvSeconds } from './edlFormats';
import { parseCuesheet, parseXmeml, parseCsv, parsePbf, parseMplayerEdl, formatCsvHuman, formatTsv, formatCsvFrames, formatCsvSeconds, getTimeFromFrameNum } from './edlFormats';
import { askForYouTubeInput } from './dialogs';
const fs = window.require('fs-extra');
@ -15,8 +15,9 @@ export async function loadCsvSeconds(path) {
return parseCsv(await fs.readFile(path, 'utf-8'));
}
export async function loadCsvFrames(path, getTimeFromFrameNum) {
return parseCsv(await fs.readFile(path, 'utf-8'), (frameNum) => getTimeFromFrameNum(frameNum));
export async function loadCsvFrames(path, fps) {
if (!fps) throw new Error('The loaded file has an unknown framerate');
return parseCsv(await fs.readFile(path, 'utf-8'), (frameNum) => getTimeFromFrameNum(fps, frameNum));
}
export async function loadXmeml(path) {
@ -64,9 +65,10 @@ export async function loadLlcProject(path) {
return JSON5.parse(await fs.readFile(path));
}
export async function readEdlFile({ type, path, getTimeFromFrameNum }) {
export async function readEdlFile({ type, path, fps }) {
if (type === 'csv') return loadCsvSeconds(path);
if (type === 'csv-frames') return loadCsvFrames(path, getTimeFromFrameNum);
if (type === 'csv-frames') return loadCsvFrames(path, fps);
if (type === 'xmeml') return loadXmeml(path);
if (type === 'cue') return loadCue(path);
if (type === 'pbf') return loadPbf(path);
@ -78,7 +80,7 @@ export async function readEdlFile({ type, path, getTimeFromFrameNum }) {
throw new Error('Invalid EDL type');
}
export async function askForEdlImport({ type, getTimeFromFrameNum }) {
export async function askForEdlImport({ type, fps }) {
if (type === 'youtube') return askForYouTubeInput();
let filters;
@ -91,7 +93,7 @@ export async function askForEdlImport({ type, getTimeFromFrameNum }) {
const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'], filters });
if (canceled || filePaths.length < 1) return [];
return readEdlFile({ type, path: filePaths[0], getTimeFromFrameNum });
return readEdlFile({ type, path: filePaths[0], fps });
}
export async function exportEdlFile({ type, cutSegments, filePath, getFrameCount }) {

Wyświetl plik

@ -391,6 +391,7 @@ function useFfmpegOperations({ filePath, enableTransferTimestamps }) {
if (!needsSmartCut) return smartCutMainPartOutPath;
try {
if (!detectedFps) throw new Error('Smart cut is not possible when FPS is unknown');
const frameDuration = 1 / detectedFps;
const encodeCutTo = Math.max(desiredCutFrom + frameDuration, smartCutFrom - frameDuration); // Subtract one frame so we don't end up with duplicates when concating, and make sure we don't create a 0 length segment