cloudinary-video-player 4.0.4-edge.2 → 4.1.1-edge.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/309.min.js +2 -2
- package/dist/{149.min.js → 526.min.js} +3 -3
- package/dist/689.min.js +2 -2
- package/dist/801.min.js +3 -3
- package/dist/adaptive-streaming.js +2 -2
- package/dist/adaptive-streaming.min.js +2 -2
- package/dist/chapters.js +2 -2
- package/dist/chapters.min.js +2 -2
- package/dist/cld-player-core.js +11 -22
- package/dist/cld-player-core.min.js +3 -3
- package/dist/cld-poster-url.js +2 -2
- package/dist/cld-poster-url.min.js +2 -2
- package/dist/cld-video-player.css +2 -154
- package/dist/cld-video-player.js +11 -22
- package/dist/cld-video-player.light.js +11 -22
- package/dist/cld-video-player.light.min.js +3 -3
- package/dist/cld-video-player.min.css +3 -3
- package/dist/cld-video-player.min.js +3 -3
- package/dist/colors.js +2 -2
- package/dist/colors.min.js +2 -2
- package/dist/dash.js +2 -2
- package/dist/dash.min.js +2 -2
- package/dist/debug.js +3 -3
- package/dist/debug.min.js +3 -3
- package/dist/ima.js +2 -2
- package/dist/ima.min.js +2 -2
- package/dist/interaction-areas.js +2 -2
- package/dist/interaction-areas.min.js +2 -2
- package/dist/node_modules_lodash_throttle_js.js +2 -2
- package/dist/player-full.js +11 -22
- package/dist/player-full.min.js +3 -3
- package/dist/player.css +2 -154
- package/dist/player.js +2 -2
- package/dist/player.min.css +3 -3
- package/dist/player.min.js +3 -3
- package/dist/playlist.js +2 -2
- package/dist/playlist.min.js +2 -2
- package/dist/recommendations-overlay.js +2 -2
- package/dist/recommendations-overlay.min.js +2 -2
- package/dist/schema.json +0 -4
- package/dist/share.js +2 -2
- package/dist/share.min.js +2 -2
- package/dist/shoppable.js +2 -2
- package/dist/shoppable.min.js +2 -2
- package/dist/utils_fetch-config_js.js +2 -2
- package/dist/utils_schedule_js.js +2 -2
- package/lib/cld-video-player.min.css +3 -3
- package/lib/debug.js +0 -1
- package/lib/index2.js +1 -2
- package/lib/player.min.css +3 -3
- package/lib/schema.json +0 -4
- package/lib/video-player.const.js +1 -1
- package/lib/video-player.js +16 -44
- package/package.json +1 -1
- package/dist/visual-search.js +0 -67
- package/dist/visual-search.min.js +0 -6
- package/lib/visual-search.js +0 -235
package/lib/video-player.js
CHANGED
|
@@ -561,7 +561,7 @@ class TitleBar extends Component {
|
|
|
561
561
|
const metadataUrl = appendQueryParams(`${urlPrefix}/_applet_/video_service/video_metadata/${deliveryType}/${utf8ToBase64(publicId)}.json`, source.queryParams());
|
|
562
562
|
fetch(metadataUrl, {
|
|
563
563
|
headers: {
|
|
564
|
-
'X-Cld-Video-Player-Version': "4.
|
|
564
|
+
'X-Cld-Video-Player-Version': "4.1.1-edge.0"
|
|
565
565
|
}
|
|
566
566
|
}).then(response => {
|
|
567
567
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
@@ -3196,7 +3196,7 @@ class CloudinaryAnalytics {
|
|
|
3196
3196
|
}, {
|
|
3197
3197
|
...(isPlainObject(this.analyticsOptions) ? this.analyticsOptions : {}),
|
|
3198
3198
|
videoPlayerType: 'cloudinary video player',
|
|
3199
|
-
videoPlayerVersion: "4.
|
|
3199
|
+
videoPlayerVersion: "4.1.1-edge.0"
|
|
3200
3200
|
});
|
|
3201
3201
|
} else if (this.currentVideoMetadata.cloudName !== metadata.cloudName || this.currentVideoMetadata.publicId !== metadata.publicId) {
|
|
3202
3202
|
this.cloudinaryAnalytics.stopManualTracking();
|
|
@@ -4189,18 +4189,6 @@ async function lazyShoppablePlugin(player, options) {
|
|
|
4189
4189
|
new ShoppableWidget(player, options.shoppable).init();
|
|
4190
4190
|
}
|
|
4191
4191
|
|
|
4192
|
-
async function lazyVisualSearchPlugin(options) {
|
|
4193
|
-
const player = this;
|
|
4194
|
-
try {
|
|
4195
|
-
const {
|
|
4196
|
-
default: initPlugin
|
|
4197
|
-
} = await import(/* webpackChunkName: "visual-search" */'./visual-search.js');
|
|
4198
|
-
player.ready(() => initPlugin(options, player));
|
|
4199
|
-
} catch (error) {
|
|
4200
|
-
console.error('Failed to load plugin:', error);
|
|
4201
|
-
}
|
|
4202
|
-
}
|
|
4203
|
-
|
|
4204
4192
|
async function lazySharePlugin(options) {
|
|
4205
4193
|
const player = this;
|
|
4206
4194
|
try {
|
|
@@ -4753,7 +4741,6 @@ const plugins = {
|
|
|
4753
4741
|
playlist: lazyPlugin,
|
|
4754
4742
|
shoppable: lazyShoppablePlugin,
|
|
4755
4743
|
interactionAreas: lazyInteractionAreasPlugin,
|
|
4756
|
-
visualSearch: lazyVisualSearchPlugin,
|
|
4757
4744
|
share: lazySharePlugin,
|
|
4758
4745
|
adaptiveStreaming: lazyAdaptiveStreamingPlugin,
|
|
4759
4746
|
textTracksManager
|
|
@@ -4906,7 +4893,7 @@ const splitOptions = flatOptions => {
|
|
|
4906
4893
|
delete playerOptions.cloudinaryConfig;
|
|
4907
4894
|
}
|
|
4908
4895
|
|
|
4909
|
-
// Source-level config (
|
|
4896
|
+
// Source-level config (chapters, textTracks, etc.)
|
|
4910
4897
|
playerOptions.sourceOptions = Utils.sliceAndUnsetProperties(playerOptions, ...SOURCE_PARAMS);
|
|
4911
4898
|
|
|
4912
4899
|
// Allow explicitly passing options to videojs using the `videojs` namespace, in order
|
|
@@ -4980,7 +4967,6 @@ const getSourceOptions = function () {
|
|
|
4980
4967
|
if (sourceOptions.chapters) return 'inline-chapters';
|
|
4981
4968
|
return undefined;
|
|
4982
4969
|
})(),
|
|
4983
|
-
visualSearch: sourceOptions.visualSearch,
|
|
4984
4970
|
download: sourceOptions.download === true ? true : undefined,
|
|
4985
4971
|
hdr: sourceOptions.hdr === true ? true : undefined,
|
|
4986
4972
|
recommendations: sourceOptions.recommendations && sourceOptions.recommendations.length,
|
|
@@ -5194,7 +5180,7 @@ class VideoPlayer {
|
|
|
5194
5180
|
const analyticsData = getAnalyticsFromPlayerOptions(options);
|
|
5195
5181
|
const analyticsParams = new URLSearchParams(analyticsData).toString();
|
|
5196
5182
|
const baseParams = new URLSearchParams({
|
|
5197
|
-
vpVersion: "4.
|
|
5183
|
+
vpVersion: "4.1.1-edge.0",
|
|
5198
5184
|
vpInstanceId: this.getVPInstanceId(),
|
|
5199
5185
|
cloudName: options.cloudinary.cloud_name,
|
|
5200
5186
|
...internalAnalyticsMetadata
|
|
@@ -5271,7 +5257,6 @@ class VideoPlayer {
|
|
|
5271
5257
|
this._initAnalytics();
|
|
5272
5258
|
this._initCloudinaryAnalytics();
|
|
5273
5259
|
this._initFloatingPlayer();
|
|
5274
|
-
this._initVisualSearch();
|
|
5275
5260
|
this._initShare();
|
|
5276
5261
|
this._initColors();
|
|
5277
5262
|
this._initTextTracks();
|
|
@@ -5404,25 +5389,12 @@ class VideoPlayer {
|
|
|
5404
5389
|
}
|
|
5405
5390
|
});
|
|
5406
5391
|
}
|
|
5407
|
-
_initVisualSearch() {
|
|
5408
|
-
// Listen for source changes to apply visual search based on source config
|
|
5409
|
-
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, _ref4) => {
|
|
5410
|
-
let {
|
|
5411
|
-
source
|
|
5412
|
-
} = _ref4;
|
|
5413
|
-
if (source?._visualSearch && this.videojs.visualSearch) {
|
|
5414
|
-
isFunction(this.videojs.visualSearch) ? this.videojs.visualSearch(source._visualSearch) : this.videojs.visualSearch.createSearchUI(source._visualSearch);
|
|
5415
|
-
} else if (!source?._visualSearch && this.videojs.visualSearch?.clearUI) {
|
|
5416
|
-
this.videojs.visualSearch.clearUI();
|
|
5417
|
-
}
|
|
5418
|
-
});
|
|
5419
|
-
}
|
|
5420
5392
|
_initShare() {
|
|
5421
5393
|
// Listen for source changes to apply Share plugin based on source config
|
|
5422
|
-
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e,
|
|
5394
|
+
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, _ref4) => {
|
|
5423
5395
|
let {
|
|
5424
5396
|
source
|
|
5425
|
-
} =
|
|
5397
|
+
} = _ref4;
|
|
5426
5398
|
if (!this.videojs.share) {
|
|
5427
5399
|
return;
|
|
5428
5400
|
}
|
|
@@ -5452,10 +5424,10 @@ class VideoPlayer {
|
|
|
5452
5424
|
}
|
|
5453
5425
|
_initTextTracks() {
|
|
5454
5426
|
this.textTracksManager = this.videojs.textTracksManager();
|
|
5455
|
-
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e,
|
|
5427
|
+
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, _ref5) => {
|
|
5456
5428
|
let {
|
|
5457
5429
|
source
|
|
5458
|
-
} =
|
|
5430
|
+
} = _ref5;
|
|
5459
5431
|
if (source?._textTracks) {
|
|
5460
5432
|
this.setTextTracks(source._textTracks);
|
|
5461
5433
|
}
|
|
@@ -5519,10 +5491,10 @@ class VideoPlayer {
|
|
|
5519
5491
|
}
|
|
5520
5492
|
_initSourceSwitcher() {
|
|
5521
5493
|
this.sourceSwitcher = this.videojs.sourceSwitcher();
|
|
5522
|
-
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e,
|
|
5494
|
+
this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, _ref6) => {
|
|
5523
5495
|
let {
|
|
5524
5496
|
source
|
|
5525
|
-
} =
|
|
5497
|
+
} = _ref6;
|
|
5526
5498
|
const videoSources = source.videoSources?.();
|
|
5527
5499
|
const isSourcesListAvailable = Array.isArray(videoSources) ? !!videoSources.length : false;
|
|
5528
5500
|
if (this.videojs.controlBar) {
|
|
@@ -5533,20 +5505,20 @@ class VideoPlayer {
|
|
|
5533
5505
|
}
|
|
5534
5506
|
}
|
|
5535
5507
|
if (isSourcesListAvailable) {
|
|
5536
|
-
const selectedIndex = videoSources.findIndex(
|
|
5508
|
+
const selectedIndex = videoSources.findIndex(_ref7 => {
|
|
5537
5509
|
let {
|
|
5538
5510
|
publicId
|
|
5539
|
-
} =
|
|
5511
|
+
} = _ref7;
|
|
5540
5512
|
return publicId === source.publicId();
|
|
5541
5513
|
});
|
|
5542
5514
|
this.sourceSwitcher.reInit({
|
|
5543
5515
|
sources: videoSources,
|
|
5544
5516
|
selectedIndex: selectedIndex === -1 ? 0 : selectedIndex,
|
|
5545
|
-
onSourceChange:
|
|
5517
|
+
onSourceChange: _ref8 => {
|
|
5546
5518
|
let {
|
|
5547
5519
|
publicId,
|
|
5548
5520
|
...newSourceOptions
|
|
5549
|
-
} =
|
|
5521
|
+
} = _ref8;
|
|
5550
5522
|
return this.source(publicId, {
|
|
5551
5523
|
...newSourceOptions,
|
|
5552
5524
|
videoSources
|
|
@@ -5651,11 +5623,11 @@ class VideoPlayer {
|
|
|
5651
5623
|
volumeBar.removeAttribute('aria-live');
|
|
5652
5624
|
}
|
|
5653
5625
|
}
|
|
5654
|
-
_onSourceChange(e,
|
|
5626
|
+
_onSourceChange(e, _ref9) {
|
|
5655
5627
|
let {
|
|
5656
5628
|
source,
|
|
5657
5629
|
sourceOptions
|
|
5658
|
-
} =
|
|
5630
|
+
} = _ref9;
|
|
5659
5631
|
this._sendInternalAnalytics({
|
|
5660
5632
|
...(sourceOptions && {
|
|
5661
5633
|
sourceOptions
|
package/package.json
CHANGED
package/dist/visual-search.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Cloudinary Video Player v4.0.4-edge.2
|
|
3
|
-
* Built on 2026-07-30T08:21:38.281Z
|
|
4
|
-
* https://github.com/cloudinary/cloudinary-video-player
|
|
5
|
-
*/
|
|
6
|
-
"use strict";
|
|
7
|
-
/*
|
|
8
|
-
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
9
|
-
* This devtool is neither made for production nor for readable output files.
|
|
10
|
-
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
11
|
-
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
12
|
-
* or disable the default devtool with "devtool: false".
|
|
13
|
-
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
14
|
-
*/
|
|
15
|
-
(self["cloudinaryVideoPlayerChunkLoading"] = self["cloudinaryVideoPlayerChunkLoading"] || []).push([["visual-search"],{
|
|
16
|
-
|
|
17
|
-
/***/ "./plugins/visual-search/components/SearchButton.js"
|
|
18
|
-
/*!**********************************************************!*\
|
|
19
|
-
!*** ./plugins/visual-search/components/SearchButton.js ***!
|
|
20
|
-
\**********************************************************/
|
|
21
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
22
|
-
|
|
23
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SearchButton: () => (/* binding */ SearchButton)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n\nconst SearchButton = onClick => {\n const button = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('button', {\n className: 'vjs-control vjs-button vjs-visual-search-button',\n title: 'Search video content',\n ariaLabel: 'Search video content'\n });\n const searchIcon = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('span', {\n className: 'vjs-icon-search'\n });\n button.appendChild(searchIcon);\n const spinnerIcon = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('span', {\n className: 'vjs-loading-spinner'\n });\n button.appendChild(spinnerIcon);\n button.addEventListener('click', onClick);\n return button;\n};\n\n//# sourceURL=webpack:///./plugins/visual-search/components/SearchButton.js?\n}");
|
|
24
|
-
|
|
25
|
-
/***/ },
|
|
26
|
-
|
|
27
|
-
/***/ "./plugins/visual-search/components/SearchInput.js"
|
|
28
|
-
/*!*********************************************************!*\
|
|
29
|
-
!*** ./plugins/visual-search/components/SearchInput.js ***!
|
|
30
|
-
\*********************************************************/
|
|
31
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
32
|
-
|
|
33
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SearchInput: () => (/* binding */ SearchInput)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n\nconst SearchInput = (onSearch, onClose) => {\n const form = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('form', {\n className: 'vjs-visual-search-form'\n });\n const input = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('input', {\n className: 'vjs-visual-search-input',\n type: 'text',\n ariaLabel: 'Search input',\n tabIndex: -1\n });\n const closeButton = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('button', {\n className: 'vjs-control vjs-button vjs-visual-search-close',\n type: 'button',\n title: 'Close search',\n ariaLabel: 'Close search',\n tabIndex: -1\n });\n\n // Add close icon\n const closeIcon = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('span', {\n className: 'vjs-icon-close'\n });\n closeButton.appendChild(closeIcon);\n form.appendChild(input);\n form.appendChild(closeButton);\n\n // Handle search submission\n form.addEventListener('submit', e => {\n e.preventDefault();\n const query = input.value.trim();\n if (query) {\n onSearch(query);\n }\n });\n\n // Handle close button\n closeButton.addEventListener('click', e => {\n e.preventDefault();\n if (onClose) {\n onClose();\n }\n });\n return {\n element: form,\n input,\n closeButton\n };\n};\n\n//# sourceURL=webpack:///./plugins/visual-search/components/SearchInput.js?\n}");
|
|
34
|
-
|
|
35
|
-
/***/ },
|
|
36
|
-
|
|
37
|
-
/***/ "./plugins/visual-search/components/SearchResults.js"
|
|
38
|
-
/*!***********************************************************!*\
|
|
39
|
-
!*** ./plugins/visual-search/components/SearchResults.js ***!
|
|
40
|
-
\***********************************************************/
|
|
41
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
42
|
-
|
|
43
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SearchResults: () => (/* binding */ SearchResults)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n\nconst SearchResults = player => {\n const clearMarkers = () => {\n player.$$('.vjs-visual-search-marker').forEach(el => el.remove());\n player.$$('.vjs-visual-search-results-wrapper').forEach(el => el.remove());\n\n // Remove the class that indicates search results are displayed\n player.removeClass('vjs-visual-search-results-active');\n };\n const displayResults = results => {\n // Clear existing markers\n clearMarkers();\n const total = player.duration();\n const seekBar = player.controlBar.progressControl.seekBar;\n\n // Create wrapper for search results\n const wrapperEl = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('div', {\n className: 'vjs-visual-search-results-wrapper',\n role: 'presentation'\n });\n\n // Add markers for each result\n results.forEach(result => {\n const {\n start_time,\n end_time\n } = result;\n const position = start_time / total * 100;\n const width = (end_time - start_time) / total * 100;\n const time = `${Math.floor(start_time / 60)}:${Math.floor(start_time % 60).toString().padStart(2, '0')}`;\n const markerEl = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('div', {\n className: 'vjs-control vjs-visual-search-marker',\n style: `left: ${position}%; width: ${width}%`,\n tabIndex: 0,\n role: 'button',\n title: `Search result at ${time}`,\n ariaLabel: `Search result at ${time}`\n });\n wrapperEl.appendChild(markerEl);\n\n // Add click handler to jump to this time\n markerEl.addEventListener('click', () => {\n player.currentTime(start_time);\n });\n\n // Add keyboard support\n markerEl.addEventListener('keydown', e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n player.currentTime(start_time);\n }\n });\n });\n\n // Add wrapper to seek bar\n seekBar.el().appendChild(wrapperEl);\n\n // Add a class to indicate search results are displayed\n if (results.length > 0) {\n player.addClass('vjs-visual-search-results-active');\n }\n };\n return {\n displayResults,\n clearMarkers\n };\n};\n\n//# sourceURL=webpack:///./plugins/visual-search/components/SearchResults.js?\n}");
|
|
44
|
-
|
|
45
|
-
/***/ },
|
|
46
|
-
|
|
47
|
-
/***/ "./plugins/visual-search/visual-search.js"
|
|
48
|
-
/*!************************************************!*\
|
|
49
|
-
!*** ./plugins/visual-search/visual-search.js ***!
|
|
50
|
-
\************************************************/
|
|
51
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
52
|
-
|
|
53
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _components_SearchButton__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components/SearchButton */ \"./plugins/visual-search/components/SearchButton.js\");\n/* harmony import */ var _components_SearchInput__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/SearchInput */ \"./plugins/visual-search/components/SearchInput.js\");\n/* harmony import */ var _components_SearchResults__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/SearchResults */ \"./plugins/visual-search/components/SearchResults.js\");\n/* harmony import */ var _visual_search_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./visual-search.scss */ \"./plugins/visual-search/visual-search.scss\");\n\n\n\n\n\nconst visualSearch = (options, player) => {\n player.addClass('vjs-visual-search');\n let isSearchActive = false;\n const searchResults = (0,_components_SearchResults__WEBPACK_IMPORTED_MODULE_3__.SearchResults)(player);\n const performSearch = async query => {\n const searchButton = player.$('.vjs-visual-search-button');\n searchButton.classList.add('vjs-waiting');\n try {\n const source = player.cloudinary.source();\n const publicId = source.publicId();\n const transformation = Object.assign({}, source.transformation());\n transformation.flags = transformation.flags || [];\n transformation.flags.push(`getinfo:search_b64_${btoa(query)}`);\n const visualSearchSrc = source.config().url(`${publicId}`, {\n transformation\n });\n const response = await fetch(visualSearchSrc, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n if (!response.ok) {\n throw new Error(`Search request failed with status: ${response.status}`);\n }\n const results = await response.json();\n searchResults.displayResults(results.timestamps);\n if (results && !player.hasStarted()) {\n // Make sure the progress bar is visible\n player.play().then(() => player.pause());\n }\n } catch (error) {\n console.error('Error performing visual search:', error);\n } finally {\n searchButton.classList.remove('vjs-waiting');\n }\n };\n const clearUI = () => {\n isSearchActive = false;\n searchResults.clearMarkers();\n player.$('.vjs-visual-search-wrapper')?.remove();\n };\n const createSearchUI = () => {\n clearUI();\n const titleBar = player.$('.vjs-title-bar');\n if (titleBar) {\n titleBar.classList.remove('vjs-hidden');\n }\n const searchContainer = video_js__WEBPACK_IMPORTED_MODULE_0___default().dom.createEl('div', {\n className: 'vjs-visual-search-wrapper'\n });\n\n // Handle the search icon click (expand or submit)\n const handleSearchButtonClick = () => {\n if (!isSearchActive) {\n isSearchActive = true;\n searchContainer.classList.add('vjs-visual-search-active');\n searchInput.input.tabIndex = 0;\n searchInput.closeButton.tabIndex = 0;\n searchInput.input.focus();\n } else {\n const query = searchInput.input.value.trim();\n if (query) {\n performSearch(query);\n }\n }\n };\n const closeSearch = () => {\n if (isSearchActive) {\n isSearchActive = false;\n searchContainer.classList.remove('vjs-visual-search-active');\n searchInput.input.value = '';\n searchInput.input.tabIndex = -1;\n searchInput.closeButton.tabIndex = -1;\n searchResults.clearMarkers();\n }\n };\n const searchButton = (0,_components_SearchButton__WEBPACK_IMPORTED_MODULE_1__.SearchButton)(handleSearchButtonClick);\n const searchInput = (0,_components_SearchInput__WEBPACK_IMPORTED_MODULE_2__.SearchInput)(performSearch, closeSearch);\n searchContainer.appendChild(searchButton);\n searchContainer.appendChild(searchInput.element);\n titleBar.prepend(searchContainer);\n player.on('keydown', e => {\n if (e.key === 'Escape' && isSearchActive) {\n closeSearch();\n }\n });\n };\n createSearchUI();\n\n // Public methods\n player.visualSearch = {\n createSearchUI,\n clearUI\n };\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (visualSearch);\n\n//# sourceURL=webpack:///./plugins/visual-search/visual-search.js?\n}");
|
|
54
|
-
|
|
55
|
-
/***/ },
|
|
56
|
-
|
|
57
|
-
/***/ "./plugins/visual-search/visual-search.scss"
|
|
58
|
-
/*!**************************************************!*\
|
|
59
|
-
!*** ./plugins/visual-search/visual-search.scss ***!
|
|
60
|
-
\**************************************************/
|
|
61
|
-
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
62
|
-
|
|
63
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack:///./plugins/visual-search/visual-search.scss?\n}");
|
|
64
|
-
|
|
65
|
-
/***/ }
|
|
66
|
-
|
|
67
|
-
}]);
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Cloudinary Video Player v4.0.4-edge.2
|
|
3
|
-
* Built on 2026-07-30T08:21:21.690Z
|
|
4
|
-
* https://github.com/cloudinary/cloudinary-video-player
|
|
5
|
-
*/
|
|
6
|
-
"use strict";(self.cloudinaryVideoPlayerChunkLoading=self.cloudinaryVideoPlayerChunkLoading||[]).push([[728],{9148(e,a,s){s.d(a,{default:()=>l});var t=s(6673),r=s.n(t);const l=(e,a)=>{a.addClass("vjs-visual-search");let s=!1;const t=(e=>{const a=()=>{e.$$(".vjs-visual-search-marker").forEach(e=>e.remove()),e.$$(".vjs-visual-search-results-wrapper").forEach(e=>e.remove()),e.removeClass("vjs-visual-search-results-active")};return{displayResults:s=>{a();const t=e.duration(),l=e.controlBar.progressControl.seekBar,n=r().dom.createEl("div",{className:"vjs-visual-search-results-wrapper",role:"presentation"});s.forEach(a=>{const{start_time:s,end_time:l}=a,c=s/t*100,o=(l-s)/t*100,i=`${Math.floor(s/60)}:${Math.floor(s%60).toString().padStart(2,"0")}`,d=r().dom.createEl("div",{className:"vjs-control vjs-visual-search-marker",style:`left: ${c}%; width: ${o}%`,tabIndex:0,role:"button",title:`Search result at ${i}`,ariaLabel:`Search result at ${i}`});n.appendChild(d),d.addEventListener("click",()=>{e.currentTime(s)}),d.addEventListener("keydown",a=>{"Enter"!==a.key&&" "!==a.key||(a.preventDefault(),e.currentTime(s))})}),l.el().appendChild(n),s.length>0&&e.addClass("vjs-visual-search-results-active")},clearMarkers:a}})(a),l=async e=>{const s=a.$(".vjs-visual-search-button");s.classList.add("vjs-waiting");try{const s=a.cloudinary.source(),r=s.publicId(),l=Object.assign({},s.transformation());l.flags=l.flags||[],l.flags.push(`getinfo:search_b64_${btoa(e)}`);const n=s.config().url(`${r}`,{transformation:l}),c=await fetch(n,{method:"GET",headers:{"Content-Type":"application/json"}});if(!c.ok)throw new Error(`Search request failed with status: ${c.status}`);const o=await c.json();t.displayResults(o.timestamps),o&&!a.hasStarted()&&a.play().then(()=>a.pause())}catch(e){console.error("Error performing visual search:",e)}finally{s.classList.remove("vjs-waiting")}},n=()=>{s=!1,t.clearMarkers(),a.$(".vjs-visual-search-wrapper")?.remove()},c=()=>{n();const e=a.$(".vjs-title-bar");e&&e.classList.remove("vjs-hidden");const c=r().dom.createEl("div",{className:"vjs-visual-search-wrapper"}),o=()=>{s&&(s=!1,c.classList.remove("vjs-visual-search-active"),d.input.value="",d.input.tabIndex=-1,d.closeButton.tabIndex=-1,t.clearMarkers())},i=(e=>{const a=r().dom.createEl("button",{className:"vjs-control vjs-button vjs-visual-search-button",title:"Search video content",ariaLabel:"Search video content"}),s=r().dom.createEl("span",{className:"vjs-icon-search"});a.appendChild(s);const t=r().dom.createEl("span",{className:"vjs-loading-spinner"});return a.appendChild(t),a.addEventListener("click",e),a})(()=>{if(s){const e=d.input.value.trim();e&&l(e)}else s=!0,c.classList.add("vjs-visual-search-active"),d.input.tabIndex=0,d.closeButton.tabIndex=0,d.input.focus()}),d=((e,a)=>{const s=r().dom.createEl("form",{className:"vjs-visual-search-form"}),t=r().dom.createEl("input",{className:"vjs-visual-search-input",type:"text",ariaLabel:"Search input",tabIndex:-1}),l=r().dom.createEl("button",{className:"vjs-control vjs-button vjs-visual-search-close",type:"button",title:"Close search",ariaLabel:"Close search",tabIndex:-1}),n=r().dom.createEl("span",{className:"vjs-icon-close"});return l.appendChild(n),s.appendChild(t),s.appendChild(l),s.addEventListener("submit",a=>{a.preventDefault();const s=t.value.trim();s&&e(s)}),l.addEventListener("click",e=>{e.preventDefault(),a&&a()}),{element:s,input:t,closeButton:l}})(l,o);c.appendChild(i),c.appendChild(d.element),e.prepend(c),a.on("keydown",e=>{"Escape"===e.key&&s&&o()})};c(),a.visualSearch={createSearchUI:c,clearUI:n}}}}]);
|
package/lib/visual-search.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { _ as _vjs } from './_videojs-proxy.js';
|
|
2
|
-
import './_commonjsHelpers.js';
|
|
3
|
-
|
|
4
|
-
const SearchButton = onClick => {
|
|
5
|
-
const button = _vjs.dom.createEl('button', {
|
|
6
|
-
className: 'vjs-control vjs-button vjs-visual-search-button',
|
|
7
|
-
title: 'Search video content',
|
|
8
|
-
ariaLabel: 'Search video content'
|
|
9
|
-
});
|
|
10
|
-
const searchIcon = _vjs.dom.createEl('span', {
|
|
11
|
-
className: 'vjs-icon-search'
|
|
12
|
-
});
|
|
13
|
-
button.appendChild(searchIcon);
|
|
14
|
-
const spinnerIcon = _vjs.dom.createEl('span', {
|
|
15
|
-
className: 'vjs-loading-spinner'
|
|
16
|
-
});
|
|
17
|
-
button.appendChild(spinnerIcon);
|
|
18
|
-
button.addEventListener('click', onClick);
|
|
19
|
-
return button;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const SearchInput = (onSearch, onClose) => {
|
|
23
|
-
const form = _vjs.dom.createEl('form', {
|
|
24
|
-
className: 'vjs-visual-search-form'
|
|
25
|
-
});
|
|
26
|
-
const input = _vjs.dom.createEl('input', {
|
|
27
|
-
className: 'vjs-visual-search-input',
|
|
28
|
-
type: 'text',
|
|
29
|
-
ariaLabel: 'Search input',
|
|
30
|
-
tabIndex: -1
|
|
31
|
-
});
|
|
32
|
-
const closeButton = _vjs.dom.createEl('button', {
|
|
33
|
-
className: 'vjs-control vjs-button vjs-visual-search-close',
|
|
34
|
-
type: 'button',
|
|
35
|
-
title: 'Close search',
|
|
36
|
-
ariaLabel: 'Close search',
|
|
37
|
-
tabIndex: -1
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Add close icon
|
|
41
|
-
const closeIcon = _vjs.dom.createEl('span', {
|
|
42
|
-
className: 'vjs-icon-close'
|
|
43
|
-
});
|
|
44
|
-
closeButton.appendChild(closeIcon);
|
|
45
|
-
form.appendChild(input);
|
|
46
|
-
form.appendChild(closeButton);
|
|
47
|
-
|
|
48
|
-
// Handle search submission
|
|
49
|
-
form.addEventListener('submit', e => {
|
|
50
|
-
e.preventDefault();
|
|
51
|
-
const query = input.value.trim();
|
|
52
|
-
if (query) {
|
|
53
|
-
onSearch(query);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Handle close button
|
|
58
|
-
closeButton.addEventListener('click', e => {
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
if (onClose) {
|
|
61
|
-
onClose();
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
return {
|
|
65
|
-
element: form,
|
|
66
|
-
input,
|
|
67
|
-
closeButton
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const SearchResults = player => {
|
|
72
|
-
const clearMarkers = () => {
|
|
73
|
-
player.$$('.vjs-visual-search-marker').forEach(el => el.remove());
|
|
74
|
-
player.$$('.vjs-visual-search-results-wrapper').forEach(el => el.remove());
|
|
75
|
-
|
|
76
|
-
// Remove the class that indicates search results are displayed
|
|
77
|
-
player.removeClass('vjs-visual-search-results-active');
|
|
78
|
-
};
|
|
79
|
-
const displayResults = results => {
|
|
80
|
-
// Clear existing markers
|
|
81
|
-
clearMarkers();
|
|
82
|
-
const total = player.duration();
|
|
83
|
-
const seekBar = player.controlBar.progressControl.seekBar;
|
|
84
|
-
|
|
85
|
-
// Create wrapper for search results
|
|
86
|
-
const wrapperEl = _vjs.dom.createEl('div', {
|
|
87
|
-
className: 'vjs-visual-search-results-wrapper',
|
|
88
|
-
role: 'presentation'
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Add markers for each result
|
|
92
|
-
results.forEach(result => {
|
|
93
|
-
const {
|
|
94
|
-
start_time,
|
|
95
|
-
end_time
|
|
96
|
-
} = result;
|
|
97
|
-
const position = start_time / total * 100;
|
|
98
|
-
const width = (end_time - start_time) / total * 100;
|
|
99
|
-
const time = `${Math.floor(start_time / 60)}:${Math.floor(start_time % 60).toString().padStart(2, '0')}`;
|
|
100
|
-
const markerEl = _vjs.dom.createEl('div', {
|
|
101
|
-
className: 'vjs-control vjs-visual-search-marker',
|
|
102
|
-
style: `left: ${position}%; width: ${width}%`,
|
|
103
|
-
tabIndex: 0,
|
|
104
|
-
role: 'button',
|
|
105
|
-
title: `Search result at ${time}`,
|
|
106
|
-
ariaLabel: `Search result at ${time}`
|
|
107
|
-
});
|
|
108
|
-
wrapperEl.appendChild(markerEl);
|
|
109
|
-
|
|
110
|
-
// Add click handler to jump to this time
|
|
111
|
-
markerEl.addEventListener('click', () => {
|
|
112
|
-
player.currentTime(start_time);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Add keyboard support
|
|
116
|
-
markerEl.addEventListener('keydown', e => {
|
|
117
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
118
|
-
e.preventDefault();
|
|
119
|
-
player.currentTime(start_time);
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Add wrapper to seek bar
|
|
125
|
-
seekBar.el().appendChild(wrapperEl);
|
|
126
|
-
|
|
127
|
-
// Add a class to indicate search results are displayed
|
|
128
|
-
if (results.length > 0) {
|
|
129
|
-
player.addClass('vjs-visual-search-results-active');
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
return {
|
|
133
|
-
displayResults,
|
|
134
|
-
clearMarkers
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const visualSearch = (options, player) => {
|
|
139
|
-
player.addClass('vjs-visual-search');
|
|
140
|
-
let isSearchActive = false;
|
|
141
|
-
const searchResults = SearchResults(player);
|
|
142
|
-
const performSearch = async query => {
|
|
143
|
-
const searchButton = player.$('.vjs-visual-search-button');
|
|
144
|
-
searchButton.classList.add('vjs-waiting');
|
|
145
|
-
try {
|
|
146
|
-
const source = player.cloudinary.source();
|
|
147
|
-
const publicId = source.publicId();
|
|
148
|
-
const transformation = Object.assign({}, source.transformation());
|
|
149
|
-
transformation.flags = transformation.flags || [];
|
|
150
|
-
transformation.flags.push(`getinfo:search_b64_${btoa(query)}`);
|
|
151
|
-
const visualSearchSrc = source.config().url(`${publicId}`, {
|
|
152
|
-
transformation
|
|
153
|
-
});
|
|
154
|
-
const response = await fetch(visualSearchSrc, {
|
|
155
|
-
method: 'GET',
|
|
156
|
-
headers: {
|
|
157
|
-
'Content-Type': 'application/json'
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
if (!response.ok) {
|
|
161
|
-
throw new Error(`Search request failed with status: ${response.status}`);
|
|
162
|
-
}
|
|
163
|
-
const results = await response.json();
|
|
164
|
-
searchResults.displayResults(results.timestamps);
|
|
165
|
-
if (results && !player.hasStarted()) {
|
|
166
|
-
// Make sure the progress bar is visible
|
|
167
|
-
player.play().then(() => player.pause());
|
|
168
|
-
}
|
|
169
|
-
} catch (error) {
|
|
170
|
-
console.error('Error performing visual search:', error);
|
|
171
|
-
} finally {
|
|
172
|
-
searchButton.classList.remove('vjs-waiting');
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
const clearUI = () => {
|
|
176
|
-
isSearchActive = false;
|
|
177
|
-
searchResults.clearMarkers();
|
|
178
|
-
player.$('.vjs-visual-search-wrapper')?.remove();
|
|
179
|
-
};
|
|
180
|
-
const createSearchUI = () => {
|
|
181
|
-
clearUI();
|
|
182
|
-
const titleBar = player.$('.vjs-title-bar');
|
|
183
|
-
if (titleBar) {
|
|
184
|
-
titleBar.classList.remove('vjs-hidden');
|
|
185
|
-
}
|
|
186
|
-
const searchContainer = _vjs.dom.createEl('div', {
|
|
187
|
-
className: 'vjs-visual-search-wrapper'
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// Handle the search icon click (expand or submit)
|
|
191
|
-
const handleSearchButtonClick = () => {
|
|
192
|
-
if (!isSearchActive) {
|
|
193
|
-
isSearchActive = true;
|
|
194
|
-
searchContainer.classList.add('vjs-visual-search-active');
|
|
195
|
-
searchInput.input.tabIndex = 0;
|
|
196
|
-
searchInput.closeButton.tabIndex = 0;
|
|
197
|
-
searchInput.input.focus();
|
|
198
|
-
} else {
|
|
199
|
-
const query = searchInput.input.value.trim();
|
|
200
|
-
if (query) {
|
|
201
|
-
performSearch(query);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
const closeSearch = () => {
|
|
206
|
-
if (isSearchActive) {
|
|
207
|
-
isSearchActive = false;
|
|
208
|
-
searchContainer.classList.remove('vjs-visual-search-active');
|
|
209
|
-
searchInput.input.value = '';
|
|
210
|
-
searchInput.input.tabIndex = -1;
|
|
211
|
-
searchInput.closeButton.tabIndex = -1;
|
|
212
|
-
searchResults.clearMarkers();
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
const searchButton = SearchButton(handleSearchButtonClick);
|
|
216
|
-
const searchInput = SearchInput(performSearch, closeSearch);
|
|
217
|
-
searchContainer.appendChild(searchButton);
|
|
218
|
-
searchContainer.appendChild(searchInput.element);
|
|
219
|
-
titleBar.prepend(searchContainer);
|
|
220
|
-
player.on('keydown', e => {
|
|
221
|
-
if (e.key === 'Escape' && isSearchActive) {
|
|
222
|
-
closeSearch();
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
};
|
|
226
|
-
createSearchUI();
|
|
227
|
-
|
|
228
|
-
// Public methods
|
|
229
|
-
player.visualSearch = {
|
|
230
|
-
createSearchUI,
|
|
231
|
-
clearUI
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
export { visualSearch as default };
|