Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/config/configSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@
},
"default": ["auto"]
},
"resourceType": {
"type": "string",
"default": "video"
},
"transformation": {
"oneOf": [
{
Expand Down
17 changes: 12 additions & 5 deletions src/plugins/cloudinary/models/video-source/video-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ class VideoSource extends BaseSource {

options = Object.assign({}, DEFAULT_VIDEO_PARAMS, options);

if (options.resourceType) {
options.resource_type = options.resourceType;
}

if (!options.poster) {
options.poster = Object.assign({ publicId }, DEFAULT_POSTER_PARAMS);
}
Expand Down Expand Up @@ -67,18 +71,18 @@ class VideoSource extends BaseSource {
this[prop](options[prop]);
}
});

// Initialize poster
this.poster(options.poster);

this.objectId = generateId();
}

// Helper method to create simple getter/setter methods
_createGetterSetters(properties) {
properties.forEach(prop => {
const privateKey = `_${prop}`;
this[prop] = function(value) {
this[prop] = function (value) {
if (value === undefined) {
// Provide sensible defaults for specific properties
if (prop === 'sourceTypes' && this[privateKey] === undefined) {
Expand Down Expand Up @@ -123,6 +127,9 @@ class VideoSource extends BaseSource {
}

options.cloudinaryConfig = options.cloudinaryConfig || this.cloudinaryConfig();

options.resource_type = this.resourceType() || options.resource_type;

this._poster = new ImageSource(publicId, options);

return this;
Expand All @@ -149,7 +156,7 @@ class VideoSource extends BaseSource {
opts.transformation = castArray(srcTransformation);
}

Object.assign(opts, { resource_type: 'video', format });
Object.assign(opts, { format });

const [type, codecTrans] = formatToMimeTypeAndTransformation(sourceType);

Expand Down Expand Up @@ -214,7 +221,7 @@ class VideoSource extends BaseSource {
}

const info = this._info || this.getInitOptions().info;

return {
title: this.title() || info?.title || '',
subtitle: this.description() || info?.subtitle || '',
Expand Down
1 change: 1 addition & 0 deletions src/utils/get-analytics-player-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const getSourceOptions = (sourceOptions = {}) => ({
autoShowRecommendations: sourceOptions.autoShowRecommendations,
fontFace: sourceOptions.fontFace,
sourceTypes: sourceOptions.sourceTypes,
resourceType: sourceOptions.resourceType,
chapters: (() => {
if (sourceOptions.chapters === true) return 'auto';
if (sourceOptions.chapters && sourceOptions.chapters.url) return 'url';
Expand Down
1 change: 1 addition & 0 deletions src/validators/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const playerValidators = {

export const sourceValidators = {
raw_transformation: validator.isString,
resourceType: validator.isString,
shoppable: validator.isPlainObject,
chapters: validator.or(validator.isBoolean, validator.isPlainObject),
visualSearch: validator.or(validator.isBoolean),
Expand Down
1 change: 1 addition & 0 deletions src/video-player.const.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const SOURCE_PARAMS = [
'publicId',
'rawTransformation',
'recommendations',
'resourceType',
'shoppable',
'source',
'sourceTransformation',
Expand Down
83 changes: 83 additions & 0 deletions test/unit/videoSource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,4 +474,87 @@ describe('test hasCodec method', () => {
});

});

describe('resourceType parameter tests', () => {
it('should use image resourceType when specified', () => {
const source = new VideoSource('sample', {
cloudinaryConfig: cld,
resourceType: 'image',
transformation: [
{ effect: 'ai:model_veo-animate;details_(prompt_!flying bee!)' },
{ format: 'auto:video' }
]
});

const srcs = source.generateSources();
expect(srcs[0].src).toContain('/image/upload/');
expect(srcs[0].src).toContain('e_ai:model_veo-animate');
});

it('should default to video resourceType when not specified', () => {
const source = new VideoSource('sea_turtle', {
cloudinaryConfig: cld
});

const srcs = source.generateSources();
expect(srcs[0].src).toContain('/video/upload/');
});

it('should use image resourceType for poster', () => {
const source = new VideoSource('sample', {
cloudinaryConfig: cld,
resourceType: 'image',
transformation: [
{ effect: 'ai:model_veo-animate' }
]
});

const posterUrl = source.poster().url();
expect(posterUrl).toContain('/image/upload/');
expect(posterUrl).toContain('sample.jpg');
});

it('should use video resourceType for poster by default', () => {
const source = new VideoSource('sea_turtle', {
cloudinaryConfig: cld
});

const posterUrl = source.poster().url();
expect(posterUrl).toContain('/video/upload/');
});

it('should use configured resourceType for seek thumbnails', () => {
const source = new VideoSource('sample', {
cloudinaryConfig: cld,
resourceType: 'image',
transformation: [
{ effect: 'ai:model_veo-animate' }
]
});

const vttUrl = source.config().url('sample.vtt', {
transformation: { flags: ['sprite'] },
resource_type: source.resourceType()
});
expect(vttUrl).toContain('/image/upload/');
expect(vttUrl).toContain('fl_sprite');
});

it('should default to video resourceType for seek thumbnails when not specified', () => {
const source = new VideoSource('sea_turtle', {
cloudinaryConfig: cld
});

const resourceType = source.resourceType() || 'video';
const vttUrl = source.config().url('sea_turtle.vtt', {
transformation: { flags: ['sprite'] },
resource_type: resourceType
});

// When resourceType is not set, resourceType() returns undefined, so we default to 'video'
expect(resourceType).toBe('video');
expect(vttUrl).toContain('/video/upload/');
expect(vttUrl).toContain('fl_sprite');
});
});
});