Skip to content

Commit 251fb28

Browse files
author
Nir Maoz
authored
Feature/add trim & volume json (#504)
1 parent 7577d8a commit 251fb28

File tree

9 files changed

+287
-1
lines changed

9 files changed

+287
-1
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {fromJson} from "../../../src/internal/fromJson";
2+
import {ITrimActionModel} from "../../../src/internal/models/ITrimActionModel";
3+
4+
describe('videoEdit.trim fromJson', () => {
5+
it('Should generate TrimAction from model', () => {
6+
const trimModel: ITrimActionModel = {
7+
actionType: 'trimVideo',
8+
duration: '30%',
9+
};
10+
11+
const transformation = fromJson({actions: [trimModel]});
12+
13+
expect(transformation.toString()).toStrictEqual('du_30p');
14+
});
15+
16+
it('Should generate ConcatenateAction with transition from model', () => {
17+
const trimModel: ITrimActionModel = {
18+
actionType: 'trimVideo',
19+
startOffset: 3,
20+
endOffset: 5,
21+
};
22+
23+
const transformation = fromJson({actions: [trimModel]});
24+
expect(transformation.toString()).toStrictEqual('eo_5,so_3');
25+
});
26+
27+
it('Should generate ConcatenateAction with ImageSource and transition from model', () => {
28+
const trimModel: ITrimActionModel = {
29+
actionType: 'trimVideo',
30+
startOffset: 3,
31+
duration: 5,
32+
};
33+
34+
const transformation = fromJson({actions: [trimModel]});
35+
36+
expect(transformation.toString()).toStrictEqual('du_5,so_3');
37+
});
38+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import {fromJson} from "../../../src/internal/fromJson";
2+
import {IVolumeActionModel} from "../../../src/internal/models/IVolumeActionModel";
3+
4+
describe('videoEdit.volume fromJson', () => {
5+
it('Should generate VolumeAction with percentage from model', () => {
6+
const trimModel: IVolumeActionModel = {
7+
actionType: 'volume',
8+
volumeValue: {
9+
mode: "percent",
10+
value: 10
11+
}
12+
};
13+
14+
const transformation = fromJson({actions: [trimModel]});
15+
16+
expect(transformation.toString()).toStrictEqual('e_volume:10');
17+
});
18+
19+
it('Should generate VolumeAction with decibels from model', () => {
20+
const trimModel: IVolumeActionModel = {
21+
actionType: 'volume',
22+
volumeValue: {
23+
mode: "decibels",
24+
value: 10
25+
}
26+
};
27+
28+
const transformation = fromJson({actions: [trimModel]});
29+
30+
expect(transformation.toString()).toStrictEqual('e_volume:10db');
31+
});
32+
33+
it('Should generate VolumeAction with mute from model', () => {
34+
const trimModel: IVolumeActionModel = {
35+
actionType: 'volume',
36+
volumeValue: {
37+
mode: "mute",
38+
}
39+
};
40+
41+
const transformation = fromJson({actions: [trimModel]});
42+
43+
expect(transformation.toString()).toStrictEqual('e_volume:mute');
44+
});
45+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {Transformation} from '../../../src';
2+
import {VideoEdit} from "../../../src/actions";
3+
4+
describe('videoEdit.trim toJson', () => {
5+
it('videoEdit.trim with duration', () => {
6+
const transformation = new Transformation()
7+
.videoEdit(VideoEdit.trim()
8+
.duration('30%')
9+
);
10+
expect(transformation.toJson()).toStrictEqual({
11+
actions: [
12+
{
13+
actionType: 'trimVideo',
14+
duration: '30%',
15+
}
16+
]
17+
});
18+
});
19+
20+
it('videoEdit.trim with startOffset and endOffset', () => {
21+
const transformation = new Transformation()
22+
.videoEdit(VideoEdit.trim()
23+
.startOffset(3)
24+
.endOffset(5)
25+
);
26+
expect(transformation.toJson()).toStrictEqual({
27+
actions: [
28+
{
29+
actionType: 'trimVideo',
30+
startOffset: 3,
31+
endOffset: 5,
32+
}
33+
]
34+
});
35+
});
36+
37+
it('videoEdit.trim with startOffset and duration', () => {
38+
const transformation = new Transformation()
39+
.videoEdit(VideoEdit.trim()
40+
.startOffset(3)
41+
.duration(5)
42+
);
43+
expect(transformation.toJson()).toStrictEqual({
44+
actions: [
45+
{
46+
actionType: 'trimVideo',
47+
startOffset: 3,
48+
duration: 5,
49+
}
50+
]
51+
});
52+
});
53+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {Transformation} from '../../../src';
2+
import {VideoEdit} from "../../../src/actions";
3+
import {byDecibels, byPercent, mute} from "../../../src/qualifiers/volume";
4+
5+
describe('videoEdit.trim toJson', () => {
6+
it('videoEdit.volume with decibels', () => {
7+
const transformation = new Transformation()
8+
.videoEdit(VideoEdit.volume(byDecibels(10))
9+
);
10+
expect(transformation.toJson()).toStrictEqual({
11+
actions: [
12+
{
13+
actionType: 'volume',
14+
volumeValue: {
15+
mode: 'decibels',
16+
value: 10
17+
}
18+
}
19+
]
20+
});
21+
});
22+
23+
it('videoEdit.volume with percent', () => {
24+
const transformation = new Transformation()
25+
.videoEdit(VideoEdit.volume(byPercent(10))
26+
);
27+
expect(transformation.toJson()).toStrictEqual({
28+
actions: [
29+
{
30+
actionType: 'volume',
31+
volumeValue: {
32+
mode: 'percent',
33+
value: 10
34+
}
35+
}
36+
]
37+
});
38+
});
39+
40+
it('videoEdit.volume with mute', () => {
41+
const transformation = new Transformation()
42+
.videoEdit(VideoEdit.volume(mute())
43+
);
44+
expect(transformation.toJson()).toStrictEqual({
45+
actions: [
46+
{
47+
actionType: 'volume',
48+
volumeValue: {
49+
mode: 'mute'
50+
}
51+
}
52+
]
53+
});
54+
});
55+
});

src/actions/videoEdit/TrimAction.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {Action} from "../../internal/Action.js";
22
import {Qualifier} from "../../internal/qualifier/Qualifier.js";
3+
import {ITrimActionModel} from "../../internal/models/ITrimActionModel.js";
4+
import {IActionModel} from "../../internal/models/IActionModel.js";
35

46
/**
57
* @description Class for shortening a video to the specified range.
@@ -8,8 +10,13 @@ import {Qualifier} from "../../internal/qualifier/Qualifier.js";
810
* @see Visit {@link Actions.VideoEdit|VideoEdit} for an example
911
*/
1012
class TrimAction extends Action {
13+
protected _actionModel: ITrimActionModel;
14+
1115
constructor() {
1216
super();
17+
this._actionModel = {
18+
actionType: 'trimVideo'
19+
};
1320
}
1421

1522
/**
@@ -32,6 +39,7 @@ class TrimAction extends Action {
3239
* @return {this}
3340
*/
3441
startOffset(offset: string|number): this {
42+
this._actionModel.startOffset = +offset;
3543
return this.addQualifier(new Qualifier('so', this.parseVal(offset)));
3644
}
3745

@@ -44,6 +52,7 @@ class TrimAction extends Action {
4452
* @return {this}
4553
*/
4654
endOffset(offset: string|number): this {
55+
this._actionModel.endOffset = +offset;
4756
return this.addQualifier(new Qualifier('eo', this.parseVal(offset)));
4857
}
4958

@@ -56,8 +65,29 @@ class TrimAction extends Action {
5665
* @return {this}
5766
*/
5867
duration(duration: string|number): this {
68+
this._actionModel.duration = duration;
5969
return this.addQualifier(new Qualifier('du', this.parseVal(duration)));
6070
}
71+
72+
static fromJson(actionModel: IActionModel): TrimAction {
73+
const {duration, startOffset, endOffset} = (actionModel as ITrimActionModel);
74+
// We are using this() to allow inheriting classes to use super.fromJson.apply(this, [actionModel])
75+
// This allows the inheriting classes to determine the class to be created
76+
const result = new this();
77+
if (duration != null){
78+
result.duration(duration);
79+
}
80+
81+
if (startOffset != null){
82+
result.startOffset(startOffset);
83+
}
84+
85+
if (endOffset != null){
86+
result.endOffset(endOffset);
87+
}
88+
89+
return result;
90+
}
6191
}
6292

6393
export default TrimAction;

src/actions/videoEdit/VolumeAction.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import {Action} from "../../internal/Action.js";
22
import {Qualifier} from "../../internal/qualifier/Qualifier.js";
33
import {QualifierValue} from "../../internal/qualifier/QualifierValue.js";
4+
import {IActionModel} from "../../internal/models/IActionModel.js";
5+
import {
6+
IVolumeActionModel,
7+
IVolumeByPercentModel,
8+
IVolumeValueModel
9+
} from "../../internal/models/IVolumeActionModel.js";
410

511
/**
612
* @description Class to Controls the volume of an audio or video file.
@@ -9,11 +15,38 @@ import {QualifierValue} from "../../internal/qualifier/QualifierValue.js";
915
* @see Visit {@link Actions.VideoEdit|VideoEdit} for an example
1016
*/
1117
class VolumeAction extends Action {
18+
protected _actionModel: IVolumeActionModel;
19+
1220
constructor(volumeValue: string | number) {
1321
super();
22+
let volumeValueModel: unknown = {mode: 'mute'};
23+
if (volumeValue !== 'mute') {
24+
volumeValueModel = {
25+
mode: (`${volumeValue}`.endsWith('db') ? 'decibels' : 'percent'),
26+
value: +(`${volumeValue}`.replace('db', ''))
27+
};
28+
}
29+
30+
this._actionModel = {
31+
actionType: 'volume',
32+
volumeValue: volumeValueModel as IVolumeValueModel
33+
};
34+
1435
const qualifierValue = new QualifierValue(['volume', volumeValue]).setDelimiter(':');
1536
this.addQualifier(new Qualifier('e', qualifierValue));
1637
}
38+
39+
static fromJson(actionModel: IActionModel): VolumeAction {
40+
const {volumeValue} = (actionModel as IVolumeActionModel);
41+
const {mode} = volumeValue;
42+
const value = mode === 'mute' ? mode : (volumeValue as IVolumeByPercentModel).value;
43+
const suffix = (mode === 'mute' || mode === "percent") ? '' : 'db';
44+
45+
46+
// We are using this() to allow inheriting classes to use super.fromJson.apply(this, [actionModel])
47+
// This allows the inheriting classes to determine the class to be created
48+
return new this(`${value}${suffix}`);
49+
}
1750
}
1851

1952
export default VolumeAction;

src/internal/fromJson.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import {DeliveryDPRAction} from "../actions/delivery/DeliveryDPRAction.js";
4343
import ConcatenateAction from "../actions/videoEdit/ConcatenateAction.js";
4444
import {ITransformationModel} from "./models/ITransformationModel.js";
4545
import {PreviewAction} from "../actions/videoEdit/PreviewAction.js";
46+
import TrimAction from "../actions/videoEdit/TrimAction.js";
47+
import VolumeAction from "../actions/videoEdit/VolumeAction.js";
4648

4749
const ActionModelMap: Record<string, IHasFromJson> = {
4850
scale: ResizeScaleAction,
@@ -95,7 +97,9 @@ const ActionModelMap: Record<string, IHasFromJson> = {
9597
brightness: EffectActionWithLevel,
9698
gamma: EffectActionWithLevel,
9799
concatenate: ConcatenateAction,
98-
preview: PreviewAction
100+
preview: PreviewAction,
101+
trimVideo: TrimAction,
102+
volume: VolumeAction
99103
};
100104

101105
/**
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {IActionModel} from "./IActionModel.js";
2+
3+
export interface ITrimActionModel extends IActionModel{
4+
duration?: string | number;
5+
startOffset?: number;
6+
endOffset?: number;
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {IActionModel} from "./IActionModel.js";
2+
3+
export interface IVolumeByDecibelsModel{
4+
mode: 'decibels'
5+
value: number;
6+
}
7+
8+
export interface IVolumeByPercentModel{
9+
mode: 'percent'
10+
value: number;
11+
}
12+
13+
export interface IVolumeMuteModel{
14+
mode: 'mute'
15+
}
16+
17+
export type IVolumeValueModel = IVolumeByDecibelsModel | IVolumeByPercentModel | IVolumeMuteModel;
18+
19+
export interface IVolumeActionModel extends IActionModel{
20+
volumeValue: IVolumeValueModel
21+
}

0 commit comments

Comments
 (0)