Skip to content

Commit 7349986

Browse files
authored
Merge pull request #33 from diffusionstudio/konstantin/fix/split-stacked-mode
Konstantin/fix/split stacked mode
2 parents 12a6081 + 9eaa6ce commit 7349986

File tree

13 files changed

+134
-13
lines changed

13 files changed

+134
-13
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@diffusionstudio/core",
33
"private": false,
4-
"version": "1.1.0",
4+
"version": "1.1.1",
55
"type": "module",
66
"description": "Build bleeding edge video processing applications",
77
"files": [

src/clips/audio/audio.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
*/
77

88
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
9+
import { captions } from '../../test/captions';
910
import { Composition } from '../../composition';
1011
import { AudioClip } from './audio';
11-
import { Timestamp } from '../../models';
12+
import { Timestamp, Transcript } from '../../models';
1213
import { AudioSource } from '../../sources';
1314

1415
import type { MockInstance } from 'vitest';
@@ -197,6 +198,7 @@ describe('Copying the AudioClip', () => {
197198
clip.duration.frames = 100;
198199
clip.muted = true;
199200
clip.volume = 0.2;
201+
clip.transcript = Transcript.fromJSON(captions);
200202

201203
const copy = clip.copy();
202204

@@ -208,6 +210,7 @@ describe('Copying the AudioClip', () => {
208210
expect(copy.muted).toBe(true);
209211
expect(copy.source).toBeInstanceOf(AudioSource);
210212
expect(copy.source.id).toBe(clip.source.id);
213+
expect(copy.transcript?.id).toBe(clip.transcript.id);
211214
});
212215

213216
it('should transfer base properties', () => {

src/clips/audio/audio.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export class AudioClip extends MediaClip<AudioClipProps> {
8686

8787
public copy(): AudioClip {
8888
const clip = AudioClip.fromJSON(JSON.parse(JSON.stringify(this)));
89+
clip.transcript = this.transcript;
8990
clip.source = this.source;
9091

9192
return clip;

src/clips/clip/clip.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ export class Clip<Props extends ClipProps = ClipProps> extends EventEmitterMixin
230230

231231
replaceKeyframes(copy, copy.start.subtract(this.start));
232232

233-
await this.track.add(copy);
233+
const index = this.track.clips.findIndex((c) => c.id == this.id);
234+
await this.track.add(copy, index + 1);
234235

235236
return copy;
236237
}

src/clips/media/media.spec.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ describe('The Media Clip', () => {
285285
expect(copy.range[0].frames).toBe(10);
286286
expect(copy.range[1]).toBeInstanceOf(Timestamp);
287287
expect(copy.range[1].frames).toBe(80);
288+
expect(copy.transcript?.id).toBe(clip.transcript.id);
288289
});
289290

290291
it('should generate a caption track using a transcript', async () => {
@@ -295,7 +296,7 @@ describe('The Media Clip', () => {
295296
const composition = new Composition();
296297
await composition.add(clip);
297298

298-
const track = await clip.generateCaptions();
299+
const track = await clip.addCaptions();
299300

300301
expect(composition.tracks.length).toBe(2);
301302

@@ -420,6 +421,48 @@ describe('Split tests - the Media Clip object', () => {
420421
await expect(() => clip.split()).rejects.toThrowError();
421422
});
422423

424+
it('should split the clip in place when the track is set to stacked', async () => {
425+
const clip1 = new MediaClip({
426+
offset: new Timestamp(1000),
427+
name: 'foo',
428+
});
429+
430+
const clip2 = new MediaClip({
431+
offset: new Timestamp(500),
432+
name: 'bar',
433+
});
434+
435+
clip1.duration.millis = 3000;
436+
clip2.duration.millis = 2000;
437+
438+
const track = new MediaTrack().stacked();
439+
440+
await track.add(clip1);
441+
await track.add(clip2);
442+
443+
expect(track.clips.length).toBe(2);
444+
445+
expect(track.clips[0].name).toBe('foo');
446+
expect(track.clips[0].start.millis).toBe(0);
447+
expect(track.clips[0].stop.millis).toBe(3000);
448+
449+
expect(track.clips[1].name).toBe('bar');
450+
expect(track.clips[1].start.millis).toBe(3001);
451+
expect(track.clips[1].stop.millis).toBe(5001);
452+
453+
await clip1.split(new Timestamp(2000));
454+
455+
expect(track.clips.length).toBe(3);
456+
expect(track.clips[0].start.millis).toBe(0);
457+
expect(track.clips[0].stop.millis).toBe(2000);
458+
459+
expect(track.clips[1].start.millis).toBe(2001);
460+
expect(track.clips[1].stop.millis).toBe(3000);
461+
462+
expect(track.clips[2].start.millis).toBe(3001);
463+
expect(track.clips[2].stop.millis).toBe(5001);
464+
});
465+
423466
it('should not split the clip when no track is provided', async () => {
424467
const clip = new MediaClip({
425468
offset: new Timestamp(1000),

src/clips/media/media.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ export class MediaClip<Props extends MediaClipProps = MediaClipProps> extends Cl
233233
}
234234

235235
public copy(): MediaClip {
236-
return MediaClip.fromJSON(JSON.parse(JSON.stringify(this)));
236+
const clip = MediaClip.fromJSON(JSON.parse(JSON.stringify(this)));
237+
clip.transcript = this.transcript;
238+
return clip;
237239
}
238240

239241
public async split(time?: frame | Timestamp): Promise<this> {
@@ -267,7 +269,8 @@ export class MediaClip<Props extends MediaClipProps = MediaClipProps> extends Cl
267269

268270
replaceKeyframes(copy, copy.start.subtract(this.start));
269271

270-
await this.track.add(copy);
272+
const index = this.track.clips.findIndex((c) => c.id == this.id);
273+
await this.track.add(copy, index + 1);
271274

272275
return copy;
273276
}

src/clips/video/video.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import { BlurFilter } from 'pixi.js';
1010
import { Source, VideoSource } from '../../sources';
1111
import { VideoClip } from './video';
1212
import { Composition } from '../../composition';
13-
import { Keyframe, Timestamp } from '../../models';
13+
import { Keyframe, Timestamp, Transcript } from '../../models';
1414
import { sleep } from '../../utils';
1515
import { FrameBuffer } from './buffer';
1616

1717
import type { MockInstance } from 'vitest';
18+
import { captions } from '../../test/captions';
1819

1920

2021
const file = new File([], 'video.mp4', { type: 'video/mp4' });
@@ -346,6 +347,7 @@ describe('Copying the VidoClip', () => {
346347
clip.duration.frames = 100;
347348
clip.muted = true;
348349
clip.volume = 0.2;
350+
clip.transcript = Transcript.fromJSON(captions);
349351

350352
const copy = clip.copy();
351353

@@ -358,6 +360,7 @@ describe('Copying the VidoClip', () => {
358360
expect(copy.muted).toBe(true);
359361
expect(copy.source).toBeInstanceOf(VideoSource);
360362
expect(copy.source.id).toBe(clip.source.id);
363+
expect(copy.transcript?.id).toBe(clip.transcript.id);
361364
});
362365

363366
it('should transfer visual properties', async () => {

src/clips/video/video.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ export class VideoClip extends VisualMixin(MediaClip<VideoClipProps>) {
142142
const clip = VideoClip.fromJSON(JSON.parse(JSON.stringify(this)));
143143
clip.filters = this.filters;
144144
clip.source = this.source;
145+
clip.transcript = this.transcript;
145146

146147
return clip;
147148
}

src/tracks/track/track.interfaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type { Timestamp } from '../../models';
1212

1313
export interface InsertStrategy<T extends InsertMode> {
1414
readonly mode: T;
15-
add(clip: Clip, track: Track<Clip>): void;
15+
add(clip: Clip, track: Track<Clip>, index?: number): void;
1616
update(clip: Clip, track: Track<Clip>): void;
1717
offset(time: Timestamp, track: Track<Clip>): void;
1818
}

src/tracks/track/track.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,45 @@ describe('The Track Object', () => {
5757
expect(track.clips.at(2)?.stop.frames).toBe(12);
5858
});
5959

60+
it('should be able to add clips at an index, if stacked', async () => {
61+
track.stacked();
62+
63+
await track.add(new Clip({ stop: 10, start: 0 }));
64+
await track.add(new Clip({ stop: 10, start: 0 }));
65+
await track.add(new Clip({ stop: 10, start: 0 }));
66+
67+
expect(track.clips.length).toBe(3);
68+
expect(track.start.frames).toBe(0);
69+
expect(track.stop.frames).toBe(30);
70+
71+
await track.add(new Clip({ stop: 2, start: 0 }), 1);
72+
73+
expect(track.clips[0].start.frames).toBe(0);
74+
expect(track.clips[0].stop.frames).toBe(10);
75+
76+
expect(track.clips[1].start.frames).toBe(10);
77+
expect(track.clips[1].stop.frames).toBe(12);
78+
79+
expect(track.clips[2].start.frames).toBe(12);
80+
expect(track.clips[2].stop.frames).toBe(22);
81+
82+
await track.add(new Clip({ stop: 15, start: 10 }), 4);
83+
84+
expect(track.clips[0].start.frames).toBe(0);
85+
expect(track.clips[0].stop.frames).toBe(10);
86+
87+
expect(track.clips[4].start.frames).toBe(32);
88+
expect(track.clips[4].stop.frames).toBe(37);
89+
90+
await track.clips[0].split(5);
91+
92+
expect(track.clips[0].start.frames).toBe(0);
93+
expect(track.clips[0].stop.frames).toBe(5);
94+
95+
expect(track.clips[1].start.frames).toBe(5);
96+
expect(track.clips[1].stop.frames).toBe(10);
97+
});
98+
6099
it('should snap the clip when it overlaps with the end of another clip', async () => {
61100
const clip0 = new Clip({ stop: 20, start: 0 });
62101
const clip1 = new Clip({ stop: 30, start: 11 });

0 commit comments

Comments
 (0)