diff --git src/wp-admin/includes/media.php src/wp-admin/includes/media.php
index 879b75b0e8..f505625beb 100644
--- src/wp-admin/includes/media.php
+++ src/wp-admin/includes/media.php
@@ -3424,6 +3424,135 @@ function wp_get_media_creation_timestamp( $metadata ) {
 	return $creation_date;
 }
 
+/**
+ * Detect MP4 Content Type
+ *
+ * The MP4 file extension is intended for video content, but might be
+ * mistakenly applied to audio files as well. This will attempt to
+ * determine an MP4 file's content and rename if needed.
+ *
+ * @since 4.9
+ *
+ * @see https://core.trac.wordpress.org/ticket/40921
+ *
+ * @param array $wp_check_filetype_and_ext File data array.
+ * @param string $file Full path to file.
+ * @param string $filename The name of the file.
+ * @param array $mimes Allowed MIME types.
+ * @return array File data.
+ */
+function wp_check_mp4_filetype_and_ext( $checked, $file, $filename, $mimes = null ) {
+	if ( 'mp4' === $checked['ext'] ) {
+		// Load ID3 parser.
+		if ( ! defined( 'GETID3_TEMP_DIR' ) ) {
+			define( 'GETID3_TEMP_DIR', get_temp_dir() );
+		}
+
+		if ( ! class_exists( 'getID3', false ) ) {
+			require( ABSPATH . WPINC . '/ID3/getid3.php' );
+		}
+
+		$id3 = new getID3();
+		$data = $id3->analyze( $file );
+
+		// This is audio if the MIME says so.
+		if (
+			isset( $data['mime_type'] ) &&
+			( 0 === strpos( $data['mime_type'], 'audio/' ) )
+		) {
+			$checked['ext'] = 'm4a';
+			$checked['type'] = 'audio/mpeg';
+		}
+
+		// The ftype might suggest its audioness.
+		elseif (
+			isset( $data['quicktime']['ftype']['signature'] ) &&
+			( 'M4A' === $data['quicktime']['ftype']['signature'] )
+		) {
+			$checked['ext'] = 'm4a';
+			$checked['type'] = 'audio/mpeg';
+		}
+
+		// This might also be audio if there is no video resolution.
+		elseif (
+			isset( $data['video']['resolution_x'] ) &&
+			! $data['video']['resolution_x'] &&
+			isset( $data['video']['resolution_y'] ) &&
+			! $data['video']['resolution_y']
+		) {
+			$checked['ext'] = 'm4a';
+			$checked['type'] = 'audio/mpeg';
+		}
+
+		// Update the filename.
+		if ( 'm4a' === $checked['ext'] ) {
+			$checked['proper_filename'] = substr( $filename, 0, -3 ) . 'm4a';
+		}
+	}
+
+	return $checked;
+}
+add_filter( 'wp_check_filetype_and_ext', 'wp_check_mp4_filetype_and_ext', 100, 4 );
+
+/**
+ * Detect OGG Content Type
+ *
+ * The OGG file extension is intended for audio content, but might be
+ * mistakenly applied to video files as well. This will attempt to
+ * determine an OGG file's content and rename if needed.
+ *
+ * @since 4.9
+ *
+ * @see https://core.trac.wordpress.org/ticket/40921
+ *
+ * @param array $wp_check_filetype_and_ext File data array.
+ * @param string $file Full path to file.
+ * @param string $filename The name of the file.
+ * @param array $mimes Allowed MIME types.
+ * @return array File data.
+ */
+function wp_check_ogg_filetype_and_ext( $checked, $file, $filename, $mimes = null ) {
+	if ( 'ogg' === $checked['ext'] ) {
+		// Load ID3 parser.
+		if ( ! defined( 'GETID3_TEMP_DIR' ) ) {
+			define( 'GETID3_TEMP_DIR', get_temp_dir() );
+		}
+
+		if ( ! class_exists( 'getID3', false ) ) {
+			require( ABSPATH . WPINC . '/ID3/getid3.php' );
+		}
+
+		$id3 = new getID3();
+		$data = $id3->analyze( $file );
+
+		// This is video if the MIME says so.
+		if (
+			isset( $data['mime_type'] ) &&
+			( 0 === strpos( $data['mime_type'], 'video/' ) )
+		) {
+			$checked['ext'] = 'ogv';
+			$checked['type'] = 'video/ogg';
+		}
+
+		// This is video if there is a resolution.
+		elseif (
+			( isset( $data['video']['resolution_x'] ) && $data['video']['resolution_x'] > 0 ) ||
+			( isset( $data['video']['resolution_y'] ) && $data['video']['resolution_y'] > 0 )
+		) {
+			$checked['ext'] = 'ogv';
+			$checked['type'] = 'video/ogg';
+		}
+
+		// Update the filename.
+		if ( 'ogv' === $checked['ext'] ) {
+			$checked['proper_filename'] = substr( $filename, 0, -3 ) . 'ogv';
+		}
+	}
+
+	return $checked;
+}
+add_filter( 'wp_check_filetype_and_ext', 'wp_check_ogg_filetype_and_ext', 100, 4 );
+
 /**
  * Encapsulate logic for Attach/Detach actions
  *
diff --git tests/phpunit/data/uploads/small-audio.mp4 tests/phpunit/data/uploads/small-audio.mp4
new file mode 100644
index 0000000000..8b823c0625
Binary files /dev/null and tests/phpunit/data/uploads/small-audio.mp4 differ
diff --git tests/phpunit/data/uploads/small-audio.ogg tests/phpunit/data/uploads/small-audio.ogg
new file mode 100644
index 0000000000..85d48d4c36
Binary files /dev/null and tests/phpunit/data/uploads/small-audio.ogg differ
diff --git tests/phpunit/data/uploads/small-video.ogg tests/phpunit/data/uploads/small-video.ogg
new file mode 100644
index 0000000000..81589009ea
Binary files /dev/null and tests/phpunit/data/uploads/small-video.ogg differ
diff --git tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php
index d9e3d5fbb8..8ea8fbaee2 100644
--- tests/phpunit/tests/functions.php
+++ tests/phpunit/tests/functions.php
@@ -1301,6 +1301,43 @@ class Tests_Functions extends WP_UnitTestCase {
 							'proper_filename' => false,
 						),
 					),
+					// MP4 Video.
+					array(
+						DIR_TESTDATA . '/uploads/small-video.mp4',
+						'small-video.mp4',
+						array(
+							'ext'             => 'mp4',
+							'type'            => 'video/mp4',
+							'proper_filename' => false,
+						),
+					),
+					array(
+						DIR_TESTDATA . '/uploads/small-audio.mp4',
+						'small-audio.mp4',
+						array(
+							'ext'             => 'm4a',
+							'type'            => 'audio/mpeg',
+							'proper_filename' => 'small-audio.m4a',
+						),
+					),
+					array(
+						DIR_TESTDATA . '/uploads/small-video.ogg',
+						'small-video.ogg',
+						array(
+							'ext'             => 'ogv',
+							'type'            => 'video/ogg',
+							'proper_filename' => 'small-video.ogv',
+						),
+					),
+					array(
+						DIR_TESTDATA . '/uploads/small-audio.ogg',
+						'small-audio.ogg',
+						array(
+							'ext'             => 'ogg',
+							'type'            => 'audio/ogg',
+							'proper_filename' => false,
+						),
+					),
 				)
 			);
 		}
