1
0
mirror of https://github.com/videojs/video.js.git synced 2025-01-02 06:32:07 +02:00

Merge branch 'main' into sass

This commit is contained in:
mister-ben 2024-10-23 13:00:47 +02:00 committed by GitHub
commit e3f687686b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 277 additions and 81 deletions

View File

@ -1,3 +1,26 @@
<a name="8.19.1"></a>
## [8.19.1](https://github.com/videojs/video.js/compare/v8.19.0...v8.19.1) (2024-10-10)
### Chores
* **package:** update http-streaming to v3.15.0 ([#8889](https://github.com/videojs/video.js/issues/8889)) ([84f4905](https://github.com/videojs/video.js/commit/84f4905))
* update mpd-parser to v1.3.1 ([#8888](https://github.com/videojs/video.js/issues/8888)) ([7c17d75](https://github.com/videojs/video.js/commit/7c17d75))
<a name="8.19.0"></a>
# [8.19.0](https://github.com/videojs/video.js/compare/v8.18.0...v8.19.0) (2024-10-09)
### Features
* Add methods to add and remove <source> elements ([#8886](https://github.com/videojs/video.js/issues/8886)) ([eddda97](https://github.com/videojs/video.js/commit/eddda97)), closes [1000#0](https://github.com/1000/issues/0)
### Bug Fixes
* Don't request fullscreen from document PIP window ([#8881](https://github.com/videojs/video.js/issues/8881)) ([077077b](https://github.com/videojs/video.js/commit/077077b)), closes [#8877](https://github.com/videojs/video.js/issues/8877)
### Chores
* **package:** Update to VHS v3.14.2 ([#8869](https://github.com/videojs/video.js/issues/8869)) ([89eb454](https://github.com/videojs/video.js/commit/89eb454))
<a name="8.18.1"></a>
## [8.18.1](https://github.com/videojs/video.js/compare/v8.18.0...v8.18.1) (2024-09-17)

View File

@ -22,8 +22,8 @@ Video.js was started in the middle of 2010 and is now used on over ~~50,000~~ ~~
Thanks to the awesome folks over at [Fastly][fastly], there's a free, CDN hosted version of Video.js that anyone can use. Add these tags to your document's `<head>`:
```html
<link href="//vjs.zencdn.net/8.18.1/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/8.18.1/video.min.js"></script>
<link href="//vjs.zencdn.net/8.19.1/video-js.min.css" rel="stylesheet">
<script src="//vjs.zencdn.net/8.19.1/video.min.js"></script>
```
Alternatively, you can include Video.js by getting it from [npm](https://videojs.com/getting-started/#install-via-npm), downloading it from [GitHub releases](https://github.com/videojs/video.js/releases) or by including it via [unpkg](https://unpkg.com) or another JavaScript CDN, like CDNjs.
@ -34,12 +34,12 @@ Alternatively, you can include Video.js by getting it from [npm](https://videojs
<script src="https://unpkg.com/video.js/dist/video.min.js"></script>
<!-- unpkg : use a specific version of Video.js (change the version numbers as necessary) -->
<link href="https://unpkg.com/video.js@8.18.1/dist/video-js.min.css" rel="stylesheet">
<script src="https://unpkg.com/video.js@8.18.1/dist/video.min.js"></script>
<link href="https://unpkg.com/video.js@8.19.1/dist/video-js.min.css" rel="stylesheet">
<script src="https://unpkg.com/video.js@8.19.1/dist/video.min.js"></script>
<!-- cdnjs : use a specific version of Video.js (change the version numbers as necessary) -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.18.1/video-js.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.18.1/video.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.19.1/video-js.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/8.19.1/video.min.js"></script>
```
Next, using Video.js is as simple as creating a `<video>` element, but with an additional `data-setup` attribute. At a minimum, this attribute must have a value of `'{}'`, but it can include any Video.js [options][options] - just make sure it contains valid JSON!

87
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "video.js",
"version": "8.18.1",
"version": "8.19.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1791,16 +1791,16 @@
}
},
"@videojs/http-streaming": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.14.2.tgz",
"integrity": "sha512-c+sg+rrrSrRekBZxd+sNpzjRteIcOEQRJllqCBcz6MrgSaGJGDzV1xhGSAFnxX8E/xfqQeF060us5474WwYi3Q==",
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.15.0.tgz",
"integrity": "sha512-6rjaqEa87gVFqDFsHaLKXGrDqL3NhNZRNi6wkMw+uyt1lrLD2OFY0SfRQRNl7Vmmx0pt5FRJoRJYlnKsowyElA==",
"requires": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.1.1",
"aes-decrypter": "^4.0.2",
"global": "^4.4.0",
"m3u8-parser": "^7.2.0",
"mpd-parser": "^1.3.0",
"mpd-parser": "^1.3.1",
"mux.js": "7.0.3",
"video.js": "^7 || ^8"
}
@ -9739,9 +9739,9 @@
}
},
"mpd-parser": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.0.tgz",
"integrity": "sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.1.tgz",
"integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
"requires": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.0.0",
@ -14842,11 +14842,6 @@
"prepend-http": "^2.0.0"
}
},
"url-toolkit": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz",
"integrity": "sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg=="
},
"urljoin": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/urljoin/-/urljoin-0.1.5.tgz",
@ -15072,74 +15067,22 @@
"dev": true
},
"video.js": {
"version": "8.17.4",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-8.17.4.tgz",
"integrity": "sha512-AECieAxKMKB/QgYK36ci50phfpWys6bFT6+pGMpSafeFYSoZaQ2Vpl83T9Qqcesv4TO7oNtiycnVeaBnrva2oA==",
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-8.18.1.tgz",
"integrity": "sha512-oQ4M/HD2fFgEPHfmVMWxGykRFIpOmVhK0XZ4PSsPTgN2jH6E6+92f/RI2mDXDb0yu+Fxv9fxMUm0M7Z2K3Zo9w==",
"requires": {
"@babel/runtime": "^7.12.5",
"@videojs/http-streaming": "3.13.3",
"@videojs/vhs-utils": "^4.0.0",
"@videojs/http-streaming": "^3.14.2",
"@videojs/vhs-utils": "^4.1.1",
"@videojs/xhr": "2.7.0",
"aes-decrypter": "^4.0.1",
"aes-decrypter": "^4.0.2",
"global": "4.4.0",
"m3u8-parser": "^7.1.0",
"m3u8-parser": "^7.2.0",
"mpd-parser": "^1.2.2",
"mux.js": "^7.0.1",
"videojs-contrib-quality-levels": "4.1.0",
"videojs-font": "4.2.0",
"videojs-vtt.js": "0.15.5"
},
"dependencies": {
"@videojs/http-streaming": {
"version": "3.13.3",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.13.3.tgz",
"integrity": "sha512-L7H+iTeqHeZ5PylzOx+pT3CVyzn4TALWYTJKkIc1pDaV/cTVfNGtG+9/vXPAydD+wR/xH1M9/t2JH8tn/DCT4w==",
"requires": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "4.0.0",
"aes-decrypter": "4.0.1",
"global": "^4.4.0",
"m3u8-parser": "^7.1.0",
"mpd-parser": "^1.3.0",
"mux.js": "7.0.3",
"video.js": "^7 || ^8"
},
"dependencies": {
"@videojs/vhs-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz",
"integrity": "sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==",
"requires": {
"@babel/runtime": "^7.12.5",
"global": "^4.4.0",
"url-toolkit": "^2.2.1"
}
},
"aes-decrypter": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.1.tgz",
"integrity": "sha512-H1nh/P9VZXUf17AA5NQfJML88CFjVBDuGkp5zDHa7oEhYN9TTpNLJknRY1ie0iSKWlDf6JRnJKaZVDSQdPy6Cg==",
"requires": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^3.0.5",
"global": "^4.4.0",
"pkcs7": "^1.0.4"
},
"dependencies": {
"@videojs/vhs-utils": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
"requires": {
"@babel/runtime": "^7.12.5",
"global": "^4.4.0",
"url-toolkit": "^2.2.1"
}
}
}
}
}
}
}
},
"videojs-contrib-quality-levels": {

View File

@ -1,7 +1,7 @@
{
"name": "video.js",
"description": "An HTML5 video player that supports HLS and DASH with a common API and skin.",
"version": "8.18.1",
"version": "8.19.1",
"main": "./dist/video.cjs.js",
"module": "./dist/video.es.js",
"style": "./dist/video-js.css",
@ -86,13 +86,13 @@
},
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/http-streaming": "^3.14.2",
"@videojs/http-streaming": "^3.15.0",
"@videojs/vhs-utils": "^4.1.1",
"@videojs/xhr": "2.7.0",
"aes-decrypter": "^4.0.2",
"global": "4.4.0",
"m3u8-parser": "^7.2.0",
"mpd-parser": "^1.2.2",
"mpd-parser": "^1.3.1",
"mux.js": "^7.0.1",
"videojs-contrib-quality-levels": "4.1.0",
"videojs-font": "4.2.0",

View File

@ -3710,6 +3710,43 @@ class Player extends Component {
return false;
}
/**
* Add a <source> element to the <video> element.
*
* @param {string} srcUrl
* The URL of the video source.
*
* @param {string} [mimeType]
* The MIME type of the video source. Optional but recommended.
*
* @return {boolean}
* Returns true if the source element was successfully added, false otherwise.
*/
addSourceElement(srcUrl, mimeType) {
if (!this.tech_) {
return false;
}
return this.tech_.addSourceElement(srcUrl, mimeType);
}
/**
* Remove a <source> element from the <video> element by its URL.
*
* @param {string} srcUrl
* The URL of the source to remove.
*
* @return {boolean}
* Returns true if the source element was successfully removed, false otherwise.
*/
removeSourceElement(srcUrl) {
if (!this.tech_) {
return false;
}
return this.tech_.removeSourceElement(srcUrl);
}
/**
* Begin loading the src data.
*/

View File

@ -783,6 +783,67 @@ class Html5 extends Tech {
this.setSrc(src);
}
/**
* Add a <source> element to the <video> element.
*
* @param {string} srcUrl
* The URL of the video source.
*
* @param {string} [mimeType]
* The MIME type of the video source. Optional but recommended.
*
* @return {boolean}
* Returns true if the source element was successfully added, false otherwise.
*/
addSourceElement(srcUrl, mimeType) {
if (!srcUrl) {
log.error('Invalid source URL.');
return false;
}
const sourceAttributes = { src: srcUrl };
if (mimeType) {
sourceAttributes.type = mimeType;
}
const sourceElement = Dom.createEl('source', {}, sourceAttributes);
this.el_.appendChild(sourceElement);
return true;
}
/**
* Remove a <source> element from the <video> element by its URL.
*
* @param {string} srcUrl
* The URL of the source to remove.
*
* @return {boolean}
* Returns true if the source element was successfully removed, false otherwise.
*/
removeSourceElement(srcUrl) {
if (!srcUrl) {
log.error('Source URL is required to remove the source element.');
return false;
}
const sourceElements = this.el_.querySelectorAll('source');
for (const sourceElement of sourceElements) {
if (sourceElement.src === srcUrl) {
this.el_.removeChild(sourceElement);
return true;
}
}
log.warn(`No matching source element found with src: ${srcUrl}`);
return false;
}
/**
* Reset the tech by removing all sources and then calling
* {@link Html5.resetMediaElement}.

View File

@ -3611,3 +3611,57 @@ QUnit.test('smooth seeking set to true should update the display time components
player.dispose();
});
QUnit.test('addSourceElement calls tech method with correct args', function(assert) {
const player = TestHelpers.makePlayer();
const addSourceElementSpy = sinon.spy(player.tech_, 'addSourceElement');
const srcUrl = 'http://example.com/video.mp4';
const mimeType = 'video/mp4';
player.addSourceElement(srcUrl, mimeType);
assert.ok(addSourceElementSpy.calledOnce, 'addSourceElement method called');
assert.ok(addSourceElementSpy.calledWith(srcUrl, mimeType), 'addSourceElement called with correct arguments');
addSourceElementSpy.restore();
player.dispose();
});
QUnit.test('addSourceElement returns false if no tech', function(assert) {
const player = TestHelpers.makePlayer();
const srcUrl = 'http://example.com/video.mp4';
const mimeType = 'video/mp4';
player.tech_ = undefined;
const added = player.addSourceElement(srcUrl, mimeType);
assert.notOk(added, 'Returned false');
player.dispose();
});
QUnit.test('removeSourceElement calls tech method with correct args', function(assert) {
const player = TestHelpers.makePlayer();
const removeSourceElementSpy = sinon.spy(player.tech_, 'removeSourceElement');
const srcUrl = 'http://example.com/video.mp4';
player.removeSourceElement(srcUrl);
assert.ok(removeSourceElementSpy.calledOnce, 'removeSourceElement method called');
assert.ok(removeSourceElementSpy.calledWith(srcUrl), 'removeSourceElement called with correct arguments');
removeSourceElementSpy.restore();
player.dispose();
});
QUnit.test('removeSourceElement returns false if no tech', function(assert) {
const player = TestHelpers.makePlayer();
const srcUrl = 'http://example.com/video.mp4';
const mimeType = 'video/mp4';
player.tech_ = undefined;
const removed = player.removeSourceElement(srcUrl, mimeType);
assert.notOk(removed, 'Returned false');
player.dispose();
});

View File

@ -905,3 +905,79 @@ QUnit.test('supportsFullScreen is always with `webkitEnterFullScreen`', function
tech.el_ = oldEl;
});
QUnit.test('addSourceElement adds a valid source element with srcUrl and mimeType', function(assert) {
const videoEl = document.createElement('video');
tech.el_ = videoEl;
const srcUrl = 'http://example.com/video.mp4';
const mimeType = 'video/mp4';
const added = tech.addSourceElement(srcUrl, mimeType);
const sourceElement = videoEl.querySelector('source');
assert.ok(added, 'Returned true');
assert.ok(sourceElement, 'A source element was added');
assert.equal(sourceElement.src, srcUrl, 'Source element has correct src');
assert.equal(sourceElement.type, mimeType, 'Source element has correct type');
});
QUnit.test('addSourceElement adds a valid source element without a mimeType', function(assert) {
const videoEl = document.createElement('video');
tech.el_ = videoEl;
const srcUrl = 'http://example.com/video2.mp4';
const added = tech.addSourceElement(srcUrl);
const sourceElement = videoEl.querySelector('source');
assert.ok(added, 'Returned true');
assert.ok(sourceElement, 'A source element was added even without a type');
assert.equal(sourceElement.src, srcUrl, 'Source element has correct src');
assert.notOk(sourceElement.type, 'Source element does not have a type attribute');
});
QUnit.test('addSourceElement does not add a source element for invalid source URL', function(assert) {
const videoEl = document.createElement('video');
tech.el_ = videoEl;
const added = tech.addSourceElement('');
const sourceElement = videoEl.querySelector('source');
assert.notOk(added, 'Returned false');
assert.notOk(sourceElement, 'No source element was added for missing src');
});
QUnit.test('removeSourceElement removes a source element by its URL', function(assert) {
const videoEl = document.createElement('video');
tech.el_ = videoEl;
tech.addSourceElement('http://example.com/video1.mp4');
tech.addSourceElement('http://example.com/video2.mp4');
let sourceElement = videoEl.querySelector('source[src="http://example.com/video1.mp4"]');
assert.ok(sourceElement, 'Source element for video1.mp4 was added');
const removed = tech.removeSourceElement('http://example.com/video1.mp4');
assert.ok(removed, 'Source element was successfully removed');
sourceElement = videoEl.querySelector('source[src="http://example.com/video1.mp4"]');
assert.notOk(sourceElement, 'Source element for video1.mp4 was removed');
});
QUnit.test('removeSourceElement does not remove a source element if URL does not match', function(assert) {
const videoEl = document.createElement('video');
tech.el_ = videoEl;
tech.addSourceElement('http://example.com/video.mp4');
const removed = tech.removeSourceElement('http://example.com/invalid.mp4');
assert.notOk(removed, 'No source element was removed for non-matching URL');
});

View File

@ -111,6 +111,8 @@ class TechFaker extends Tech {
}
return 'movie.mp4';
}
addSourceElement() {}
removeSourceElement() {}
load() {
}
currentSrc() {