Index: src/wp-includes/functions.php
===================================================================
--- src/wp-includes/functions.php	(revision 42717)
+++ src/wp-includes/functions.php	(working copy)
@@ -283,6 +283,62 @@
 }
 
 /**
+ * Convert a filelength to human readable format.
+ *
+ * @since 5.0
+ *
+ * @param string $filelength Duration will be in string format (HH:ii:ss) OR (ii:ss).
+ * @return boolean|string A human readable filelength string, false on failure.
+ */
+function human_readable_duration( $filelength = '' ) {
+	// Return false if filelength is empty or not in format.
+	if ( ( empty( $filelength ) || ! is_string( $filelength ) ) ) {
+		return false;
+	}
+
+	// Validate filelength format.
+	if ( ! ( (bool) preg_match( '/^(([0-3]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$/', $filelength ) ) ) {
+		return false;
+	}
+
+	$human_readable_duration = [];
+
+	// Extract duration.
+	$durations      = array_reverse( explode( ':', $filelength ) );
+	$duration_count = count( $durations );
+
+	if ( 3 === $duration_count ) {
+		// Three parts: hours, minutes & seconds.
+		list( $second, $minute, $hour ) = $durations;
+	} elseif ( 2 === $duration_count ) {
+		// Two parts: minutes & seconds.
+		list( $second, $minute ) = $durations;
+	} else {
+		return false;
+	}
+
+	// Add the hour part to the string.
+	if ( ! empty( $hour ) && is_numeric( $hour ) ) {
+		/* translators: Time duration in hour or hours. */
+		$human_readable_duration[] = sprintf( _n( '%s hour', '%s hours', $hour ), (int) $hour );
+	}
+
+	// Add the minute part to the string.
+	if ( ! empty( $minute ) && is_numeric( $minute ) ) {
+		/* translators: Time duration in minute or minutes. */
+		$human_readable_duration[] = sprintf( _n( '%s minute', '%s minutes', $minute ), (int) $minute );
+	}
+
+	// Add the second part to the string.
+	if ( ! empty( $second ) && is_numeric( $second ) ) {
+		/* translators: Time duration in second or seconds. */
+		$human_readable_duration[] = sprintf( _n( '%s second', '%s seconds', $second ), (int) $second );
+	}
+
+	return implode( ', ', $human_readable_duration );
+}
+
+/**
  * Get the week start and end from the datetime or date string from MySQL.
  *
  * @since 0.71
@@ -673,11 +729,11 @@
 /**
  * Determines whether the publish date of the current post in the loop is different
  * from the publish date of the previous post in the loop.
- * 
+ *
  * For more information on this and similar theme functions, check out
- * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 
+ * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  * Conditional Tags} article in the Theme Developer Handbook.
- * 
+ *
  * @since 0.71
  *
  * @global string $currentday  The day of the current post in the loop.
@@ -1393,9 +1449,9 @@
  * cache, and the database goes away, then you might have problems.
  *
  * Checks for the 'siteurl' option for whether WordPress is installed.
- * 
+ *
  * For more information on this and similar theme functions, check out
- * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 
+ * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  * Conditional Tags} article in the Theme Developer Handbook.
  *
  * @since 2.1.0
Index: src/wp-includes/media-template.php
===================================================================
--- src/wp-includes/media-template.php	(revision 42717)
+++ src/wp-includes/media-template.php	(working copy)
@@ -371,12 +371,20 @@
 				<div class="file-size"><strong><?php _e( 'File size:' ); ?></strong> {{ data.filesizeHumanReadable }}</div>
 				<# if ( 'image' === data.type && ! data.uploading ) { #>
 					<# if ( data.width && data.height ) { #>
-						<div class="dimensions"><strong><?php _e( 'Dimensions:' ); ?></strong> {{ data.width }} &times; {{ data.height }}</div>
+						<div class="dimensions"><strong><?php _e( 'Dimensions:' ); ?></strong>
+							<?php
+							/* translators: 1: a number of pixels wide, 2: a number of pixels tall. */
+							printf( __( '%1$s by %2$s pixels' ), '{{ data.width }}', '{{ data.height }}' );
+							?>
+						</div>
 					<# } #>
 				<# } #>
 
-				<# if ( data.fileLength ) { #>
-					<div class="file-length"><strong><?php _e( 'Length:' ); ?></strong> {{ data.fileLength }}</div>
+				<# if ( data.fileLength && data.fileLengthHumanReadable ) { #>
+					<div class="file-length"><strong><?php _e( 'Length:' ); ?></strong>
+						<span aria-hidden="true">{{ data.fileLength }}</span>
+						<span class="screen-reader-text">{{ data.fileLengthHumanReadable }}</span>
+					</div>
 				<# } #>
 
 				<# if ( 'audio' === data.type && data.meta.bitrate ) { #>
@@ -547,7 +555,12 @@
 				<div class="file-size">{{ data.filesizeHumanReadable }}</div>
 				<# if ( 'image' === data.type && ! data.uploading ) { #>
 					<# if ( data.width && data.height ) { #>
-						<div class="dimensions">{{ data.width }} &times; {{ data.height }}</div>
+						<div class="dimensions">
+							<?php
+							/* translators: 1: a number of pixels wide, 2: a number of pixels tall. */
+							printf( __( '%1$s by %2$s pixels' ), '{{ data.width }}', '{{ data.height }}' );
+							?>
+						</div>
 					<# } #>
 
 					<# if ( data.can.save && data.sizes ) { #>
@@ -555,8 +568,11 @@
 					<# } #>
 				<# } #>
 
-				<# if ( data.fileLength ) { #>
-					<div class="file-length"><?php _e( 'Length:' ); ?> {{ data.fileLength }}</div>
+				<# if ( data.fileLength && data.fileLengthHumanReadable ) { #>
+					<div class="file-length"><?php _e( 'Length:' ); ?>
+						<span aria-hidden="true">{{ data.fileLength }}</span>
+						<span class="screen-reader-text">{{ data.fileLengthHumanReadable }}</span>
+					</div>
 				<# } #>
 
 				<# if ( ! data.uploading && data.can.remove ) { #>
Index: src/wp-includes/media.php
===================================================================
--- src/wp-includes/media.php	(revision 42717)
+++ src/wp-includes/media.php	(working copy)
@@ -3372,7 +3372,8 @@
 
 	if ( $meta && ( 'audio' === $type || 'video' === $type ) ) {
 		if ( isset( $meta['length_formatted'] ) ) {
-			$response['fileLength'] = $meta['length_formatted'];
+			$response['fileLength']              = $meta['length_formatted'];
+			$response['fileLengthHumanReadable'] = human_readable_duration( $meta['length_formatted'] );
 		}
 
 		$response['meta'] = array();
Index: tests/phpunit/tests/functions.php
===================================================================
--- tests/phpunit/tests/functions.php	(revision 42717)
+++ tests/phpunit/tests/functions.php	(working copy)
@@ -1451,4 +1451,43 @@
 
 		);
 	}
+
+	/**
+	 * Test the human_readable_duration function.
+	 *
+	 * @ticket 39667
+	 * @dataProvider _datahuman_readable_duration()
+	 *
+	 * @param $input
+	 * @param $expected
+	 */
+	public function test_duration_format( $input, $expected ) {
+		$this->assertSame( $expected, human_readable_duration( $input ) );
+	}
+
+	public function _datahuman_readable_duration() {
+		return array(
+			array( array(), false ),
+			array( '30:00', '30 minutes, 0 seconds' ),
+			array( 'Batman Begins !', false ),
+			array( '', false ),
+			array( '-1', false ),
+			array( -1, false ),
+			array( 0, false ),
+			array( 1, false ),
+			array( '00', false ),
+			array( '00:00', '0 minutes, 0 seconds' ),
+			array( '00:00:00', '0 hours, 0 minutes, 0 seconds' ),
+			array( '10:30:34', '10 hours, 30 minutes, 34 seconds' ),
+			array( '00:30:34', '0 hours, 30 minutes, 34 seconds' ),
+			array( 'MM:30:00', false ),
+			array( '30:MM', false ),
+			array( 'MM:00', false ),
+			array( 'MM:MM', false ),
+			array( '01:01', '1 minute, 1 second' ),
+			array( '01:01:01', '1 hour, 1 minute, 1 second' ),
+			array( '0:05', '5 seconds' ),
+			array( '1:02:00', '1 hour, 2 minutes, 0 seconds' ),
+		);
+	}
 }
