{"id":123048,"date":"2026-06-04T08:16:06","date_gmt":"2026-06-04T08:16:06","guid":{"rendered":"https:\/\/make.wordpress.org\/core\/?p=123048"},"modified":"2026-06-04T12:47:42","modified_gmt":"2026-06-04T12:47:42","slug":"call-for-testing-client-side-media-processing","status":"publish","type":"post","link":"https:\/\/make.wordpress.org\/core\/2026\/06\/04\/call-for-testing-client-side-media-processing\/","title":{"rendered":"Call for Testing: client-side media processing"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Client-side media processing is a progressive <span tabindex='0' class='glossary-item-container'>enhancement<span class='glossary-item-hidden-content'><span class='glossary-item-header'>enhancement<\/span> <span class='glossary-item-description'>Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature.<\/span><\/span><\/span> to WordPress\u2019s existing server-based media pipeline. When a user uploads an image in the <span tabindex='0' class='glossary-item-container'>block<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Block<\/span> <span class='glossary-item-description'>Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.<\/span><\/span><\/span> editor, their browser decodes, resizes, and encodes all sub-sizes locally using the VIPS image processing library running in WebAssembly (via<a href=\"https:\/\/github.com\/kleisauke\/wasm-vips\"> wasm-vips<\/a>) before sending them to the server. Browsers that can\u2019t handle the work silently fall back to the existing server-side path without user-visible errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The advantage of this approach is that we can provide a uniform, modern image processing experience across all WordPress sites without relying on server-side <span tabindex='0' class='glossary-item-container'>capabilities<span class='glossary-item-hidden-content'><span class='glossary-item-header'>capability<\/span> <span class='glossary-item-description'>A\u00a0<strong>capability<\/strong>\u00a0is permission to perform one or more types of task. Checking if a user has a capability is performed by the <code>current_user_can<\/code> function. Each user of a WordPress site might have some permissions but not others, depending on their\u00a0role. For example, users who have the Author role usually have permission to edit their own posts (the \u201cedit_posts\u201d capability), but not permission to edit other users\u2019 posts (the \u201cedit_others_posts\u201d capability).<\/span><\/span><\/span>. The client-side pipeline supports modern formats (AVIF, WebP, HEIC, UltraHDR, JPEG XL), offering better compression, and more consistent resizing quality regardless of hosting environment. It also <em>reduces CPU and memory load on the server during image uploads<\/em> by offloading the work to capable devices.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The feature graduated from a <span tabindex='0' class='glossary-item-container'>Gutenberg<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Gutenberg<\/span> <span class='glossary-item-description'>The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses \u2018blocks\u2019 to add richness rather than shortcodes, custom HTML etc.\r<a href=\"https:\/\/wordpress.org\/gutenberg\/\">https:\/\/wordpress.org\/gutenberg\/<\/a><\/span><\/span><\/span> experiment to a <span tabindex='0' class='glossary-item-container'>core<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Core<\/span> <span class='glossary-item-description'>Core is the set of software required to run WordPress. The Core Development Team builds WordPress.<\/span><\/span><\/span> Gutenberg feature during the 7.0 cycle and is now targeting <strong>WordPress 7.1<\/strong> as a core <span tabindex='0' class='glossary-item-container'>capability<span class='glossary-item-hidden-content'><span class='glossary-item-header'>capability<\/span> <span class='glossary-item-description'>A\u00a0<strong>capability<\/strong>\u00a0is permission to perform one or more types of task. Checking if a user has a capability is performed by the <code>current_user_can<\/code> function. Each user of a WordPress site might have some permissions but not others, depending on their\u00a0role. For example, users who have the Author role usually have permission to edit their own posts (the \u201cedit_posts\u201d capability), but not permission to edit other users\u2019 posts (the \u201cedit_others_posts\u201d capability).<\/span><\/span><\/span>.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With 7.1 on the horizon, the feature could use testing to help us shake out bugs, validate performance on real content and devices, and stress-test the new capabilities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Tracking issues:<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/issues\/76756\">#76756 \u2014 Client Side Media iteration for WordPress 7.1<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/WordPress\/gutenberg\/issues\/74333\">#74333 \u2014 Client Side Media iteration for WordPress 7.0<\/a> (previous cycle, closed)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What\u2019s included in this round of testing<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The 7.1 iteration tracked in <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/issues\/76756\">#76756<\/a> builds on the 7.0 groundwork and adds several new capabilities. Highlights include improved format support, error handling and upload resilience. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A note on bundle size<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Download weight and the lack of new capabilities was the biggest piece of feedback during the 7.0 cycle, so it has been a focus this iteration. Client-side processing now\u00a0<em>exceeds<\/em>\u00a0the format and quality capabilities of the best server-side setups, while loading less ahead of time than the 7.0 prototype<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Nothing heavy loads up front.<\/strong>\u00a0The WebAssembly image pipeline (wasm-vips and friends) is fetched on demand the first time a user uploads media \u2013 it is\u00a0<em>not<\/em>\u00a0part of the editor\u2019s initial bundle.<\/li>\n\n\n\n<li><strong>New capabilities<\/strong>\u00a0UltraHDR, HEIC and JPEGXL support, as well as the new GIF\u2192video conversion feature, are all new capabilities and added minimal weight.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How to test<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Please run through as many of the scenarios below as your environment allows, and report anything that looks wrong \u2014 slow, broken, unexpectedly falling back to server-side, visibly lower quality, etc. Test with the latest Gutenberg <span tabindex='0' class='glossary-item-container'>plugin<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Plugin<\/span> <span class='glossary-item-description'>A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory <a href=\"https:\/\/wordpress.org\/plugins\/\">https:\/\/wordpress.org\/plugins\/<\/a> or can be cost-based plugin from a third-party.<\/span><\/span><\/span> and in a chromium browser for the feature to be active.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">System and Browser Requirements<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Non-Chromium browsers<\/strong>: Disabled by default because Firefox and Safari don\u2019t support <code>Document-Isolation-Policy<\/code>. The HEIC canvas fallback still runs in Safari.<\/li>\n\n\n\n<li><strong>Low-memory devices<\/strong>: Devices reporting 2 GB of RAM or less are excluded.<\/li>\n\n\n\n<li><strong>2g \/ slow-2g \/ Browsers sending the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Reference\/Headers\/Save-Data\">Save-Data header<\/a><\/strong>: Excluded because of the large worker download and increased upload bandwidth.<\/li>\n\n\n\n<li><strong>CSP restrictions<\/strong>: Sites with <code>worker-src<\/code> directives that don\u2019t allow <code>blob:<\/code> fall back to server-side.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You can verify that the feature is active by checking <code>window.__clientSideMediaProcessing<\/code> in the browser console (should be <code>true<\/code>), or by looking for <span tabindex='0' class='glossary-item-container'>network<span class='glossary-item-hidden-content'><span class='glossary-item-header'>network<\/span> <span class='glossary-item-description'>(versus site, blog)<\/span><\/span><\/span> requests to the sideload endpoint. You can also use <a href=\"https:\/\/gist.github.com\/adamsilverstein\/3f5d2a38916198573f543fc6ce643764\">this mini plugin<\/a> to check the upload processing type (client or server) \u2013 it shows a label on the front end and adds a column to the Media library list view.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Baseline upload flow<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Upload a handful of JPEGs, WebPs, HEICs, AVIFs, GIFs and PNGs (mix of sizes: ~500 KB, ~5 MB, and a &gt;20 MB original) in the editor.<\/li>\n\n\n\n<li>Confirm the Image block renders the uploaded image.<\/li>\n\n\n\n<li>Verify all expected sub-sizes exist on disk.<\/li>\n\n\n\n<li>Compare file sizes and visual quality to the same image uploaded using the media library (which uses server processing).<\/li>\n\n\n\n<li>Test uploading avif, webp, heic, png (with various transparency and bit depths), and jpg files and confirm they are processed correctly.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. HEIC (iPhone photos)<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Upload a `.heic` image from an iPhone. Use your computer to do the upload (the iPhone\u2019s uploader will automatically convert to JPEG before upload, so you won\u2019t be testing the client-side features if you upload directly from the phone).<\/li>\n\n\n\n<li>Confirm it is transcoded to a web format (JPEG\/WebP\/AVIF depending on your settings) and that sub-sizes are generated.<\/li>\n\n\n\n<li>Confirm the original HEIC is also uploaded and preserved.<\/li>\n\n\n\n<li>Confirm Portrait and Landscape HEICs work correctly.<\/li>\n\n\n\n<li>Try a browser that lacks native HEIC decoding to verify the canvas fallback \u2013 see <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/76731\">#76731<\/a> for browser support details.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Modern output formats (AVIF \/ WebP)<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>use the <code>image_editor_output_format<\/code> <span tabindex='0' class='glossary-item-container'>filter<span class='glossary-item-hidden-content'><span class='glossary-item-header'>Filter<\/span> <span class='glossary-item-description'>Filters are one of the two types of Hooks <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Hooks\">https:\/\/codex.wordpress.org\/Plugin_API\/Hooks<\/a>. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.<\/span><\/span><\/span> to output different formats from jpeg uploads.<\/li>\n\n\n\n<li>test uploading avif, webp, heic, png (with various transparency and bit depths), and jpg files and confirm they are processed correctly according to the configured output format.<\/li>\n\n\n\n<li>Upload a large JPEG and confirm sub-sizes are emitted in the configured format, including the <code>-scaled<\/code> variant.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Ultra HDR<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Testable in <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/74873\">#74873<\/a><\/li>\n\n\n\n<li>Upload an Ultra HDR image (you can capture one on a recent Pixel or iPhone, or download samples from <a href=\"https:\/\/github.com\/MONOGRID\/gainmap-js\">gainmap-js demos<\/a>).<\/li>\n\n\n\n<li>Confirm the gain map is preserved through resizing and that sub-sizes still render as HDR on a capable display\/browser.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. JPEG XL (JXL)<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Testable in <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/77584\">#77584<\/a>.  <\/li>\n\n\n\n<li>Upload a `.jxl` image (<a href=\"https:\/\/jpegxl.info\/resources\/gallery\/\">sample gallery<\/a>).<\/li>\n\n\n\n<li>Confirm it is accepted and processed. Report any unexpected behavior.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. Animated GIF \u2192 video<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ready to test once <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/76946\">#76946<\/a> merges<\/li>\n\n\n\n<li>Upload a large animated GIF.<\/li>\n\n\n\n<li>Confirm it is converted to an MP4 or WebM (depending on implementation), and that the resulting block plays correctly in the editor and on the front end.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. Batch and concurrent uploads<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Drag-and-drop 10\u201320 images at once into the Image block or Media Library.<\/li>\n\n\n\n<li>Watch for progress <span tabindex='0' class='glossary-item-container'>UI<span class='glossary-item-hidden-content'><span class='glossary-item-header'>UI<\/span> <span class='glossary-item-description'>User interface<\/span><\/span><\/span>, confirm all uploads complete, and check timing against a baseline where client-side is disabled.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8. Resilience<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test in <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/76765\">#76765<\/a>.<\/li>\n\n\n\n<li>Use browser dev-tools to simulate a slow\/flaky network during a batch upload and confirm retry behavior.<\/li>\n\n\n\n<li>Try to save a post mid-upload and confirm the editor prevents or defers the save <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/76973\">#76973<\/a>.<\/li>\n\n\n\n<li>Upload something, then refresh mid-upload \u2014 confirm the editor recovers cleanly.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>9. Fallback paths<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test in a browser that does <strong>not<\/strong> meet capability requirements (Safari, Firefox)<\/li>\n\n\n\n<li>Confirm the upload succeeds via the server-side path without user-visible errors. The only signal should be a developer-console message.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>10. Extensibility<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If you maintain a media-related plugin (image optimizers, DAM integrations, custom workflows), try it against a site with client-side media enabled.<\/li>\n\n\n\n<li>Exercise the new filters\/actions from <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/74913\">#74913<\/a> and report any gaps.<\/li>\n\n\n\n<li>Test disabling Client-side media.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>11. Low-powered devices<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test on a low-end laptop, older Chromebook, or mid-range phone.<\/li>\n\n\n\n<li>Confirm that the capability detection correctly gates the feature off when the device is underpowered and that processing does not lock up the browser.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Questions &amp; bugs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Please report bugs by opening issues on the Gutenberg repo tagged with <code>[Feature: Client Side Media]<\/code>. Or, leave questions or comments on <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/issues\/76756\">the tracking issue<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Thank you<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Client-side media is a substantial shift in how WordPress handles images, and it only ships well with real-world testing across the full diversity of WordPress sites, browsers, and devices. Every report helps!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Props<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Thanks to <a href=\"https:\/\/profiles.wordpress.org\/jorbin\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>jorbin<\/a> and <a href=\"https:\/\/profiles.wordpress.org\/ozgursar\/\" class=\"mention\"><span class=\"mentions-prefix\">@<\/span>ozgursar<\/a> for reviewing this post!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n<p class=\"o2-appended-tags\"><a href=\"https:\/\/make.wordpress.org\/core\/tag\/call-for-testing\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>call-for-testing<\/a>, <a href=\"https:\/\/make.wordpress.org\/core\/tag\/media\/\" class=\"tag\"><span class=\"tag-prefix\">#<\/span>media<\/a><\/p><nav class='o2-post-footer-actions'><ul class='o2-post-footer-action-row'><li class='o2-post-footer-action'><a href=\"https:\/\/login.wordpress.org\/?redirect_to=https%3A%2F%2Fmake.wordpress.org%2Fcore%2F2026%2F06%2F04%2Fcall-for-testing-client-side-media-processing%2F%23respond&#038;locale=en_US\" title=\"Login to Reply\"  class=\"genericon  genericon-reply\"  data-action=\"login-to-reply\"  data-actionstate=\"default\" >Login to Reply<\/a><\/li><\/ul><div class='o2-post-footer-action-likes'><\/div><ul class='o2-post-footer-action-row'><\/ul><\/nav>","protected":false},"excerpt":{"rendered":"<p>Client-side media processing is a progressive enhancementenhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. to WordPress\u2019s existing server-based media pipeline. When a user uploads an image in the blockBlock Block is the abstract term used to describe units of [&hellip;]<\/p>\n","protected":false},"author":10464658,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[4424],"tags":[1404,1397],"class_list":["post-123048","post","type-post","status-publish","format-standard","hentry","category-core","tag-call-for-testing","tag-media","mentions-jorbin","mentions-ozgursar","author-adamsilverstein"],"revision_note":"","jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2AvED-w0E","_links":{"self":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/123048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/users\/10464658"}],"replies":[{"embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/comments?post=123048"}],"version-history":[{"count":29,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/123048\/revisions"}],"predecessor-version":[{"id":123756,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/posts\/123048\/revisions\/123756"}],"wp:attachment":[{"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/media?parent=123048"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/categories?post=123048"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/make.wordpress.org\/core\/wp-json\/wp\/v2\/tags?post=123048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}