transfer labels when inverting segments #2362

pull/2376/head
Mikael Finstad 1 year ago
parent 2503218d29
commit 2503214f86
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -85,3 +85,63 @@ exports[`converts segments to chapters with single long segment 1`] = `
},
]
`;
exports[`invertSegments > adjacent 1`] = `
[
{
"end": 2,
"start": 0,
},
{
"end": 100,
"name": "Segment 2",
"start": 4,
},
]
`;
exports[`invertSegments > none 1`] = `[]`;
exports[`invertSegments > normal 1`] = `
[
{
"end": 1,
"start": 0,
},
{
"end": 2,
"name": "Marker 1",
"start": 1,
},
{
"end": 5,
"name": "Segment 2",
"start": 3,
},
{
"end": 100,
"name": "Segment 3",
"start": 5,
},
]
`;
exports[`invertSegments > overlap 1 1`] = `[]`;
exports[`invertSegments > overlap 2 1`] = `[]`;
exports[`invertSegments > undefined duration 1`] = `
[
{
"end": 3,
"start": 0,
},
{
"end": undefined,
"name": "Marker 1",
"start": 3,
},
]
`;
exports[`invertSegments > undefined duration 2 1`] = `[]`;

@ -280,7 +280,7 @@ function useSegments({ filePath, workingRef, setWorking, setProgress, videoStrea
const invertAllSegments = useCallback(() => {
// todo leave non selected segments as is?
// treat markers as 0 length
const sortedSegments = sortSegments(selectedSegments.map(({ end, ...rest }) => ({ ...rest, end: end ?? rest.start })));
const sortedSegments = sortSegments(selectedSegments);
const inverseSegmentsAndMarkers = invertSegments(sortedSegments, true, true, fileDuration);

@ -1,6 +1,6 @@
import { test, it, expect } from 'vitest';
import { test, it, expect, describe } from 'vitest';
import { convertSegmentsToChapters, partitionIntoOverlappingRanges, formatSegNum, combineOverlappingSegments } from './segments';
import { convertSegmentsToChapters, partitionIntoOverlappingRanges, formatSegNum, combineOverlappingSegments, invertSegments } from './segments';
it('converts segments to chapters with gaps', () => {
expect(convertSegmentsToChapters([
@ -166,3 +166,50 @@ test('formatSegNum', () => {
expect(formatSegNum(0, 10, 2)).toBe('01');
expect(formatSegNum(0, 10, 3)).toBe('001');
});
describe('invertSegments', () => {
test('normal', () => {
expect(invertSegments([
{ start: 1, name: 'Marker 1' },
{ start: 2, end: 3, name: 'Segment 2' },
{ start: 5, name: 'Segment 3' },
], true, true, 100)).toMatchSnapshot();
});
test('none', () => {
expect(invertSegments([], true, true, 100)).toMatchSnapshot();
});
test('adjacent', () => {
expect(invertSegments([
{ start: 2, end: 3, name: 'Segment 1' },
{ start: 3, end: 4, name: 'Segment 2' },
], true, true, 100)).toMatchSnapshot();
});
test('overlap 1', () => {
expect(invertSegments([
{ start: 2, end: 3.5 },
{ start: 3, end: 4 },
], true, true, 100)).toMatchSnapshot();
});
test('overlap 2', () => {
expect(invertSegments([
{ start: 2, end: 5 },
{ start: 3, end: 4 },
], true, true, 100)).toMatchSnapshot();
});
test('undefined duration', () => {
expect(invertSegments([
{ start: 3, name: 'Marker 1' },
], true, true)).toMatchSnapshot();
});
test('undefined duration 2', () => {
expect(invertSegments([
{ start: 3 },
], false, false)).toMatchSnapshot();
});
});

@ -155,15 +155,22 @@ export function hasAnySegmentOverlap(sortedSegments: { start: number, end: numbe
}
// eslint-disable-next-line space-before-function-paren
export function invertSegments(sortedCutSegments: ({ start: number, end: number, segId?: string | undefined })[], includeFirstSegment: boolean, includeLastSegment: boolean, duration?: number) {
if (sortedCutSegments.length === 0) return [];
export function invertSegments(
sortedSegmentsIn: ({ start: number, end?: number | undefined, segId?: string | undefined, name?: string | undefined })[],
includeFirstSegment: boolean,
includeLastSegment: boolean,
duration?: number,
) {
const sortedSegments = sortedSegmentsIn.map((seg) => ({ ...seg, end: seg.end ?? seg.start }));
if (hasAnySegmentOverlap(sortedCutSegments)) return [];
if (sortedSegments.length === 0) return [];
if (hasAnySegmentOverlap(sortedSegments)) return [];
const ret: { start: number, end?: number | undefined, segId?: string | undefined }[] = [];
const ret: { start: number, end?: number | undefined, segId?: string | undefined, name?: string | undefined }[] = [];
if (includeFirstSegment) {
const firstSeg = sortedCutSegments[0]!;
const firstSeg = sortedSegments[0]!;
if (firstSeg.start > 0) {
ret.push({
start: 0,
@ -173,26 +180,26 @@ export function invertSegments(sortedCutSegments: ({ start: number, end: number,
}
}
sortedCutSegments.forEach((cutSegment, i) => {
sortedSegments.forEach((segment, i) => {
if (i === 0) return;
const previousSeg = sortedCutSegments[i - 1]!;
const inverted: typeof sortedCutSegments[number] = {
const previousSeg = sortedSegments[i - 1]!;
ret.push({
start: previousSeg.end,
end: cutSegment.start,
};
if (previousSeg.segId != null && cutSegment.segId != null) inverted.segId = `${previousSeg.segId}-${cutSegment.segId}`;
ret.push(inverted);
end: segment.start,
...(previousSeg.segId != null && segment.segId != null && { segId: `${previousSeg.segId}-${segment.segId}` }),
...(previousSeg.name != null && { name: previousSeg.name }),
});
});
if (includeLastSegment) {
const lastSeg = sortedCutSegments.at(-1)!;
const lastSeg = sortedSegments.at(-1)!;
if (duration == null || (lastSeg.end != null && lastSeg.end < duration)) {
const inverted: typeof ret[number] = {
ret.push({
start: lastSeg.end,
end: duration,
};
if (lastSeg.segId != null) inverted.segId = `${lastSeg.segId}-end`;
ret.push(inverted);
...(lastSeg.segId != null && { segId: `${lastSeg.segId}-end` }),
...(lastSeg.name != null && { name: lastSeg.name }),
});
}
}
@ -206,7 +213,8 @@ export function convertSegmentsToChapters(sortedSegments: { start: number, end:
if (sortedSegments.length === 0) return [];
if (hasAnySegmentOverlap(sortedSegments)) throw new Error('Segments cannot overlap');
const invertedSegments = invertSegments(sortedSegments, true, false).map(({ end, ...seg }) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const invertedSegments = invertSegments(sortedSegments, true, false).map(({ end, name: _ignored, ...seg }) => {
invariant(end != null); // to please typescript
return { ...seg, end };
});

Loading…
Cancel
Save