Skip to content

Commit aa79d8c

Browse files
committed
optimized and tested composition update
1 parent 4b57993 commit aa79d8c

File tree

4 files changed

+63
-33
lines changed

4 files changed

+63
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<img src="https://img.shields.io/badge/Made with-Typescript-blue?color=000000&logo=typescript&logoColor=ffffff" alt="Static Badge">
99
<a href="https://vitejs.dev"><img src="https://img.shields.io/badge/Powered%20by-Vite-000000?style=flat&logo=Vite&logoColor=ffffff" alt="powered by vite"></a>
1010
<a href="https://discord.gg/zPQJrNGuFB"><img src="https://img.shields.io/discord/1115673443141156924?style=flat&logo=discord&logoColor=fff&color=000000" alt="discord"></a>
11-
<a href="https://x.com/diffusionstudi0"><img src="https://img.shields.io/badge/Follow for-Updates-blue?color=000000&logo=X&logoColor=ffffff" alt="Static Badge"></a>
11+
<a href="https://x.com/diffusionmov"><img src="https://img.shields.io/badge/Follow for-Updates-blue?color=000000&logo=X&logoColor=ffffff" alt="Static Badge"></a>
1212
</p>
1313
<br/>
1414

src/composition/composition.spec.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
* Public License, v. 2.0 that can be found in the LICENSE file.
66
*/
77

8-
import { describe, expect, it, beforeEach, vi, afterEach, afterAll } from 'vitest';
8+
import { describe, expect, it, beforeEach, vi, afterEach, afterAll, MockInstance } from 'vitest';
99
import { Composition } from './composition';
1010
import { Clip, TextClip } from '../clips';
1111
import { AudioTrack, CaptionTrack, HtmlTrack, ImageTrack, TextTrack, Track, VideoTrack } from '../tracks';
1212
import { Timestamp } from '../models';
1313

1414
describe('The composition', () => {
1515
let composition: Composition;
16+
let computeMock: MockInstance<() => void>;
17+
1618
const frameMock = vi.fn();
1719
const playMock = vi.fn();
1820
const pauseMock = vi.fn();
@@ -33,6 +35,7 @@ describe('The composition', () => {
3335
composition.state = 'IDLE';
3436

3537
localStorage.clear();
38+
computeMock = vi.spyOn(composition, 'computeFrame');
3639
});
3740

3841
it('should initialize with default settings', () => {
@@ -173,7 +176,7 @@ describe('The composition', () => {
173176
expect(composition.duration.seconds).toBe(0.5);
174177

175178
const seekMock = vi.spyOn(track, 'seek');
176-
const computeMock = vi.spyOn(composition, 'computeFrame');
179+
computeMock.mockClear();
177180

178181
const frameCallbacks: number[] = [];
179182
composition.on('currentframe', (evt) => frameCallbacks.push(evt.detail));
@@ -381,6 +384,36 @@ describe('The composition', () => {
381384
expect(track1.clips.length).toBe(2);
382385
});
383386

387+
it('should redraw the composition when it changes', async () => {
388+
expect(composition.duration.frames).toBe(0);
389+
expect(computeMock).toBeCalledTimes(0);
390+
391+
const track = composition.createTrack('base');
392+
393+
expect(composition.duration.frames).toBe(0);
394+
expect(computeMock).toBeCalledTimes(1);
395+
396+
await track.add(new Clip({ stop: 20 }));
397+
398+
expect(composition.duration.frames).toBe(20);
399+
expect(computeMock).toBeCalledTimes(2);
400+
401+
const clip = await track.add(new Clip({ start: 30, stop: 60 }));
402+
403+
expect(composition.duration.frames).toBe(60);
404+
expect(computeMock).toBeCalledTimes(3);
405+
406+
clip.stop = 80;
407+
408+
expect(composition.duration.frames).toBe(80);
409+
expect(computeMock).toBeCalledTimes(4);
410+
411+
track.remove(clip);
412+
413+
expect(composition.duration.frames).toBe(20);
414+
expect(computeMock).toBeCalledTimes(5);
415+
});
416+
384417
afterEach(() => {
385418
frameMock.mockClear();
386419
playMock.mockClear();

src/composition/composition.ts

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
5656

5757
/**
5858
* User defined fixed duration, use the duration
59-
* property to change this value
59+
* property to set this value
6060
*/
61-
public durationLimit?: Timestamp;
61+
public fixedDuration?: Timestamp;
6262

6363
/**
6464
* Defines the current state of the composition
@@ -92,13 +92,12 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
9292

9393
this.settings = { height, width, background, backend };
9494

95-
this.on('update', this.computeFrame.bind(this));
96-
this.on('attach', this.computeFrame.bind(this));
97-
this.on('detach', this.computeFrame.bind(this));
98-
this.on('load', this.computeFrame.bind(this));
99-
this.on('frame', this.computeFrame.bind(this));
100-
this.on('error', this.computeFrame.bind(this));
101-
this.on('*', this.updateDuration.bind(this));
95+
this.on('update', this.update.bind(this));
96+
this.on('attach', this.update.bind(this));
97+
this.on('detach', this.update.bind(this));
98+
this.on('load', this.update.bind(this));
99+
this.on('frame', this.update.bind(this));
100+
this.on('error', this.update.bind(this));
102101

103102
autoDetectRenderer({ ...this.settings, preference: backend })
104103
.then(renderer => {
@@ -147,8 +146,8 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
147146
* This is where the playback stops playing
148147
*/
149148
public get duration(): Timestamp {
150-
if (this.durationLimit) {
151-
return this.durationLimit;
149+
if (this.fixedDuration) {
150+
return this.fixedDuration;
152151
}
153152
return this._duration;
154153
}
@@ -158,14 +157,14 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
158157
*/
159158
public set duration(time: frame | Timestamp | undefined) {
160159
if (!time) {
161-
this.durationLimit = undefined;
160+
this.fixedDuration = undefined;
162161
} else if (time instanceof Timestamp) {
163-
this.durationLimit = time;
162+
this.fixedDuration = time;
164163
} else {
165-
this.durationLimit = Timestamp.fromFrames(time);
164+
this.fixedDuration = Timestamp.fromFrames(time);
166165
}
167166

168-
this.trigger('frame', this.durationLimit?.frames ?? 0);
167+
this.trigger('frame', this.fixedDuration?.frames ?? 0);
169168
}
170169

171170
/**
@@ -256,10 +255,6 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
256255
const removed = this.tracks.filter((track) => track instanceof Track);
257256
this.tracks = this.tracks.filter((track) => !(track instanceof Track));
258257

259-
if (removed.length > 0) {
260-
this.updateDuration();
261-
}
262-
263258
return removed;
264259
}
265260

@@ -508,15 +503,17 @@ export class Composition extends EventEmitterMixin<CompositionEvents, typeof Ser
508503
}
509504
}
510505

511-
private updateDuration(): void {
512-
const lastFrames = this.tracks
513-
.filter((track) => !track.disabled)
514-
.map((track) => track.stop?.frames ?? 0);
515-
516-
const lastFrame = Math.max(...lastFrames, 0);
506+
/**
507+
* Updates the state of the composition
508+
*/
509+
private update(): void {
510+
this._duration.frames = Math.max(
511+
...this.tracks
512+
.filter((track) => !track.disabled)
513+
.map((track) => track.stop?.frames ?? 0),
514+
0
515+
);
517516

518-
if (lastFrame != this._duration.frames) {
519-
this._duration.frames = lastFrame;
520-
}
517+
this.computeFrame();
521518
}
522519
}

src/tracks/track/track.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export class Track<Clp extends Clip> extends EventEmitterMixin<Events, typeof Se
176176
* Adds a new clip to the track
177177
* @throws Error if the clip can't be added
178178
*/
179-
public async add(clip: Clp): Promise<this> {
179+
public async add(clip: Clp): Promise<Clp> {
180180
// only append clip if composition is initialized
181181
if (this.composition && !this.composition.renderer) {
182182
await new Promise(this.composition.resolve('init'));
@@ -193,7 +193,7 @@ export class Track<Clp extends Clip> extends EventEmitterMixin<Events, typeof Se
193193

194194
this.trigger('attach', undefined);
195195

196-
return this;
196+
return clip;
197197
}
198198

199199
/**

0 commit comments

Comments
 (0)