Index: src/js/media/models/attachments.js
===================================================================
--- src/js/media/models/attachments.js	(revision 46238)
+++ src/js/media/models/attachments.js	(working copy)
@@ -293,6 +293,8 @@
 		this.reset( [], { silent: true } );
 		this.observe( attachments );
 
+		// Used for the search results.
+		this.trigger( 'attachments:received', this );
 		return this;
 	},
 	/**
@@ -332,6 +334,9 @@
 			if ( this === attachments.mirroring ) {
 				deferred.resolveWith( this );
 			}
+
+			// Used for the search results.
+			attachments.trigger( 'attachments:received', this );
 		});
 
 		return deferred.promise();
Index: src/js/media/views/attachments/browser.js
===================================================================
--- src/js/media/views/attachments/browser.js	(revision 46238)
+++ src/js/media/views/attachments/browser.js	(working copy)
@@ -83,8 +83,40 @@
 		}
 
 		this.collection.on( 'add remove reset', this.updateContent, this );
+
+		// The non-cached or cached attachments query has completed.
+		this.collection.on( 'attachments:received', this.announceSearchResults, this );
 	},
 
+	/**
+	 * Updates the `wp.a11y.speak()` ARIA live region with a message to communicate
+	 * the number of search results to screen reader users. This function is
+	 * debounced because the collection updates multiple times.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @returns {void}
+	 */
+	announceSearchResults: _.debounce( function() {
+		var count;
+
+		if ( this.collection.mirroring.args.s ) {
+			count = this.collection.length;
+
+			if ( 0 === count ) {
+				wp.a11y.speak( l10n.noMediaTryNewSearch );
+				return;
+			}
+
+			if ( this.collection.hasMore() ) {
+				wp.a11y.speak( l10n.mediaFoundHasMoreResults.replace( '%d', count ) );
+				return;
+			}
+
+			wp.a11y.speak( l10n.mediaFound.replace( '%d', count ) );
+		}
+	}, 200 ),
+
 	editSelection: function( modal ) {
 		// When editing a selection, move focus to the "Return to library" button.
 		modal.$( '.media-button-backToLibrary' ).focus();
Index: src/js/media/views/focus-manager.js
===================================================================
--- src/js/media/views/focus-manager.js	(revision 46238)
+++ src/js/media/views/focus-manager.js	(working copy)
@@ -71,8 +71,9 @@
 	 * provided element and other elements that should not be hidden.
 	 *
 	 * The reason why we use `aria-hidden` is that `aria-modal="true"` is buggy
-	 * in Safari 11.1 and support is spotty in other browsers. In the future we
-	 * should consider to remove this helper function and only use `aria-modal="true"`.
+	 * in Safari 11.1 and support is spotty in other browsers. Also, `aria-modal="true"`
+	 * prevents the `wp.a11y.speak()` ARIA live regions to work as they're outside
+	 * of the modal dialog and get hidden from assistive technologies.
 	 *
 	 * @since 5.2.3
 	 *
Index: src/js/media/views/search.js
===================================================================
--- src/js/media/views/search.js	(revision 46238)
+++ src/js/media/views/search.js	(working copy)
@@ -22,8 +22,7 @@
 	},
 
 	events: {
-		'input':  'search',
-		'keyup':  'search'
+		'input': 'search'
 	},
 
 	/**
@@ -35,12 +34,15 @@
 	},
 
 	search: _.debounce( function( event ) {
-		if ( event.target.value ) {
-			this.model.set( 'search', event.target.value );
+		var searchTerm = event.target.value.trim();
+
+		// Trigger the search only after 2 ASCII characters.
+		if ( searchTerm && searchTerm.length > 1 ) {
+			this.model.set( 'search', searchTerm );
 		} else {
-			this.model.unset('search');
+			this.model.unset( 'search' );
 		}
-	}, 300 )
+	}, 500 )
 });
 
 module.exports = Search;
Index: src/wp-includes/media-template.php
===================================================================
--- src/wp-includes/media-template.php	(revision 46238)
+++ src/wp-includes/media-template.php	(working copy)
@@ -187,7 +187,7 @@
 
 	<?php // Template for the media modal. ?>
 	<script type="text/html" id="tmpl-media-modal">
-		<div tabindex="0" class="<?php echo $class; ?>" role="dialog" aria-modal="true" aria-labelledby="media-frame-title">
+		<div tabindex="0" class="<?php echo $class; ?>" role="dialog" aria-labelledby="media-frame-title">
 			<# if ( data.hasCloseButton ) { #>
 				<button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></span></button>
 			<# } #>
Index: src/wp-includes/media.php
===================================================================
--- src/wp-includes/media.php	(revision 46238)
+++ src/wp-includes/media.php	(working copy)
@@ -3854,7 +3854,10 @@
 		'filterByType'                => __( 'Filter by type' ),
 		'searchMediaLabel'            => __( 'Search Media' ),
 		'searchMediaPlaceholder'      => __( 'Search media items...' ), // placeholder (no ellipsis)
-		'noMedia'                     => __( 'No media files found.' ),
+		'mediaFound'                  => __( 'Number of media items found: %d' ),
+		'mediaFoundHasMoreResults'    => __( 'Number of media items displayed: %d. Scroll the page for more results.' ),
+		'noMedia'                     => __( 'No media items found.' ),
+		'noMediaTryNewSearch'         => __( 'No media items found. Try a different search.' ),
 
 		// Library Details
 		'attachmentDetails'           => __( 'Attachment Details' ),
Index: src/wp-includes/script-loader.php
===================================================================
--- src/wp-includes/script-loader.php	(revision 46238)
+++ src/wp-includes/script-loader.php	(working copy)
@@ -1624,7 +1624,7 @@
 
 	// To enqueue media-views or media-editor, call wp_enqueue_media().
 	// Both rely on numerous settings, styles, and templates to operate correctly.
-	$scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'wp-api-request' ), false, 1 );
+	$scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'wp-api-request', 'wp-a11y' ), false, 1 );
 	$scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
 	$scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 );
 	$scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'jquery', 'media-views', 'media-audiovideo' ), false, 1 );
