Skip to content

Update MediaElement.js to 7.1.0 - #6714

Open
adamsilverstein wants to merge 16 commits into
WordPress:trunkfrom
adamsilverstein:56320-update-mediaelement-to-latest
Open

adamsilverstein wants to merge 16 commits into
WordPress:trunkfrom
adamsilverstein:56320-update-mediaelement-to-latest

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented Jun 3, 2024 •

Copy link
Copy Markdown
Member

Claude handled the version bump and wrote up the details:

Updates the bundled MediaElement.js library from 4.2.17 to the latest release, 7.1.0, and reviews the WordPress integration for compatibility.

Trac ticket: https://core.trac.wordpress.org/ticket/56320

What changed

  • Vendor files updated to the 7.1.0 build from npm: mediaelement-and-player.js, mediaelement.js, the player stylesheets, mejs-controls.svg, and the Vimeo renderer. The YouTube, DASH, and HLS renderers remain part of the main bundle, so no new files are needed for those.
  • Registered script and style versions in script-loader.php bumped from 4.2.17 to 7.1.0 so browsers cache-bust the new files.
  • iconSprite added to the localized _wpmejsSettings - since MediaElement.js 5.0 the control icons are referenced from an SVG sprite, and without this setting players fall back to a page-relative path and icons fail to load.
  • mediaelement-migrate.js gains one new shim: since 7.0, MediaElementPlayer.prototype.remove() no longer deletes the destroyed player from the mejs.players registry. WordPress iterates that registry (wp.media.mixin.removeAllPlayers(), mce-view, and wp-playlist re-creates a player per track change), so the shim restores the pre-7.0 cleanup.
  • One existing migrate shim is corrected: it converted player.container, player.controls, and player.layers to jQuery objects for 4.x back compat, but 7.x internals call native DOM methods on them - setResponsiveMode() calls container.querySelector() for percentage-width players, which is exactly how [playlist] renders. Player construction threw and playlists could not switch or play tracks. The properties now stay HTML elements, with jQuery wrappers exposed as player.$container, player.$controls, and player.$layers instead. Core itself only calls container.remove(), which works natively.
  • The favicon.ico that slipped in from the npm package build directory was removed.

Compatibility review

Every mejs API WordPress touches was checked against the 7.1.0 build: window.mejs, mejs.players, mejs.Utils.getTypeFromFile, mejs.Features, the mejsL10n i18n hook, the jQuery .mediaelementplayer() plugin, MediaElementPlayer and the prototype methods used by media-audiovideo.js, wp-playlist.js, and the customizer (remove, pause, globalBind/globalUnbind, getElement, buildfeatures, _meReady). The new 7.1.0 keyboard bindings go through player.getElement(), which the migrate shim's jQuery unwrapping already handles, and the default features list is unchanged, so the shim's buildfeatures override has not drifted. The 7.0.5 to 7.1.0 delta upstream is accessibility additions (keyboard play/pause, screen reader text for time/duration) and fullscreen fixes - no API changes.

Tests

  • New QUnit module (tests/qunit/wp-includes/js/mediaelement.js) exercising the API surface above, including a functional check that instantiating a player builds its controls from the configured iconSprite and that remove() unregisters the player, plus a fluid-width player test covering the responsive sizing path. The QUnit page now also loads mediaelement-migrate.js in the same order production does. This test is what caught the mejs.players registry regression.
  • New PHPUnit tests (tests/phpunit/tests/dependencies/mediaelement.php) that read the bundled library version out of mediaelement-and-player.js and assert every registered mediaelement script and style version matches it - so the files can no longer be updated without bumping the registered versions - and that the localized settings carry a resolvable iconSprite path.
  • New e2e tests (tests/e2e/specs/media-playback.test.js) - the first front-end playback coverage in core. Each test publishes a post over REST and drives the real player in the browser: [audio] and [video] shortcodes (play, pause, SVG sprite controls, mejs.players registry), [playlist] audio track switching, [playlist type="video"], and the YouTube and Vimeo renderers (asserting their embed iframes attach). Playback assertions use mp3 and webm fixtures because Playwright's Chromium lacks proprietary codecs. The playlist test is what surfaced the responsive-mode fix above - playlists are the one core surface rendering a percentage-width player, and neither core nor Gutenberg had any test exercising these players before.

The QUnit suite (601 tests), the 6 PHPUnit tests, and the full e2e suite pass locally.

Testing Instructions

Test in WordPress Playground

AI Use

Code, tests, and description all written with 🤖 Claude Code. I will review and test.

@github-actions

github-actions Bot commented Jun 3, 2024

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@adamsilverstein adamsilverstein changed the title Updated mediaelement.js to 5.0.5 Updated mediaelement.js to 7.0.5 Jun 4, 2024
The 7.1.0 release adds keyboard play/pause controls on the player
container, screen reader text for current time and total duration, and
mobile/desktop fullscreen fixes. No public API changes affect the
WordPress integration.

Also bump the registered script and style versions from 4.2.17 to 7.1.0
so browsers cache-bust the updated files, and drop the favicon.ico that
was copied in from the npm package by mistake - WordPress does not ship
it.
Since MediaElement.js 7.0, MediaElementPlayer.prototype.remove() no
longer deletes the destroyed player from the mejs.players registry.
WordPress iterates that registry to pause and tear down players
(wp.media.mixin.removeAllPlayers(), mce-view), and wp-playlist re-creates
a player on the same node for every track change, so stale entries would
accumulate and dead players would be acted on. Wrap remove() in the
migrate shim to restore the pre-7.0 cleanup.
QUnit now loads mediaelement-migrate.js in the same order production
does and exercises the API surface WordPress depends on: the mejs
globals, the migrate shim aliases, the jQuery integration, the player
methods used by media-audiovideo and wp-playlist, and a functional check
that instantiating a player builds controls from the configured
iconSprite and that remove() unregisters the player.

The PHPUnit tests read the bundled library version out of
mediaelement-and-player.js and assert every registered mediaelement
script and style version matches it, so the files can no longer be
updated without bumping the registered versions (or vice versa), and
verify the localized settings carry a resolvable iconSprite path.
@adamsilverstein adamsilverstein changed the title Updated mediaelement.js to 7.0.5 Update MediaElement.js to 7.1.0 Aug 31, 2026
adamsilverstein and others added 3 commits August 31, 2026 16:28
The migrate shim converted player.container, player.controls, and
player.layers to jQuery objects inside _meReady() for 4.x back compat.
MediaElement.js 7.x calls native DOM methods on those properties:
setResponsiveMode() calls container.querySelector() for players with
percentage widths, which is how playlists render. Construction threw,
the success callback never fired, and wp-playlist.js was left without
its mejs reference, so switching or playing tracks threw again.

Keep the properties as HTML elements and expose jQuery wrappers under
$container, $controls, and $layers instead. Core itself only calls
container.remove(), which works natively on an element; code written
against the 4.x jQuery API can use the new wrappers. Add a QUnit
regression test instantiating a fluid-width player, which follows the
responsive code path the fixed-size player test never reached.
Nothing in core or Gutenberg exercised the players MediaElement.js
powers, so a library update could break front-end playback without any
test noticing. Cover each player surface WordPress exposes: the [audio]
and [video] shortcodes (real play and pause, SVG sprite controls, the
mejs.players registry), audio [playlist] track switching, video
playlists, and the YouTube and Vimeo renderers.

Playback assertions use mp3 and webm fixtures (copied from the PHPUnit
data set) because Playwright's Chromium ships without proprietary
codecs. The external renderer tests assert the embed iframes attach
rather than real playback to limit exposure to third-party outages.

The playlist test is what surfaced the responsive-mode regression fixed
in 58b2540: playlists are the one core surface that renders a
percentage-width player.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DxbbMKz3sa741SjHuE1ZLS
@adamsilverstein
adamsilverstein marked this pull request as ready for review October 1, 2026 03:52
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props coquardcyr, adamsilverstein.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants