From c10a5c91c7169e658f9d72cec72699458cb33cbc Mon Sep 17 00:00:00 2001 From: Oded Hutzler <31587052+odedhutzler@users.noreply.github.com> Date: Mon, 24 Dec 2018 14:30:42 +0200 Subject: [PATCH] feat(FEC-8766): add closed captions from multi request to external #74 feat(FEC-8766): add closed captions from multi request to external --- flow-typed/types/caption-type.js | 2 + flow-typed/types/env-config.js | 3 +- flow-typed/types/external-caption-object.js | 8 ++++ flow-typed/types/media-config-sources.js | 3 +- flow-typed/types/media-sources.js | 3 +- src/entities/media-sources.js | 1 + src/k-provider/ovp/config.js | 3 +- .../ovp/external-captions-builder.js | 43 +++++++++++++++++++ .../ovp/loaders/media-entry-loader.js | 13 +++++- src/k-provider/ovp/provider-parser.js | 4 ++ src/k-provider/ovp/provider.js | 3 ++ .../response-types/kaltura-caption-list.js | 20 +++++++++ .../ovp/services/captions-service.js | 28 ++++++++++++ 13 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 flow-typed/types/caption-type.js create mode 100644 flow-typed/types/external-caption-object.js create mode 100644 src/k-provider/ovp/external-captions-builder.js create mode 100644 src/k-provider/ovp/response-types/kaltura-caption-list.js create mode 100644 src/k-provider/ovp/services/captions-service.js diff --git a/flow-typed/types/caption-type.js b/flow-typed/types/caption-type.js new file mode 100644 index 00000000..1e2dbe34 --- /dev/null +++ b/flow-typed/types/caption-type.js @@ -0,0 +1,2 @@ +// @flow +declare type CaptionType = { [type: string]: string }; diff --git a/flow-typed/types/env-config.js b/flow-typed/types/env-config.js index 2b00cf99..52866a35 100644 --- a/flow-typed/types/env-config.js +++ b/flow-typed/types/env-config.js @@ -1,5 +1,6 @@ // @flow declare type ProviderEnvConfigObject = { serviceUrl: string, - cdnUrl?: string + cdnUrl?: string, + experimentalLoadApiCaptions?: boolean }; diff --git a/flow-typed/types/external-caption-object.js b/flow-typed/types/external-caption-object.js new file mode 100644 index 00000000..d51cc42d --- /dev/null +++ b/flow-typed/types/external-caption-object.js @@ -0,0 +1,8 @@ +// @flow +declare type PKExternalCaptionObject = { + url: string, + label: string, + language: string, + default: ?boolean, + type: ?string +}; diff --git a/flow-typed/types/media-config-sources.js b/flow-typed/types/media-config-sources.js index f9117620..17c30e0f 100644 --- a/flow-typed/types/media-config-sources.js +++ b/flow-typed/types/media-config-sources.js @@ -9,5 +9,6 @@ declare type ProviderMediaConfigSourcesObject = { poster: string | Array, dvr: boolean, vr: ?Object, - metadata: ProviderMediaConfigMetadataObject + metadata: ProviderMediaConfigMetadataObject, + captions?: Array }; diff --git a/flow-typed/types/media-sources.js b/flow-typed/types/media-sources.js index 7133c016..3825d7ff 100644 --- a/flow-typed/types/media-sources.js +++ b/flow-typed/types/media-sources.js @@ -2,5 +2,6 @@ declare type ProviderMediaSourcesObject = { progressive: Array, dash: Array, - hls: Array + hls: Array, + captions?: Array }; diff --git a/src/entities/media-sources.js b/src/entities/media-sources.js index 86f7e94a..fe091855 100644 --- a/src/entities/media-sources.js +++ b/src/entities/media-sources.js @@ -21,6 +21,7 @@ export default class MediaSources { * @public */ hls: Array; + captions: Array; /** * @constructor diff --git a/src/k-provider/ovp/config.js b/src/k-provider/ovp/config.js index c1082450..13c6d61e 100644 --- a/src/k-provider/ovp/config.js +++ b/src/k-provider/ovp/config.js @@ -7,7 +7,8 @@ const defaultConfig: Object = { serviceParams: { apiVersion: '3.3.0', format: 1 - } + }, + experimentalLoadApiCaptions: false }; export default class OVPConfiguration { diff --git a/src/k-provider/ovp/external-captions-builder.js b/src/k-provider/ovp/external-captions-builder.js new file mode 100644 index 00000000..bb93438b --- /dev/null +++ b/src/k-provider/ovp/external-captions-builder.js @@ -0,0 +1,43 @@ +// @flow +import OVPConfiguration from './config'; + +const KalturaCaptionType: CaptionType = { + SRT: '1', + DFXP: '2', + WEBVTT: '3', + CAP: '4' +}; + +const CaptionsFormats: {[format: string]: string} = { + WEBVTT: 'vtt' +}; + +const BASE_URL: string = 'index.php/service/caption_captionasset/action/serveWebVTT/captionAssetId/ASSET_ID/segmentIndex/-1/version/2/captions.vtt'; + +const ASSET_ID_INDEX: number = 6; +const VERSION_INDEX: number = 10; + +class ExternalCaptionsBuilder { + static createConfig(metadata: Object, ks: string): Array { + return metadata.filter(meta => [KalturaCaptionType.WEBVTT, KalturaCaptionType.SRT].includes(meta.format)).map(meta => { + return { + type: CaptionsFormats.WEBVTT, + language: meta.language, + label: meta.label, + url: ExternalCaptionsBuilder.createUrl(meta, ks) + }; + }); + } + + static createUrl(metadata: Object, ks: string): string { + const config = OVPConfiguration.get(); + let path = BASE_URL.split('/'); + path[ASSET_ID_INDEX] = metadata.id; + path[VERSION_INDEX] = metadata.version; + path = path.join('/'); + ks = ks ? `/ks/${ks}` : ``; + return `${config.serviceUrl}/${path}${ks}`; + } +} + +export {ExternalCaptionsBuilder}; diff --git a/src/k-provider/ovp/loaders/media-entry-loader.js b/src/k-provider/ovp/loaders/media-entry-loader.js index b4d5f373..d8779f4a 100644 --- a/src/k-provider/ovp/loaders/media-entry-loader.js +++ b/src/k-provider/ovp/loaders/media-entry-loader.js @@ -7,11 +7,14 @@ import KalturaPlaybackContext from '../response-types/kaltura-playback-context'; import KalturaMetadataListResponse from '../response-types/kaltura-metadata-list-response'; import KalturaBaseEntryListResponse from '../response-types/kaltura-base-entry-list-response'; import KalturaMediaEntry from '../response-types/kaltura-media-entry'; +import OVPCaptionService from '../services/captions-service'; +import KalturaCaptionAssetListResponse from '../response-types/kaltura-caption-list'; type OVPMediaEntryLoaderResponse = { entry: KalturaMediaEntry, playBackContextResult: KalturaPlaybackContext, - metadataListResult: KalturaMetadataListResponse + metadataListResult: KalturaMetadataListResponse, + captionResult?: KalturaCaptionAssetListResponse }; export type {OVPMediaEntryLoaderResponse}; @@ -27,6 +30,7 @@ export default class OVPMediaEntryLoader implements ILoader { /** * @constructor * @param {Object} params loader params + * @boolean {boolean} useExternalCaptions - if we should add captions request to the multirequests. */ constructor(params: Object) { this.requests = this.buildRequests(params); @@ -42,10 +46,14 @@ export default class OVPMediaEntryLoader implements ILoader { } set response(response: any) { + const config = OVPConfiguration.get(); let mediaEntryResponse: KalturaBaseEntryListResponse = new KalturaBaseEntryListResponse(response[0].data); this._response.entry = mediaEntryResponse.entries[0]; this._response.playBackContextResult = new KalturaPlaybackContext(response[1].data); this._response.metadataListResult = new KalturaMetadataListResponse(response[2].data); + if (config.experimentalLoadApiCaptions) { + this._response.captionResult = new KalturaCaptionAssetListResponse(response[3].data); + } } get response(): OVPMediaEntryLoaderResponse { @@ -65,6 +73,9 @@ export default class OVPMediaEntryLoader implements ILoader { requests.push(OVPBaseEntryService.list(config.serviceUrl, params.ks, params.entryId, params.redirectFromEntryId)); requests.push(OVPBaseEntryService.getPlaybackContext(config.serviceUrl, params.ks, params.entryId)); requests.push(OVPMetadataService.list(config.serviceUrl, params.ks, params.entryId)); + if (config.experimentalLoadApiCaptions) { + requests.push(OVPCaptionService.list(config.serviceUrl, params.ks, params.entryId)); + } return requests; } diff --git a/src/k-provider/ovp/provider-parser.js b/src/k-provider/ovp/provider-parser.js index 558f9435..79e3b3fa 100644 --- a/src/k-provider/ovp/provider-parser.js +++ b/src/k-provider/ovp/provider-parser.js @@ -18,6 +18,7 @@ import EntryList from '../../entities/entry-list'; import KalturaRuleAction from './response-types/kaltura-rule-action'; import KalturaAccessControlMessage from '../common/response-types/kaltura-access-control-message'; import type {OVPMediaEntryLoaderResponse} from './loaders/media-entry-loader'; +import {ExternalCaptionsBuilder} from './external-captions-builder'; export default class OVPProviderParser { static _logger = getLogger('OVPProviderParser'); @@ -41,6 +42,9 @@ export default class OVPProviderParser { const kalturaSources = playbackContext.sources; mediaEntry.sources = OVPProviderParser._getParsedSources(kalturaSources, ks, partnerId, uiConfId, entry, playbackContext); + if (mediaEntryResponse.captionResult) { + mediaEntry.sources.captions = ExternalCaptionsBuilder.createConfig(mediaEntryResponse.captionResult.data, ks); + } OVPProviderParser._fillBaseData(mediaEntry, entry, metadataList); return mediaEntry; } diff --git a/src/k-provider/ovp/provider.js b/src/k-provider/ovp/provider.js index 97ead4ad..176d536c 100644 --- a/src/k-provider/ovp/provider.js +++ b/src/k-provider/ovp/provider.js @@ -265,6 +265,9 @@ export default class OVPProvider extends BaseProvider -1) { sourcesObject.vr = {}; } diff --git a/src/k-provider/ovp/response-types/kaltura-caption-list.js b/src/k-provider/ovp/response-types/kaltura-caption-list.js new file mode 100644 index 00000000..9d98c8be --- /dev/null +++ b/src/k-provider/ovp/response-types/kaltura-caption-list.js @@ -0,0 +1,20 @@ +//@flow +import ServiceResult from '../../common/base-service-result'; + +export default class KalturaCaptionAssetListResponse extends ServiceResult { + totalCount: number; + captions: Array; + + /** + * @constructor + * @param {Object} metaDataResponse The response + * @param {Object} urlObject response of the url + */ + constructor(metaDataResponse: Object) { + super(metaDataResponse); + if (!this.hasError) { + this.totalCount = metaDataResponse.totalCount; + this.data = metaDataResponse.objects; + } + } +} diff --git a/src/k-provider/ovp/services/captions-service.js b/src/k-provider/ovp/services/captions-service.js new file mode 100644 index 00000000..28a1d1f8 --- /dev/null +++ b/src/k-provider/ovp/services/captions-service.js @@ -0,0 +1,28 @@ +//@flow +import OVPService from './ovp-service'; +import RequestBuilder from '../../../util/request-builder'; + +const SERVICE_NAME: string = 'caption_captionasset'; + +export default class OVPCaptionService extends OVPService { + /** + * Creates an instance of RequestBuilder for caption_captionasset.list + * @function post + * @param {string} serviceUrl The service base URL + * @param {string} ks The ks + * @param {string} entryId The uiConf ID + * @returns {RequestBuilder} The request builder + * @static + */ + static list(serviceUrl: string, ks: string, entryId: string): RequestBuilder { + const headers: Map = new Map(); + headers.set('Content-Type', 'application/json'); + const request = new RequestBuilder(headers); + request.service = SERVICE_NAME; + request.action = 'list'; + request.method = 'POST'; + request.url = request.getUrl(serviceUrl); + request.params = {ks: ks, 'filter:entryIdEqual': entryId}; + return request; + } +}