zzaria 2024-05-21 08:31:09 +00:00 zatwierdzone przez GitHub
commit 3e55196040
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
3 zmienionych plików z 43 dodań i 8 usunięć

Wyświetl plik

@ -328,8 +328,9 @@ export async function askForAlignSegments() {
nearest: i18n.t('Nearest keyframe'),
before: i18n.t('Previous keyframe'),
after: i18n.t('Next keyframe'),
consistent: i18n.t('True keyframe cut'),
},
inputValue: 'before',
inputValue: 'consistent',
text: i18n.t('Do you want to align segment times to the nearest, previous or next keyframe?'),
});

Wyświetl plik

@ -106,7 +106,7 @@ export const findNextKeyframe = (keyframes: Keyframe[], time: number) => keyfram
const findPreviousKeyframe = (keyframes: Keyframe[], time: number) => keyframes.findLast((keyframe) => keyframe.time <= time);
const findNearestKeyframe = (keyframes: Keyframe[], time: number) => minBy(keyframes, (keyframe) => Math.abs(keyframe.time - time));
export type FindKeyframeMode = 'nearest' | 'before' | 'after';
export type FindKeyframeMode = 'nearest' | 'before' | 'after' | 'consistent';
function findKeyframe(keyframes: Keyframe[], time: number, mode: FindKeyframeMode) {
switch (mode) {
@ -119,6 +119,9 @@ function findKeyframe(keyframes: Keyframe[], time: number, mode: FindKeyframeMod
case 'after': {
return findNextKeyframe(keyframes, time);
}
case 'consistent': {
return findNextKeyframe(keyframes,time);
}
default: {
return undefined;
}

Wyświetl plik

@ -5,7 +5,7 @@ import pMap from 'p-map';
import invariant from 'tiny-invariant';
import sortBy from 'lodash/sortBy';
import { detectSceneChanges as ffmpegDetectSceneChanges, readFrames, mapTimesToSegments, findKeyframeNearTime } from '../ffmpeg';
import { detectSceneChanges as ffmpegDetectSceneChanges, readFrames, mapTimesToSegments, findKeyframeNearTime, getStreamFps, getDuration } from '../ffmpeg';
import { handleError, shuffleArray } from '../util';
import { errorToast } from '../swal';
import { showParametersDialog } from '../dialogs/parameters';
@ -280,18 +280,49 @@ function useSegments({ filePath, workingRef, setWorking, setCutProgress, videoSt
if (response == null) return;
setWorking({ text: i18n.t('Aligning segments to keyframes') });
const { mode, startOrEnd } = response;
if (filePath == null) throw new Error();
const frameTime = 1 / (getStreamFps(videoStream) || 1000);
const duration = await getDuration(filePath);
await modifySelectedSegmentTimes(async (segment) => {
const newSegment = { ...segment };
async function align(key) {
async function align(key: string) {
const time = newSegment[key];
if (filePath == null) throw new Error();
const keyframe = await findKeyframeNearTime({ filePath, streamIndex: videoStream.index, time, mode });
if (keyframe == null) throw new Error(`Cannot find any keyframe within 60 seconds of frame ${time}`);
let keyframe = await findKeyframeNearTime({ filePath, streamIndex: videoStream.index, time, mode });
if (keyframe == null) {
if (mode != 'consistent') {
throw new Error(`Cannot find any keyframe within 60 seconds of frame ${time}`);
}
keyframe = duration;
}
newSegment[key] = keyframe;
}
if (startOrEnd.includes('start')) await align('start');
if (startOrEnd.includes('end')) await align('end');
if (startOrEnd.includes('start')) {
if (mode == 'consistent') {
newSegment.start += frameTime * 0.3;
}
await align('start');
if (mode == 'consistent') {
newSegment.start -= frameTime * 0.7;
}
}
if (startOrEnd.includes('end')) {
await align('end');
if (mode == 'consistent' && newSegment.end != duration) {
newSegment.end -= frameTime * 0.3;
}
}
if (startOrEnd.includes('start')) {
newSegment.start = Math.min(newSegment.start, newSegment.end - frameTime * 0.99); //don't know how ffmpeg interprets cuts between frames
}
else {
newSegment.end = Math.max(newSegment.start + frameTime * 0.99, newSegment.end);
}
return newSegment;
});
} catch (err) {