Moxie-Multimedia / frontend /src /tests /smart-split.test.ts
turtle89431's picture
Upload folder using huggingface_hub
7312c42 verified
Raw History Blame Contribute Delete
4.92 kB
import { describe, expect, it } from 'vitest'
import {
applySmartSplit,
applySmartSplitToMatchingTasks,
hasMatchingTaskSegment,
splitTrackSegmentAtFrame,
type SmartSplitResult,
} from '@/lib/smart-split'
import type { TrackData } from '@/types/multitrack'
function result(ranges: Array<[number, number]>): SmartSplitResult {
return {
ranges,
}
}
function trackData(): TrackData {
return {
frame_rate: 24,
total_length: 300,
tracks: [
{
id: 'task-track', name: 'Task', type: 'task', color: 'var(--primary)', muted: false, locked: false,
segments: [
{
id: 'linked-task', start_frame: 24, end_frame: 264, color: 'var(--primary)',
content: {
media_type: 'none', text: 'linked', system_prompt: 'system',
images: [{ id: 'image', source_type: 'input', file_path: 'image.png' }],
},
},
{ id: 'other-task', start_frame: 0, end_frame: 24, color: 'var(--primary)', content: { media_type: 'none', text: 'other' } },
],
},
{
id: 'video-track', name: 'Video', type: 'video', color: 'var(--secondary)', muted: false, locked: false,
segments: [{
id: 'video', start_frame: 24, end_frame: 264, color: 'var(--secondary)',
content: { media_type: 'video', source_type: 'input', file_path: 'clip.mp4' },
}],
},
],
}
}
describe('applySmartSplit', () => {
it('maps detector frames to timeline frames and splits linked task ranges', () => {
const updated = applySmartSplit(trackData(), 'video', result([[0, 60], [60, 120], [120, 240]]))
const video = updated.tracks.find((track) => track.type === 'video')!
const task = updated.tracks.find((track) => track.type === 'task')!
expect(video.segments.map(({ start_frame, end_frame }) => [start_frame, end_frame])).toEqual([
[24, 84], [84, 144], [144, 264],
])
expect(video.segments.map((segment) => segment.origin_start_frame)).toEqual([24, 24, 24])
expect(task.segments.filter((segment) => segment.content.text === 'linked')
.map(({ start_frame, end_frame }) => [start_frame, end_frame])).toEqual([
[24, 84], [84, 144], [144, 264],
])
expect(task.segments.find((segment) => segment.id === 'other-task')).toMatchObject({ start_frame: 0, end_frame: 24 })
expect(task.segments.every((segment) => segment.origin_start_frame === undefined)).toBe(true)
const clonedTasks = task.segments.filter((segment) => segment.content.text === 'linked')
expect(clonedTasks.every((segment) => (
segment.content.system_prompt === 'system' && segment.content.images?.[0]?.file_path === 'image.png'
))).toBe(true)
expect(clonedTasks[0].content.images).not.toBe(clonedTasks[1].content.images)
})
it('preserves an existing source trim origin when splitting an already-trimmed video', () => {
const data = trackData()
data.tracks[1].segments[0].origin_start_frame = 0
const updated = applySmartSplit(data, 'video', result([[0, 60], [60, 240]]))
expect(updated.tracks[1].segments.map((segment) => segment.origin_start_frame)).toEqual([0, 0, 0])
expect(updated.tracks[1].segments.map(({ start_frame, end_frame }) => [start_frame, end_frame])).toEqual([
[24, 60], [60, 240], [240, 264],
])
})
it('leaves data unchanged when no internal cut was detected', () => {
const data = trackData()
expect(applySmartSplit(data, 'video', result([[0, 240]]))).toBe(data)
})
it('splits only matching task segments and leaves the video unchanged', () => {
const data = trackData()
expect(hasMatchingTaskSegment(data, 'video')).toBe(true)
const updated = applySmartSplitToMatchingTasks(data, 'video', result([[0, 120], [120, 240]]))
expect(updated.tracks[1].segments).toEqual(data.tracks[1].segments)
expect(updated.tracks[0].segments.filter((segment) => segment.content.text === 'linked')
.map(({ start_frame, end_frame }) => [start_frame, end_frame])).toEqual([
[24, 144], [144, 264],
])
})
it('manually cuts media with a shared source origin and clones task content', () => {
const data = trackData()
const videoResult = splitTrackSegmentAtFrame(data, 'video', 84)
expect(videoResult.tracks[1].segments.map((segment) => ({
range: [segment.start_frame, segment.end_frame],
origin: segment.origin_start_frame,
}))).toEqual([
{ range: [24, 84], origin: 24 },
{ range: [84, 264], origin: 24 },
])
const taskResult = splitTrackSegmentAtFrame(data, 'linked-task', 84)
const tasks = taskResult.tracks[0].segments.filter((segment) => segment.content.text === 'linked')
expect(tasks).toHaveLength(2)
expect(tasks.every((segment) => segment.content.images?.[0]?.file_path === 'image.png')).toBe(true)
expect(tasks[0].content.images).not.toBe(tasks[1].content.images)
})
})